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.struts2;
009
010 import org.picocontainer.web.PicoServletContainerListener;
011 import org.picocontainer.web.ThreadLocalLifecycleState;
012 import org.picocontainer.web.ScopedContainers;
013 import org.picocontainer.DefaultPicoContainer;
014 import org.picocontainer.MutablePicoContainer;
015 import org.picocontainer.PicoCompositionException;
016 import org.picocontainer.ComponentMonitor;
017 import org.picocontainer.monitors.NullComponentMonitor;
018 import org.picocontainer.lifecycle.NullLifecycleStrategy;
019 import org.picocontainer.behaviors.Caching;
020 import org.picocontainer.behaviors.Storing;
021 import org.picocontainer.behaviors.Guarding;
022 import com.opensymphony.xwork2.Action;
023 import com.opensymphony.xwork2.Result;
024
025 import javax.servlet.ServletContextEvent;
026
027 import ognl.OgnlRuntime;
028
029 public class Struts2PicoServletContainerListener extends PicoServletContainerListener {
030
031 public void contextInitialized(ServletContextEvent event) {
032 OgnlRuntime.setSecurityManager(null);
033 super.contextInitialized(event);
034 }
035
036 protected ScopedContainers makeScopedContainers(boolean stateless) {
037
038 //NullLifecycleStrategy ls = new NullLifecycleStrategy();
039
040 DefaultPicoContainer appCtnr = new DefaultPicoContainer(new Guarding().wrap(new Caching()), makeLifecycleStrategy(), makeParentContainer(), makeAppComponentMonitor());
041 Storing sessStoring = new Storing();
042 DefaultPicoContainer sessCtnr = new DefaultPicoContainer(new Guarding().wrap(sessStoring), makeLifecycleStrategy(), appCtnr, makeSessionComponentMonitor());
043 Storing reqStoring = new Storing();
044 DefaultPicoContainer reqCtnr = new DefaultPicoContainer(new Guarding().wrap(addRequestBehaviors(reqStoring)), makeLifecycleStrategy(), sessCtnr, makeRequestComponentMonitor());
045 ThreadLocalLifecycleState sessionState = new ThreadLocalLifecycleState();
046 ThreadLocalLifecycleState requestState = new ThreadLocalLifecycleState();
047 sessCtnr.setLifecycleState(sessionState);
048 reqCtnr.setLifecycleState(requestState);
049
050 return new ScopedContainers(appCtnr, sessCtnr, reqCtnr, sessStoring, reqStoring, sessionState, requestState);
051
052 }
053
054 /**
055 * Struts2 handles whole value objects in some configurations.
056 * This enables lazy instantiation of them
057 */
058 @Override
059 protected ComponentMonitor makeRequestComponentMonitor() {
060 return new StrutsActionInstantiatingComponentMonitor();
061 }
062
063 public static class StrutsActionInstantiatingComponentMonitor extends NullComponentMonitor {
064 public Object noComponentFound(MutablePicoContainer mutablePicoContainer, Object o) {
065 return noComponent(mutablePicoContainer, o);
066 }
067
068 private Object noComponent(MutablePicoContainer mutablePicoContainer, Object o) {
069 if (o instanceof Class) {
070 Class clazz = (Class) o;
071 if (Action.class.isAssignableFrom(clazz) || Result.class.isAssignableFrom(clazz)) {
072 try {
073 mutablePicoContainer.addComponent(clazz);
074 } catch (NoClassDefFoundError e) {
075 if (e.getMessage().equals("org/apache/velocity/context/Context")) {
076 // half expected. XWork seems to setup stuff that cannot
077 // work
078 // TODO if this is the case we should make configurable
079 // the list of classes we "expect" not to find. Odd!
080 } else {
081 throw e;
082 }
083 }
084
085 return null;
086 }
087 try {
088 if (clazz.getConstructor(new Class[0]) != null) {
089 return clazz.newInstance();
090 }
091 } catch (InstantiationException e) {
092 throw new PicoCompositionException("can't instantiate " + o);
093 } catch (IllegalAccessException e) {
094 throw new PicoCompositionException("illegal access " + o);
095 } catch (NoSuchMethodException e) {
096 }
097 }
098 return super.noComponentFound(mutablePicoContainer, o);
099 }
100 }
101 }