/* 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 { @Override 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. * * */