Python Server Pages: Part 2 by Kirby W. Angell Listing One public class PSPServlet extends HttpServlet { PyObject m_cgEngine = null; static { // Initialize the JPython interpreter PSP.interp.exec( "import sys" ); // Put our installation directory at the beginning of the JPython // search path. That means our modules get loaded before anything else, // keeping us away from any nasty module colisions. PSP.interp.set( "PSPSearchPath", Py.java2py(PSP.pspRoot) ); PSP.interp.exec( "sys.path = [PSPSearchPath] + sys.path" ); // Load up the JPython based code generator module used by PSP PyObject cg = __builtin__.__import__( new PyString("cg") ); PyObject cgVersion = cg.__getattr__( "Version" ); // Create an instance of the code generator that we can use String cachedir = PSP.pspRoot + "cache"; PyObject engineClass = cg.__getattr__( "cgEngine" ); PyObject engine = engineClass.__call__( Py.java2py(cachedir) ); PSP.codeGenerator = engine; } public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { String psp = ((HttpServletRequest)req).getServletPath(); // Get an application object to satisify this request. PSPAppContext ac = getApplication( (HttpServletRequest)req ); ac.processPage( psp, (HttpServletRequest)req, (HttpServletResponse)res ); } // service synchronized PSPAppContext getApplication( HttpServletRequest req ) { String psp = req.getServletPath(); psp = psp.replace( '/', File.separatorChar ); psp = psp.replace( '\\', File.separatorChar ); // Get application name File pspFile = new File( psp ); String appName = pspFile.getParent(); PSPAppContext app = (PSPAppContext) PSP.getApp( appName ); if ( app == null ) return loadApplication( appName, req ); else return app; } // getApplication PSPAppContext loadApplication( String name, HttpServletRequest req ) { File pspFile = new File( name ); String appName = name; // Look for a global script file indicating the // base directory of an application. while ( appName != null ) { String globalScript = req.getRealPath( appName + File.separatorChar + PSP.GLOBAL_SCRIPT); File f = new File(globalScript); if ( f.exists() ) break; pspFile = new File( appName); appName = pspFile.getParent(); } // while if ( appName == null ) appName = new String( "" + File.separatorChar); PSPAppContext app = (PSPAppContext) PSP.getApp( appName ); if ( app == null ) { app = new PSPAppContext( (PyStringMap)PSP.interp.getLocals(), tr, appName ); PSP.addApp( appName, app ); } // If we didn't find this application in the same // directory where we started if ( !appName.equals(name) ) { // Put this application object in the cache // under the directory name where we finally found it. PSP.addApp( name, app ); } return app; } // loadApplication } Listing Two public class PSP { static PythonInterpreter interp = new PythonInterpreter(); static PyObject codeGenerator = null; static Hashtable apps = new Hashtable(); // Cache for Application Contexts static String pspRoot = findRoot(); static final String GLOBAL_SCRIPT = "global.psa"; // finds the directory where psp is installed public static String findRoot() { String root; // If find psp.jar in class.path String classpath = System.getProperty("java.class.path"); if (classpath == null) return null; int jpy = classpath.toLowerCase().indexOf("psp.jar"); if (jpy == -1) { return null; } int start = classpath.lastIndexOf(java.io.File.pathSeparator, jpy)+1; return classpath.substring(start, jpy); } // findRoot // adds a new application context to the cache static public synchronized void addApp( String name, PSPAppContext app ) { apps.put( name, app ); } // gets a cached application context from the cache static public synchronized PSPAppContext getApp( String name ) { return (PSPAppContext)apps.get( name ); } // clears the application cache for the servlet static public synchronized void clearCache( boolean newValue ) { apps = new Hashtable(); System.gc(); } // returns a python dictionary with statistics for the loaded apps static public synchronized PyDictionary getAppStats() { Hashtable ht = new Hashtable( apps.size() ); Enumeration e = apps.elements(); while ( e.hasMoreElements() ) { PSPAppContext app = (PSPAppContext)e.nextElement(); Hashtable htPages = new Hashtable( app.g_scripts.size() ); Enumeration scripts = app.g_scripts.keys(); Enumeration dates = app.g_dates.elements(); while ( scripts.hasMoreElements() ) { PyString script = new PyString( (String)scripts.nextElement() ); PyLong date = new PyLong( ((Long)dates.nextElement()).longValue() ); htPages.put( script, date ); } // While ht.put( Py.java2py(app.g_appName), new PyDictionary(htPages) ); } // while return new PyDictionary( ht ); } // getAppStats // generate a PyDictionary containing HTTP cookies static public PyDictionary makeCookies( Cookie[] cookies ) { if ( cookies == null ) return new PyDictionary(); Hashtable ht = new Hashtable( cookies.length ); for( int i = 0; i < cookies.length; i++ ) { Cookie cookie = cookies[i]; ht.put( Py.java2py( cookie.getName() ), Py.java2py( cookie ) ); } // for return new PyDictionary( ht ); } // makeCookies } Listing Three import org.python.util.PythonInterpreter; import org.python.core.*; public class SimpleEmbedded { public static void main(String []args) throws PyException { PythonInterpreter interp = new PythonInterpreter(); System.out.println("Hello, brave new world"); interp.exec("import sys"); interp.exec("print sys"); interp.set("a", new PyInteger(42)); interp.exec("print a"); interp.exec("x = 2+2"); PyObject x = interp.get("x"); System.out.println("x: "+x); System.out.println("Goodbye, cruel world"); } } 1