Implemented ProxyFactory.
git-svn-id: https://google-guice.googlecode.com/svn/trunk@62 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/build.properties b/build.properties
index fa25685..d2d3374 100644
--- a/build.properties
+++ b/build.properties
@@ -3,4 +3,4 @@
src.dir=src
test.dir=test
build.dir=build
-javadoc.packagenames=com.google.inject
+javadoc.packagenames=com.google.inject,com.google.inject.spi,com.google.inject.intercept
diff --git a/guice.iml b/guice.iml
index e507620..3064cae 100644
--- a/guice.iml
+++ b/guice.iml
@@ -49,6 +49,15 @@
</library>
</orderEntry>
<orderEntry type="library" name="cglib-nodep-2.1_3" level="project" />
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/lib/aopalliance.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
<orderEntryProperties />
</component>
</module>
diff --git a/guice.iws b/guice.iws
index 706aabd..4730906 100644
--- a/guice.iws
+++ b/guice.iws
@@ -18,21 +18,14 @@
</component>
<component name="ChangeListManager">
<list default="true" name="Default" comment="">
- <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/ContextualCallable.java" afterPath="$PROJECT_DIR$/src/com/google/inject/ContextualCallable.java" />
- <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/intercept/Queries.java" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/Queries.java" />
- <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/spi/DefaultConstructionProxyFactory.java" afterPath="$PROJECT_DIR$/src/com/google/inject/spi/DefaultConstructionProxyFactory.java" />
- <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/ErrorMessages.java" afterPath="$PROJECT_DIR$/src/com/google/inject/ErrorMessages.java" />
- <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java" />
- <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxy.java" afterPath="$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxy.java" />
- <change type="MODIFICATION" beforePath="$PROJECT_DIR$/test/com/google/inject/ReflectionTest.java" afterPath="$PROJECT_DIR$/test/com/google/inject/ReflectionTest.java" />
- <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/ConstructorInjector.java" afterPath="$PROJECT_DIR$/src/com/google/inject/ConstructorInjector.java" />
+ <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/lib/aopalliance.jar" />
+ <change type="MODIFICATION" beforePath="$PROJECT_DIR$/guice.iml" afterPath="$PROJECT_DIR$/guice.iml" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactory.java" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactory.java" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/guice.iws" afterPath="$PROJECT_DIR$/guice.iws" />
- <change type="MODIFICATION" beforePath="$PROJECT_DIR$/test/com/google/inject/intercept/QueryTest.java" afterPath="$PROJECT_DIR$/test/com/google/inject/intercept/QueryTest.java" />
- <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/intercept/AbstractQuery.java" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/AbstractQuery.java" />
- <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxyFactory.java" afterPath="$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxyFactory.java" />
- <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/util/ToStringBuilder.java" afterPath="$PROJECT_DIR$/src/com/google/inject/util/ToStringBuilder.java" />
- <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/intercept/Query.java" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/Query.java" />
+ <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/test/com/google/inject/intercept/ProxyFactoryTest.java" />
+ <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/MethodAspect.java" />
+ <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/InterceptorStackCallback.java" />
+ <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java" />
</list>
</component>
<component name="ChangeListSynchronizer" />
@@ -202,183 +195,10 @@
</component>
<component name="FileEditorManager">
<leaf>
- <file leaf-file-name="ConstructionProxy.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxy.java">
+ <file leaf-file-name="Message.java" pinned="false" current="false" current-in-tab="false">
+ <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/Message.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="ConstructionProxyFactory.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxyFactory.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="ContainerCreationException.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/ContainerCreationException.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="38" column="0" selection-start="1207" selection-end="1207" vertical-scroll-proportion="0.6612642">
- <folding>
- <element signature="imports" expanded="true" />
- </folding>
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="ErrorMessages.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/ErrorMessages.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="ReflectionTest.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/test/com/google/inject/ReflectionTest.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="AbstractQuery.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/AbstractQuery.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="TypeLiteral.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/TypeLiteral.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="32" column="8" selection-start="1141" selection-end="1141" vertical-scroll-proportion="0.027552674">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="Binding.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/Binding.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="0" column="0" selection-start="0" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="ContainerBuilder.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/ContainerBuilder.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="334" column="31" selection-start="10275" selection-end="10275" vertical-scroll-proportion="0.3922204">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="ConstantFactory.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/ConstantFactory.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="38" column="14" selection-start="1098" selection-end="1098" vertical-scroll-proportion="0.6337115">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="ContainerScope.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/ContainerScope.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="50" column="15" selection-start="1625" selection-end="1625" vertical-scroll-proportion="0.9918963">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="Queries.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/Queries.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="guice.iws" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/guice.iws">
- <provider selected="true" editor-type-id="text-editor">
- <state line="871" column="2" selection-start="44011" selection-end="44011" vertical-scroll-proportion="0.3936877">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="Query.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/Query.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="QueryTest.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/test/com/google/inject/intercept/QueryTest.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="package-info.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/package-info.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="18" column="3" selection-start="647" selection-end="647" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="ContainerImpl.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/ContainerImpl.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="51" column="6" selection-start="1627" selection-end="1627" vertical-scroll-proportion="0.3306321">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="ConstructorInjector.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/ConstructorInjector.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="15" column="0" selection-start="596" selection-end="596" vertical-scroll-proportion="0.027552674">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="ContextualCallable.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/ContextualCallable.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="AllTests.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/test/com/google/inject/AllTests.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="49" column="19" selection-start="1724" selection-end="1724" vertical-scroll-proportion="0.7714749">
+ <state line="45" column="3" selection-start="1286" selection-end="1286" vertical-scroll-proportion="0.8541329">
<folding />
</state>
</provider>
@@ -387,7 +207,92 @@
<file leaf-file-name="ProxyFactory.java" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactory.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+ <state line="148" column="48" selection-start="5256" selection-end="5256" vertical-scroll-proportion="0.48460293">
+ <folding>
+ <element signature="imports" expanded="true" />
+ </folding>
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="FastClass.java" pinned="false" current="false" current-in-tab="false">
+ <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/reflect/FastClass.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="38" column="0" selection-start="1207" selection-end="1207" vertical-scroll-proportion="0.33225283">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="ProxyFactoryTest.java" pinned="false" current="true" current-in-tab="true">
+ <entry file="file://$PROJECT_DIR$/test/com/google/inject/intercept/ProxyFactoryTest.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="23" column="7" selection-start="654" selection-end="654" vertical-scroll-proportion="0.6337115">
+ <folding>
+ <element signature="imports" expanded="true" />
+ </folding>
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="MethodInterceptor.class" pinned="false" current="false" current-in-tab="false">
+ <entry file="jar://$PROJECT_DIR$/lib/aopalliance.jar!/org/aopalliance/intercept/MethodInterceptor.class">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="5" column="17" selection-start="167" selection-end="167" vertical-scroll-proportion="0.110210694">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="InterceptorStackCallback.java" pinned="false" current="false" current-in-tab="false">
+ <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/InterceptorStackCallback.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="23" column="9" selection-start="596" selection-end="596" vertical-scroll-proportion="0.016207455">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="MethodProxy.java" pinned="false" current="false" current-in-tab="false">
+ <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/proxy/MethodProxy.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="164" column="18" selection-start="6352" selection-end="6352" vertical-scroll-proportion="1.3111831">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="Joinpoint.class" pinned="false" current="false" current-in-tab="false">
+ <entry file="jar://$PROJECT_DIR$/lib/aopalliance.jar!/org/aopalliance/intercept/Joinpoint.class">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="11" column="37" selection-start="313" selection-end="313" vertical-scroll-proportion="0.27552673">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="Enhancer.java" pinned="false" current="false" current-in-tab="false">
+ <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/proxy/Enhancer.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="589" column="23" selection-start="26039" selection-end="26039" vertical-scroll-proportion="0.33225283">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="DuplicatesPredicate.java" pinned="false" current="false" current-in-tab="false">
+ <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/core/DuplicatesPredicate.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="20" column="13" selection-start="712" selection-end="712" vertical-scroll-proportion="0.13776337">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="ReflectUtils.java" pinned="false" current="false" current-in-tab="false">
+ <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/core/ReflectUtils.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="344" column="23" selection-start="13257" selection-end="13257" vertical-scroll-proportion="0.5656402">
<folding />
</state>
</provider>
@@ -396,61 +301,65 @@
<file leaf-file-name="ProxyFactoryBuilder.java" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+ <state line="39" column="36" selection-start="1268" selection-end="1268" vertical-scroll-proportion="0.68881685">
+ <folding>
+ <element signature="imports" expanded="true" />
+ </folding>
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="Query.java" pinned="false" current="false" current-in-tab="false">
+ <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/Query.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="23" column="17" selection-start="764" selection-end="764" vertical-scroll-proportion="0.24797407">
<folding />
</state>
</provider>
</entry>
</file>
- <file leaf-file-name="InternalContext.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/InternalContext.java">
+ <file leaf-file-name="QueryTest.java" pinned="false" current="false" current-in-tab="false">
+ <entry file="file://$PROJECT_DIR$/test/com/google/inject/intercept/QueryTest.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="71" column="1" selection-start="2161" selection-end="2161" vertical-scroll-proportion="1.5429498">
+ <state line="34" column="13" selection-start="1234" selection-end="1234" vertical-scroll-proportion="0.24797407">
<folding />
</state>
</provider>
</entry>
</file>
- <file leaf-file-name="PerformanceComparison.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/test/com/google/inject/PerformanceComparison.java">
+ <file leaf-file-name="MethodAspect.java" pinned="false" current="false" current-in-tab="false">
+ <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/MethodAspect.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="149" column="37" selection-start="5048" selection-end="5048" vertical-scroll-proportion="2.4246354">
+ <state line="25" column="22" selection-start="735" selection-end="735" vertical-scroll-proportion="0.68881685">
+ <folding>
+ <element signature="imports" expanded="true" />
+ </folding>
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="Queries.java" pinned="false" current="false" current-in-tab="false">
+ <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/Queries.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="28" column="13" selection-start="889" selection-end="889" vertical-scroll-proportion="0.30307943">
<folding />
</state>
</provider>
</entry>
</file>
- <file leaf-file-name="NumberFormat.java" pinned="false" current="false" current-in-tab="false">
- <entry file="jar:///usr/local/src.zip!/java/text/NumberFormat.java">
+ <file leaf-file-name="ConstructionProxy.java" pinned="false" current="false" current-in-tab="false">
+ <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxy.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="509" column="9" selection-start="19846" selection-end="19846" vertical-scroll-proportion="0.28200972">
+ <state line="26" column="17" selection-start="837" selection-end="837" vertical-scroll-proportion="0.3306321">
<folding />
</state>
</provider>
</entry>
</file>
- <file leaf-file-name="ConstructionContext.java" pinned="false" current="false" current-in-tab="false">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/ConstructionContext.java">
+ <file leaf-file-name="ConstructionProxyFactory.java" pinned="false" current="false" current-in-tab="false">
+ <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxyFactory.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="30" column="6" selection-start="973" selection-end="973" vertical-scroll-proportion="-1.0858995">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="ToStringCreator.class" pinned="false" current="false" current-in-tab="false">
- <entry file="jar://$PROJECT_DIR$/lib/build/spring-core.jar!/org/springframework/core/style/ToStringCreator.class">
- <provider selected="true" editor-type-id="text-editor">
- <state line="5" column="13" selection-start="168" selection-end="168" vertical-scroll-proportion="0.110210694">
- <folding />
- </state>
- </provider>
- </entry>
- </file>
- <file leaf-file-name="ToStringBuilder.java" pinned="false" current="true" current-in-tab="true">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/util/ToStringBuilder.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.38573745">
+ <state line="25" column="17" selection-start="785" selection-end="785" vertical-scroll-proportion="0.30307943">
<folding />
</state>
</provider>
@@ -459,7 +368,7 @@
<file leaf-file-name="DefaultConstructionProxyFactory.java" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/DefaultConstructionProxyFactory.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+ <state line="46" column="0" selection-start="1116" selection-end="1602" vertical-scroll-proportion="0.88168555">
<folding>
<element signature="imports" expanded="true" />
</folding>
@@ -650,6 +559,32 @@
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$/src" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$/src/com/google/inject" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$/src/com/google/inject/intercept" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ </PATH>
+ <PATH>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="guice.ipr" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="guice" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
<option name="myItemId" value="PsiDirectory:$PROJECT_DIR$/lib" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
@@ -660,7 +595,7 @@
<option name="STATE" value="0" />
</component>
<component name="ProjectView">
- <navigator currentView="ProjectPane" proportions="0.16666667" version="1" splitterProportion="0.5">
+ <navigator currentView="PackagesPane" proportions="0.16666667" version="1" splitterProportion="0.5">
<flattenPackages PackagesPane="true" />
<showMembers />
<showModules PackagesPane="false" />
@@ -725,16 +660,16 @@
</key>
</component>
<component name="RestoreUpdateTree" />
- <component name="RunManager" selected="JUnit.AllTests">
- <tempConfiguration default="false" name="QueryTest" type="JUnit" factoryName="JUnit" enabled="false" merge="false">
- <pattern value="com.google.inject.*" />
+ <component name="RunManager" selected="JUnit.ProxyFactoryTest.testSimpleCase">
+ <tempConfiguration default="false" name="ProxyFactoryTest.testSimpleCase" type="JUnit" factoryName="JUnit" enabled="false" merge="false">
+ <pattern value="com.google.inject.intercept.*" />
<module name="guice" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" value="com.google.inject.intercept" />
- <option name="MAIN_CLASS_NAME" value="com.google.inject.intercept.QueryTest" />
- <option name="METHOD_NAME" />
- <option name="TEST_OBJECT" value="class" />
+ <option name="MAIN_CLASS_NAME" value="com.google.inject.intercept.ProxyFactoryTest" />
+ <option name="METHOD_NAME" value="testSimpleCase" />
+ <option name="TEST_OBJECT" value="method" />
<option name="VM_PARAMETERS" />
<option name="PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
@@ -742,13 +677,7 @@
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
- <RunnerSettings RunnerId="Debug">
- <option name="DEBUG_PORT" value="41735" />
- <option name="TRANSPORT" value="0" />
- <option name="LOCAL" value="true" />
- </RunnerSettings>
<RunnerSettings RunnerId="Run" />
- <ConfigurationWrapper RunnerId="Debug" />
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="Make" value="true" />
@@ -942,7 +871,7 @@
</component>
<component name="ToolWindowManager">
<frame x="4" y="44" width="1916" height="1156" extended-state="0" />
- <editor active="false" />
+ <editor active="true" />
<layout>
<window_info id="UI Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="3" />
<window_info id="CVS" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="8" />
@@ -960,7 +889,7 @@
<window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="3" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.14623655" order="1" />
<window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3282876" order="8" />
- <window_info id="Run" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.40018922" order="2" />
+ <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.40018922" order="2" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" order="2" />
<window_info id="File View" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="6" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.39978448" order="0" />
@@ -1059,113 +988,121 @@
<option name="myLastEditedConfigurable" value="Default" />
</component>
<component name="editorHistoryManager">
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/ErrorMessages.java">
+ <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/core/ReflectUtils.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+ <state line="344" column="23" selection-start="13257" selection-end="13257" vertical-scroll-proportion="0.5656402">
<folding />
</state>
</provider>
</entry>
- <entry file="file://$PROJECT_DIR$/test/com/google/inject/ReflectionTest.java">
+ <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/core/DuplicatesPredicate.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+ <state line="20" column="13" selection-start="712" selection-end="712" vertical-scroll-proportion="0.13776337">
<folding />
</state>
</provider>
</entry>
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/AbstractQuery.java">
+ <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/Message.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+ <state line="45" column="3" selection-start="1286" selection-end="1286" vertical-scroll-proportion="0.8541329">
<folding />
</state>
</provider>
</entry>
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactory.java">
+ <entry file="jar://$PROJECT_DIR$/lib/aopalliance.jar!/org/aopalliance/intercept/Joinpoint.class">
<provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+ <state line="11" column="37" selection-start="313" selection-end="313" vertical-scroll-proportion="0.27552673">
<folding />
</state>
</provider>
</entry>
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java">
+ <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/proxy/MethodProxy.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/Queries.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/Query.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- <entry file="file://$PROJECT_DIR$/guice.iws">
- <provider selected="true" editor-type-id="text-editor">
- <state line="871" column="2" selection-start="44011" selection-end="44011" vertical-scroll-proportion="0.3936877">
- <folding />
- </state>
- </provider>
- </entry>
- <entry file="file://$PROJECT_DIR$/test/com/google/inject/intercept/QueryTest.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+ <state line="164" column="18" selection-start="6352" selection-end="6352" vertical-scroll-proportion="1.3111831">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxy.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
- <folding />
- </state>
- </provider>
- </entry>
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxyFactory.java">
- <provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+ <state line="26" column="17" selection-start="837" selection-end="837" vertical-scroll-proportion="0.3306321">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/DefaultConstructionProxyFactory.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+ <state line="46" column="0" selection-start="1116" selection-end="1602" vertical-scroll-proportion="0.88168555">
<folding>
<element signature="imports" expanded="true" />
</folding>
</state>
</provider>
</entry>
- <entry file="jar://$PROJECT_DIR$/lib/build/spring-core.jar!/org/springframework/core/style/ToStringCreator.class">
+ <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/InterceptorStackCallback.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="5" column="13" selection-start="168" selection-end="168" vertical-scroll-proportion="0.110210694">
+ <state line="23" column="9" selection-start="596" selection-end="596" vertical-scroll-proportion="0.016207455">
<folding />
</state>
</provider>
</entry>
- <entry file="file://$PROJECT_DIR$/COPYING">
+ <entry file="jar://$PROJECT_DIR$/lib/aopalliance.jar!/org/aopalliance/intercept/MethodInterceptor.class">
<provider selected="true" editor-type-id="text-editor">
- <state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="-3.857143">
+ <state line="5" column="17" selection-start="167" selection-end="167" vertical-scroll-proportion="0.110210694">
<folding />
</state>
</provider>
</entry>
- <entry file="file://$PROJECT_DIR$/src/com/google/inject/util/ToStringBuilder.java">
+ <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/MethodAspect.java">
<provider selected="true" editor-type-id="text-editor">
- <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.38573745">
+ <state line="25" column="22" selection-start="735" selection-end="735" vertical-scroll-proportion="0.68881685">
+ <folding>
+ <element signature="imports" expanded="true" />
+ </folding>
+ </state>
+ </provider>
+ </entry>
+ <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="39" column="36" selection-start="1268" selection-end="1268" vertical-scroll-proportion="0.68881685">
+ <folding>
+ <element signature="imports" expanded="true" />
+ </folding>
+ </state>
+ </provider>
+ </entry>
+ <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/proxy/Enhancer.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="589" column="23" selection-start="26039" selection-end="26039" vertical-scroll-proportion="0.33225283">
<folding />
</state>
</provider>
</entry>
+ <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/reflect/FastClass.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="38" column="0" selection-start="1207" selection-end="1207" vertical-scroll-proportion="0.33225283">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactory.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="148" column="48" selection-start="5256" selection-end="5256" vertical-scroll-proportion="0.48460293">
+ <folding>
+ <element signature="imports" expanded="true" />
+ </folding>
+ </state>
+ </provider>
+ </entry>
+ <entry file="file://$PROJECT_DIR$/test/com/google/inject/intercept/ProxyFactoryTest.java">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="23" column="7" selection-start="654" selection-end="654" vertical-scroll-proportion="0.6337115">
+ <folding>
+ <element signature="imports" expanded="true" />
+ </folding>
+ </state>
+ </provider>
+ </entry>
</component>
</project>
diff --git a/lib/aopalliance.jar b/lib/aopalliance.jar
new file mode 100644
index 0000000..578b1a0
--- /dev/null
+++ b/lib/aopalliance.jar
Binary files differ
diff --git a/src/com/google/inject/intercept/InterceptorStackCallback.java b/src/com/google/inject/intercept/InterceptorStackCallback.java
new file mode 100644
index 0000000..703c4a8
--- /dev/null
+++ b/src/com/google/inject/intercept/InterceptorStackCallback.java
@@ -0,0 +1,78 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+package com.google.inject.intercept;
+
+import net.sf.cglib.proxy.MethodProxy;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.AccessibleObject;
+import java.util.List;
+
+/**
+ * Intercepts a method with a stack of interceptors.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+class InterceptorStackCallback implements net.sf.cglib.proxy.MethodInterceptor {
+
+ final MethodInterceptor[] interceptors;
+ final Method method;
+
+ public InterceptorStackCallback(Method method,
+ List<MethodInterceptor> interceptors) {
+ this.method = method;
+ this.interceptors = interceptors.toArray(
+ new MethodInterceptor[interceptors.size()]);
+ }
+
+ public Object intercept(Object proxy, Method method, Object[] arguments,
+ MethodProxy methodProxy) throws Throwable {
+ return new InterceptedMethodInvocation(
+ proxy, methodProxy, arguments).proceed();
+ }
+
+ class InterceptedMethodInvocation implements MethodInvocation {
+
+ final Object proxy;
+ final Object[] arguments;
+ final MethodProxy methodProxy;
+ int index = -1;
+
+ public InterceptedMethodInvocation(Object proxy, MethodProxy methodProxy,
+ Object[] arguments) {
+ this.proxy = proxy;
+ this.methodProxy = methodProxy;
+ this.arguments = arguments;
+ }
+
+ public Object proceed() throws Throwable {
+ try {
+ index++;
+ return index == interceptors.length
+ ? methodProxy.invokeSuper(proxy, arguments)
+ : interceptors[index].invoke(this);
+ } finally {
+ index--;
+ }
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+
+ public Object[] getArguments() {
+ return arguments;
+ }
+
+ public Object getThis() {
+ return proxy;
+ }
+
+ public AccessibleObject getStaticPart() {
+ return getMethod();
+ }
+ }
+}
diff --git a/src/com/google/inject/intercept/MethodAspect.java b/src/com/google/inject/intercept/MethodAspect.java
new file mode 100644
index 0000000..ff5765d
--- /dev/null
+++ b/src/com/google/inject/intercept/MethodAspect.java
@@ -0,0 +1,40 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+package com.google.inject.intercept;
+
+import com.google.inject.util.Objects;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+import java.lang.reflect.Method;
+
+/**
+ * Ties a query to a method interceptor.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+class MethodAspect {
+
+ final Query<? super Class> classQuery;
+ final Query<? super Method> methodQuery;
+ final MethodInterceptor interceptor;
+
+ MethodAspect(Query<? super Class> classQuery, Query<? super Method> methodQuery,
+ MethodInterceptor interceptor) {
+ this.classQuery = Objects.nonNull(classQuery, "class query");
+ this.methodQuery = Objects.nonNull(methodQuery, "method query");
+ this.interceptor = Objects.nonNull(interceptor, "interceptor");
+ }
+
+ boolean matches(Class<?> clazz) {
+ return classQuery.matches(clazz);
+ }
+
+ boolean matches(Method method) {
+ return methodQuery.matches(method);
+ }
+
+ MethodInterceptor interceptor() {
+ return interceptor;
+ }
+}
diff --git a/src/com/google/inject/intercept/ProxyFactory.java b/src/com/google/inject/intercept/ProxyFactory.java
index 039844c..719acba 100644
--- a/src/com/google/inject/intercept/ProxyFactory.java
+++ b/src/com/google/inject/intercept/ProxyFactory.java
@@ -16,9 +16,171 @@
package com.google.inject.intercept;
+import com.google.inject.spi.ConstructionProxyFactory;
+import com.google.inject.spi.ConstructionProxy;
+import com.google.inject.spi.DefaultConstructionProxyFactory;
+import com.google.inject.util.ReferenceCache;
+
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.Callback;
+import net.sf.cglib.proxy.NoOp;
+import net.sf.cglib.proxy.CallbackFilter;
+import net.sf.cglib.reflect.FastClass;
+import net.sf.cglib.reflect.FastConstructor;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
/**
+ * Proxies classes applying interceptors to methods as specified in
+ * {@link ProxyFactoryBuilder}.
+ *
* @author crazybob@google.com (Bob Lee)
*/
-public interface ProxyFactory {
+public class ProxyFactory implements ConstructionProxyFactory {
+ final List<MethodAspect> methodAspects;
+ final ConstructionProxyFactory defaultFactory =
+ new DefaultConstructionProxyFactory();
+
+ ProxyFactory(List<MethodAspect> methodAspects) {
+ this.methodAspects = methodAspects;
+ }
+
+ Map<Constructor<?>, ConstructionProxy<?>> constructionProxies =
+ new ReferenceCache<Constructor<?>, ConstructionProxy<?>>() {
+ protected ConstructionProxy<?> create(Constructor<?> constructor) {
+ return createConstructionProxy(constructor);
+ }
+ };
+
+ <T> ConstructionProxy<T> createConstructionProxy(Constructor<T> constructor) {
+ Class<T> declaringClass = constructor.getDeclaringClass();
+
+ // Find applicable aspects. Bow out if none are applicable to this class.
+ List<MethodAspect> applicableAspects = new ArrayList<MethodAspect>();
+ for (MethodAspect methodAspect : methodAspects) {
+ if (methodAspect.matches(declaringClass)) {
+ applicableAspects.add(methodAspect);
+ }
+ }
+ if (applicableAspects.isEmpty()) {
+ return defaultFactory.get(constructor);
+ }
+
+ // Get list of methods from cglib.
+ List<Method> methods = new ArrayList<Method>();
+ Enhancer.getMethods(declaringClass, null, methods);
+ final Map<Method, Integer> indices = new HashMap<Method, Integer>();
+
+ // Create method/interceptor holders and record indices.
+ List<MethodInterceptorsPair> methodInterceptorsPairs =
+ new ArrayList<MethodInterceptorsPair>();
+ for (int i = 0; i < methods.size(); i++) {
+ Method method = methods.get(i);
+ methodInterceptorsPairs.add(new MethodInterceptorsPair(method));
+ indices.put(method, i);
+ }
+
+ // Iterate over aspects and add interceptors for the methods they apply
+ // to.
+ boolean anyMatched = false;
+ for (MethodAspect methodAspect : applicableAspects) {
+ for (MethodInterceptorsPair methodInterceptorsPair
+ : methodInterceptorsPairs) {
+ if (methodAspect.matches(methodInterceptorsPair.method)) {
+ methodInterceptorsPair.add(methodAspect.interceptor());
+ anyMatched = true;
+ }
+ }
+ }
+ if (!anyMatched) {
+ return defaultFactory.get(constructor);
+ }
+
+ // Create callbacks.
+ Callback[] callbacks = new Callback[methods.size()];
+ Class<? extends Callback>[] callbackTypes = new Class[methods.size()];
+ for (int i = 0; i < methods.size(); i++) {
+ MethodInterceptorsPair methodInterceptorsPair =
+ methodInterceptorsPairs.get(i);
+ if (!methodInterceptorsPair.hasInterceptors()) {
+ callbacks[i] = NoOp.INSTANCE;
+ callbackTypes[i] = NoOp.class;
+ } else {
+ callbacks[i] = new InterceptorStackCallback(
+ methodInterceptorsPair.method, methodInterceptorsPair.interceptors);
+ callbackTypes[i] = net.sf.cglib.proxy.MethodInterceptor.class;
+ }
+ }
+
+ // Create the proxied class.
+ Enhancer enhancer = new Enhancer();
+ enhancer.setSuperclass(declaringClass);
+ enhancer.setUseCache(false); // We do enough caching.
+ enhancer.setCallbackFilter(new CallbackFilter() {
+ public int accept(Method method) {
+ return indices.get(method);
+ }
+ });
+ enhancer.setCallbackTypes(callbackTypes);
+ enhancer.setUseFactory(false);
+
+ Class<?> proxied = enhancer.createClass();
+
+ // Store callbacks.
+ Enhancer.registerStaticCallbacks(proxied, callbacks);
+
+ return createConstructionProxy(proxied, constructor.getParameterTypes());
+ }
+
+ /**
+ * Creates a construction proxy given a class and parameter types.
+ */
+ <T> ConstructionProxy<T> createConstructionProxy(Class<?> clazz,
+ Class[] parameterTypes) {
+ FastClass fastClass = FastClass.create(clazz);
+ final FastConstructor fastConstructor =
+ fastClass.getConstructor(parameterTypes);
+ return new ConstructionProxy<T>() {
+ @SuppressWarnings({"unchecked"})
+ public T newInstance(Object... arguments)
+ throws InvocationTargetException {
+ return (T) fastConstructor.newInstance(arguments);
+ }
+ };
+ }
+
+ static class MethodInterceptorsPair {
+
+ final Method method;
+ List<MethodInterceptor> interceptors;
+
+ public MethodInterceptorsPair(Method method) {
+ this.method = method;
+ }
+
+ void add(MethodInterceptor interceptor) {
+ if (interceptors == null) {
+ interceptors = new ArrayList<MethodInterceptor>();
+ }
+ interceptors.add(interceptor);
+ }
+
+ boolean hasInterceptors() {
+ return interceptors != null;
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public <T> ConstructionProxy<T> get(Constructor<T> constructor) {
+ return (ConstructionProxy<T>) constructionProxies.get(constructor);
+ }
}
diff --git a/src/com/google/inject/intercept/ProxyFactoryBuilder.java b/src/com/google/inject/intercept/ProxyFactoryBuilder.java
index 4b00f4e..bedcfe6 100644
--- a/src/com/google/inject/intercept/ProxyFactoryBuilder.java
+++ b/src/com/google/inject/intercept/ProxyFactoryBuilder.java
@@ -16,9 +16,37 @@
package com.google.inject.intercept;
+import org.aopalliance.intercept.MethodInterceptor;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.lang.reflect.Method;
+
/**
+ * Creates a {@link ProxyFactory}.
+ *
* @author crazybob@google.com (Bob Lee)
*/
public class ProxyFactoryBuilder {
+ final List<MethodAspect> methodAspects = new ArrayList<MethodAspect>();
+
+ /**
+ * Applies the given method interceptor to the methods matched by the class
+ * and method queries.
+ */
+ public ProxyFactoryBuilder intercept(Query<? super Class> classQuery,
+ Query<? super Method> methodQuery, MethodInterceptor interceptor) {
+ methodAspects.add(new MethodAspect(classQuery, methodQuery, interceptor));
+ return this;
+ }
+
+ /**
+ * Creates a {@code ProxyFactory}.
+ */
+ public ProxyFactory create() {
+ List<MethodAspect> methodAspects = new ArrayList<MethodAspect>();
+ methodAspects.addAll(this.methodAspects);
+ return new ProxyFactory(methodAspects);
+ }
}
diff --git a/test/com/google/inject/intercept/ProxyFactoryTest.java b/test/com/google/inject/intercept/ProxyFactoryTest.java
new file mode 100644
index 0000000..c042eb8
--- /dev/null
+++ b/test/com/google/inject/intercept/ProxyFactoryTest.java
@@ -0,0 +1,54 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+package com.google.inject.intercept;
+
+import com.google.inject.spi.ConstructionProxy;
+
+import junit.framework.TestCase;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ProxyFactoryTest extends TestCase {
+
+ public void testSimpleCase()
+ throws NoSuchMethodException, InvocationTargetException {
+ SimpleInterceptor interceptor = new SimpleInterceptor();
+
+ ProxyFactoryBuilder builder = new ProxyFactoryBuilder();
+ builder.intercept(Queries.any(), Queries.any(), interceptor);
+ ProxyFactory factory = builder.create();
+
+ ConstructionProxy<Simple> constructor =
+ factory.get(Simple.class.getDeclaredConstructor());
+
+ Simple simple = constructor.newInstance();
+ simple.invoke();
+ assertTrue(simple.invoked);
+ assertTrue(interceptor.invoked);
+ }
+
+ static class Simple {
+ boolean invoked = false;
+ public void invoke() {
+ invoked = true;
+ }
+ }
+
+ static class SimpleInterceptor implements MethodInterceptor {
+
+ boolean invoked = false;
+
+ public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+ invoked = true;
+ return methodInvocation.proceed();
+ }
+ }
+
+
+}