diff options
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.java | 1193 |
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. + * + * + */ + |
