View Javadoc

1   package org.apache.turbine.services.assemblerbroker.util.python;
2   
3   /*
4    * Copyright 2001-2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License")
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.io.File;
20  
21  import org.apache.commons.configuration.Configuration;
22  
23  import org.apache.commons.lang.StringUtils;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  import org.apache.turbine.modules.Assembler;
29  import org.apache.turbine.services.assemblerbroker.TurbineAssemblerBroker;
30  import org.apache.turbine.services.assemblerbroker.util.AssemblerFactory;
31  
32  import org.python.core.Py;
33  import org.python.util.PythonInterpreter;
34  
35  /***
36   * A factory that attempts to load a python class in the
37   * JPython interpreter and execute it as a Turbine screen.
38   * The JPython script should inherit from Turbine Screen or one
39   * of its subclasses.
40   *
41   * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
42   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
43   * @version $Id: PythonBaseFactory.java 264148 2005-08-29 14:21:04Z henning $
44   */
45  public abstract class PythonBaseFactory
46          implements AssemblerFactory
47  {
48      /*** Key for the python path */
49      public static final String PYTHON_PATH = "python.path";
50  
51      /*** Global config file. This is executed before every screen */
52      public static final String PYTHON_CONFIG_FILE = "conf.py";
53  
54      /*** Logging */
55      private static Log log = LogFactory.getLog(PythonBaseFactory.class);
56  
57      /*** Our configuration */
58      private Configuration conf =
59          TurbineAssemblerBroker.getService().getConfiguration();
60  
61      /***
62       * Get an Assembler.
63       *
64       * @param subDirectory subdirectory within python.path
65       * @param name name of the requested Assembler
66       * @return an Assembler
67       * @throws Exception generic exception
68       */
69      public Assembler getAssembler(String subDirectory, String name)
70              throws Exception
71      {
72          String path = conf.getString(PYTHON_PATH);
73  
74          if (StringUtils.isEmpty(path))
75          {
76              throw new Exception(
77                  "Python path not found - check your Properties");
78          }
79  
80          log.debug("Screen name for JPython: " + name);
81  
82          Assembler assembler = null;
83  
84          String confName = path + "/" + PYTHON_CONFIG_FILE;
85  
86          // The filename of the Python script
87          StringBuffer fName = new StringBuffer();
88  
89          fName.append(path);
90          fName.append("/");
91          fName.append(subDirectory);
92          fName.append("/");
93          fName.append(name.toLowerCase());
94          fName.append(".py");
95  
96          File f = new File(fName.toString());
97  
98          if (f.exists())
99          {
100             try
101             {
102                 // We try to open the Py Interpreter
103                 PythonInterpreter interp = new PythonInterpreter();
104 
105                 // Make sure the Py Interpreter use the right classloader
106                 // This is necessary for servlet engines generally has
107                 // their own classloader implementations and servlets aren't
108                 // loaded in the system classloader.  The python script will
109                 // load java package
110                 // org.apache.turbine.services.assemblerbroker.util.python;
111                 // the new classes to it as well.
112                 Py.getSystemState().setClassLoader(
113                         this.getClass().getClassLoader());
114 
115                 // We import the Python SYS module. Now we don't need to do this
116                 // explicitely in the script.  We always use the sys module to
117                 // do stuff like loading java package
118                 // org.apache.turbine.services.assemblerbroker.util.python;
119                 interp.exec("import sys");
120 
121                 // Now we try to load the script file
122                 interp.execfile(confName);
123                 interp.execfile(fName.toString());
124 
125                 try
126                 {
127                     // We create an instance of the screen class from the
128                     // python script
129                     interp.exec("scr = " + name + "()");
130                 }
131                 catch (Throwable e)
132                 {
133                     throw new Exception(
134                         "\nCannot create an instance of the python class.\n"
135                         + "You probably gave your class the wrong name.\n"
136                         + "Your class should have the same name as your "
137                         + "filename.\nFilenames should be all lowercase and "
138                         + "classnames should start with a capital.\n"
139                         + "Expected class name: " + name + "\n");
140                 }
141 
142                 // Here we convert the python sceen instance to a java instance.
143                 assembler = (Assembler) interp.get("scr", Assembler.class);
144             }
145             catch (Exception e)
146             {
147                 // We log the error here because this code is not widely tested
148                 // yet. After we tested the code on a range of platforms this
149                 // won't be usefull anymore.
150                 log.error("PYTHON SCRIPT SCREEN LOADER ERROR:", e);
151                 throw e;
152             }
153         }
154         return assembler;
155     }
156 }