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 @SuppressWarnings("serial")
030 public static class ServletFilter extends PicoServletContainerFilter {
031 private static ThreadLocal<MutablePicoContainer> currentRequestContainer = new ThreadLocal<MutablePicoContainer>();
032 private static ThreadLocal<MutablePicoContainer> currentSessionContainer = new ThreadLocal<MutablePicoContainer>();
033 private static ThreadLocal<MutablePicoContainer> currentAppContainer = new ThreadLocal<MutablePicoContainer>();
034
035 protected void setAppContainer(MutablePicoContainer container) {
036 currentAppContainer.set(container);
037 }
038
039 protected void setRequestContainer(MutablePicoContainer container) {
040 currentRequestContainer.set(container);
041 }
042
043 protected void setSessionContainer(MutablePicoContainer container) {
044 currentSessionContainer.set(container);
045 }
046
047 protected static MutablePicoContainer getRequestContainerForThread() {
048 return currentRequestContainer.get();
049 }
050
051 protected static MutablePicoContainer getSessionContainerForThread() {
052 return currentSessionContainer.get();
053 }
054
055 protected static MutablePicoContainer getApplicationContainerForThread() {
056 return currentAppContainer.get();
057 }
058
059 }
060
061 private final Map<String, Class<?>> classCache = new HashMap<String, Class<?>>();
062
063 public Action getActionImpl(String className) {
064 try {
065 Class<?> actionClass = getActionClass(className);
066 Action action = null;
067 try {
068 action = instantiateAction(actionClass);
069 } catch (Exception e) {
070 // swallow these exceptions and return null action
071 }
072 return action;
073 } catch (PicoCompositionException e) {
074 return null;
075 }
076 }
077
078 protected Action instantiateAction(Class<?> actionClass) {
079 MutablePicoContainer actionsContainer = ServletFilter.getRequestContainerForThread();
080 Action action = (Action) actionsContainer.getComponent(actionClass);
081
082 if (action == null) {
083 // The action wasn't registered. Attempt to instantiate it.
084 actionsContainer.addComponent(actionClass);
085 action = (Action) actionsContainer.getComponent(actionClass);
086 }
087 return action;
088 }
089
090 public Class<?> getActionClass(String className) throws PicoCompositionException {
091 try {
092 return loadClass(className);
093 } catch (ClassNotFoundException e) {
094 throw new PicoCompositionException("Action class '" + className + "' not found", e);
095 }
096 }
097
098 protected Class<?> loadClass(String className) throws ClassNotFoundException {
099 if (classCache.containsKey(className)) {
100 return (Class<?>) classCache.get(className);
101 } else {
102 Class<?> result = Thread.currentThread().getContextClassLoader().loadClass(className);
103 classCache.put(className, result);
104 return result;
105 }
106 }
107
108 }