Home | History | Annotate | Download | only in internal
      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.internal;
     18 
     19 import com.google.common.collect.ImmutableMap;
     20 import com.google.inject.internal.BytecodeGen.Visibility;
     21 import com.google.inject.spi.InjectionPoint;
     22 
     23 import java.lang.reflect.Constructor;
     24 import java.lang.reflect.InvocationTargetException;
     25 import java.lang.reflect.Method;
     26 import java.lang.reflect.Modifier;
     27 import java.util.List;
     28 
     29 /**
     30  * Produces construction proxies that invoke the class constructor.
     31  *
     32  * @author crazybob (at) google.com (Bob Lee)
     33  */
     34 final class DefaultConstructionProxyFactory<T> implements ConstructionProxyFactory<T> {
     35 
     36   private final InjectionPoint injectionPoint;
     37 
     38   /**
     39    * @param injectionPoint an injection point whose member is a constructor of {@code T}.
     40    */
     41   DefaultConstructionProxyFactory(InjectionPoint injectionPoint) {
     42     this.injectionPoint = injectionPoint;
     43   }
     44 
     45   public ConstructionProxy<T> create() {
     46     @SuppressWarnings("unchecked") // the injection point is for a constructor of T
     47     final Constructor<T> constructor = (Constructor<T>) injectionPoint.getMember();
     48 
     49     // Use FastConstructor if the constructor is public.
     50     if (Modifier.isPublic(constructor.getModifiers())) {
     51       Class<T> classToConstruct = constructor.getDeclaringClass();
     52       /*if[AOP]*/
     53       try {
     54         final net.sf.cglib.reflect.FastConstructor fastConstructor
     55             = BytecodeGen.newFastClass(classToConstruct, Visibility.forMember(constructor))
     56                 .getConstructor(constructor);
     57 
     58       return new ConstructionProxy<T>() {
     59         @SuppressWarnings("unchecked")
     60         public T newInstance(Object... arguments) throws InvocationTargetException {
     61           return (T) fastConstructor.newInstance(arguments);
     62         }
     63         public InjectionPoint getInjectionPoint() {
     64           return injectionPoint;
     65         }
     66         public Constructor<T> getConstructor() {
     67           return constructor;
     68         }
     69         public ImmutableMap<Method, List<org.aopalliance.intercept.MethodInterceptor>>
     70             getMethodInterceptors() {
     71           return ImmutableMap.of();
     72         }
     73       };
     74       } catch (net.sf.cglib.core.CodeGenerationException e) {/* fall-through */}
     75       /*end[AOP]*/
     76       if (!Modifier.isPublic(classToConstruct.getModifiers())) {
     77         constructor.setAccessible(true);
     78       }
     79     } else {
     80       constructor.setAccessible(true);
     81     }
     82 
     83     return new ConstructionProxy<T>() {
     84       public T newInstance(Object... arguments) throws InvocationTargetException {
     85         try {
     86           return constructor.newInstance(arguments);
     87         } catch (InstantiationException e) {
     88           throw new AssertionError(e); // shouldn't happen, we know this is a concrete type
     89         } catch (IllegalAccessException e) {
     90           throw new AssertionError(e); // a security manager is blocking us, we're hosed
     91         }
     92       }
     93       public InjectionPoint getInjectionPoint() {
     94         return injectionPoint;
     95       }
     96       public Constructor<T> getConstructor() {
     97         return constructor;
     98       }
     99       /*if[AOP]*/
    100       public ImmutableMap<Method, List<org.aopalliance.intercept.MethodInterceptor>>
    101           getMethodInterceptors() {
    102         return ImmutableMap.of();
    103       }
    104       /*end[AOP]*/
    105     };
    106   }
    107 }
    108