/extensions/struts2/src/com/google/inject/struts2/Struts2Factory.java
Java | 231 lines | 153 code | 37 blank | 41 comment | 18 complexity | 577cc8a5c5e605f0ac617a781008b4ea MD5 | raw file
- /**
- * Copyright (C) 2009 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package com.google.inject.struts2;
- import com.google.inject.AbstractModule;
- import com.google.inject.Binder;
- import com.google.inject.Injector;
- import com.google.inject.internal.Annotations;
- import com.opensymphony.xwork2.ActionInvocation;
- import com.opensymphony.xwork2.ObjectFactory;
- import com.opensymphony.xwork2.config.ConfigurationException;
- import com.opensymphony.xwork2.config.entities.InterceptorConfig;
- import com.opensymphony.xwork2.inject.Inject;
- import com.opensymphony.xwork2.interceptor.Interceptor;
- import java.lang.annotation.Annotation;
- import java.util.ArrayList;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import java.util.logging.Logger;
- /**
- * Cleanup up version from Bob's GuiceObjectFactory. Now works properly with
- * GS2 and fixes several bugs.
- *
- * @author dhanji@gmail.com
- * @author benmccann.com
- */
- public class Struts2Factory extends ObjectFactory {
- private static final long serialVersionUID = 1L;
- private static final Logger logger = Logger.getLogger(Struts2Factory.class.getName());
- private static final String ERROR_NO_INJECTOR =
- "Cannot find a Guice injector. Are you sure you registered a GuiceServletContextListener "
- + "that uses the Struts2GuicePluginModule in your application's web.xml?";
- private static @com.google.inject.Inject Injector injector;
- private final List<ProvidedInterceptor> interceptors = new ArrayList<ProvidedInterceptor>();
- private volatile Injector strutsInjector;
- @Override
- public boolean isNoArgConstructorRequired() {
- return false;
- }
- @Inject(value = "guice.module", required = false)
- void setModule(String moduleClassName) {
- throw new RuntimeException("The struts2 plugin no longer supports"
- + " specifying a module via the 'guice.module' property in XML."
- + " Please install your module via a GuiceServletContextListener instead.");
- }
- Set<Class<?>> boundClasses = new HashSet<Class<?>>();
- public Class<?> getClassInstance(String name) throws ClassNotFoundException {
- Class<?> clazz = super.getClassInstance(name);
- synchronized (this) {
- if (strutsInjector == null) {
- // We can only bind each class once.
- if (!boundClasses.contains(clazz)) {
- try {
- // Calling these methods now helps us detect ClassNotFoundErrors
- // early.
- clazz.getDeclaredFields();
- clazz.getDeclaredMethods();
- boundClasses.add(clazz);
- } catch (Throwable t) {
- // Struts should still work even though some classes aren't in the
- // classpath. It appears we always get the exception here when
- // this is the case.
- return clazz;
- }
- }
- }
- }
- return clazz;
- }
- @Override @SuppressWarnings("unchecked")
- public Object buildBean(Class clazz, Map<String, Object> extraContext) {
- if (strutsInjector == null) {
- synchronized (this) {
- if (strutsInjector == null) {
- createInjector();
- }
- }
- }
- return strutsInjector.getInstance(clazz);
- }
- private void createInjector() {
- logger.info("Loading struts2 Guice support...");
- // Something is wrong, since this should be there if GuiceServletContextListener
- // was present.
- if (injector == null) {
- logger.severe(ERROR_NO_INJECTOR);
- throw new RuntimeException(ERROR_NO_INJECTOR);
- }
- this.strutsInjector = injector.createChildInjector(new AbstractModule() {
- protected void configure() {
- // Tell the injector about all the action classes, etc., so it
- // can validate them at startup.
- for (Class<?> boundClass : boundClasses) {
- // TODO: Set source from Struts XML.
- bind(boundClass);
- }
- // Validate the interceptor class.
- for (ProvidedInterceptor interceptor : interceptors) {
- interceptor.validate(binder());
- }
- }
- });
- // Inject interceptors.
- for (ProvidedInterceptor interceptor : interceptors) {
- interceptor.inject();
- }
- logger.info("Injector created successfully.");
- }
- @SuppressWarnings("unchecked")
- public Interceptor buildInterceptor(InterceptorConfig interceptorConfig,
- Map interceptorRefParams) throws ConfigurationException {
- // Ensure the interceptor class is present.
- Class<? extends Interceptor> interceptorClass;
- try {
- interceptorClass = (Class<? extends Interceptor>)
- getClassInstance(interceptorConfig.getClassName());
- } catch (ClassNotFoundException e) {
- throw new RuntimeException(e);
- }
- ProvidedInterceptor providedInterceptor = new ProvidedInterceptor(
- interceptorConfig, interceptorRefParams, interceptorClass);
- interceptors.add(providedInterceptor);
- return providedInterceptor;
- }
- private Interceptor superBuildInterceptor(InterceptorConfig interceptorConfig,
- Map<String, String> interceptorRefParams) throws ConfigurationException {
- return super.buildInterceptor(interceptorConfig, interceptorRefParams);
- }
- private class ProvidedInterceptor implements Interceptor {
- private static final long serialVersionUID = 1L;
- private final InterceptorConfig config;
- private final Map<String, String> params;
- private final Class<? extends Interceptor> interceptorClass;
- private Interceptor delegate;
- ProvidedInterceptor(InterceptorConfig config, Map<String, String> params,
- Class<? extends Interceptor> interceptorClass) {
- this.config = config;
- this.params = params;
- this.interceptorClass = interceptorClass;
- }
- void validate(Binder binder) {
- // TODO: Set source from Struts XML.
- if (hasScope(interceptorClass)) {
- binder.addError("Scoping interceptors is not currently supported."
- + " Please remove the scope annotation from "
- + interceptorClass.getName() + ".");
- }
- // Make sure it implements Interceptor.
- if (!Interceptor.class.isAssignableFrom(interceptorClass)) {
- binder.addError(interceptorClass.getName() + " must implement "
- + Interceptor.class.getName() + ".");
- }
- }
- void inject() {
- delegate = superBuildInterceptor(config, params);
- }
- public void destroy() {
- if (null != delegate) {
- delegate.destroy();
- }
- }
- public void init() {
- throw new AssertionError();
- }
- public String intercept(ActionInvocation invocation) throws Exception {
- return delegate.intercept(invocation);
- }
- }
- /**
- * Returns true if the given class has a scope annotation.
- */
- private static boolean hasScope(Class<? extends Interceptor> interceptorClass) {
- for (Annotation annotation : interceptorClass.getAnnotations()) {
- if (Annotations.isScopeAnnotation(annotation.annotationType())) {
- return true;
- }
- }
- return false;
- }
- }