001 /*******************************************************************************
002 * Copyright (C) PicoContainer Organization. All rights reserved.
003 * ---------------------------------------------------------------------------
004 * The software in this package is published under the terms of the BSD style
005 * license a copy of which has been included with this distribution in the
006 * LICENSE.txt file.
007 ******************************************************************************/
008 package org.picocontainer.web.webwork;
009
010 import java.util.HashMap;
011 import java.util.Map;
012
013 import org.picocontainer.MutablePicoContainer;
014 import org.picocontainer.PicoCompositionException;
015 import org.picocontainer.web.PicoServletContainerFilter;
016
017 import webwork.action.Action;
018 import webwork.action.factory.ActionFactory;
019
020 /**
021 * Replacement for the standard WebWork JavaActionFactory that uses a
022 * PicoContainer to resolve all of the dependencies an Action may have.
023 *
024 * @author Joe Walnes
025 * @author Mauro Talevi
026 */
027 public final class PicoActionFactory extends ActionFactory {
028
029 private static ThreadLocal<MutablePicoContainer> currentRequestContainer = new ThreadLocal<MutablePicoContainer>();
030 private static ThreadLocal<MutablePicoContainer> currentSessionContainer = new ThreadLocal<MutablePicoContainer>();
031 private static ThreadLocal<MutablePicoContainer> currentAppContainer = new ThreadLocal<MutablePicoContainer>();
032
033 @SuppressWarnings("serial")
034 public static class ServletFilter extends PicoServletContainerFilter {
035 protected void setAppContainer(MutablePicoContainer container) {
036 currentAppContainer.set(container);
037 }
038 protected void setRequestContainer(MutablePicoContainer container) {
039 currentRequestContainer.set(container);
040 }
041 protected void setSessionContainer(MutablePicoContainer container) {
042 currentSessionContainer.set(container);
043 }
044 }
045
046 private final Map<String, Class<?>> classCache = new HashMap<String, Class<?>>();
047
048 public Action getActionImpl(String className) {
049 try {
050 Class<?> actionClass = getActionClass(className);
051 Action action = null;
052 try {
053 action = instantiateAction(actionClass);
054 } catch (Exception e) {
055 // swallow these exceptions and return null action
056 }
057 return action;
058 } catch (PicoCompositionException e) {
059 return null;
060 }
061 }
062
063 protected Action instantiateAction(Class<?> actionClass) {
064 MutablePicoContainer actionsContainer = currentRequestContainer.get();
065 Action action = (Action) actionsContainer.getComponent(actionClass);
066
067 if (action == null) {
068 // The action wasn't registered. Attempt to instantiate it.
069 actionsContainer.addComponent(actionClass);
070 action = (Action) actionsContainer.getComponent(actionClass);
071 }
072 return action;
073 }
074
075 public Class<?> getActionClass(String className) throws PicoCompositionException {
076 try {
077 return loadClass(className);
078 } catch (ClassNotFoundException e) {
079 throw new PicoCompositionException("Action class '" + className + "' not found", e);
080 }
081 }
082
083 protected Class<?> loadClass(String className) throws ClassNotFoundException {
084 if (classCache.containsKey(className)) {
085 return (Class<?>) classCache.get(className);
086 } else {
087 Class<?> result = Thread.currentThread().getContextClassLoader().loadClass(className);
088 classCache.put(className, result);
089 return result;
090 }
091 }
092
093 }