/*
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.
*
*
*/