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