summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/WOApplication.java
diff options
context:
space:
mode:
Diffstat (limited to 'projects/net.wotonomy.web/src/main/java/net/wotonomy/web/WOApplication.java')
-rw-r--r--projects/net.wotonomy.web/src/main/java/net/wotonomy/web/WOApplication.java1193
1 files changed, 1193 insertions, 0 deletions
diff --git a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/WOApplication.java b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/WOApplication.java
new file mode 100644
index 0000000..90e40c6
--- /dev/null
+++ b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/WOApplication.java
@@ -0,0 +1,1193 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Blacksmith, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.web;
+
+import java.lang.reflect.Constructor;
+import java.util.List;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.NSDictionary;
+import net.wotonomy.foundation.NSMutableDictionary;
+import net.wotonomy.web.util.BrowserLauncher;
+
+import org.mortbay.http.HttpListener;
+import org.mortbay.http.HttpServer;
+import org.mortbay.jetty.servlet.ServletHandler;
+import org.mortbay.util.InetAddrPort;
+
+/**
+* A pure java implementation of WOApplication. <br><br>
+*
+* The application is responsible for creating and managing sessions
+* and dispatching requests to the appropriate handlers. <br><br>
+*
+* This implementation extends HttpServlet, so the application itself
+* is a servlet and can be configured and managed as such by the servlet
+* container.
+*
+* @author michael@mpowers.net
+* @author $Author: cgruber $
+* @version $Revision: 905 $
+*/
+public class WOApplication
+ extends HttpServlet
+{
+ /**
+ * A tricky way to allow multiple WOApplications
+ * in the same servlet container.
+ */
+ static private ThreadLocal threadLocal;
+ //static private WOApplication application;
+
+ /**
+ * Determines application-wide page caching.
+ * Pages may individually prevent caching.
+ */
+ static private boolean cachingEnabled = false;
+ private static boolean autoOpenInBrowser = true;
+
+ private String name;
+ private WORequestHandler defaultRequestHandler;
+ private NSMutableDictionary requestHandlers;
+ private WOSessionStore sessionStore;
+ private WOResourceManager resourceManager;
+ private boolean pageRefreshOnBacktrack;
+ private int pageCacheSize;
+ private int permanentPageCacheSize;
+
+ public static final String WOApplicationWillFinishLaunchingNotification
+ = "WOApplicationWillFinishLaunchingNotification";
+ public static final String WOApplicationDidFinishLaunchingNotification
+ = "WOApplicationDidFinishLaunchingNotification";
+ public static final String WOGarbageCollectionPeriodKey
+ = "WOGarbageCollectionPeriodKey";
+
+ static String _DirectActionRequestHandlerKey = "_DirectActionRequestHandlerKey";
+ static String _ComponentRequestHandlerKey = "_ComponentRequestHandlerKey";
+ static String _ResourceRequestHandlerKey = "_ResourceRequestHandlerKey";
+ static String WOPort = "WOPort";
+ static String WOSMTPHost = "WOSMTPHost";
+ static final String ELEMENT_CLASS = "elementClass";
+
+ public WOApplication ()
+ {
+ if ( threadLocal == null )
+ {
+ threadLocal = new ThreadLocal();
+ }
+ threadLocal.set( this );
+
+ //application = this;
+ resourceManager = createResourceManager();
+ requestHandlers = new NSMutableDictionary();
+ defaultRequestHandler = new WODirectActionRequestHandler();
+ registerRequestHandler( defaultRequestHandler, directActionRequestHandlerKey() );
+ registerRequestHandler( new WOComponentRequestHandler(), componentRequestHandlerKey() );
+ registerRequestHandler( new WOResourceRequestHandler(), resourceRequestHandlerKey() );
+ sessionStore = WOSessionStore.serverSessionStore();
+
+ pageRefreshOnBacktrack = true;
+ pageCacheSize = 30;
+ permanentPageCacheSize = 30;
+
+ threadLocal.set( null );
+ }
+
+ /**
+ * Dispatches the request and updates the specified response
+ * as appropriate. This implementation creates a new WORequest
+ * and WOContext from the request, sends the response to the
+ * appropriate WORequestHandler, and then updates the servlet
+ * response from the resulting WOResponse.
+ */
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, java.io.IOException
+ {
+ threadLocal.set( this );
+
+ WORequest request = new WORequest( req, this );
+ WOResponse response = dispatchRequest( request );
+ response.generateServletResponse( resp );
+ }
+
+ /**
+ * Handles post requests by calling doGet(), since the framework
+ * handles both gets and posts similarly. Override to handle
+ * post requests in a different manner.
+ */
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, java.io.IOException
+ {
+ doGet( req, resp );
+ }
+
+ // obtaining attributes
+
+ /**
+ * Returns the singleton instance of this application.
+ */
+ public static WOApplication application()
+ {
+ return (WOApplication) threadLocal.get();
+ //return application;
+ }
+
+ /**
+ * Returns the name of the application. This implementation returns
+ * the name the jar file or directory from which the class was loaded,
+ * with no extensions.
+ */
+ public String name()
+ {
+ if ( name == null )
+ {
+ name = path();
+ int i;
+ if ( name.endsWith( "/" ) )
+ { // path
+ name = name.substring( 0, name.length() - 1 );
+ }
+ else
+ { // jar file
+ i = name.lastIndexOf( '.' );
+ if ( i != -1 ) name = name.substring( 0, i );
+ }
+ i = name.lastIndexOf( '/' );
+ if ( i != -1 ) name = name.substring( i+1 );
+ }
+ return name;
+ }
+
+ /**
+ * Returns the absolute path to the application on the local file system.
+ * Note that the application might be embedded inside of a jar file.
+ */
+ public String path ()
+ {
+ return getClass().getProtectionDomain().getCodeSource().getLocation().toString();
+ }
+
+ /**
+ * Returns the path to the application on the local file system
+ * relative to the server's document root.
+ */
+ public String baseURL ()
+ {
+ String root = getServletContext().getRealPath( "/" );
+ String result = path();
+ if ( result.endsWith("/") )
+ { // path
+ if ( result.startsWith( root ) )
+ { // relative to root
+ result = result.substring( root.length() );
+ }
+ // else leave as absolute reference
+ }
+ // jar or war file: leave as absolute reference
+ return result;
+ }
+
+ // concurrent request handling
+
+ /**
+ * Returns whether this application allows request
+ * to be handled concurrently.
+ * This implementation returns true.
+ * Subclasses may override to return false to force
+ * single-threaded request handling, although this
+ * is not implemented.
+ */
+ public boolean allowsConcurrentRequestHandling ()
+ {
+ return true;
+ }
+
+ /**
+ * Returns whether this application allows request
+ * to be handled concurrently.
+ * This implementation returns true.
+ */
+ public boolean adaptorsDispatchRequestsConcurrently ()
+ {
+ return true;
+ }
+
+ /**
+ * Returns whether this application allows request
+ * to be handled concurrently.
+ * This implementation returns true.
+ */
+ public boolean isConcurrentRequestHandlingEnabled ()
+ {
+ return true;
+ }
+
+ // handling requests
+
+ /**
+ * Invoked first in the request-response cycle.
+ * Override to perform any kind of initialization at the
+ * start of a request. This implementation does nothing.
+ */
+ public void awake ()
+ {
+
+ }
+
+ /**
+ * Invoked to start the first phase of the request-response cycle,
+ * after all calls to awake() have been completed.
+ */
+ public void takeValuesFromRequest (WORequest aRequest, WOContext aContext)
+ {
+ aContext.session().takeValuesFromRequest( aRequest, aContext );
+ }
+
+ /**
+ * Invoked to start the second phase of the request-response cycle,
+ * after all calls to takeValuesFromRequest have finished.
+ */
+ public WOActionResults invokeAction (WORequest aRequest, WOContext aContext)
+ {
+ return aContext.session().invokeAction( aRequest, aContext );
+ }
+
+ /**
+ * Invoked to start the third phase of the request-response cycle,
+ * after invokeAction() has completed and returned a WOResponse.
+ */
+ public void appendToResponse (WOResponse aResponse, WOContext aContext)
+ {
+ aContext.session().appendToResponse( aResponse, aContext );
+ }
+
+ /**
+ * Invoked last in the request-response cycle.
+ * Override to perform any kind of clean-up at the
+ * end of a request. This implementation does nothing.
+ */
+ public void sleep ()
+ {
+
+ }
+
+ /**
+ * Dispatches the request to the appropriate handler.
+ */
+ public WOResponse dispatchRequest (WORequest aRequest)
+ {
+ return handlerForRequest( aRequest ).handleRequest( aRequest );
+ }
+
+ // request handling
+
+ /**
+ * Returns the default request handler used if the requested
+ * handler isn't specified or cannot be found. (This defaults
+ * to the WODirectActionRequestHandler.)
+ */
+ public WORequestHandler defaultRequestHandler ()
+ {
+ return defaultRequestHandler;
+ }
+
+ /**
+ * Sets the default request handler used if the requested
+ * handler isn't specified or cannot be found.
+ */
+ public void setDefaultRequestHandler (WORequestHandler aRequestHandler)
+ {
+ defaultRequestHandler = aRequestHandler;
+ }
+
+ /**
+ * Registers the specified request handler for the specified key.
+ */
+ public void registerRequestHandler (WORequestHandler aRequestHandler, String aKey)
+ {
+ requestHandlers.setObjectForKey( aRequestHandler, aKey );
+ }
+
+ /**
+ * Unregisters any existing request handler for the specified key
+ * returning the existing request handler, if any.
+ */
+ public WORequestHandler removeRequestHandlerForKey (String aKey)
+ {
+ WORequestHandler result = requestHandlerForKey( aKey );
+ requestHandlers.removeObjectForKey( aKey );
+ return result;
+ }
+
+ /**
+ * Returns the keys under which request handlers are registered.
+ */
+ public NSArray registeredRequestHandlerKeys ()
+ {
+ return requestHandlers.allKeys();
+ }
+
+ /**
+ * Returns the request handler registered for the specified key,
+ * or null if no request handler is registered for that key.
+ */
+ public WORequestHandler requestHandlerForKey (String aKey)
+ {
+ return (WORequestHandler) requestHandlers.objectForKey( aKey );
+ }
+
+ /**
+ * Returns the request handler that would best service the specified request.
+ */
+ public WORequestHandler handlerForRequest (WORequest aRequest)
+ {
+ WORequestHandler result = requestHandlerForKey( aRequest.requestHandlerKey() );
+ if ( aRequest == null ) result = defaultRequestHandler();
+ return result;
+ }
+
+ // handling errors
+
+ public WOResponse handleSessionCreationErrorInContext( WOContext aContext )
+ {
+ WOResponse response = new WOResponse();
+ response.setStatus( 500 ); // internal server error
+ //TODO: add more useful information to the response
+ System.err.println( "Failed to create session: " + aContext );
+new RuntimeException().printStackTrace(); // remove me
+ return response;
+ }
+
+ public WOResponse handleSessionRestorationErrorInContext( WOContext aContext )
+ {
+ WOResponse response = new WOResponse();
+ response.setStatus( 500 ); // internal server error
+ //TODO: add more useful information to the response
+ System.err.println( "Failed to restore session: " + aContext );
+new RuntimeException().printStackTrace(); // remove me
+ return response;
+ }
+
+ public WOResponse handlePageRestorationErrorInContext( WOContext aContext )
+ {
+ WOResponse response = new WOResponse();
+ response.setStatus( 500 ); // internal server error
+ //TODO: add more useful information to the response
+ System.err.println( "Failed to restore page: " + aContext );
+new RuntimeException().printStackTrace(); // remove me
+ return response;
+ }
+
+ public WOResponse handleException( Throwable aThrowable, WOContext aContext )
+ {
+ WOResponse response = new WOResponse();
+ response.setStatus( 500 ); // internal server error
+ System.err.println( "Exception occurred: " + aContext );
+ if ( aThrowable.getMessage() != null )
+ {
+ response.appendContentString( aThrowable.getMessage() );
+ aThrowable.printStackTrace();
+ }
+ else
+ {
+ response.appendContentString( aThrowable.toString() );
+ aThrowable.printStackTrace();
+ }
+ aThrowable.printStackTrace();
+ return response;
+ }
+
+ // managing pages
+
+ /**
+ * Sets the number of pages that will be retained
+ * in the user's session. Set to zero to disable page caching.
+ */
+ public void setPageCacheSize (int aPositiveInt)
+ {
+ pageCacheSize = aPositiveInt;
+ }
+
+ /**
+ * Returns the number of pages that will be retained
+ * in the user's session. The default page cache size is 30.
+ */
+ public int pageCacheSize ()
+ {
+ return pageCacheSize;
+ }
+
+ /**
+ * Returns the number of pages that will be retained in the
+ * longer-term "permanent" page cache in the user's session,
+ * which is typically used for navigation bars in frames, etc.
+ * The default permanent page cache size is 30.
+ */
+ public int permanentPageCacheSize ()
+ {
+ return permanentPageCacheSize;
+ }
+
+ /**
+ * Returns the number of pages that will be retained in the
+ * longer-term "permanent" page cache in the user's session,
+ * which is typically used for navigation bars in frames, etc.
+ * Set to zero to disable permanent page caching.
+ */
+ public void setPermanentPageCacheSize (int aPositiveInt)
+ {
+ permanentPageCacheSize = aPositiveInt;
+ }
+
+ /**
+ * Returns whether a "backtrack" for an existing page should
+ * simply call generateResponse() on the existing page instance.
+ * If false, a new page is created instead. The default is true.
+ */
+ public void setPageRefreshOnBacktrackEnabled (boolean enabled)
+ {
+ pageRefreshOnBacktrack = enabled;
+ }
+
+ /**
+ * Returns whether a "backtrack" for an existing page should
+ * simply call generateResponse() on the existing page instance.
+ * If false, a new page is created instead. The default is true.
+ */
+ public boolean isPageRefreshOnBacktrackEnabled ()
+ {
+ return pageRefreshOnBacktrack;
+ }
+
+ // managing sessions
+
+ /**
+ * Sets the session store used by this application to persist
+ * sessions between request-response transactions.
+ */
+ public void setSessionStore(WOSessionStore aSessionStore)
+ {
+ sessionStore = aSessionStore;
+ }
+
+ /**
+ * Returns the session store used by this application to persist
+ * sessions between request-response transactions.
+ */
+ public WOSessionStore sessionStore()
+ {
+ return sessionStore;
+ }
+
+ /**
+ * Called at the end of the request-response cycle
+ * to persist the current session until the user's next request.
+ */
+ public void saveSessionForContext(WOContext aContext)
+ {
+ sessionStore.saveSessionForContext( aContext );
+ }
+
+ /**
+ * Called at the beginning of the request-response cycle
+ * to obtain the current session from the user's last request.
+ * Returns null if no such session has been created.
+ * This method sets the context of the session to the specified context.
+ */
+ public WOSession restoreSessionWithID(String aSessionID, WOContext aContext)
+ {
+ WORequest request = aContext.request();
+ WOSession session = sessionStore.restoreSessionWithID( aSessionID, request );
+ if ( session != null )
+ {
+ session.setContext( aContext );
+ session.setServletSession( request.servletRequest().getSession() );
+ }
+ return session;
+ }
+
+ /**
+ * Called to create a session for a new request. This implementation
+ * looks for a class in the same package as the application class
+ * called "Session" and failing that returns a WOSession.
+ */
+ public WOSession createSessionForRequest(WORequest aRequest)
+ {
+ WOSession result = null;
+ try
+ {
+ // using our class loader, which is hopefully dynamic.
+ result = (WOSession) getLocalClass( "Session" ).newInstance();
+ }
+ catch ( Throwable t )
+ {
+ // ignore: fall back to WOSession
+ //t.printStackTrace();
+ }
+
+ if ( result == null )
+ {
+ result = new WOSession();
+ }
+
+ result.setServletSession( aRequest.servletRequest().getSession( true ) );
+ return result;
+ }
+
+ /**
+ * Returns the page component with the specified name.
+ * A context is created with the specified request,
+ * along with a session if necessary.
+ */
+ public WOComponent pageWithName (String aName, WORequest aRequest)
+ {
+ return pageWithName( aName, WOContext.contextWithRequest( aRequest ) );
+ }
+
+ /**
+ * Called to retrieve a component for the specified context.
+ */
+ public WOComponent pageWithName (String aName, WOContext aContext)
+ {
+ if ( aName == null )
+ {
+ throw new IllegalArgumentException(
+ "WOApplication.pageWithName: name is null" );
+ }
+
+ WOComponent result = null;
+ try
+ {
+ // using our class loader, which is hopefully dynamic.
+ Class c = getLocalClass( aName );
+
+ if ( c != null )
+ {
+ // get constructor
+ Constructor ctor;
+ try
+ {
+ ctor = c.getConstructor( new Class[] { WOContext.class } );
+ }
+ catch ( NoSuchMethodException nsme )
+ {
+ ctor = null;
+ }
+
+ // create instance of class
+ if ( ctor != null )
+ {
+ result = (WOComponent) ctor.newInstance( new Object[] { aContext } );
+ }
+ else // call back on default constructor (deprecated)
+ {
+ result = (WOComponent) c.newInstance();
+ }
+ }
+ }
+ catch ( Throwable t )
+ {
+ // ignore for now
+ //TODO: Throw appropriate exception here
+ //System.err.println( "Not found: pageWithName: " + aName );
+ t.printStackTrace();
+ }
+
+ if ( result != null && aContext != null )
+ {
+ // this is where components get their context
+ result.ensureAwakeInContext( aContext );
+ }
+ else
+ if ( result == null )
+ {
+ System.err.println( "Not found: pageWithName: " + aName );
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns a class in the same package as the Application class,
+ * or, failing that, from the WOApplication package, or finally
+ * from the root of the class path. Returns null if not found.
+ */
+ Class getLocalClass( String aName )
+ {
+ Class result = null;
+ if ( getClass() != WOApplication.class )
+ {
+ result = loadLocalClass( getClass(), aName );
+ }
+ if ( result == null )
+ {
+ result = loadLocalClass( WOApplication.class, aName );
+ }
+ if ( result == null )
+ {
+ result = loadLocalClass( null, aName );
+ }
+ return result;
+ }
+
+ private static final Class loadLocalClass( Class aClass, String aName )
+ {
+ ClassLoader loader;
+ String packageName = "";
+ if ( aClass != null )
+ {
+ loader = aClass.getClassLoader();
+ packageName = aClass.getName();
+ int index = packageName.lastIndexOf( "." );
+ if ( index > -1 )
+ {
+ packageName = packageName.substring( 0, index+1 );
+ }
+ else
+ {
+ packageName = "";
+ }
+ }
+ else
+ {
+ loader = WOApplication.class.getClassLoader();
+ }
+
+ try
+ {
+ return loader.loadClass( packageName + aName );
+ }
+ catch ( ClassNotFoundException e )
+ {
+ return null;
+ }
+ }
+
+ // creating elements
+
+ /**
+ * Returns either a dynamic element or a component
+ * for the specified name.
+ */
+ public WOElement dynamicElementWithName(
+ String anElementName, NSDictionary anAssociationMap,
+ WOElement aBodyElement, List aLanguageList)
+ {
+ WOElement element = null;
+ Class c = null;
+ try
+ {
+ c = getLocalClass( anElementName );
+ if ( c == null )
+ {
+ System.out.println( "Not found: dynamicElementWithName: " +
+ "could not find WODynamicElement subclass: " + anElementName );
+ c = WODynamicElement.class;
+ }
+
+ // get constructor
+ Class[] params = new Class[]
+ { String.class, NSDictionary.class, WOElement.class };
+ Constructor ctor = c.getConstructor( params );
+
+ // create instance of class
+ if ( ctor != null )
+ {
+ element = (WODynamicElement) ctor.newInstance(
+ new Object[] { anElementName, anAssociationMap, aBodyElement } );
+ }
+ }
+ catch ( Throwable t )
+ {
+ // ignore: not a dynamic element
+ //System.out.println( "Not a dynamic element: dynamicElementWithName: " + t );
+ //exc.printStackTrace();
+ }
+
+ // no dynamic element found: look for a component
+ if ( element == null )
+ {
+ WOComponent component = (WOComponent) pageWithName( anElementName, (WOContext) null );
+
+ // this seems hackish:
+ // I don't see another way of setting the bindings.
+ component.associations = anAssociationMap;
+ component.rootElement = aBodyElement;
+
+ element = component;
+ }
+
+ return element;
+ }
+
+ // resource handling
+
+ /**
+ * Called to create the application's resource manager.
+ * Override to create a custom resource manager.
+ */
+ public WOResourceManager createResourceManager()
+ {
+ return new WOResourceManager();
+ }
+
+ /**
+ * Returns the application's current resource manager.
+ */
+ public WOResourceManager resourceManager()
+ {
+ return resourceManager;
+ }
+
+ /**
+ * Installs a custom resource manager into the current application.
+ * @deprecated Override createResourceManager() instead.
+ */
+ public void setResourceManager(WOResourceManager aResourceManager)
+ {
+ resourceManager = aResourceManager;
+ }
+
+/*
+ // request handling undocumented
+
+ public WOComponent pageWithName (String);
+ public void savePage (WOComponent);
+ public WOComponent restorePageForContextID (String);
+ public WOContext context ();
+ public WOSession session ();
+ public WOSession createSession ();
+ public WOSession restoreSession ();
+ public void saveSession (WOSession);
+
+ public WOResponse handleRequest (WORequest aRequest)
+ {
+ }
+
+ // error handling undocumented
+
+ WOResponse handleSessionCreationError ();
+ WOResponse handleSessionRestorationError ();
+ WOResponse handlePageRestorationError ();
+ WOResponse handleException (Throwable);
+
+ // running
+
+ public NSRunLoop runLoop ();
+ public void run ();
+ public void setTimeOut (double);
+ public double timeOut ();
+ public void terminate ();
+ public boolean isTerminating ();
+
+ // script debugging
+
+ public void traceScriptedMessages (boolean);
+ public void traceAssignments (boolean);
+ public void traceStatements (boolean);
+ public void traceObjectiveCMessages (boolean);
+ public void trace (boolean);
+ public void logTakeValueForDeclarationNamed (String, String, String, String, Object);
+ public void logSetValueForDeclarationNamed (String, String, String, String, Object);
+
+ // script handling
+
+ public String scriptedClassNameWithPath (String);
+ public String scriptedClassNameWithPathEncoding (String, int);
+
+ // statistics report
+
+ public void setStatisticsStore (WOStatisticsStore);
+ public WOStatisticsStore statisticsStore ();
+ public NSDictionary statistics ();
+
+ // managing adaptors
+
+ public WOAdaptor adaptorWithName (String, NSDictionary);
+ public NSArray adaptors ();
+
+ // monitor support
+
+ public boolean monitoringEnabled ();
+ public int activeSessionsCount ();
+ public void refuseNewSessions (boolean);
+ public boolean isRefusingNewSessions ();
+ public void setMinimumActiveSessionsCount (int);
+ public int minimumActiveSessionsCount ();
+ public void terminateAfterTimeInterval (double);
+
+ // garbage collection undocumented
+
+ int garbageCollectionPeriod ();
+ void setGarbageCollectionPeriod (int);
+
+ // backwards compatibility
+
+ public boolean requiresWOF35RequestHandling ();
+ public boolean requiresWOF35TemplateParser ();
+
+ public void setPrintsHTMLParserDiagnostics (boolean);
+ public boolean printsHTMLParserDiagnostics ();
+
+ // configuration and defaults
+
+ public static NSArray loadFrameworks ();
+ public static void setLoadFrameworks (NSArray);
+*/
+ static boolean debuggingEnabled = false;
+ /**
+ * Returns whether the application is in "debug mode".
+ */
+ public static boolean isDebuggingEnabled()
+ {
+ return debuggingEnabled;
+ }
+
+ /**
+ * Sets whether the application is in "debug mode".
+ */
+ public static void setDebuggingEnabled( boolean enabled )
+ {
+ debuggingEnabled = enabled;
+ }
+
+ /**
+ * Sets whether templates are cached. If true, templates will
+ * only be read once per application lifetime. Otherwise, templates
+ * will be read each time this class is instantiated. Defaults to false.
+ */
+ public static void setCachingEnabled (boolean enabled)
+ {
+ cachingEnabled = enabled;
+ }
+
+ /**
+ * Returns whether templates are cached. If true, templates are
+ * read once per application lifetime. Otherwise, templates are
+ * read each time this class is instantiated.
+ */
+ public static boolean isCachingEnabled ()
+ {
+ return cachingEnabled;
+ }
+
+ // configuration
+
+ /**
+ * Returns the component request handler key,
+ * which is defined by the system property _ComponentRequestHandlerKey.
+ * The default is "wo".
+ */
+ public static String componentRequestHandlerKey()
+ {
+ return System.getProperty( _ComponentRequestHandlerKey, "wo" );
+ }
+
+ /**
+ * Sets the component request handler key.
+ * @deprecated Set the system property _ComponentRequestHandlerKey.
+ */
+ public static void setComponentRequestHandlerKey(String aKey)
+ {
+ System.setProperty( _ComponentRequestHandlerKey, aKey );
+ }
+
+ /**
+ * Returns the direct action request handler key,
+ * which is defined by the system property _DirectActionRequestHandlerKey.
+ * The default is "wa".
+ */
+ public static String directActionRequestHandlerKey()
+ {
+ return System.getProperty( _DirectActionRequestHandlerKey, "wa" );
+ }
+
+ /**
+ * Sets the direct action request handler key.
+ * @deprecated Set the system property _DirectActionRequestHandlerKey.
+ */
+ public static void setDirectActionRequestHandlerKey(String aKey)
+ {
+ System.setProperty( _DirectActionRequestHandlerKey, aKey );
+ }
+
+ /**
+ * Returns the resource request handler key,
+ * which is defined by the system property _ResourceRequestHandlerKey.
+ * The default is "wr".
+ */
+ public static String resourceRequestHandlerKey()
+ {
+ return System.getProperty( _ResourceRequestHandlerKey, "wr" );
+ }
+
+ /**
+ * Sets the resource request handler key.
+ * @deprecated Set the system property _ResourceRequestHandlerKey.
+ */
+ public static void setResourceRequestHandlerKey(String aKey)
+ {
+ System.setProperty( _ResourceRequestHandlerKey, aKey );
+ }
+
+ /**
+ * Returns whether this application should attempt to open
+ * a web browser on the host machine when launched standalone.
+ * The default is true.
+ */
+ public static boolean autoOpenInBrowser()
+ {
+ return autoOpenInBrowser;
+ }
+
+ /**
+ * Sets whether this application should attempt to open
+ * a web browser on the host machine when launched standalone.
+ */
+ public static void setAutoOpenInBrowser(boolean autoOpen)
+ {
+ autoOpenInBrowser = autoOpen;
+ }
+
+ /**
+ * Gets the port used when run as a standalone server.
+ * Returns the value of the system property WOPort.
+ * By default, this is zero, which causes the application
+ * to automatically select an available port.
+ */
+ public static Number port ()
+ {
+ return Integer.getInteger( WOPort, 0 );
+ }
+
+ /**
+ * Gets the smtp server that will be used to send email.
+ * Returns the system property WOSMTPHost.
+ */
+ public static String SMTPHost()
+ {
+ return System.getProperty( WOSMTPHost );
+ }
+
+ /**
+ * Sets the smtp server that will be used to send email.
+ * @deprecated Set the system property WOSMTPHost.
+ */
+ public static void setSMTPHost( String aHost )
+ {
+ System.setProperty( WOSMTPHost, aHost );
+ }
+/*
+ public static boolean isDirectConnectEnabled ();
+ public static void setDirectConnectEnabled (boolean);
+ public static String cgiAdaptorURL ();
+ public static void setCGIAdaptorURL (String);
+ public static String applicationBaseURL ();
+ public static void setApplicationBaseURL (String);
+ public static String frameworksBaseURL ();
+ public static void setFrameworksBaseURL (String);
+ public static String recordingPath ();
+ public static void setRecordingPath (String);
+ public static NSArray projectSearchPath ();
+ public static void setProjectSearchPath (NSArray);
+ public static boolean isMonitorEnabled ();
+ public static void setMonitorEnabled (boolean);
+ public static String monitorHost ();
+ public static String adaptor ();
+ public String number (); // deprecated
+ public static Number listenQueueSize ();
+ public static void setListenQueueSize (Number);
+ public static NSArray additionalAdaptors ();
+ public static void setAdditionalAdaptors (NSArray);
+ public static boolean includeCommentsInResponses ();
+ public static void setIncludeCommentsInResponses (boolean);
+ public static void setSessionTimeOut (Number);
+ public static Number sessionTimeOut ();
+ public static void logString (String);
+ public static void debugString (String);
+ public static void logToMonitorString (String);
+*/
+
+ /**
+ * Main entry point for applications that do not subclass WOApplication.
+ */
+ public static void main( String[] argv )
+ {
+ main( argv, WOApplication.class );
+ }
+
+ /**
+ * Subclasses may call this method to start a self-hosted
+ * web server to serve themselves directly (for testing).
+ */
+ public static void main( String[] argv, Class subclass )
+ {
+ try
+ {
+ int port = 0;
+ boolean open = false;
+ try
+ {
+ port = ((Number)subclass.getMethod( "port",
+ new Class[0]).invoke(subclass,new Object[0])).intValue();
+ open = ((Boolean)subclass.getMethod( "autoOpenInBrowser",
+ new Class[0]).invoke(subclass,new Object[0])).booleanValue();
+ }
+ catch ( Throwable t )
+ {
+ System.err.print("Error reading configuration:" );
+ t.printStackTrace();
+ }
+
+ HttpServer server = new HttpServer();
+ HttpListener listener = server.addListener(new InetAddrPort(port));
+ org.mortbay.http.HttpContext context = server.getContext("/");
+ ServletHandler handler = new ServletHandler();
+ handler.addServlet("/",subclass.getName());
+ context.addHandler(handler);
+ server.start();
+ port = listener.getPort();
+ System.out.println("Waiting for requests: http://127.0.0.1:" + port);
+ if ( open )
+ {
+ BrowserLauncher.openURL( "http://127.0.0.1:" + port );
+ }
+ }
+ catch ( Throwable t )
+ {
+ t.printStackTrace();
+ }
+ }
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/19 01:44:02 cgruber
+ * Add xmlrpc files
+ * Remove jclark and replace with dom4j and javax.xml.sax stuff
+ * Re-work dependencies and imports so it all compiles.
+ *
+ * Revision 1.1 2006/02/16 13:22:22 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.30 2003/03/28 18:01:19 mpowers
+ * Now defaulting port to zero.
+ *
+ * Revision 1.29 2003/03/28 17:31:58 mpowers
+ * Implemented support for autoselection of free port. (thanks gmuth!)
+ *
+ * Revision 1.28 2003/03/28 17:26:17 mpowers
+ * Implemented package support: Applications can now live in packages.
+ * Better support for locating package local classes.
+ *
+ * Revision 1.27 2003/02/21 16:40:22 mpowers
+ * Now reading port and smtp host from system properties.
+ * Implemented WOApplication.main.
+ *
+ * Revision 1.26 2003/02/14 22:33:18 mpowers
+ * Better handling for standalone mode.
+ *
+ * Revision 1.25 2003/02/14 15:18:27 mpowers
+ * Now launching standalone app as a servlet, not a webapp.
+ * Disabled jetty's event logging.
+ *
+ * Revision 1.24 2003/02/13 22:41:04 mpowers
+ * WOApplications can now be self-serving. Added configuration params too.
+ *
+ * Revision 1.23 2003/01/28 19:33:51 mpowers
+ * Implemented the rest of WOResourceManager.
+ * Implemented support for java-style i18n.
+ * Components now use the resource manager to load templates.
+ *
+ * Revision 1.22 2003/01/27 15:08:00 mpowers
+ * Implemented WOResourceManager, using java resources for now.
+ *
+ * Revision 1.21 2003/01/24 20:13:22 mpowers
+ * Now accepting immutable NSDictionary in constructor, not Map.
+ *
+ * Revision 1.20 2003/01/20 17:50:11 mpowers
+ * Caught a loop condition when same declaration was used twice.
+ *
+ * Revision 1.19 2003/01/19 22:33:25 mpowers
+ * Fixed problems with classpath and dynamic class loading.
+ * Dynamic elements now pass on ensureAwakeInContext.
+ * Parser how handles <standalone/> tags.
+ *
+ * Revision 1.18 2003/01/18 23:54:50 mpowers
+ * Implemented debugging enabled.
+ *
+ * Revision 1.17 2003/01/17 20:58:18 mpowers
+ * Fixed up WOHyperlink.
+ *
+ * Revision 1.16 2003/01/17 20:34:17 mpowers
+ * Rudimentary support for resource requests.
+ *
+ * Revision 1.15 2003/01/17 15:31:56 mpowers
+ * Removed spurious error message.
+ *
+ * Revision 1.14 2003/01/17 14:39:00 mpowers
+ * Now calling preferred constructor: WOComponent(WOContext)
+ *
+ * Revision 1.13 2003/01/16 20:10:46 mpowers
+ * - components now synchronize bindings
+ * - support for WOComponentContent
+ * - implemented performParentAction
+ *
+ * Revision 1.12 2003/01/16 15:50:43 mpowers
+ * More robust declaration parsing.
+ * Subcomponents are now supported.
+ * dynamicElementWithName can now return subcomponents.
+ *
+ * Revision 1.11 2003/01/15 19:50:49 mpowers
+ * Fixed issues with WOSession and Serializable.
+ * Can now persist sessions between classloaders (hot swap of class impls).
+ *
+ * Revision 1.10 2003/01/13 22:24:18 mpowers
+ * Request-response cycle is working with session and page persistence.
+ *
+ * Revision 1.9 2003/01/10 20:17:41 mpowers
+ * Component action urls are now working.
+ *
+ * Revision 1.8 2003/01/10 19:16:40 mpowers
+ * Implemented support for page caching.
+ *
+ * Revision 1.4 2002/12/19 17:58:52 mpowers
+ * Rewrote the template parsing - no longer confused about "root element".
+ *
+ * Revision 1.3 2002/12/18 14:12:38 mpowers
+ * Support for differentiated request handlers.
+ * Support url generation for WOContext and WORequest.
+ *
+ * Revision 1.2 2002/12/17 14:57:41 mpowers
+ * Minor corrections to WORequests's parsing, and updated javadocs.
+ *
+ * Revision 1.1.1.1 2000/12/21 15:52:50 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.2 2000/12/20 16:25:49 michael
+ * Added log to all files.
+ *
+ *
+ */
+