View Javadoc

1   /**
2    * This file Copyright (c) 2011-2014 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.objectfactory.guice;
35  
36  import info.magnolia.objectfactory.CandidateParameterResolver;
37  import info.magnolia.objectfactory.ComponentFactory;
38  import info.magnolia.objectfactory.ComponentProvider;
39  import info.magnolia.objectfactory.NoSuchComponentException;
40  import info.magnolia.objectfactory.ObjectManufacturer;
41  import info.magnolia.objectfactory.ParameterResolver;
42  
43  import java.util.Arrays;
44  import java.util.Map;
45  
46  import javax.inject.Inject;
47  import javax.inject.Provider;
48  
49  import org.slf4j.Logger;
50  import org.slf4j.LoggerFactory;
51  
52  import com.google.inject.Injector;
53  
54  
55  /**
56   * ComponentProvider implementation based on Guice.
57   *
58   * @version $Id$
59   * @see ComponentProvider
60   * @see GuiceComponentProviderBuilder
61   */
62  public class GuiceComponentProvider implements ComponentProvider {
63  
64      private static Logger logger = LoggerFactory.getLogger(GuiceComponentProvider.class);
65  
66      @Inject
67      private Injector injector;
68      private ObjectManufacturer manufacturer;
69      private final Map<Class<?>, Class<?>> typeMappings;
70      private final GuiceComponentProvider parentComponentProvider;
71  
72      public GuiceComponentProvider(Map<Class<?>, Class<?>> typeMappings, GuiceComponentProvider parentComponentProvider) {
73          this.parentComponentProvider = parentComponentProvider;
74          this.typeMappings = typeMappings;
75      }
76  
77      @Override
78      public <T> Class<? extends T> getImplementation(Class<T> type) {
79          Class<?> implementation = typeMappings.get(type);
80          if (implementation == null) {
81              if (parentComponentProvider != null) {
82                  return parentComponentProvider.getImplementation(type);
83              }
84              return type;
85          }
86          if (ComponentFactory.class.isAssignableFrom(implementation)) {
87              return type;
88          }
89          return (Class<? extends T>) implementation;
90      }
91  
92      @Override
93      @Deprecated
94      public <T> T getSingleton(Class<T> type) {
95          return getComponent(type);
96      }
97  
98      @Override
99      public <T> T getComponent(Class<T> type) throws NoSuchComponentException{
100         if (!GuiceUtils.hasExplicitBindingFor(injector, type)) {
101             throw new NoSuchComponentException("No component configuration for type [" + type.getName() + "] found. Please add a configuration to your module descriptor.");
102         }
103         return injector.getInstance(type);
104     }
105 
106     @Override
107     public <T> T newInstance(Class<T> type, Object... parameters) {
108         return newInstanceWithParameterResolvers(type, new CandidateParameterResolver(parameters));
109     }
110 
111     @Override
112     public <T> T newInstanceWithParameterResolvers(Class<T> type, ParameterResolver... parameterResolvers) {
113         if (this.manufacturer == null) {
114             this.manufacturer = new ObjectManufacturer();
115         }
116         Class<? extends T> implementation = getImplementation(type);
117         parameterResolvers = concat(parameterResolvers, new GuiceParameterResolver(injector));
118         T instance = (T) manufacturer.newInstance(implementation, parameterResolvers);
119         injectMembers(instance);
120         return instance;
121     }
122 
123     private ParameterResolver[] concat(ParameterResolver[] array, ParameterResolver extra) {
124         ParameterResolver[] newArray = Arrays.copyOf(array, array.length + 1);
125         newArray[array.length] = extra;
126         return newArray;
127     }
128 
129     public Injector getInjector() {
130         return injector;
131     }
132 
133     public <T> Provider<T> getProvider(Class<T> type) {
134         if (!GuiceUtils.hasExplicitBindingFor(injector, type)) {
135             return null;
136         }
137         return injector.getProvider(type);
138     }
139 
140     public void injectMembers(Object instance) {
141         injector.injectMembers(instance);
142     }
143 
144     public void destroy() {
145         /*
146 
147        Destroy using @PreDestroy is disabled because the implementation acquires instances for lazy-init singletons
148        only to destroy them. It also tries to acquire instances that have non-existing scopes leading to exceptions
149        being thrown. This usually results in shutdown of the application being interrupted before having a chance to
150        properly close down JackRabbit. With (at least) the derby persistence manager this results in threads not being
151        closed down properly and therefore Tomcat stalls at shutdown.
152 
153         */
154     }
155 
156     @Override
157     public GuiceComponentProvider getParent() {
158         return parentComponentProvider;
159     }
160 }