Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gissuebot/5e89c8647637450144e6 to your computer and use it in GitHub Desktop.
Save gissuebot/5e89c8647637450144e6 to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 94, comment 27
Index: test/com/google/inject/ProxyFactoryTest.java
===================================================================
--- test/com/google/inject/ProxyFactoryTest.java (revision 345)
+++ test/com/google/inject/ProxyFactoryTest.java (working copy)
@@ -20,6 +20,7 @@
import static com.google.inject.matcher.Matchers.any;
import static com.google.inject.matcher.Matchers.not;
import static com.google.inject.matcher.Matchers.only;
+import com.google.inject.internal.GuiceCodeGen;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationTargetException;
@@ -34,11 +35,12 @@
public void testSimpleCase()
throws NoSuchMethodException, InvocationTargetException {
+ GuiceCodeGen defaultCodeGen = new GuiceCodeGen(new DefaultClassLoaderHook());
SimpleInterceptor interceptor = new SimpleInterceptor();
ProxyFactoryBuilder builder = new ProxyFactoryBuilder();
builder.intercept(any(), any(), interceptor);
- ProxyFactory factory = builder.create();
+ ProxyFactory factory = builder.create(defaultCodeGen);
Provider<Simple> creator = factory.getFactory(Simple.class);
@@ -67,13 +69,14 @@
public void testInterceptOneMethod()
throws NoSuchMethodException, InvocationTargetException {
+ GuiceCodeGen defaultCodeGen = new GuiceCodeGen(new DefaultClassLoaderHook());
SimpleInterceptor interceptor = new SimpleInterceptor();
ProxyFactoryBuilder builder = new ProxyFactoryBuilder();
builder.intercept(
only(Bar.class), annotatedWith(Intercept.class), interceptor);
- ProxyFactory factory = builder.create();
+ ProxyFactory factory = builder.create(defaultCodeGen);
ConstructionProxy<Foo> fooFactory =
factory.get(Foo.class.getDeclaredConstructor());
@@ -124,11 +127,12 @@
public void testWithConstructorArguments()
throws InvocationTargetException, NoSuchMethodException {
+ GuiceCodeGen defaultCodeGen = new GuiceCodeGen(new DefaultClassLoaderHook());
SimpleInterceptor interceptor = new SimpleInterceptor();
ProxyFactoryBuilder builder = new ProxyFactoryBuilder();
builder.intercept(any(), any(), interceptor);
- ProxyFactory factory = builder.create();
+ ProxyFactory factory = builder.create(defaultCodeGen);
ConstructionProxy<A> constructor =
factory.get(A.class.getDeclaredConstructor(int.class));
@@ -140,11 +144,12 @@
public void testNotProxied()
throws NoSuchMethodException, InvocationTargetException {
+ GuiceCodeGen defaultCodeGen = new GuiceCodeGen(new DefaultClassLoaderHook());
SimpleInterceptor interceptor = new SimpleInterceptor();
ProxyFactoryBuilder builder = new ProxyFactoryBuilder();
builder.intercept(not(any()), not(any()), interceptor);
- ProxyFactory factory = builder.create();
+ ProxyFactory factory = builder.create(defaultCodeGen);
ConstructionProxy<A> constructor =
factory.get(A.class.getDeclaredConstructor(int.class));
@@ -163,12 +168,13 @@
public void testMultipleInterceptors()
throws NoSuchMethodException, InvocationTargetException {
+ GuiceCodeGen defaultCodeGen = new GuiceCodeGen(new DefaultClassLoaderHook());
DoubleInterceptor doubleInterceptor = new DoubleInterceptor();
CountingInterceptor countingInterceptor = new CountingInterceptor();
ProxyFactoryBuilder builder = new ProxyFactoryBuilder();
builder.intercept(any(), any(), doubleInterceptor, countingInterceptor);
- ProxyFactory factory = builder.create();
+ ProxyFactory factory = builder.create(defaultCodeGen);
ConstructionProxy<Counter> constructor =
factory.get(Counter.class.getDeclaredConstructor());
Index: src/com/google/inject/ConstructorInjector.java
===================================================================
--- src/com/google/inject/ConstructorInjector.java (revision 345)
+++ src/com/google/inject/ConstructorInjector.java (working copy)
@@ -123,7 +123,7 @@
if (constructionContext.isConstructing()) {
// TODO (crazybob): if we can't proxy this object, can we proxy the
// other object?
- return constructionContext.createProxy(expectedType);
+ return constructionContext.createProxy(context.injector.codeGen, expectedType);
}
// If we're re-entering this factory while injecting fields or methods,
Index: src/com/google/inject/DefaultConstructionProxyFactory.java
===================================================================
--- src/com/google/inject/DefaultConstructionProxyFactory.java (revision 345)
+++ src/com/google/inject/DefaultConstructionProxyFactory.java (working copy)
@@ -16,7 +16,7 @@
package com.google.inject;
-import com.google.inject.internal.GuiceFastClass;
+import com.google.inject.internal.GuiceCodeGen;
import com.google.inject.internal.Objects;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -33,6 +33,12 @@
*/
class DefaultConstructionProxyFactory implements ConstructionProxyFactory {
+ final GuiceCodeGen codeGen;
+
+ public DefaultConstructionProxyFactory(GuiceCodeGen codeGen) {
+ this.codeGen = codeGen;
+ }
+
public <T> ConstructionProxy<T> get(final Constructor<T> constructor) {
// We can't use FastConstructor if the constructor is private or protected.
if (Modifier.isPrivate(constructor.getModifiers())
@@ -56,7 +62,7 @@
}
Class<T> classToConstruct = constructor.getDeclaringClass();
- FastClass fastClass = GuiceFastClass.create(classToConstruct);
+ FastClass fastClass = codeGen.getFastClass(classToConstruct);
final FastConstructor fastConstructor
= fastClass.getConstructor(constructor);
return new ConstructionProxy<T>() {
Index: src/com/google/inject/internal/GuiceFastClass.java
===================================================================
--- src/com/google/inject/internal/GuiceFastClass.java (revision 345)
+++ src/com/google/inject/internal/GuiceFastClass.java (working copy)
@@ -1,39 +0,0 @@
-/**
- * Copyright (C) 2006 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 net.sf.cglib.reflect.FastClass;
-
-/**
- * Gives Guice classes custom names.
- *
- * @author crazybob@google.com (Bob Lee)
- */
-public class GuiceFastClass {
-
- public static FastClass create(Class type) {
- return create(type.getClassLoader(), type);
- }
-
- public static FastClass create(ClassLoader loader, Class type) {
- FastClass.Generator generator = new FastClass.Generator();
- generator.setType(type);
- generator.setClassLoader(loader);
- generator.setNamingPolicy(new GuiceNamingPolicy());
- return generator.create();
- }
-}
Index: src/com/google/inject/internal/GuiceCodeGen.java
===================================================================
--- src/com/google/inject/internal/GuiceCodeGen.java (revision 345)
+++ src/com/google/inject/internal/GuiceCodeGen.java (working copy)
@@ -16,6 +16,10 @@
package com.google.inject.internal;
+import com.google.inject.ClassLoaderHook;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.reflect.FastClass;
/**
@@ -23,17 +27,42 @@
*
* @author crazybob@google.com (Bob Lee)
*/
-public class GuiceFastClass {
+public class GuiceCodeGen {
- public static FastClass create(Class type) {
- return create(type.getClassLoader(), type);
+ final ClassLoaderHook classLoaderHook;
+
+ public GuiceCodeGen(ClassLoaderHook classLoaderHook) {
+ this.classLoaderHook = classLoaderHook;
}
- public static FastClass create(ClassLoader loader, Class type) {
+ public FastClass getFastClass(Class<?> type) {
+ ClassLoader loader = classLoaderHook.get(type.getClassLoader());
FastClass.Generator generator = new FastClass.Generator();
+
generator.setType(type);
generator.setClassLoader(loader);
generator.setNamingPolicy(new GuiceNamingPolicy());
+
return generator.create();
}
+
+ public Enhancer getEnhancer(Class<?> type) {
+ Enhancer enhancer = new Enhancer() {
+ protected ClassLoader getDefaultClassLoader() {
+ return classLoaderHook.get(super.getDefaultClassLoader());
+ }
+ };
+
+ enhancer.setSuperclass(type);
+ enhancer.setUseCache(false); // We do enough caching.
+ enhancer.setUseFactory(false);
+ enhancer.setNamingPolicy(new GuiceNamingPolicy());
+
+ return enhancer;
+ }
+
+ public Object getProxy(Class<?> type, InvocationHandler handler) {
+ ClassLoader loader = classLoaderHook.get(type.getClassLoader());
+ return Proxy.newProxyInstance(loader, new Class[] {type}, handler);
+ }
}
Index: src/com/google/inject/Guice.java
===================================================================
--- src/com/google/inject/Guice.java (revision 345)
+++ src/com/google/inject/Guice.java (working copy)
@@ -88,10 +88,37 @@
* construction
*/
public static Injector createInjector(Stage stage, Iterable<Module> modules) {
+ return createInjector(new DefaultClassLoaderHook(), stage, modules);
+ }
+
+ /**
+ * Creates an injector for the given set of modules, in a given development
+ * stage, with a given classloading hook.
+ *
+ * @throws CreationException if one or more errors occur during Injector
+ * construction
+ */
+ public static Injector createInjector(ClassLoaderHook classLoaderHook,
+ Stage stage, Module... modules) {
+
+ return createInjector(classLoaderHook, stage, Arrays.asList(modules));
+ }
+
+ /**
+ * Creates an injector for the given set of modules, in a given development
+ * stage, with a given classloading hook.
+ *
+ * @throws CreationException if one or more errors occur during Injector
+ * construction
+ */
+ public static Injector createInjector(ClassLoaderHook classLoaderHook,
+ Stage stage, Iterable<Module> modules) {
+
BinderImpl binder = new BinderImpl(stage);
for (Module module : modules) {
binder.install(module);
}
- return binder.createInjector();
+
+ return binder.createInjector(classLoaderHook);
}
}
Index: src/com/google/inject/InjectorImpl.java
===================================================================
--- src/com/google/inject/InjectorImpl.java (revision 345)
+++ src/com/google/inject/InjectorImpl.java (working copy)
@@ -16,7 +16,7 @@
package com.google.inject;
-import com.google.inject.internal.GuiceFastClass;
+import com.google.inject.internal.GuiceCodeGen;
import com.google.inject.internal.Objects;
import com.google.inject.internal.ReferenceCache;
import com.google.inject.internal.StackTraceElements;
@@ -83,6 +83,7 @@
private static final Map<Class<?>, Converter<?>> PRIMITIVE_CONVERTERS
= new PrimitiveConverters();
+ final GuiceCodeGen codeGen;
final ConstructionProxyFactory constructionProxyFactory;
final Map<Key<?>, BindingImpl<?>> bindings;
final BindingsMultimap bindingsMultimap = new BindingsMultimap();
@@ -91,9 +92,11 @@
ErrorHandler errorHandler = new InvalidErrorHandler();
Object defaultSource = SourceProviders.UNKNOWN_SOURCE;
- InjectorImpl(ConstructionProxyFactory constructionProxyFactory,
+ InjectorImpl(GuiceCodeGen codeGen,
+ ConstructionProxyFactory constructionProxyFactory,
Map<Key<?>, BindingImpl<?>> bindings,
Map<Class<? extends Annotation>, Scope> scopes) {
+ this.codeGen = codeGen;
this.constructionProxyFactory = constructionProxyFactory;
this.bindings = bindings;
this.scopes = scopes;
@@ -549,7 +552,7 @@
};
}
else {
- FastClass fastClass = GuiceFastClass.create(method.getDeclaringClass());
+ FastClass fastClass = injector.codeGen.getFastClass(method.getDeclaringClass());
final FastMethod fastMethod = fastClass.getMethod(method);
this.methodInvoker = new MethodInvoker() {
Index: src/com/google/inject/ProxyFactory.java
===================================================================
--- src/com/google/inject/ProxyFactory.java (revision 345)
+++ src/com/google/inject/ProxyFactory.java (working copy)
@@ -16,7 +16,7 @@
package com.google.inject;
-import com.google.inject.internal.GuiceFastClass;
+import com.google.inject.internal.GuiceCodeGen;
import com.google.inject.internal.GuiceNamingPolicy;
import com.google.inject.internal.Objects;
import com.google.inject.internal.ReferenceCache;
@@ -43,12 +43,14 @@
*/
class ProxyFactory implements ConstructionProxyFactory {
+ final GuiceCodeGen codeGen;
final List<MethodAspect> methodAspects;
- final ConstructionProxyFactory defaultFactory
- = new DefaultConstructionProxyFactory();
+ final ConstructionProxyFactory defaultFactory;
- ProxyFactory(List<MethodAspect> methodAspects) {
+ ProxyFactory(GuiceCodeGen codeGen, List<MethodAspect> methodAspects) {
+ this.codeGen = codeGen;
this.methodAspects = methodAspects;
+ this.defaultFactory = new DefaultConstructionProxyFactory(codeGen);
}
Map<Constructor<?>, ConstructionProxy<?>> constructionProxies
@@ -140,17 +142,13 @@
}
// Create the proxied class.
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(declaringClass);
- enhancer.setUseCache(false); // We do enough caching.
+ Enhancer enhancer = codeGen.getEnhancer(declaringClass);
enhancer.setCallbackFilter(new CallbackFilter() {
public int accept(Method method) {
return indices.get(method);
}
});
enhancer.setCallbackTypes(callbackTypes);
- enhancer.setUseFactory(false);
- enhancer.setNamingPolicy(new GuiceNamingPolicy());
Class<?> proxied = enhancer.createClass();
@@ -165,7 +163,7 @@
*/
<T> ConstructionProxy<T> createConstructionProxy(Class<?> clazz,
Class[] parameterTypes) {
- FastClass fastClass = GuiceFastClass.create(clazz);
+ FastClass fastClass = codeGen.getFastClass(clazz);
final FastConstructor fastConstructor
= fastClass.getConstructor(parameterTypes);
return new ConstructionProxy<T>() {
Index: src/com/google/inject/ProxyFactoryBuilder.java
===================================================================
--- src/com/google/inject/ProxyFactoryBuilder.java (revision 345)
+++ src/com/google/inject/ProxyFactoryBuilder.java (working copy)
@@ -16,6 +16,7 @@
package com.google.inject;
+import com.google.inject.internal.GuiceCodeGen;
import com.google.inject.matcher.Matcher;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -52,7 +53,7 @@
/**
* Creates a {@code ProxyFactory}.
*/
- public ProxyFactory create() {
- return new ProxyFactory(new ArrayList<MethodAspect>(methodAspects));
+ public ProxyFactory create(GuiceCodeGen codeGen) {
+ return new ProxyFactory(codeGen, new ArrayList<MethodAspect>(methodAspects));
}
}
Index: src/com/google/inject/ConstructionContext.java
===================================================================
--- src/com/google/inject/ConstructionContext.java (revision 345)
+++ src/com/google/inject/ConstructionContext.java (working copy)
@@ -23,6 +23,8 @@
import java.util.ArrayList;
import java.util.List;
+import com.google.inject.internal.GuiceCodeGen;
+
/**
* Context of a dependency construction. Used to manage circular references.
*
@@ -60,7 +62,7 @@
invocationHandlers = null;
}
- Object createProxy(Class<?> expectedType) {
+ Object createProxy(GuiceCodeGen codeGen, Class<?> expectedType) {
// TODO: if I create a proxy which implements all the interfaces of
// the implementation type, I'll be able to get away with one proxy
// instance (as opposed to one per caller).
@@ -80,8 +82,7 @@
= new DelegatingInvocationHandler<T>();
invocationHandlers.add(invocationHandler);
- Object object = Proxy.newProxyInstance(expectedType.getClassLoader(),
- new Class[] { expectedType }, invocationHandler);
+ Object object = codeGen.getProxy(expectedType, invocationHandler);
return expectedType.cast(object);
}
Index: src/com/google/inject/ClassLoaderHook.java
===================================================================
--- src/com/google/inject/ClassLoaderHook.java (revision 0)
+++ src/com/google/inject/ClassLoaderHook.java (revision 0)
@@ -0,0 +1,29 @@
+/**
+ * Copyright (C) 2007 Stuart McCulloch.
+ *
+ * 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;
+
+/**
+ * Provide classloading interception for Guice enhanced classes and proxies.
+ *
+ * @author stuart.mcculloch@jayway.net (Stuart McCulloch)
+ */
+public interface ClassLoaderHook {
+
+ void setInternalLoader(ClassLoader internalLoader);
+
+ ClassLoader get(ClassLoader typeLoader);
+}
Property changes on: src/com/google/inject/ClassLoaderHook.java
___________________________________________________________________
Name: svn:eol-style
+ native
Index: src/com/google/inject/DefaultClassLoaderHook.java
===================================================================
--- src/com/google/inject/DefaultClassLoaderHook.java (revision 0)
+++ src/com/google/inject/DefaultClassLoaderHook.java (revision 0)
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2007 Stuart McCulloch.
+ *
+ * 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;
+
+
+/**
+ * Default {@link ClassLoaderHook} implementation (no interception).
+ *
+ * @author stuart.mcculloch@jayway.net (Stuart McCulloch)
+ */
+class DefaultClassLoaderHook implements ClassLoaderHook {
+
+ public void setInternalLoader(ClassLoader internalLoader) {
+ /* not interested */
+ }
+
+ public ClassLoader get(ClassLoader typeLoader) {
+ return typeLoader;
+ }
+}
Property changes on: src/com/google/inject/DefaultClassLoaderHook.java
___________________________________________________________________
Name: svn:eol-style
+ native
Index: src/com/google/inject/BinderImpl.java
===================================================================
--- src/com/google/inject/BinderImpl.java (revision 345)
+++ src/com/google/inject/BinderImpl.java (working copy)
@@ -20,6 +20,8 @@
import static com.google.inject.Scopes.SINGLETON;
import com.google.inject.internal.Annotations;
import static com.google.inject.internal.Objects.nonNull;
+
+import com.google.inject.internal.GuiceCodeGen;
import com.google.inject.internal.StackTraceElements;
import com.google.inject.internal.Stopwatch;
import com.google.inject.matcher.Matcher;
@@ -241,11 +243,27 @@
* @throws IllegalStateException if called more than once
*/
Injector createInjector() throws CreationException {
+ return createInjector(new DefaultClassLoaderHook());
+ }
+
+ /**
+ * Creates a {@link Injector} instance. Injects static members for classes
+ * which were registered using {@link #requestStaticInjection(Class...)}.
+ * Also registers a classloading hook for enhanced classes and proxies.
+ *
+ * @throws CreationException if configuration errors are found. The
+ * expectation is that the application will log this exception and exit.
+ * @throws IllegalStateException if called more than once
+ */
+ Injector createInjector(ClassLoaderHook classLoaderHook) throws CreationException {
stopwatch.resetAndLog(logger, "Configuration");
+ classLoaderHook.setInternalLoader(getClass().getClassLoader());
+ GuiceCodeGen codeGen = new GuiceCodeGen(classLoaderHook);
+
Map<Key<?>, BindingImpl<?>> bindings = new HashMap<Key<?>, BindingImpl<?>>();
injector = new InjectorImpl(
- proxyFactoryBuilder.create(), bindings, scopes);
+ codeGen, proxyFactoryBuilder.create(codeGen), bindings, scopes);
injector.setErrorHandler(configurationErrorHandler);
createConstantBindings();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment