001 /*****************************************************************************
002 * Copyright (C) NanoContainer Organization. All rights reserved. *
003 * ------------------------------------------------------------------------- *
004 * The software in this package is published under the terms of the BSD *
005 * style license a copy of which has been included with this distribution in *
006 * the LICENSE.txt file. *
007 * *
008 *****************************************************************************/
009 package org.nanocontainer.nanowar.struts;
010
011 import javax.servlet.http.HttpServletRequest;
012
013 import org.apache.struts.action.Action;
014 import org.apache.struts.action.ActionMapping;
015 import org.apache.struts.action.ActionServlet;
016 import org.nanocontainer.nanowar.ActionsContainerFactory;
017 import org.picocontainer.MutablePicoContainer;
018 import org.picocontainer.PicoInitializationException;
019 import org.picocontainer.PicoIntrospectionException;
020
021 /**
022 * Uses PicoContainer to produce Actions and inject dependencies into them.
023 * If you have your own <code>RequestProcessor</code> implementation, you can use an
024 * <code>ActionFactory</code> in your <code>RequestProcessor.processActionCreate</code>
025 * method to Picofy your Actions.
026 *
027 * @author Stephen Molitor
028 * @author Mauro Talevi
029 */
030 public class ActionFactory {
031
032 private ActionsContainerFactory actionsContainerFactory = new ActionsContainerFactory();
033
034 /**
035 * Gets the <code>Action</code> specified by the mapping type from a PicoContainer.
036 * The action will be instantiated if necessary, and its
037 * dependencies will be injected. The action will be instantiated via a
038 * special PicoContainer that just contains actions. If this container
039 * already exists in the request attribute, this method will use it. If no
040 * such container exists, this method will create a new Pico container and
041 * place it in the request. The parent container will either be the request
042 * container, or if that container can not be found the session container,
043 * or if that container can not be found, the application container. If no
044 * parent container can be found, a <code>PicoInitializationException</code>
045 * will be thrown. The action path specified in the mapping is used as
046 * the component key for the action.
047 *
048 * @param request the Http servlet request.
049 * @param mapping the Struts mapping object, whose type property tells us what
050 * Action class is required.
051 * @param servlet the Struts <code>ActionServlet</code>.
052 * @return the <code>Action</code> instance.
053 * @throws PicoIntrospectionException if the mapping type does not specify a valid action.
054 * @throws PicoInitializationException if no request, session, or application scoped Pico container
055 * can be found.
056 */
057 public Action getAction(HttpServletRequest request, ActionMapping mapping, ActionServlet servlet)
058 throws PicoIntrospectionException, PicoInitializationException {
059
060 MutablePicoContainer actionsContainer = actionsContainerFactory.getActionsContainer(request);
061 Object actionKey = mapping.getPath();
062 Class actionType = actionsContainerFactory.getActionClass(mapping.getType());
063
064 Action action = (Action) actionsContainer.getComponentInstance(actionKey);
065 if (action == null) {
066 actionsContainer.registerComponentImplementation(actionKey, actionType);
067 action = (Action) actionsContainer.getComponentInstance(actionKey);
068 }
069
070 action.setServlet(servlet);
071 return action;
072 }
073
074 }