/* 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 net.wotonomy.foundation.NSArray; /** * An implementation of WORequestHandler that dispatches * DirectActions.

* * See WODirectAction for the rules for parsing a request. * In short, className defaults to "DirectAction", and the * action defaults to "default". The action class is expected * to have a constructor that takes a WORequest parameter. * * @author michael@mpowers.net * @author $Author: cgruber $ * @version $Revision: 905 $ */ public class WODirectActionRequestHandler extends WORequestHandler { public WOResponse handleRequest (WORequest aRequest) { WOResponse response = null; // no concurrent access is allowed to a user's session: // a user/browser/machine with multiple requests will have to wait. // NOTE: this forces a session creation for any direct action (!) synchronized ( aRequest.request.getSession() ) { WOApplication application = aRequest.application(); WOContext context = WOContext.contextWithRequest( aRequest ); String className = "DirectAction"; String actionName = "default"; NSArray path = aRequest.requestHandlerPathArray(); if ( path.count() > 0 ) { className = path.objectAtIndex( 0 ).toString(); if ( path.count() > 1 ) { actionName = path.objectAtIndex( path.count() - 1 ).toString(); } if ( path.count() > 2 ) { for ( int i = 1; i < path.count()-1; i++ ) { className = className + "." + path.objectAtIndex( i ).toString(); } } } //FIXME: sessions are supposed to be lazily created for direct actions WOSession session = null; String sessionID = aRequest.sessionID(); if ( sessionID != null ) { session = application.restoreSessionWithID( sessionID, context ); } if ( session == null ) { session = application.createSessionForRequest( aRequest ); if ( session == null ) { response = application.handleSessionCreationErrorInContext( context ); } else { session.setContext( context ); } } context.setSession( session ); application.awake(); session.awake(); try { if ( response == null ) { Class c = null; c = application.getLocalClass( className ); if ( ( c == null ) && ( path.count() == 1 ) ) { actionName = className; className = "DirectAction"; c = application.getLocalClass( className ); } if ( c == null ) { throw new RuntimeException( "Could not find class named \"" + className + "\": " ); } java.lang.reflect.Constructor ctor = c.getConstructor( new Class[] { WORequest.class } ); WODirectAction action = (WODirectAction) ctor.newInstance( new Object[] { aRequest } ); action.context = context; //HACK: how else can action call pageWithName? WOActionResults result = action.performActionNamed( actionName ); if ( result instanceof WOComponent ) { //HACK: I'm not sure where this should have gone: seems hackish here. context.pushElement( (WOComponent) result ); ((WOComponent)result).ensureAwakeInContext( context ); //context.popElement(); } response = result.generateResponse(); // calls session.savePage (?) if ( result instanceof WOComponent ) { //HACK: I'm not sure where this should have gone: seems hackish here. ((WOComponent)result).sleep(); } } } catch ( NoSuchMethodException exc ) { WOResponse error = new WOResponse(); exc.printStackTrace(); error.setStatus( 404 ); // not found error.appendContentString( "Could not find request constructor for class named \"" + className + "\": " ); response = error; } catch ( Exception exc ) { WOResponse error = new WOResponse(); error.setStatus( 500 ); // error if ( exc.getMessage() != null ) { error.appendContentString( exc.getMessage() ); exc.printStackTrace(); } else { error.appendContentString( exc.toString() ); exc.printStackTrace(); } response = error; } session.sleep(); session.setContext( null ); application.saveSessionForContext( context ); application.sleep(); } return response; } } /* * $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.10 2003/03/28 17:26:18 mpowers * Implemented package support: Applications can now live in packages. * Better support for locating package local classes. * * Revision 1.9 2003/01/19 22:33:26 mpowers * Fixed problems with classpath and dynamic class loading. * Dynamic elements now pass on ensureAwakeInContext. * Parser how handles tags. * * Revision 1.8 2003/01/17 20:34:57 mpowers * Better handling for components and parents in the context's element stack. * * Revision 1.7 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.5 2003/01/13 22:25:00 mpowers * Request-response cycle is working with session and page persistence. * * Revision 1.4 2003/01/09 21:16:49 mpowers * Bringing request-response cycle more into conformance. * * Revision 1.2 2002/12/17 14:57:44 mpowers * Minor corrections to WORequests's parsing, and updated javadocs. * * Revision 1.1.1.1 2000/12/21 15:53:19 mpowers * Contributing wotonomy. * * Revision 1.2 2000/12/20 16:25:50 michael * Added log to all files. * * */