Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* 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.internal;
import com.google.inject.ProvisionException;
import static com.google.inject.internal.BytecodeGen.newFastClass;
import com.google.inject.internal.util.ImmutableList;
import com.google.inject.internal.util.ImmutableMap;
import com.google.inject.internal.util.Lists;
import com.google.inject.internal.util.Maps;
import com.google.inject.spi.InjectionPoint;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.reflect.FastClass;
import net.sf.cglib.reflect.FastConstructor;
import org.aopalliance.intercept.MethodInterceptor;
/**
* Builds a construction proxy that can participate in AOP. This class manages applying type and
* method matchers to come up with the set of intercepted methods.
*
* @author [email protected] (Jesse Wilson)
*/
final class ProxyFactory implements ConstructionProxyFactory {
private static final net.sf.cglib.proxy.MethodInterceptor NO_OP_METHOD_INTERCEPTOR
= new net.sf.cglib.proxy.MethodInterceptor() {
public Object intercept(
Object proxy, Method method, Object[] arguments, MethodProxy methodProxy)
throws Throwable {
return methodProxy.invokeSuper(proxy, arguments);
}
};
private final InjectionPoint injectionPoint;
private final ImmutableMap> interceptors;
private final Class declaringClass;
private final List methods;
private final Callback[] callbacks;
/**
* PUBLIC is default; it's used if all the methods we're intercepting are public. This impacts
* which classloader we should use for loading the enhanced class
*/
private BytecodeGen.Visibility visibility = BytecodeGen.Visibility.PUBLIC;
ProxyFactory(InjectionPoint injectionPoint, Iterable methodAspects) {
this.injectionPoint = injectionPoint;
@SuppressWarnings("unchecked") // the member of injectionPoint is always a Constructor
Constructor constructor = (Constructor) injectionPoint.getMember();
declaringClass = constructor.getDeclaringClass();
// Find applicable aspects. Bow out if none are applicable to this class.
List applicableAspects = Lists.newArrayList();
for (MethodAspect methodAspect : methodAspects) {
if (methodAspect.matches(declaringClass)) {
applicableAspects.add(methodAspect);
}
}
if (applicableAspects.isEmpty()) {
interceptors = ImmutableMap.of();
methods = ImmutableList.of();
callbacks = null;
return;
}
// Get list of methods from cglib.
methods = Lists.newArrayList();
Enhancer.getMethods(declaringClass, null, methods);
// Create method/interceptor holders and record indices.
List methodInterceptorsPairs = Lists.newArrayList();
for (Method method : methods) {
methodInterceptorsPairs.add(new MethodInterceptorsPair(method));
}
// Iterate over aspects and add interceptors for the methods they apply to
boolean anyMatched = false;
for (MethodAspect methodAspect : applicableAspects) {
for (MethodInterceptorsPair pair : methodInterceptorsPairs) {
if (methodAspect.matches(pair.method)) {
visibility = visibility.and(BytecodeGen.Visibility.forMember(pair.method));
pair.addAll(methodAspect.interceptors());
anyMatched = true;
}
}
}
if (!anyMatched) {
interceptors = ImmutableMap.of();
callbacks = null;
return;
}
ImmutableMap.Builder> interceptorsMapBuilder = null; // lazy
callbacks = new Callback[methods.size()];
for (int i = 0; i < methods.size(); i++) {
MethodInterceptorsPair pair = methodInterceptorsPairs.get(i);
if (!pair.hasInterceptors()) {
callbacks[i] = NO_OP_METHOD_INTERCEPTOR;
continue;
}
if (interceptorsMapBuilder == null) {
interceptorsMapBuilder = ImmutableMap.builder();
}
interceptorsMapBuilder.put(pair.method, ImmutableList.copyOf(pair.interceptors));
callbacks[i] = new InterceptorStackCallback(pair.method, pair.interceptors);
}
interceptors = interceptorsMapBuilder != null
? interceptorsMapBuilder.build()
: ImmutableMap.>of();
}
/**
* Returns the interceptors that apply to the constructed type.
*/
public ImmutableMap> getInterceptors() {
return interceptors;
}
public ConstructionProxy create() throws ErrorsException {
if (interceptors.isEmpty()) {
return new DefaultConstructionProxyFactory(injectionPoint).create();
}
@SuppressWarnings("unchecked")
Class extends Callback>[] callbackTypes = new Class[methods.size()];
Arrays.fill(callbackTypes, net.sf.cglib.proxy.MethodInterceptor.class);
// Create the proxied class. We're careful to ensure that all enhancer state is not-specific
// to this injector. Otherwise, the proxies for each injector will waste PermGen memory
try {
Enhancer enhancer = BytecodeGen.newEnhancer(declaringClass, visibility);
enhancer.setCallbackFilter(new IndicesCallbackFilter(declaringClass, methods));
enhancer.setCallbackTypes(callbackTypes);
return new ProxyConstructor(enhancer, injectionPoint, callbacks, interceptors);
} catch (Throwable e) {
throw new Errors().errorEnhancingClass(declaringClass, e).toException();
}
}
private static class MethodInterceptorsPair {
final Method method;
List interceptors; // lazy
MethodInterceptorsPair(Method method) {
this.method = method;
}
void addAll(List interceptors) {
if (this.interceptors == null) {
this.interceptors = Lists.newArrayList();
}
this.interceptors.addAll(interceptors);
}
boolean hasInterceptors() {
return interceptors != null;
}
}
/**
* A callback filter that maps methods to unique IDs. We define equals and hashCode using the
* declaring class so that enhanced classes can be shared between injectors.
*/
private static class IndicesCallbackFilter implements CallbackFilter {
final Class> declaringClass;
final Map indices;
IndicesCallbackFilter(Class> declaringClass, List methods) {
this.declaringClass = declaringClass;
final Map indices = Maps.newHashMap();
for (int i = 0; i < methods.size(); i++) {
Method method = methods.get(i);
indices.put(method, i);
}
this.indices = indices;
}
public int accept(Method method) {
return indices.get(method);
}
@Override public boolean equals(Object o) {
return o instanceof IndicesCallbackFilter &&
((IndicesCallbackFilter) o).declaringClass == declaringClass;
}
@Override public int hashCode() {
return declaringClass.hashCode();
}
}
/**
* Constructs instances that participate in AOP.
*/
private static class ProxyConstructor implements ConstructionProxy {
final Class> enhanced;
final InjectionPoint injectionPoint;
final Constructor constructor;
final Callback[] callbacks;
final FastConstructor fastConstructor;
final ImmutableMap> methodInterceptors;
@SuppressWarnings("unchecked") // the constructor promises to construct 'T's
ProxyConstructor(Enhancer enhancer, InjectionPoint injectionPoint, Callback[] callbacks,
ImmutableMap> methodInterceptors) {
this.enhanced = enhancer.createClass(); // this returns a cached class if possible
this.injectionPoint = injectionPoint;
this.constructor = (Constructor) injectionPoint.getMember();
this.callbacks = callbacks;
this.methodInterceptors = methodInterceptors;
FastClass fastClass = newFastClass(enhanced, BytecodeGen.Visibility.forMember(constructor));
this.fastConstructor = fastClass.getConstructor(constructor.getParameterTypes());
}
@SuppressWarnings("unchecked") // the constructor promises to produce 'T's
public T newInstance(Object... arguments) throws InvocationTargetException {
Enhancer.registerCallbacks(enhanced, callbacks);
try {
return (T) fastConstructor.newInstance(arguments);
} finally {
Enhancer.registerCallbacks(enhanced, null);
}
}
public InjectionPoint getInjectionPoint() {
return injectionPoint;
}
public Constructor getConstructor() {
return constructor;
}
public ImmutableMap> getMethodInterceptors() {
return methodInterceptors;
}
}
}