1 /** 2 * Copyright (C) 2008 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.inject.internal.BytecodeGen.Visibility; 20 import com.google.inject.internal.InjectorImpl.MethodInvoker; 21 import com.google.inject.spi.InjectionPoint; 22 23 import java.lang.reflect.InvocationTargetException; 24 import java.lang.reflect.Method; 25 import java.lang.reflect.Modifier; 26 27 /** 28 * Invokes an injectable method. 29 */ 30 final class SingleMethodInjector implements SingleMemberInjector { 31 private final MethodInvoker methodInvoker; 32 private final SingleParameterInjector<?>[] parameterInjectors; 33 private final InjectionPoint injectionPoint; 34 SingleMethodInjector(InjectorImpl injector, InjectionPoint injectionPoint, Errors errors)35 SingleMethodInjector(InjectorImpl injector, InjectionPoint injectionPoint, Errors errors) 36 throws ErrorsException { 37 this.injectionPoint = injectionPoint; 38 final Method method = (Method) injectionPoint.getMember(); 39 methodInvoker = createMethodInvoker(method); 40 parameterInjectors = injector.getParametersInjectors(injectionPoint.getDependencies(), errors); 41 } 42 createMethodInvoker(final Method method)43 private MethodInvoker createMethodInvoker(final Method method) { 44 45 // We can't use FastMethod if the method is private. 46 int modifiers = method.getModifiers(); 47 if (!Modifier.isPrivate(modifiers) && !Modifier.isProtected(modifiers)) { 48 /*if[AOP]*/ 49 try { 50 final net.sf.cglib.reflect.FastMethod fastMethod 51 = BytecodeGen.newFastClass(method.getDeclaringClass(), Visibility.forMember(method)) 52 .getMethod(method); 53 54 return new MethodInvoker() { 55 public Object invoke(Object target, Object... parameters) 56 throws IllegalAccessException, InvocationTargetException { 57 return fastMethod.invoke(target, parameters); 58 } 59 }; 60 } catch (net.sf.cglib.core.CodeGenerationException e) {/* fall-through */} 61 /*end[AOP]*/ 62 } 63 64 if (!Modifier.isPublic(modifiers) || 65 !Modifier.isPublic(method.getDeclaringClass().getModifiers())) { 66 method.setAccessible(true); 67 } 68 69 return new MethodInvoker() { 70 public Object invoke(Object target, Object... parameters) 71 throws IllegalAccessException, InvocationTargetException { 72 return method.invoke(target, parameters); 73 } 74 }; 75 } 76 77 public InjectionPoint getInjectionPoint() { 78 return injectionPoint; 79 } 80 81 public void inject(Errors errors, InternalContext context, Object o) { 82 Object[] parameters; 83 try { 84 parameters = SingleParameterInjector.getAll(errors, context, parameterInjectors); 85 } catch (ErrorsException e) { 86 errors.merge(e.getErrors()); 87 return; 88 } 89 90 try { 91 methodInvoker.invoke(o, parameters); 92 } catch (IllegalAccessException e) { 93 throw new AssertionError(e); // a security manager is blocking us, we're hosed 94 } catch (InvocationTargetException userException) { 95 Throwable cause = userException.getCause() != null 96 ? userException.getCause() 97 : userException; 98 errors.withSource(injectionPoint).errorInjectingMethod(cause); 99 } 100 } 101 } 102