Save This Page
Home » Guice-2.0 » com.google » inject » struts2 » [javadoc | source]
    1   /**
    2    * Copyright (C) 2006 Google Inc.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    * http://www.apache.org/licenses/LICENSE-2.0
    9    *
   10    * Unless required by applicable law or agreed to in writing, software
   11    * distributed under the License is distributed on an "AS IS" BASIS,
   12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13    * See the License for the specific language governing permissions and
   14    * limitations under the License.
   15    */
   16   
   17   package com.google.inject.struts2;
   18   
   19   import com.google.inject.AbstractModule;
   20   import com.google.inject.Binder;
   21   import com.google.inject.Guice;
   22   import com.google.inject.Injector;
   23   import com.google.inject.Module;
   24   import com.google.inject.ScopeAnnotation;
   25   import com.google.inject.servlet.ServletModule;
   26   import com.opensymphony.xwork2.ActionInvocation;
   27   import com.opensymphony.xwork2.ObjectFactory;
   28   import com.opensymphony.xwork2.config.ConfigurationException;
   29   import com.opensymphony.xwork2.config.entities.InterceptorConfig;
   30   import com.opensymphony.xwork2.inject.Inject;
   31   import com.opensymphony.xwork2.interceptor.Interceptor;
   32   import java.lang.annotation.Annotation;
   33   import java.util.ArrayList;
   34   import java.util.HashSet;
   35   import java.util.List;
   36   import java.util.Map;
   37   import java.util.Set;
   38   import java.util.logging.Logger;
   39   
   40   public class GuiceObjectFactory extends ObjectFactory {
   41   
   42     static final Logger logger =
   43         Logger.getLogger(GuiceObjectFactory.class.getName());
   44   
   45     Module module;
   46     volatile Injector injector;
   47     boolean developmentMode = false;
   48     List<ProvidedInterceptor> interceptors
   49         = new ArrayList<ProvidedInterceptor>();
   50   
   51     @Override
   52     public boolean isNoArgConstructorRequired() {
   53       return false;
   54     }
   55   
   56     @Inject(value = "guice.module", required = false)
   57     void setModule(String moduleClassName) {
   58       try {
   59         // Instantiate user's module.
   60         @SuppressWarnings({"unchecked"})
   61         Class<? extends Module> moduleClass =
   62             (Class<? extends Module>) Class.forName(moduleClassName);
   63         this.module = moduleClass.newInstance();
   64       } catch (Exception e) {
   65         throw new RuntimeException(e);
   66       }
   67     }
   68   
   69     @Inject(value = "struts.devMode", required = false)
   70     void setDevelopmentMode(String developmentMode) {
   71       this.developmentMode = developmentMode.trim().equals("true");
   72     }
   73   
   74     Set<Class<?>> boundClasses = new HashSet<Class<?>>();
   75   
   76     public Class getClassInstance(String name) throws ClassNotFoundException {
   77       Class<?> clazz = super.getClassInstance(name);
   78   
   79       synchronized (this) {
   80         if (injector == null) {
   81           // We can only bind each class once.
   82           if (!boundClasses.contains(clazz)) {
   83             try {
   84               // Calling these methods now helps us detect ClassNotFoundErrors
   85               // early.
   86               clazz.getDeclaredFields();
   87               clazz.getDeclaredMethods();
   88   
   89               boundClasses.add(clazz);
   90             } catch (Throwable t) {
   91               // Struts should still work even though some classes aren't in the
   92               // classpath. It appears we always get the exception here when
   93               // this is the case.
   94               return clazz;
   95             }
   96           }
   97         }
   98       }
   99   
  100       return clazz;
  101     }
  102   
  103     @SuppressWarnings("unchecked")
  104     public Object buildBean(Class clazz, Map extraContext) {
  105       if (injector == null) {
  106         synchronized (this) {
  107           if (injector == null) {
  108             createInjector();
  109           }
  110         }
  111       }
  112   
  113       return injector.getInstance(clazz);
  114     }
  115   
  116     private void createInjector() {
  117       try {
  118         logger.info("Creating injector...");
  119         this.injector = Guice.createInjector(new AbstractModule() {
  120           protected void configure() {
  121             // Install default servlet bindings.
  122             install(new ServletModule());
  123   
  124             // Install user's module.
  125             if (module != null) {
  126               logger.info("Installing " + module + "...");
  127               install(module);
  128             }
  129             else {
  130               logger.info("No module found. Set 'guice.module' to a Module "
  131                   + "class name if you'd like to use one.");
  132             }
  133   
  134             // Tell the injector about all the action classes, etc., so it
  135             // can validate them at startup.
  136             for (Class<?> boundClass : boundClasses) {
  137               // TODO: Set source from Struts XML.
  138               bind(boundClass);
  139             }
  140   
  141             // Validate the interceptor class.
  142             for (ProvidedInterceptor interceptor : interceptors) {
  143               interceptor.validate(binder());
  144             }
  145           }
  146         });
  147   
  148         // Inject interceptors.
  149         for (ProvidedInterceptor interceptor : interceptors) {
  150           interceptor.inject();
  151         }
  152   
  153       } catch (Throwable t) {
  154         t.printStackTrace();
  155         System.exit(1);
  156       }
  157       logger.info("Injector created successfully.");
  158     }
  159   
  160     @SuppressWarnings("unchecked")
  161     public Interceptor buildInterceptor(InterceptorConfig interceptorConfig,
  162         Map interceptorRefParams) throws ConfigurationException {
  163       // Ensure the interceptor class is present.
  164       Class<? extends Interceptor> interceptorClass;
  165       try {
  166         interceptorClass = getClassInstance(interceptorConfig.getClassName());
  167       } catch (ClassNotFoundException e) {
  168         throw new RuntimeException(e);
  169       }
  170   
  171       ProvidedInterceptor providedInterceptor = new ProvidedInterceptor(
  172           interceptorConfig, interceptorRefParams, interceptorClass);
  173       interceptors.add(providedInterceptor);
  174       return providedInterceptor;
  175     }
  176   
  177     Interceptor superBuildInterceptor(InterceptorConfig interceptorConfig,
  178         Map interceptorRefParams) throws ConfigurationException {
  179       return super.buildInterceptor(interceptorConfig, interceptorRefParams);
  180     }
  181   
  182     class ProvidedInterceptor implements Interceptor {
  183   
  184       final InterceptorConfig config;
  185       final Map params;
  186       final Class<? extends Interceptor> interceptorClass;
  187       Interceptor delegate;
  188   
  189       ProvidedInterceptor(InterceptorConfig config, Map params,
  190           Class<? extends Interceptor> interceptorClass) {
  191         this.config = config;
  192         this.params = params;
  193         this.interceptorClass = interceptorClass;
  194       }
  195   
  196       void validate(Binder binder) {
  197         // TODO: Set source from Struts XML.
  198         if (hasScope(interceptorClass)) {
  199           binder.addError("Scoping interceptors is not currently supported."
  200               + " Please remove the scope annotation from "
  201               + interceptorClass.getName() + ".");
  202         }
  203   
  204         // Make sure it implements Interceptor.
  205         if (!Interceptor.class.isAssignableFrom(interceptorClass)) {
  206           binder.addError(interceptorClass.getName() + " must implement "
  207             + Interceptor.class.getName() + ".");
  208         }
  209       }
  210   
  211       void inject() {
  212         delegate = superBuildInterceptor(config, params);
  213       }
  214   
  215       public void destroy() {
  216         delegate.destroy();
  217       }
  218   
  219       public void init() {
  220         throw new AssertionError();
  221       }
  222   
  223       public String intercept(ActionInvocation invocation) throws Exception {
  224         return delegate.intercept(invocation);
  225       }
  226     }
  227   
  228     /**
  229      * Returns true if the given class has a scope annotation.
  230      */
  231     private static boolean hasScope(
  232         Class<? extends Interceptor> interceptorClass) {
  233       for (Annotation annotation : interceptorClass.getAnnotations()) {
  234         if (annotation.annotationType()
  235             .isAnnotationPresent(ScopeAnnotation.class)) {
  236           return true;
  237         }
  238       }
  239       return false;
  240     }
  241   }

Save This Page
Home » Guice-2.0 » com.google » inject » struts2 » [javadoc | source]