Creating release tag per documentation found at:

http://commons.apache.org/releases/prepare.html

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/proxy/branches/proxy-1.0-rc1@629117 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/proxy-1.0-work/LICENSE.txt b/proxy-1.0-work/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/proxy-1.0-work/LICENSE.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/proxy-1.0-work/NOTICE.txt b/proxy-1.0-work/NOTICE.txt
new file mode 100644
index 0000000..62625d9
--- /dev/null
+++ b/proxy-1.0-work/NOTICE.txt
@@ -0,0 +1,5 @@
+Apache Commons Proxy
+Copyright 2006-2007 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
\ No newline at end of file
diff --git a/proxy-1.0-work/PROPOSAL.html b/proxy-1.0-work/PROPOSAL.html
new file mode 100644
index 0000000..82499cd
--- /dev/null
+++ b/proxy-1.0-work/PROPOSAL.html
@@ -0,0 +1,96 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You 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.
+  -->
+<html>
+<head>
+    <title>Proposal for Proxy Package</title>
+</head>
+
+<body bgcolor="white">
+
+<div align="center">
+    <h1>Proposal for <em>Proxy</em> Package</h1>
+</div>
+
+<h3>(0) Rationale</h3>
+
+<p>
+    Many projects require the use of proxies in order to support such features as method interception/decoration, lazy
+    loading, dependency injection, etc. There are many different techniques for creating proxy objects which delegate to
+    other objects (JDK proxies, CGLIB, and Javassist to name a few). Using these technologies can prove to be quite
+    daunting. This package seeks to abstract away the difficult code required to implement proxies effectively and
+    efficiently so that developers can concentrate on implementing the core implementations and method interceptors.
+</p>
+
+<h3>(1) Scope of the Package</h3>
+
+<p>
+    The package shall create and maintain a suite of utility classes for creating dynamic proxy objects written in the
+    Java language to be distributed under the ASF license.  The package will include many different "core object
+    provider" implementations supporting many existing remoting technologies (EJB, Hessian, Burlap, JAX-RPC, Apache
+    XML-RPC, RMI, etc.) as well as many other "in-vm" implementations (bean instantiation, cloning, constant, etc.).
+    The package will also provide "decorator object providers" which add functionality to the object providers they wrap
+    such as pooling, singleton, caching, etc.  The package will also serve as a repository for many useful interceptor
+    implementations which support such features as logging, asynchronous invocation, etc.  The package will provide
+    multiple "proxy factory" implementations, supporting different proxying technologies (JDK proxies, CGLIB, Javassist,
+    etc.).
+</p>
+
+<h3>(1.5) Interaction With Other Packages</h3>
+
+<p>
+    <em>Proxy</em> utilizes the JUnit unit testing framework for developing and executing unit tests, but this is of
+    interest only to developers of the component. The original will include support for the Hessian and Burlap remoting
+    protocols.  The original codebase will also include support for CGLIB and Javassist-base proxies.
+</p>
+
+<p>No external configuration files are utilized.</p>
+
+<h3>(2) Initial Source of the Package</h3>
+
+<p>
+    The initial codebase will be contributed by James Carman based on code in the Syringe (http://syringe.dev.java.net)
+    project and can be distributed under the Apache license.
+</p>
+
+<p>The proposed package name for the new component is
+    <code>org.apache.commons.proxy</code>.</p>
+
+
+<h3>(3) Required Jakarta-Commons Resources</h3>
+
+<ul>
+    <li>SVN Repository - New directory <code>proxy</code> in the
+        <code>jakarta-commons</code> SVN repository. All initial committers
+        are already committers on <code>jakarta-commons</code>, so no
+        additional user setups are required.</li>
+    <li>Mailing List - Discussions will take place on the general
+        <em>jakarta-commons@jakarta.apache.org</em> mailing list. To help
+        list subscribers identify messages of interest, it is suggested that
+        the message subject of messages about this component be prefixed with
+        [proxy].</li>
+    <li>Bugzilla - New component "Proxy" under the "Commons" product
+        category, with appropriate version identifiers as needed.</li>
+    <li>Jyve FAQ - New category "commons-proxy" (when available). </li>
+</ul>
+
+
+<h3>(4) Initial Committers</h3>
+<ul>
+    <li>James Carman</li>
+</ul>
+</body>
+</html>
\ No newline at end of file
diff --git a/proxy-1.0-work/RELEASE-NOTES.txt b/proxy-1.0-work/RELEASE-NOTES.txt
new file mode 100644
index 0000000..ef95eb5
--- /dev/null
+++ b/proxy-1.0-work/RELEASE-NOTES.txt
@@ -0,0 +1,27 @@
+	     Apache Commons Proxy Package
+			    Version 1.0
+			   Release Notes
+
+
+INTRODUCTION:
+
+Apache Commons Proxy is a package of utility classes which facilitate the
+creation of dynamic proxies in Java.
+
+NOTES:
+
+*** This is the initial release ***
+
+
+FEEDBACK:
+
+Open source works best when you give feedback:
+http://commons.apache.org/proxy/
+
+Please direct all bug reports to JIRA
+http://issues.apache.org/jira/browse/PROXY
+
+Or subscribe to the commons-user mailing list (please prefix email subject with [proxy])
+http://commons.apache.org/mail-lists.html
+
+The Commons-Proxy Team
\ No newline at end of file
diff --git a/proxy-1.0-work/checkstyle.xml b/proxy-1.0-work/checkstyle.xml
new file mode 100644
index 0000000..078e428
--- /dev/null
+++ b/proxy-1.0-work/checkstyle.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  -->     
+<!DOCTYPE module PUBLIC
+    "-//Puppy Crawl//DTD Check Configuration 1.1//EN"
+    "http://www.puppycrawl.com/dtds/configuration_1_1.dtd">
+
+<!-- commons proxy customization of default Checkstyle behavior -->
+<module name="Checker">
+  <property name="localeLanguage" value="en"/>
+
+  <module name="TreeWalker">
+    <!-- Verify that EVERY source file has the appropriate license -->
+    <module name="Header">
+      <property name="headerFile" value="license-header.txt"/>
+    </module>
+
+    <!-- no tabs allowed in files -->
+    <module name="TabCharacter"/>
+
+    <!-- check sane import statements -->
+    <module name="AvoidStarImport"/>
+    <module name="RedundantImport"/>
+    <module name="UnusedImports"/>
+
+    <module name="LineLength">
+      <property name="max" value="120"/>
+    </module>
+  </module>
+</module>
\ No newline at end of file
diff --git a/proxy-1.0-work/license-header.txt b/proxy-1.0-work/license-header.txt
new file mode 100644
index 0000000..f974c9a
--- /dev/null
+++ b/proxy-1.0-work/license-header.txt
@@ -0,0 +1,16 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
\ No newline at end of file
diff --git a/proxy-1.0-work/pom.xml b/proxy-1.0-work/pom.xml
new file mode 100644
index 0000000..30161b9
--- /dev/null
+++ b/proxy-1.0-work/pom.xml
@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-parent</artifactId>
+        <version>7</version>
+    </parent>
+    <artifactId>commons-proxy</artifactId>
+    <version>1.0-rc1</version>
+    <name>Commons Proxy</name>
+    <description>Java library for dynamic proxying</description>
+    <url>http://commons.apache.org/proxy/</url>
+    <inceptionYear>2005</inceptionYear>
+
+    <issueManagement>
+        <system>JIRA</system>
+        <url>http://issues.apache.org/jira/browse/PROXY</url>
+    </issueManagement>
+
+    <developers>
+        <developer>
+            <id>jcarman</id>
+            <name>James Carman</name>
+            <email>james@carmanconsulting.com</email>
+            <organization>Carman Consulting, Inc.</organization>
+            <roles>
+                <role>admin</role>
+                <role>designer</role>
+                <role>developer</role>
+            </roles>
+            <url>http://www.carmanconsulting.com/</url>
+            <timezone>-5</timezone>
+        </developer>
+        <developer>
+            <id>knut</id>
+            <name>Knut Wannheden</name>
+            <email>knut@apache.org</email>
+            <roles>
+                <role>designer</role>
+                <role>developer</role>
+            </roles>
+            <timezone>+1</timezone>
+        </developer>
+        <developer>
+            <name>J&#246;rg Hohwiller</name>
+            <email>hohwille@users.sourceforge.net</email>
+            <organization/>
+            <roles>
+                <role>mavenizer</role>
+                <role>developer</role>
+            </roles>
+            <url></url>
+        </developer>
+    </developers>
+
+    <contributors>
+        <contributor>
+            <name>J&#246;rg Schaible</name>
+            <email>joerg.schaible@gmx.de</email>
+            <organization/>
+            <roles>
+                <role>advisor</role>
+            </roles>
+            <url></url>
+        </contributor>
+        <contributor>
+            <name>Howard M. Lewis Ship</name>
+            <email>hlship@apache.org</email>
+            <organization/>
+            <roles>
+                <role>advisor</role>
+            </roles>
+            <url>http://www.howardlewisship.com/</url>
+        </contributor>
+    </contributors>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/proxy/trunk/</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/proxy/trunk/</developerConnection>
+        <url>http://svn.apache.org/repos/asf/commons/proper/proxy/trunk/</url>
+    </scm>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>.</directory>
+                <targetPath>META-INF</targetPath>
+                <includes>
+                    <include>NOTICE.txt</include>
+                    <include>LICENSE.txt</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <descriptors>
+                        <descriptor>src/assembly/bin.xml</descriptor>
+                        <descriptor>src/assembly/src.xml</descriptor>
+                    </descriptors>
+                    <tarLongFileMode>gnu</tarLongFileMode>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>cglib</groupId>
+            <artifactId>cglib-nodep</artifactId>
+            <version>2.1_3</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>jboss</groupId>
+            <artifactId>javassist</artifactId>
+            <version>3.0</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>aopalliance</groupId>
+            <artifactId>aopalliance</artifactId>
+            <version>1.0</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>axis</groupId>
+            <artifactId>axis-jaxrpc</artifactId>
+            <version>1.2.1</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>hessian</groupId>
+            <artifactId>hessian</artifactId>
+            <version>3.0.1</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>burlap</groupId>
+            <artifactId>burlap</artifactId>
+            <version>2.1.7</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+            <version>1.0.4</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+            <version>3.1</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>concurrent</groupId>
+            <artifactId>concurrent</artifactId>
+            <version>1.3.4</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>jmock</groupId>
+            <artifactId>jmock</artifactId>
+            <version>1.0.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>xmlrpc</groupId>
+            <artifactId>xmlrpc</artifactId>
+            <version>2.0</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>1.3</version>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <reporting>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-changelog-plugin</artifactId>
+                <version>2.1</version>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <configuration>
+                    <configLocation>checkstyle.xml</configLocation>
+                </configuration>
+            </plugin>
+        </plugins>
+    </reporting>
+
+    <distributionManagement>
+        <site>
+            <id>apache.website</id>
+            <name>Apache Website</name>
+            <url>scp://people.apache.org/www/commons.apache.org/proper/proxy/</url>
+        </site>
+    </distributionManagement>
+
+</project>
diff --git a/proxy-1.0-work/src/assembly/bin.xml b/proxy-1.0-work/src/assembly/bin.xml
new file mode 100644
index 0000000..5762291
--- /dev/null
+++ b/proxy-1.0-work/src/assembly/bin.xml
@@ -0,0 +1,44 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<assembly>
+    <id>bin</id>
+    <formats>
+        <format>tar.gz</format>
+        <format>zip</format>
+    </formats>
+    <includeSiteDirectory>false</includeSiteDirectory>
+    <fileSets>
+        <fileSet>
+            <includes>
+                <include>LICENSE.txt</include>
+                <include>NOTICE.txt</include>
+                <include>RELEASE-NOTES.txt</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>target</directory>
+            <outputDirectory></outputDirectory>
+            <includes>
+                <include>*.jar</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>target/site/apidocs</directory>
+            <outputDirectory>apidocs</outputDirectory>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/proxy-1.0-work/src/assembly/src.xml b/proxy-1.0-work/src/assembly/src.xml
new file mode 100644
index 0000000..0d0ac18
--- /dev/null
+++ b/proxy-1.0-work/src/assembly/src.xml
@@ -0,0 +1,41 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<assembly>
+    <id>src</id>
+    <formats>
+        <format>tar.gz</format>
+        <format>zip</format>
+    </formats>
+    <baseDirectory>${project.artifactId}-${project.version}-src</baseDirectory>
+    <fileSets>
+        <fileSet>
+            <includes>
+                <include>checkstyle.xml</include>
+                <include>LICENSE.txt</include>
+                <include>license-header.txt</include>
+                <include>NOTICE.txt</include>
+                <include>pom.xml</include>
+                <include>PROPOSAL.html</include>
+                <include>RELEASE-NOTES.txt</include>
+                <include>STATUS.html</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>src</directory>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/Interceptor.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/Interceptor.java
new file mode 100644
index 0000000..e899b72
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/Interceptor.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy;
+
+/**
+ * "Intercepts" a method invocation.
+ * 
+ * @author James Carman
+ * @since 1.0
+ */
+public interface Interceptor
+{
+    public Object intercept( Invocation invocation ) throws Throwable;
+}
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/Invocation.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/Invocation.java
new file mode 100644
index 0000000..2ec3ae0
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/Invocation.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy;
+
+import java.lang.reflect.Method;
+
+/**
+ * Represents a method invocation.
+ * 
+ * @author James Carman
+ * @since 1.0
+ */
+public interface Invocation
+{
+    public Method getMethod();
+    public Object[] getArguments();
+    public Object getProxy();
+    public Object proceed() throws Throwable;
+}
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/Invoker.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/Invoker.java
new file mode 100644
index 0000000..75b4a94
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/Invoker.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy;
+
+import java.lang.reflect.Method;
+
+/**
+ * An invoker is responsible for handling a method invocation.
+ * 
+ * @author James Carman
+ * @since 1.0
+ */
+public interface Invoker
+{
+    /**
+     * "Invokes" the method.  Implementation should throw a {@link org.apache.commons.proxy.exception.InvokerException}
+     * if problems arise while trying to invoke the method.
+     * @param proxy the proxy object
+     * @param method the method being invoked
+     * @param arguments the arguments
+     * @return the return value
+     * @throws Throwable thrown by the implementation
+     */
+    public Object invoke( Object proxy, Method method, Object[] arguments ) throws Throwable;
+}
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/ObjectProvider.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/ObjectProvider.java
new file mode 100644
index 0000000..16937bc
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/ObjectProvider.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy;
+
+/**
+ * Provides an object to a delegating proxy.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public interface ObjectProvider
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Other Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Returns an object.  Implementing classes should throw a
+     * {@link org.apache.commons.proxy.exception.ObjectProviderException} if any problems arise while
+     * constructing/finding the object.
+     *
+     * @return the object on which the method should be called
+     */
+    public Object getObject();
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/ProxyFactory.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/ProxyFactory.java
new file mode 100644
index 0000000..15e724a
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/ProxyFactory.java
@@ -0,0 +1,259 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+/**
+ * A <code>ProxyFactory</code> can be used to create three different &quot;flavors&quot; of proxy objects.
+ *
+ * <ul>
+ *   <li>Delegator - the proxy will delegate to an object provided by an {@link ObjectProvider}</li>
+ *   <li>Interceptor - the proxy will pass each method invocation through an {@link Interceptor}</li>
+ *   <li>Invoker - the proxy will allow an {@link Invoker} to handle all method invocations</li>
+ * </ul>
+ *
+ * <p>
+ * Originally, the ProxyFactory class was an interface.  However, to allow for future changes to the
+ * class without breaking binary or semantic compatibility, it has been changed to a concrete class.
+ *
+ * </p>
+ * <p>
+ * <b>Note</b>: This class uses Java reflection.  For more efficient proxies, try using either
+ * {@link org.apache.commons.proxy.factory.cglib.CglibProxyFactory CglibProxyFactory} or
+ * {@link org.apache.commons.proxy.factory.javassist.JavassistProxyFactory JavassistProxyFactory} instead.
+ * </p>
+ * @author James Carman
+ * @since 1.0
+ */
+public class ProxyFactory
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Other Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Returns true if all <code>proxyClasses</code> are interfaces.
+     *
+     * @param proxyClasses the proxy classes
+     * @return true if all <code>proxyClasses</code> are interfaces
+     */
+    public boolean canProxy( Class[] proxyClasses )
+    {
+        for( int i = 0; i < proxyClasses.length; i++ )
+        {
+            Class proxyClass = proxyClasses[i];
+            if( !proxyClass.isInterface() )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Creates a proxy which delegates to the object provided by <code>delegateProvider</code>.  The proxy will be
+     * generated using the current thread's "context class loader."
+     *
+     * @param delegateProvider the delegate provider
+     * @param proxyClasses     the interfaces that the proxy should implement
+     * @return a proxy which delegates to the object provided by the target object provider
+     */
+    public Object createDelegatorProxy( ObjectProvider delegateProvider, Class[] proxyClasses )
+    {
+        return createDelegatorProxy( Thread.currentThread().getContextClassLoader(), delegateProvider, proxyClasses );
+    }
+
+    /**
+     * Creates a proxy which delegates to the object provided by <code>delegateProvider</code>.
+     *
+     * @param classLoader      the class loader to use when generating the proxy
+     * @param delegateProvider the delegate provider
+     * @param proxyClasses     the interfaces that the proxy should implement
+     * @return a proxy which delegates to the object provided by the target <code>delegateProvider>
+     */
+    public Object createDelegatorProxy( ClassLoader classLoader, ObjectProvider delegateProvider,
+                                        Class[] proxyClasses )
+    {
+        return Proxy.newProxyInstance( classLoader, proxyClasses,
+                                       new DelegatorInvocationHandler( delegateProvider ) );
+    }
+
+    /**
+     * Creates a proxy which passes through a {@link Interceptor interceptor} before eventually reaching the
+     * <code>target</code> object.  The proxy will be generated using the current thread's "context class loader."
+     *
+     * @param target       the target object
+     * @param interceptor  the method interceptor
+     * @param proxyClasses the interfaces that the proxy should implement
+     * @return a proxy which passes through a {@link Interceptor interceptor} before eventually reaching the
+     *         <code>target</code> object.
+     */
+    public Object createInterceptorProxy( Object target, Interceptor interceptor,
+                                          Class[] proxyClasses )
+    {
+        return createInterceptorProxy( Thread.currentThread().getContextClassLoader(), target, interceptor,
+                                       proxyClasses );
+    }
+
+    /**
+     * Creates a proxy which passes through a {@link Interceptor interceptor} before eventually reaching the
+     * <code>target</code> object.
+     *
+     * @param classLoader  the class loader to use when generating the proxy
+     * @param target       the target object
+     * @param interceptor  the method interceptor
+     * @param proxyClasses the interfaces that the proxy should implement.
+     * @return a proxy which passes through a {@link Interceptor interceptor} before eventually reaching the
+     *         <code>target</code> object.
+     */
+    public Object createInterceptorProxy( ClassLoader classLoader, Object target, Interceptor interceptor,
+                                          Class[] proxyClasses )
+    {
+        return Proxy
+                .newProxyInstance( classLoader, proxyClasses, new InterceptorInvocationHandler( target, interceptor ) );
+    }
+
+    /**
+     * Creates a proxy which uses the provided {@link Invoker} to handle all method invocations.  The proxy will be
+     * generated using the current thread's "context class loader."
+     *
+     * @param invoker      the invoker
+     * @param proxyClasses the interfaces that the proxy should implement
+     * @return a proxy which uses the provided {@link Invoker} to handle all method invocations
+     */
+    public Object createInvokerProxy( Invoker invoker, Class[] proxyClasses )
+    {
+        return createInvokerProxy( Thread.currentThread().getContextClassLoader(), invoker,
+                                   proxyClasses );
+    }
+
+    /**
+     * Creates a proxy which uses the provided {@link Invoker} to handle all method invocations.
+     *
+     * @param classLoader  the class loader to use when generating the proxy
+     * @param invoker      the invoker
+     * @param proxyClasses the interfaces that the proxy should implement
+     * @return a proxy which uses the provided {@link Invoker} to handle all method invocations
+     */
+    public Object createInvokerProxy( ClassLoader classLoader, Invoker invoker,
+                                      Class[] proxyClasses )
+    {
+        return Proxy.newProxyInstance( classLoader, proxyClasses, new InvokerInvocationHandler( invoker ) );
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Inner Classes
+//----------------------------------------------------------------------------------------------------------------------
+
+    private static class DelegatorInvocationHandler implements InvocationHandler
+    {
+        private final ObjectProvider delegateProvider;
+        protected DelegatorInvocationHandler( ObjectProvider delegateProvider )
+        {
+            this.delegateProvider = delegateProvider;
+        }
+
+        public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
+        {
+            try
+            {
+                return method.invoke( delegateProvider.getObject(), args );
+            }
+            catch( InvocationTargetException e )
+            {
+                throw e.getTargetException();
+            }
+        }
+    }
+
+    private static class InterceptorInvocationHandler implements InvocationHandler
+    {
+        private final Object target;
+        private final Interceptor methodInterceptor;
+        public InterceptorInvocationHandler( Object target, Interceptor methodInterceptor )
+        {
+            this.target = target;
+            this.methodInterceptor = methodInterceptor;
+        }
+
+        public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
+        {
+            final ReflectionInvocation invocation = new ReflectionInvocation( target, method, args );
+            return methodInterceptor.intercept( invocation );
+        }
+    }
+
+    private static class ReflectionInvocation implements Invocation
+    {
+        private final Method method;
+        private final Object[] arguments;
+        private final Object target;
+        public ReflectionInvocation( Object target, Method method, Object[] arguments )
+        {
+            this.method = method;
+            this.arguments = ( arguments == null ? ProxyUtils.EMPTY_ARGUMENTS : arguments );
+            this.target = target;
+        }
+
+        public Object[] getArguments()
+        {
+            return arguments;
+        }
+
+        public Method getMethod()
+        {
+            return method;
+        }
+
+        public Object getProxy()
+        {
+            return target;
+        }
+
+        public Object proceed() throws Throwable
+        {
+            try
+            {
+                return method.invoke( target, arguments );
+            }
+            catch( InvocationTargetException e )
+            {
+                throw e.getTargetException();
+            }
+        }
+    }
+
+    private static class InvokerInvocationHandler implements InvocationHandler
+    {
+        private final Invoker invoker;
+        public InvokerInvocationHandler( Invoker invoker )
+        {
+            this.invoker = invoker;
+        }
+
+        public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
+        {
+            return invoker.invoke( proxy, method, args );
+        }
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/ProxyUtils.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/ProxyUtils.java
new file mode 100644
index 0000000..086d2be
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/ProxyUtils.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy;
+
+import org.apache.commons.proxy.invoker.NullInvoker;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * Provides some helpful proxy utility methods.
+ * 
+ * @author James Carman
+ * @since 1.0
+ */
+public class ProxyUtils
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    public static final Object[] EMPTY_ARGUMENTS = new Object[0];
+    public static final Class[] EMPTY_ARGUMENT_TYPES = new Class[0];
+    private static final Map wrapperClassMap = new HashMap();
+
+//----------------------------------------------------------------------------------------------------------------------
+// Static Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    static
+    {
+        wrapperClassMap.put( Integer.TYPE, Integer.class );
+        wrapperClassMap.put( Character.TYPE, Character.class );
+        wrapperClassMap.put( Boolean.TYPE, Boolean.class );
+        wrapperClassMap.put( Short.TYPE, Short.class );
+        wrapperClassMap.put( Long.TYPE, Long.class );
+        wrapperClassMap.put( Float.TYPE, Float.class );
+        wrapperClassMap.put( Double.TYPE, Double.class );
+        wrapperClassMap.put( Byte.TYPE, Byte.class );
+    }
+    /**
+     * Creates a "null object" which implements the <code>proxyClasses</code>.
+     *
+     * @param proxyFactory the proxy factory to be used to create the proxy object
+     * @param proxyClasses the proxy interfaces
+     * @return a "null object" which implements the <code>proxyClasses</code>.
+     */
+    public static Object createNullObject( ProxyFactory proxyFactory, Class[] proxyClasses )
+    {
+        return proxyFactory.createInvokerProxy( new NullInvoker(), proxyClasses );
+    }
+
+    /**
+     * Creates a "null object" which implements the <code>proxyClasses</code>.
+     *
+     * @param proxyFactory the proxy factory to be used to create the proxy object
+     * @param classLoader  the class loader to be used by the proxy factory to create the proxy object
+     * @param proxyClasses the proxy interfaces
+     * @return a "null object" which implements the <code>proxyClasses</code>.
+     */
+    public static Object createNullObject( ProxyFactory proxyFactory, ClassLoader classLoader, Class[] proxyClasses )
+    {
+        return proxyFactory.createInvokerProxy( classLoader, new NullInvoker(), proxyClasses );
+    }
+
+    /**
+     * <p>Gets an array of {@link Class} objects representing all interfaces implemented by the given class and its
+     * superclasses.</p>
+     * <p/>
+     * <p>The order is determined by looking through each interface in turn as declared in the source file and following
+     * its hierarchy up. Then each superclass is considered in the same way. Later duplicates are ignored, so the order
+     * is maintained.</p>
+     * <p/>
+     * <b>Note</b>: Implementation of this method was "borrowed" from
+     * <a href="http://commons.apache.org/lang/">Apache Commons Lang</a> to avoid a dependency.</p>
+     *
+     * @param cls the class to look up, may be <code>null</code>
+     * @return an array of {@link Class} objects representing all interfaces implemented by the given class and its
+     *         superclasses or <code>null</code> if input class is null.
+     */
+    public static Class[] getAllInterfaces( Class cls )
+    {
+        final List interfaces = getAllInterfacesImpl( cls, new LinkedList() );
+        return interfaces == null ? null : ( Class[] ) interfaces.toArray( new Class[interfaces.size()] );
+    }
+
+    private static List getAllInterfacesImpl( Class cls, List list )
+    {
+        if( cls == null )
+        {
+            return null;
+        }
+        while( cls != null )
+        {
+            Class[] interfaces = cls.getInterfaces();
+            for( int i = 0; i < interfaces.length; i++ )
+            {
+                if( !list.contains( interfaces[i] ) )
+                {
+                    list.add( interfaces[i] );
+                }
+                getAllInterfacesImpl( interfaces[i], list );
+            }
+            cls = cls.getSuperclass();
+        }
+        return list;
+    }
+
+    /**
+     * Returns the class name as you would expect to see it in Java code.
+     * <p/>
+     * <b>Examples:</b> <ul> <li>getJavaClassName( Object[].class ) == "Object[]"</li> <li>getJavaClassName(
+     * Object[][].class ) == "Object[][]"</li> <li>getJavaClassName( Integer.TYPE ) == "int"</li> </p>
+     *
+     * @param clazz the class
+     * @return the class' name as you would expect to see it in Java code
+     */
+    public static String getJavaClassName( Class clazz )
+    {
+        if( clazz.isArray() )
+        {
+            return getJavaClassName( clazz.getComponentType() ) + "[]";
+        }
+        return clazz.getName();
+    }
+
+    /**
+     * Returns the wrapper class for the given primitive type.
+     * @param primitiveType the primitive type
+     * @return the wrapper class
+     */
+    public static Class getWrapperClass( Class primitiveType )
+    {
+        return ( Class )wrapperClassMap.get( primitiveType );
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/exception/InvokerException.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/exception/InvokerException.java
new file mode 100644
index 0000000..0ed4f63
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/exception/InvokerException.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.exception;
+
+/**
+ * To be used by an {@link org.apache.commons.proxy.Invoker} when they encounter an error.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class InvokerException extends RuntimeException
+{
+    public InvokerException()
+    {
+    }
+
+    public InvokerException( String message )
+    {
+        super( message );
+    }
+
+    public InvokerException( Throwable cause )
+    {
+        super( cause );
+    }
+
+    public InvokerException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/exception/ObjectProviderException.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/exception/ObjectProviderException.java
new file mode 100644
index 0000000..7afe7d2
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/exception/ObjectProviderException.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.exception;
+
+/**
+ * {@link org.apache.commons.proxy.ObjectProvider} implementations should throw this exception type to indicate that
+ * there was a problem creating/finding the object.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class ObjectProviderException extends RuntimeException
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public ObjectProviderException()
+    {
+    }
+
+    public ObjectProviderException( String message )
+    {
+        super( message );
+    }
+
+    public ObjectProviderException( Throwable cause )
+    {
+        super( cause );
+    }
+
+    public ObjectProviderException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/exception/ProxyFactoryException.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/exception/ProxyFactoryException.java
new file mode 100644
index 0000000..f6fe5d5
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/exception/ProxyFactoryException.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.exception;
+
+/**
+ * A runtime exception type to be used by {@link org.apache.commons.proxy.ProxyFactory proxy factories} when a problem
+ * occurs.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class ProxyFactoryException extends RuntimeException
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public ProxyFactoryException()
+    {
+    }
+
+    public ProxyFactoryException( String message )
+    {
+        super( message );
+    }
+
+    public ProxyFactoryException( Throwable cause )
+    {
+        super( cause );
+    }
+
+    public ProxyFactoryException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/cglib/CglibProxyFactory.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/cglib/CglibProxyFactory.java
new file mode 100644
index 0000000..65cd3bd
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/cglib/CglibProxyFactory.java
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory.cglib;
+
+import net.sf.cglib.proxy.Callback;
+import net.sf.cglib.proxy.CallbackFilter;
+import net.sf.cglib.proxy.Dispatcher;
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.MethodProxy;
+import net.sf.cglib.proxy.NoOp;
+import org.apache.commons.proxy.Interceptor;
+import org.apache.commons.proxy.Invocation;
+import org.apache.commons.proxy.Invoker;
+import org.apache.commons.proxy.ObjectProvider;
+import org.apache.commons.proxy.factory.util.AbstractSubclassingProxyFactory;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * A <a href="http://cglib.sourceforge.net/">CGLIB</a>-based {@link org.apache.commons.proxy.ProxyFactory}
+ * implementation.
+ * <p/>
+ * <p/>
+ * <b>Dependencies</b>: <ul> <li>CGLIB version 2.0.2 or greater</li> </ul> </p>
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class CglibProxyFactory extends AbstractSubclassingProxyFactory
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private static CallbackFilter callbackFilter = new PublicCallbackFilter();
+
+//----------------------------------------------------------------------------------------------------------------------
+// ProxyFactory Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object createDelegatorProxy( ClassLoader classLoader, ObjectProvider targetProvider,
+                                        Class[] proxyClasses )
+    {
+        final Enhancer enhancer = new Enhancer();
+        enhancer.setClassLoader( classLoader );
+        enhancer.setInterfaces( toInterfaces( proxyClasses ) );
+        enhancer.setSuperclass( getSuperclass( proxyClasses ) );
+        enhancer.setCallbackFilter( callbackFilter );
+        enhancer.setCallbacks( new Callback[]{ new ObjectProviderDispatcher( targetProvider ), NoOp.INSTANCE } );
+        return enhancer.create();
+    }
+
+    public Object createInterceptorProxy( ClassLoader classLoader, Object target, Interceptor interceptor,
+                                          Class[] proxyClasses )
+    {
+        final Enhancer enhancer = new Enhancer();
+        enhancer.setClassLoader( classLoader );
+        enhancer.setInterfaces( toInterfaces( proxyClasses ) );
+        enhancer.setSuperclass( getSuperclass( proxyClasses ) );
+        enhancer.setCallbackFilter( callbackFilter );
+        enhancer.setCallbacks( new Callback[]{ new InterceptorBridge( target, interceptor ), NoOp.INSTANCE } );
+        return enhancer.create();
+    }
+
+    public Object createInvokerProxy( ClassLoader classLoader, Invoker invoker,
+                                      Class[] proxyClasses )
+    {
+        final Enhancer enhancer = new Enhancer();
+        enhancer.setClassLoader( classLoader );
+        enhancer.setInterfaces( toInterfaces( proxyClasses ) );
+        enhancer.setSuperclass( getSuperclass( proxyClasses ) );
+        enhancer.setCallbackFilter( callbackFilter );
+        enhancer.setCallbacks( new Callback[]{ new InvokerBridge( invoker ), NoOp.INSTANCE } );
+        return enhancer.create();
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Inner Classes
+//----------------------------------------------------------------------------------------------------------------------
+
+    private static class PublicCallbackFilter implements CallbackFilter
+    {
+        public int accept( Method method )
+        {
+            return Modifier.isPublic( method.getModifiers() ) ? 0 : 1;
+        }
+    }
+
+    private class InvokerBridge implements net.sf.cglib.proxy.InvocationHandler
+    {
+        private final Invoker original;
+
+        public InvokerBridge( Invoker original )
+        {
+            this.original = original;
+        }
+
+        public Object invoke( Object object, Method method, Object[] objects ) throws Throwable
+        {
+            return original.invoke( object, method, objects );
+        }
+    }
+
+    private class InterceptorBridge implements net.sf.cglib.proxy.MethodInterceptor
+    {
+        private final Interceptor inner;
+        private final Object target;
+
+        public InterceptorBridge( Object target, Interceptor inner )
+        {
+            this.inner = inner;
+            this.target = target;
+        }
+
+        public Object intercept( Object object, Method method, Object[] args, MethodProxy methodProxy ) throws Throwable
+        {
+            return inner.intercept( new MethodProxyInvocation( target, method, args, methodProxy ) );
+        }
+    }
+
+    private class MethodProxyInvocation implements Invocation
+    {
+        private final MethodProxy methodProxy;
+        private final Method method;
+        private final Object[] args;
+        private final Object target;
+
+        public MethodProxyInvocation( Object target, Method method, Object[] args, MethodProxy methodProxy )
+        {
+            this.target = target;
+            this.method = method;
+            this.methodProxy = methodProxy;
+            this.args = args;
+        }
+
+        public Method getMethod()
+        {
+            return method;
+        }
+
+        public Object[] getArguments()
+        {
+            return args;
+        }
+
+        public Object proceed() throws Throwable
+        {
+            return methodProxy.invoke( target, args );
+        }
+
+        public Object getProxy()
+        {
+            return target;
+        }
+    }
+
+    private class ObjectProviderDispatcher implements Dispatcher
+    {
+        private final ObjectProvider delegateProvider;
+
+        public ObjectProviderDispatcher( ObjectProvider delegateProvider )
+        {
+            this.delegateProvider = delegateProvider;
+        }
+
+        public Object loadObject()
+        {
+            return delegateProvider.getObject();
+        }
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/javassist/JavassistInvocation.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/javassist/JavassistInvocation.java
new file mode 100644
index 0000000..6258f67
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/javassist/JavassistInvocation.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory.javassist;
+
+import javassist.CannotCompileException;
+import javassist.CtClass;
+import javassist.CtConstructor;
+import javassist.CtMethod;
+import org.apache.commons.proxy.Invocation;
+import org.apache.commons.proxy.ProxyUtils;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public abstract class JavassistInvocation implements Invocation
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+    private static WeakHashMap loaderToClassCache = new WeakHashMap();
+    protected final Method method;
+    protected final Object target;
+    protected final Object[] arguments;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Static Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    private static String createCastExpression( Class type, String objectToCast )
+    {
+        if( !type.isPrimitive() )
+        {
+            return "( " + ProxyUtils.getJavaClassName( type ) + " )" + objectToCast;
+        }
+        else
+        {
+            return "( ( " + ProxyUtils.getWrapperClass( type ).getName() + " )" + objectToCast + " )." +
+                   type.getName() + "Value()";
+        }
+    }
+
+    private static Class createInvocationClass( ClassLoader classLoader, Method interfaceMethod )
+            throws CannotCompileException
+    {
+        Class invocationClass;
+        final CtClass ctClass = JavassistUtils.createClass(
+                getSimpleName( interfaceMethod.getDeclaringClass() ) + "_" + interfaceMethod.getName() +
+                "_invocation",
+                JavassistInvocation.class );
+        final CtConstructor constructor = new CtConstructor(
+                JavassistUtils.resolve( new Class[]{ Method.class, Object.class, Object[].class } ),
+                ctClass );
+        constructor.setBody( "{\n\tsuper($$);\n}" );
+        ctClass.addConstructor( constructor );
+        final CtMethod proceedMethod = new CtMethod( JavassistUtils.resolve( Object.class ), "proceed",
+                                                     JavassistUtils.resolve( new Class[0] ), ctClass );
+        final Class[] argumentTypes = interfaceMethod.getParameterTypes();
+        final StringBuffer proceedBody = new StringBuffer( "{\n" );
+        if( !Void.TYPE.equals( interfaceMethod.getReturnType() ) )
+        {
+            proceedBody.append( "\treturn " );
+            if( interfaceMethod.getReturnType().isPrimitive() )
+            {
+                proceedBody.append( "new " );
+                proceedBody.append( ProxyUtils.getWrapperClass( interfaceMethod.getReturnType() ).getName() );
+                proceedBody.append( "( " );
+            }
+        }
+        else
+        {
+            proceedBody.append( "\t" );
+        }
+        proceedBody.append( "( (" );
+        proceedBody.append( ProxyUtils.getJavaClassName( interfaceMethod.getDeclaringClass() ) );
+        proceedBody.append( " )target )." );
+        proceedBody.append( interfaceMethod.getName() );
+        proceedBody.append( "(" );
+        for( int i = 0; i < argumentTypes.length; ++i )
+        {
+            final Class argumentType = argumentTypes[i];
+            proceedBody.append( createCastExpression( argumentType, "arguments[" + i + "]" ) );
+            if( i != argumentTypes.length - 1 )
+            {
+                proceedBody.append( ", " );
+            }
+        }
+        if( !Void.TYPE.equals( interfaceMethod.getReturnType() ) && interfaceMethod.getReturnType().isPrimitive() )
+        {
+            proceedBody.append( ") );\n" );
+        }
+        else
+        {
+            proceedBody.append( ");\n" );
+        }
+        if( Void.TYPE.equals( interfaceMethod.getReturnType() ) )
+        {
+            proceedBody.append( "\treturn null;\n" );
+        }
+        proceedBody.append( "}" );
+        final String body = proceedBody.toString();
+        proceedMethod.setBody( body );
+        ctClass.addMethod( proceedMethod );
+        invocationClass = ctClass.toClass( classLoader );
+        return invocationClass;
+    }
+
+    private static Map getClassCache( ClassLoader classLoader )
+    {
+        Map cache = ( Map ) loaderToClassCache.get( classLoader );
+        if( cache == null )
+        {
+            cache = new HashMap();
+            loaderToClassCache.put( classLoader, cache );
+        }
+        return cache;
+    }
+
+    public synchronized static Class getMethodInvocationClass( ClassLoader classLoader,
+                                                               Method interfaceMethod )
+            throws CannotCompileException
+    {
+        final Map classCache = getClassCache( classLoader );
+        final String key = toClassCacheKey( interfaceMethod );
+        final WeakReference invocationClassRef = ( WeakReference ) classCache.get( key );
+        Class invocationClass;
+        if( invocationClassRef == null )
+        {
+            invocationClass = createInvocationClass( classLoader, interfaceMethod );
+            classCache.put( key, new WeakReference( invocationClass ) );
+        }
+        else
+        {
+            synchronized( invocationClassRef )
+            {
+                invocationClass = ( Class ) invocationClassRef.get();
+                if( invocationClass == null )
+                {
+                    invocationClass = createInvocationClass( classLoader, interfaceMethod );
+                    classCache.put( key, new WeakReference( invocationClass ) );
+                }
+            }
+        }
+        return invocationClass;
+    }
+
+    private static String getSimpleName( Class c )
+    {
+        final String name = c.getName();
+        final int ndx = name.lastIndexOf( '.' );
+        return ndx == -1 ? name : name.substring( ndx + 1 );
+    }
+
+    private static String toClassCacheKey( Method method )
+    {
+        return String.valueOf( method );
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public JavassistInvocation( Method method, Object target, Object[] arguments )
+    {
+        this.method = method;
+        this.target = target;
+        this.arguments = arguments;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Invocation Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object[] getArguments()
+    {
+        return arguments;
+    }
+
+    public Method getMethod()
+    {
+        return method;
+    }
+
+    public Object getProxy()
+    {
+        return target;
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/javassist/JavassistProxyFactory.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/javassist/JavassistProxyFactory.java
new file mode 100644
index 0000000..9dc329a
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/javassist/JavassistProxyFactory.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory.javassist;
+
+import javassist.CannotCompileException;
+import javassist.CtClass;
+import javassist.CtConstructor;
+import javassist.CtMethod;
+import org.apache.commons.proxy.Interceptor;
+import org.apache.commons.proxy.Invoker;
+import org.apache.commons.proxy.ObjectProvider;
+import org.apache.commons.proxy.exception.ProxyFactoryException;
+import org.apache.commons.proxy.factory.util.AbstractProxyClassGenerator;
+import org.apache.commons.proxy.factory.util.AbstractSubclassingProxyFactory;
+import org.apache.commons.proxy.factory.util.ProxyClassCache;
+
+import java.lang.reflect.Method;
+
+/**
+ * A <a href="http://www.jboss.org/products/javassist">Javassist</a>-based {@link org.apache.commons.proxy.ProxyFactory}
+ * implementation.
+ * <p/>
+ * <b>Dependencies</b>: <ul> <li>Javassist version 3.0 or greater</li> </ul> </p>
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class JavassistProxyFactory extends AbstractSubclassingProxyFactory
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+    private static final ProxyClassCache delegatingProxyClassCache = new ProxyClassCache(
+            new DelegatingProxyClassGenerator() );
+    private static final ProxyClassCache interceptorProxyClassCache = new ProxyClassCache(
+            new InterceptorProxyClassGenerator() );
+    private static final ProxyClassCache invocationHandlerProxyClassCache = new ProxyClassCache(
+            new InvokerProxyClassGenerator() );
+
+//----------------------------------------------------------------------------------------------------------------------
+// ProxyFactory Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object createDelegatorProxy( ClassLoader classLoader, ObjectProvider targetProvider,
+                                        Class[] proxyClasses )
+    {
+        try
+        {
+            final Class clazz = delegatingProxyClassCache.getProxyClass( classLoader, proxyClasses );
+            return clazz.getConstructor( new Class[]{ ObjectProvider.class } )
+                    .newInstance( new Object[]{ targetProvider } );
+        }
+        catch( Exception e )
+        {
+            throw new ProxyFactoryException( "Unable to instantiate proxy from generated proxy class.", e );
+        }
+    }
+
+    public Object createInterceptorProxy( ClassLoader classLoader, Object target, Interceptor interceptor,
+                                          Class[] proxyClasses )
+    {
+        try
+        {
+            final Class clazz = interceptorProxyClassCache.getProxyClass( classLoader, proxyClasses );
+            final Method[] methods = AbstractProxyClassGenerator.getImplementationMethods( proxyClasses );
+            return clazz.getConstructor( new Class[]{ Method[].class, Object.class, Interceptor.class } )
+                    .newInstance( new Object[]{ methods, target, interceptor } );
+        }
+        catch( Exception e )
+        {
+            throw new ProxyFactoryException( "Unable to instantiate proxy class instance.", e );
+        }
+    }
+
+    public Object createInvokerProxy( ClassLoader classLoader, Invoker invoker,
+                                      Class[] proxyClasses )
+    {
+        try
+        {
+            final Class clazz = invocationHandlerProxyClassCache.getProxyClass( classLoader, proxyClasses );
+            final Method[] methods = AbstractProxyClassGenerator.getImplementationMethods( proxyClasses );
+            return clazz.getConstructor( new Class[]{ Method[].class, Invoker.class } )
+                    .newInstance( new Object[]{ methods, invoker } );
+        }
+        catch( Exception e )
+        {
+            throw new ProxyFactoryException( "Unable to instantiate proxy from generated proxy class.", e );
+        }
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Inner Classes
+//----------------------------------------------------------------------------------------------------------------------
+
+    private static class InvokerProxyClassGenerator extends AbstractProxyClassGenerator
+    {
+        public Class generateProxyClass( ClassLoader classLoader, Class[] proxyClasses )
+        {
+            try
+            {
+                final CtClass proxyClass = JavassistUtils.createClass( getSuperclass( proxyClasses ) );
+                final Method[] methods = getImplementationMethods( proxyClasses );
+                JavassistUtils.addInterfaces( proxyClass, toInterfaces( proxyClasses ) );
+                JavassistUtils.addField( Method[].class, "methods", proxyClass );
+                JavassistUtils.addField( Invoker.class, "invoker", proxyClass );
+                final CtConstructor proxyConstructor = new CtConstructor(
+                        JavassistUtils.resolve(
+                                new Class[]{ Method[].class, Invoker.class } ),
+                        proxyClass );
+                proxyConstructor
+                        .setBody( "{\n\tthis.methods = $1;\n\tthis.invoker = $2; }" );
+                proxyClass.addConstructor( proxyConstructor );
+                for( int i = 0; i < methods.length; ++i )
+                {
+                    final CtMethod method = new CtMethod( JavassistUtils.resolve( methods[i].getReturnType() ),
+                                                          methods[i].getName(),
+                                                          JavassistUtils.resolve( methods[i].getParameterTypes() ),
+                                                          proxyClass );
+                    final String body = "{\n\t return ( $r ) invoker.invoke( this, methods[" + i +
+                                        "], $args );\n }";
+                    method.setBody( body );
+                    proxyClass.addMethod( method );
+                }
+                return proxyClass.toClass( classLoader );
+            }
+            catch( CannotCompileException e )
+            {
+                throw new ProxyFactoryException( "Could not compile class.", e );
+            }
+        }
+    }
+
+    private static class InterceptorProxyClassGenerator extends AbstractProxyClassGenerator
+    {
+        public Class generateProxyClass( ClassLoader classLoader, Class[] proxyClasses )
+        {
+            try
+            {
+                final CtClass proxyClass = JavassistUtils.createClass( getSuperclass( proxyClasses ) );
+                final Method[] methods = getImplementationMethods( proxyClasses );
+                JavassistUtils.addInterfaces( proxyClass, toInterfaces( proxyClasses ) );
+                JavassistUtils.addField( Method[].class, "methods", proxyClass );
+                JavassistUtils.addField( Object.class, "target", proxyClass );
+                JavassistUtils.addField( Interceptor.class, "interceptor", proxyClass );
+                final CtConstructor proxyConstructor = new CtConstructor(
+                        JavassistUtils.resolve(
+                                new Class[]{ Method[].class, Object.class, Interceptor.class } ),
+                        proxyClass );
+                proxyConstructor
+                        .setBody(
+                                "{\n\tthis.methods = $1;\n\tthis.target = $2;\n\tthis.interceptor = $3; }" );
+                proxyClass.addConstructor( proxyConstructor );
+                for( int i = 0; i < methods.length; ++i )
+                {
+                    final CtMethod method = new CtMethod( JavassistUtils.resolve( methods[i].getReturnType() ),
+                                                          methods[i].getName(),
+                                                          JavassistUtils.resolve( methods[i].getParameterTypes() ),
+                                                          proxyClass );
+                    final Class invocationClass = JavassistInvocation
+                            .getMethodInvocationClass( classLoader, methods[i] );
+                    final String body = "{\n\t return ( $r ) interceptor.intercept( new " + invocationClass.getName() +
+                                        "( methods[" + i + "], target, $args ) );\n }";
+                    method.setBody( body );
+                    proxyClass.addMethod( method );
+
+                }
+                return proxyClass.toClass( classLoader );
+            }
+            catch( CannotCompileException e )
+            {
+                throw new ProxyFactoryException( "Could not compile class.", e );
+            }
+        }
+    }
+
+    private static class DelegatingProxyClassGenerator extends AbstractProxyClassGenerator
+    {
+        public Class generateProxyClass( ClassLoader classLoader, Class[] proxyClasses )
+        {
+            try
+            {
+                final CtClass proxyClass = JavassistUtils.createClass( getSuperclass( proxyClasses ) );
+                JavassistUtils.addField( ObjectProvider.class, "provider", proxyClass );
+                final CtConstructor proxyConstructor = new CtConstructor(
+                        JavassistUtils.resolve( new Class[]{ ObjectProvider.class } ),
+                        proxyClass );
+                proxyConstructor.setBody( "{ this.provider = $1; }" );
+                proxyClass.addConstructor( proxyConstructor );
+                JavassistUtils.addInterfaces( proxyClass, toInterfaces( proxyClasses ) );
+                final Method[] methods = getImplementationMethods( proxyClasses );
+                for( int i = 0; i < methods.length; ++i )
+                {
+                    final Method method = methods[i];
+                    final CtMethod ctMethod = new CtMethod( JavassistUtils.resolve( method.getReturnType() ),
+                                                            method.getName(),
+                                                            JavassistUtils.resolve( method.getParameterTypes() ),
+                                                            proxyClass );
+                    final String body = "{ return ( $r ) ( ( " + method.getDeclaringClass().getName() +
+                                        " )provider.getObject() )." +
+                                        method.getName() + "($$); }";
+                    ctMethod.setBody( body );
+                    proxyClass.addMethod( ctMethod );
+
+                }
+                return proxyClass.toClass( classLoader );
+            }
+            catch( CannotCompileException e )
+            {
+                throw new ProxyFactoryException( "Could not compile class.", e );
+            }
+        }
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/javassist/JavassistUtils.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/javassist/JavassistUtils.java
new file mode 100644
index 0000000..b637b98
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/javassist/JavassistUtils.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory.javassist;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.LoaderClassPath;
+import javassist.NotFoundException;
+import org.apache.commons.proxy.ProxyUtils;
+import org.apache.commons.proxy.exception.ObjectProviderException;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class JavassistUtils
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+    public static final String DEFAULT_BASE_NAME = "JavassistUtilsGenerated";
+    private static int classNumber = 0;
+    private static final ClassPool classPool = new ClassPool();
+
+    static
+    {
+        classPool.appendClassPath( new LoaderClassPath( ClassLoader.getSystemClassLoader() ) );
+    }
+
+    private static final Set classLoaders = new HashSet();
+//----------------------------------------------------------------------------------------------------------------------
+// Static Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    public static void addField( Class fieldType, String fieldName, CtClass enclosingClass )
+            throws CannotCompileException
+    {
+        enclosingClass.addField( new CtField( resolve( fieldType ), fieldName, enclosingClass ) );
+    }
+
+    public static CtClass resolve( Class clazz )
+    {
+        synchronized( classLoaders )
+        {
+            try
+            {
+                final ClassLoader loader = clazz.getClassLoader();
+                if( loader != null && !classLoaders.contains( loader ) )
+                {
+                    classLoaders.add( loader );
+                    classPool.appendClassPath( new LoaderClassPath( loader ) );
+                }
+                return classPool.get( ProxyUtils.getJavaClassName( clazz ) );
+            }
+            catch( NotFoundException e )
+            {
+                throw new ObjectProviderException(
+                        "Unable to find class " + clazz.getName() + " in default Javassist class pool.", e );
+            }
+        }
+    }
+
+    public static void addInterfaces( CtClass ctClass, Class[] proxyClasses )
+    {
+        for( int i = 0; i < proxyClasses.length; i++ )
+        {
+            Class proxyInterface = proxyClasses[i];
+            ctClass.addInterface( resolve( proxyInterface ) );
+        }
+    }
+
+    public static CtClass createClass( Class superclass )
+    {
+        return createClass( DEFAULT_BASE_NAME, superclass );
+    }
+
+    public synchronized static CtClass createClass( String baseName, Class superclass )
+    {
+        return classPool.makeClass( baseName + "_" + classNumber++, resolve( superclass ) );
+    }
+
+    public static CtClass[] resolve( Class[] classes )
+    {
+        final CtClass[] ctClasses = new CtClass[classes.length];
+        for( int i = 0; i < ctClasses.length; ++i )
+        {
+            ctClasses[i] = resolve( classes[i] );
+        }
+        return ctClasses;
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/AbstractProxyClassGenerator.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/AbstractProxyClassGenerator.java
new file mode 100644
index 0000000..b1edcc1
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/AbstractProxyClassGenerator.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory.util;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A useful superclass for {@link ProxyClassGenerator} implementations.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public abstract class AbstractProxyClassGenerator implements ProxyClassGenerator
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Static Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Returns all methods that a proxy class must implement from the proxy interfaces.  This method makes sure there
+     * are no method signature clashes. For methods with the same signature (name and parameter types), the one
+     * encountered first will be returned in the result. Final methods are also excluded from the result.
+     *
+     * @param proxyClasses the interfaces the proxy class must implement
+     * @return all methods that the proxy class must implement
+     */
+    public static Method[] getImplementationMethods( Class[] proxyClasses )
+    {
+        final Map signatureMethodMap = new HashMap();
+        final Set finalizedSignatures = new HashSet();
+        for( int i = 0; i < proxyClasses.length; i++ )
+        {
+            Class proxyInterface = proxyClasses[i];
+            final Method[] methods = proxyInterface.getMethods();
+            for( int j = 0; j < methods.length; j++ )
+            {
+                final MethodSignature signature = new MethodSignature( methods[j] );
+                if( Modifier.isFinal( methods[j].getModifiers() ) )
+                {
+                    finalizedSignatures.add( signature );
+                }
+                else if( !signatureMethodMap.containsKey( signature ) )
+                {
+                    signatureMethodMap.put( signature, methods[j] );
+                }
+            }
+        }
+        final Collection resultingMethods = signatureMethodMap.values();
+        for( Iterator i = finalizedSignatures.iterator(); i.hasNext(); )
+        {
+            MethodSignature signature = ( MethodSignature ) i.next();
+            resultingMethods.remove( signatureMethodMap.get( signature ) );
+        }
+        return ( Method[] ) resultingMethods.toArray( new Method[resultingMethods.size()] );
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/AbstractSubclassingProxyFactory.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/AbstractSubclassingProxyFactory.java
new file mode 100644
index 0000000..8b4a98a
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/AbstractSubclassingProxyFactory.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory.util;
+
+import org.apache.commons.proxy.ProxyFactory;
+import org.apache.commons.proxy.exception.ProxyFactoryException;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public abstract class AbstractSubclassingProxyFactory extends ProxyFactory
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Static Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    private static boolean hasSuitableDefaultConstructor( Class superclass )
+    {
+        final Constructor[] declaredConstructors = superclass.getDeclaredConstructors();
+        for( int i = 0; i < declaredConstructors.length; i++ )
+        {
+            Constructor constructor = declaredConstructors[i];
+            if( constructor.getParameterTypes().length == 0 && ( Modifier.isPublic( constructor.getModifiers() ) ||
+                                                                 Modifier.isProtected( constructor.getModifiers() ) ) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns the <code>proxyClasses</code> transformed into an array of only the interface classes.
+     *
+     * @param proxyClasses the proxy classes
+     * @return the <code>proxyClasses</code> transformed into an array of only the interface classes
+     */
+    protected static Class[] toInterfaces( Class[] proxyClasses )
+    {
+        final Collection interfaces = new LinkedList();
+        for( int i = 0; i < proxyClasses.length; i++ )
+        {
+            Class proxyInterface = proxyClasses[i];
+            if( proxyInterface.isInterface() )
+            {
+                interfaces.add( proxyInterface );
+            }
+        }
+        return ( Class[] ) interfaces.toArray( new Class[interfaces.size()] );
+    }
+
+    private static Class[] toNonInterfaces( Class[] proxyClasses )
+    {
+        final List superclasses = new LinkedList();
+        for( int i = 0; i < proxyClasses.length; i++ )
+        {
+            Class proxyClass = proxyClasses[i];
+            if( !proxyClass.isInterface() )
+            {
+                superclasses.add( proxyClass );
+            }
+        }
+        return ( Class[] ) superclasses.toArray( new Class[superclasses.size()] );
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Other Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Returns true if a suitable superclass can be found, given the desired <code>proxyClasses</code>.
+     *
+     * @param proxyClasses the proxy classes
+     * @return true if a suitable superclass can be found, given the desired <code>proxyClasses</code>
+     */
+    public boolean canProxy( Class[] proxyClasses )
+    {
+        try
+        {
+            getSuperclass( proxyClasses );
+            return true;
+        }
+        catch( ProxyFactoryException e )
+        {
+            return false;
+        }
+    }
+
+    /**
+     * Returns either {@link Object} if all of the <code>proxyClasses</code> are interfaces or the single non-interface
+     * class from <code>proxyClasses</code>.
+     *
+     * @param proxyClasses the proxy classes
+     * @return either {@link Object} if all of the <code>proxyClasses</code> are interfaces or the single non-interface
+     *         class from <code>proxyClasses</code>
+     * @throws ProxyFactoryException if multiple non-interface classes are contained in <code>proxyClasses</code> or any
+     *                               of the non-interface classes are final
+     */
+    public static Class getSuperclass( Class[] proxyClasses )
+    {
+        final Class[] superclasses = toNonInterfaces( proxyClasses );
+        switch( superclasses.length )
+        {
+            case 0:
+                return Object.class;
+            case 1:
+                final Class superclass = superclasses[0];
+                if( Modifier.isFinal( superclass.getModifiers() ) )
+                {
+                    throw new ProxyFactoryException(
+                            "Proxy class cannot extend " + superclass.getName() + " as it is final." );
+                }
+                if( !hasSuitableDefaultConstructor( superclass ) )
+                {
+                    throw new ProxyFactoryException( "Proxy class cannot extend " + superclass.getName() +
+                                                     ", because it has no visible \"default\" constructor." );
+                }
+                return superclass;
+            default:
+                final StringBuffer errorMessage = new StringBuffer( "Proxy class cannot extend " );
+                for( int i = 0; i < superclasses.length; i++ )
+                {
+                    Class c = superclasses[i];
+                    errorMessage.append( c.getName() );
+                    if( i != superclasses.length - 1 )
+                    {
+                        errorMessage.append( ", " );
+                    }
+                }
+                errorMessage.append( "; multiple inheritance not allowed." );
+                throw new ProxyFactoryException( errorMessage.toString() );
+        }
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/MethodSignature.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/MethodSignature.java
new file mode 100644
index 0000000..05b5b65
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/MethodSignature.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory.util;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class MethodSignature
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private final String name;
+    private final List parameterTypes;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public MethodSignature( Method method )
+    {
+        this.name = method.getName();
+        this.parameterTypes = Arrays.asList( method.getParameterTypes() );
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Canonical Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+        final MethodSignature that = ( MethodSignature ) o;
+        if( !name.equals( that.name ) )
+        {
+            return false;
+        }
+        if( !parameterTypes.equals( that.parameterTypes ) )
+        {
+            return false;
+        }
+        return true;
+    }
+
+    public int hashCode()
+    {
+        int result;
+        result = name.hashCode();
+        result = 29 * result + parameterTypes.hashCode();
+        return result;
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/ProxyClassCache.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/ProxyClassCache.java
new file mode 100644
index 0000000..c9ee4f0
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/ProxyClassCache.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory.util;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class ProxyClassCache
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private final Map loaderToClassCache = new WeakHashMap();
+    private final ProxyClassGenerator proxyClassGenerator;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public ProxyClassCache( ProxyClassGenerator proxyClassGenerator )
+    {
+        this.proxyClassGenerator = proxyClassGenerator;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Other Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    public synchronized Class getProxyClass( ClassLoader classLoader, Class[] proxyClasses )
+    {
+        final Map classCache = getClassCache( classLoader );
+        final String key = toClassCacheKey( proxyClasses );
+        Class proxyClass;
+        WeakReference proxyClassReference = ( WeakReference )classCache.get( key );
+        if( proxyClassReference == null )
+        {
+            proxyClass = proxyClassGenerator.generateProxyClass( classLoader, proxyClasses );
+            classCache.put( key, new WeakReference( proxyClass ) );
+        }
+        else
+        {
+            synchronized( proxyClassReference )
+            {
+                proxyClass = ( Class )proxyClassReference.get();
+                if( proxyClass == null )
+                {
+                    proxyClass = proxyClassGenerator.generateProxyClass( classLoader, proxyClasses );
+                    classCache.put( key, new WeakReference( proxyClass ) );
+                }
+            }
+        }
+        return proxyClass;
+    }
+
+    private Map getClassCache( ClassLoader classLoader )
+    {
+        Map cache = ( Map )loaderToClassCache.get( classLoader );
+        if( cache == null )
+        {
+            cache = new HashMap();
+            loaderToClassCache.put( classLoader, cache );
+        }
+        return cache;
+    }
+
+    private String toClassCacheKey( Class[] proxyClasses )
+    {
+        final StringBuffer sb = new StringBuffer();
+        for( int i = 0; i < proxyClasses.length; i++ )
+        {
+            Class proxyInterface = proxyClasses[i];
+            sb.append( proxyInterface.getName() );
+            if( i != proxyClasses.length - 1 )
+            {
+                sb.append( "," );
+            }
+        }
+        return sb.toString();
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/ProxyClassGenerator.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/ProxyClassGenerator.java
new file mode 100644
index 0000000..75928a6
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/factory/util/ProxyClassGenerator.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory.util;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public interface ProxyClassGenerator
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Other Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Class generateProxyClass( ClassLoader classLoader, Class[] proxyClasses );
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/ExecutorInterceptor.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/ExecutorInterceptor.java
new file mode 100644
index 0000000..0ecf77b
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/ExecutorInterceptor.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor;
+
+import EDU.oswego.cs.dl.util.concurrent.Executor;
+import org.apache.commons.proxy.Invocation;
+import org.apache.commons.proxy.Interceptor;
+
+/**
+ * A method interceptor that uses an {@link Executor} to execute the method invocation.
+ * <p/>
+ * <b>Note</b>: Only <em>void</em> methods can be intercepted using this class!  Any attempts to intercept non-void
+ * methods will result in an {@link IllegalArgumentException}.  If the proxy interfaces include non-void methods, try
+ * using a {@link FilteredInterceptor} along with a
+ * {@link org.apache.commons.proxy.interceptor.filter.ReturnTypeFilter} to wrap an instance of this class.
+ *
+ * <p>
+ * <b>Dependencies</b>:
+ * <ul>
+ *   <li>Concurrent API version 1.3.4 or greater</li>
+ * </ul>
+ * </p>
+ * @author James Carman
+ * @since 1.0
+ */
+public class ExecutorInterceptor implements Interceptor
+{
+    private final Executor executor;
+
+    public ExecutorInterceptor( Executor executor )
+    {
+        this.executor = executor;
+    }
+
+    public Object intercept( final Invocation invocation ) throws Throwable
+    {
+        if( Void.TYPE.equals( invocation.getMethod().getReturnType() ) )
+        {
+            // Special case for finalize() method (should not be run in a different thread)...
+            if( !( invocation.getMethod().getName().equals( "finalize" ) &&
+                   invocation.getMethod().getParameterTypes().length == 0 ) )
+            {
+                executor.execute( new Runnable()
+                {
+                    public void run()
+                    {
+                        try
+                        {
+                            invocation.proceed();
+                        }
+                        catch( Throwable t )
+                        {
+                            // What to do here?  I can't convey the failure back to the caller.
+                        }
+                    }
+                } );
+                return null;
+            }
+            else
+            {
+                return invocation.proceed();
+            }
+        }
+        else
+        {
+            throw new IllegalArgumentException( "Only void methods can be executed in a different thread." );
+        }
+    }
+}
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/FilteredInterceptor.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/FilteredInterceptor.java
new file mode 100644
index 0000000..bf42506
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/FilteredInterceptor.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor;
+
+import org.apache.commons.proxy.Invocation;
+import org.apache.commons.proxy.Interceptor;
+
+/**
+ * Decorates another <code>MethodInterceptor</code> by only calling it if the method is accepted by the supplied
+ * <code>MethodFilter</code>.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class FilteredInterceptor implements Interceptor
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private final Interceptor inner;
+    private final MethodFilter filter;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public FilteredInterceptor( Interceptor inner, MethodFilter filter )
+    {
+        this.inner = inner;
+        this.filter = filter;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// MethodInterceptor Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object intercept( Invocation invocation ) throws Throwable
+    {
+        if( filter.accepts( invocation.getMethod() ) )
+        {
+            return inner.intercept( invocation );
+        }
+        else
+        {
+            return invocation.proceed();
+        }
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/InterceptorChain.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/InterceptorChain.java
new file mode 100644
index 0000000..234f19c
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/InterceptorChain.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor;
+
+import org.apache.commons.proxy.ObjectProvider;
+import org.apache.commons.proxy.ProxyFactory;
+import org.apache.commons.proxy.ProxyUtils;
+import org.apache.commons.proxy.Interceptor;
+
+/**
+ * An <code>InterceptorChain</code> assists with creating proxies which go through a series of
+ * <code>Interceptors</code>.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class InterceptorChain
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+    private final Interceptor[] interceptors;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public InterceptorChain( Interceptor[] interceptors )
+    {
+        this.interceptors = interceptors;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Other Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    private Object createProxy( ProxyFactory proxyFactory, ClassLoader classLoader, Object terminus,
+                                Class[] proxyClasses )
+    {
+        Object currentTarget = terminus;
+        for( int i = interceptors.length - 1; i >= 0; --i )
+        {
+            currentTarget = proxyFactory
+                    .createInterceptorProxy( classLoader, currentTarget, interceptors[i], proxyClasses );
+        }
+        return currentTarget;
+    }
+
+    public ObjectProvider createProxyProvider( ProxyFactory proxyFactory, Object terminus )
+    {
+        return createProxyProvider( proxyFactory, terminus, null );
+    }
+
+    public ObjectProvider createProxyProvider( ProxyFactory proxyFactory, Object terminus, Class[] proxyClasses )
+    {
+        return createProxyProvider( proxyFactory, Thread.currentThread().getContextClassLoader(), terminus,
+                                    proxyClasses );
+    }
+
+    public ObjectProvider createProxyProvider( ProxyFactory proxyFactory, ClassLoader classLoader, Object terminus,
+                                               Class[] proxyClasses )
+    {
+        if( proxyClasses == null || proxyClasses.length == 0 )
+        {
+            proxyClasses = ProxyUtils.getAllInterfaces( terminus.getClass() );
+        }
+        return new ProxyObjectProvider( proxyFactory, classLoader, terminus, proxyClasses );
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Inner Classes
+//----------------------------------------------------------------------------------------------------------------------
+
+    private class ProxyObjectProvider implements ObjectProvider
+    {
+        private final ClassLoader classLoader;
+        private final Class[] proxyClasses;
+        private final Object terminus;
+        private final ProxyFactory proxyFactory;
+
+        public ProxyObjectProvider( ProxyFactory proxyFactory, ClassLoader classLoader, Object terminus,
+                                    Class[] proxyClasses )
+        {
+            this.classLoader = classLoader;
+            this.proxyClasses = proxyClasses;
+            this.terminus = terminus;
+            this.proxyFactory = proxyFactory;
+        }
+
+        public Object getObject()
+        {
+            return createProxy( proxyFactory, classLoader, terminus, proxyClasses );
+        }
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/LoggingInterceptor.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/LoggingInterceptor.java
new file mode 100644
index 0000000..f206a18
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/LoggingInterceptor.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.proxy.ProxyUtils;
+import org.apache.commons.proxy.Interceptor;
+import org.apache.commons.proxy.Invocation;
+
+/**
+ * An interceptor which logs each method invocation.
+ * <b>Note</b>: The implementation of this class was borrowed from
+ * HiveMind's logging interceptor.
+ *
+ * <p>
+ * <b>Dependencies</b>:
+ * <ul>
+ *   <li>Apache Commons Logging version 1.0.4 or greater</li>
+ * </ul>
+ * </p>
+ * @author James Carman
+ * @since 1.0
+ */
+public class LoggingInterceptor implements Interceptor
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private static final int BUFFER_SIZE = 100;
+    private Log log;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public LoggingInterceptor( Log log )
+    {
+        this.log = log;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// MethodInterceptor Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object intercept( Invocation invocation ) throws Throwable
+    {
+        if( log.isDebugEnabled() )
+        {
+            final String methodName = invocation.getMethod().getName();
+            entry( methodName, invocation.getArguments() );
+            try
+            {
+                Object result = invocation.proceed();
+                if( Void.TYPE.equals( invocation.getMethod().getReturnType() ) )
+                {
+                    voidExit( methodName );
+                }
+                else
+                {
+                    exit( methodName, result );
+                }
+                return result;
+            }
+            catch( Throwable t )
+            {
+                exception( methodName, t );
+                throw t;
+            }
+        }
+        else
+        {
+            return invocation.proceed();
+        }
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Other Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    private void entry( String methodName, Object[] args )
+    {
+        StringBuffer buffer = new StringBuffer( BUFFER_SIZE );
+        buffer.append( "BEGIN " );
+        buffer.append( methodName );
+        buffer.append( "(" );
+        int count = args.length;
+        for( int i = 0; i < count; i++ )
+        {
+            Object arg = args[i];
+            if( i > 0 )
+            {
+                buffer.append( ", " );
+            }
+            convert( buffer, arg );
+        }
+        buffer.append( ")" );
+        log.debug( buffer.toString() );
+    }
+
+    private void convert( StringBuffer buffer, Object input )
+    {
+        if( input == null )
+        {
+            buffer.append( "<null>" );
+            return;
+        }
+
+        // Primitive types, and non-object arrays
+        // use toString().  Less than ideal for int[], etc., but
+        // that's a lot of work for a rare case.
+        if( !( input instanceof Object[] ) )
+        {
+            buffer.append( input.toString() );
+            return;
+        }
+        buffer.append( "(" );
+        buffer.append( ProxyUtils.getJavaClassName( input.getClass() ) );
+        buffer.append( "){" );
+        Object[] array = ( Object[] ) input;
+        int count = array.length;
+        for( int i = 0; i < count; i++ )
+        {
+            if( i > 0 )
+            {
+                buffer.append( ", " );
+            }
+
+            // We use convert() again, because it could be a multi-dimensional array
+            // (god help us) where each element must be converted.
+            convert( buffer, array[i] );
+        }
+        buffer.append( "}" );
+    }
+
+    private void exception( String methodName, Throwable t )
+    {
+        StringBuffer buffer = new StringBuffer( BUFFER_SIZE );
+        buffer.append( "EXCEPTION " );
+        buffer.append( methodName );
+        buffer.append( "() -- " );
+        buffer.append( t.getClass().getName() );
+        log.debug( buffer.toString(), t );
+    }
+
+    private void exit( String methodName, Object result )
+    {
+        StringBuffer buffer = new StringBuffer( BUFFER_SIZE );
+        buffer.append( "END " );
+        buffer.append( methodName );
+        buffer.append( "() [" );
+        convert( buffer, result );
+        buffer.append( "]" );
+        log.debug( buffer.toString() );
+    }
+
+    private void voidExit( String methodName )
+    {
+        StringBuffer buffer = new StringBuffer( BUFFER_SIZE );
+        buffer.append( "END " );
+        buffer.append( methodName );
+        buffer.append( "()" );
+        log.debug( buffer.toString() );
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/MethodFilter.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/MethodFilter.java
new file mode 100644
index 0000000..e4837b2
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/MethodFilter.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor;
+
+import java.lang.reflect.Method;
+
+/**
+ * A <code>MethodFilter</code> determines whether or not a method is accepted.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public interface MethodFilter
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Other Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    public boolean accepts( Method method );
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/MethodInterceptorAdapter.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/MethodInterceptorAdapter.java
new file mode 100644
index 0000000..98c417f
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/MethodInterceptorAdapter.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.commons.proxy.Interceptor;
+import org.apache.commons.proxy.Invocation;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Method;
+
+/**
+ * An adapter class to adapt AOP Alliance's {@link MethodInterceptor} interface to Commons Proxy's
+ * {@link Interceptor} interface.
+ *
+ * <p>
+ * <b>Dependencies</b>:
+ * <ul>
+ *   <li>AOP Alliance API version 1.0 or greater</li>
+ * </ul>
+ * </p>
+ * @author James Carman
+ * @since 1.0
+ */
+public class MethodInterceptorAdapter implements Interceptor
+{
+    private final MethodInterceptor methodInterceptor;
+
+    public MethodInterceptorAdapter( MethodInterceptor methodInterceptor )
+    {
+        this.methodInterceptor = methodInterceptor;
+    }
+
+    public Object intercept( Invocation invocation ) throws Throwable
+    {
+        return methodInterceptor.invoke( new MethodInvocationAdapter( invocation ) );
+    }
+
+    private static class MethodInvocationAdapter implements MethodInvocation
+    {
+        private final Invocation invocation;
+
+        public MethodInvocationAdapter( Invocation invocation )
+        {
+            this.invocation = invocation;
+        }
+
+        public Method getMethod()
+        {
+            return invocation.getMethod();
+        }
+
+        public Object[] getArguments()
+        {
+            return invocation.getArguments();
+        }
+
+        public Object proceed() throws Throwable
+        {
+            return invocation.proceed();
+        }
+
+        public Object getThis()
+        {
+            return invocation.getProxy();
+        }
+
+        public AccessibleObject getStaticPart()
+        {
+            return invocation.getMethod();
+        }
+    }
+}
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/SerializingInterceptor.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/SerializingInterceptor.java
new file mode 100644
index 0000000..a113874
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/SerializingInterceptor.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor;
+
+import org.apache.commons.proxy.Interceptor;
+import org.apache.commons.proxy.Invocation;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * An interceptor which makes a serialized copy of all parameters and return values.  This
+ * is useful when testing remote services to ensure that all parameter/return types
+ * are in fact serializable/deserializable.
+ * @since 1.0
+ */
+public class SerializingInterceptor implements Interceptor
+{
+    public Object intercept(Invocation invocation) throws Throwable
+    {
+        Object[] arguments = invocation.getArguments();
+        for (int i = 0; i < arguments.length; i++)
+        {
+            arguments[i] = serializedCopy(arguments[i]);
+        }
+        return serializedCopy(invocation.proceed());
+    }
+
+    private Object serializedCopy(Object original)
+    {
+        try
+        {
+            final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+            final ObjectOutputStream oout = new ObjectOutputStream(bout);
+            oout.writeObject(original);
+            oout.close();
+            bout.close();
+            final ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+            final ObjectInputStream oin = new ObjectInputStream(bin);
+            final Object copy = oin.readObject();
+            oin.close();
+            bin.close();
+            return copy;
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException( "Unable to make serialized copy of " +
+                    original.getClass().getName() + " object.", e );
+        }
+        catch (ClassNotFoundException e)
+        {
+            throw new RuntimeException( "Unable to make serialized copy of " +
+                    original.getClass().getName() + " object.", e );
+        }
+    }
+}
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/filter/PatternFilter.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/filter/PatternFilter.java
new file mode 100644
index 0000000..a78a42f
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/filter/PatternFilter.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor.filter;
+
+import org.apache.commons.proxy.interceptor.MethodFilter;
+
+import java.lang.reflect.Method;
+
+/**
+ * A method filter implementation that returns true if the method's name matches a supplied regular expression (JDK
+ * regex) pattern string.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class PatternFilter implements MethodFilter
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    public static String GETTER_SETTER_PATTERN = "get\\w+|set\\w+";
+    private final String pattern;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Static Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Returns a {@link MethodFilter} which accepts only "getters" and "setters."
+     *
+     * @return a {@link MethodFilter} which accepts only "getters" and "setters."
+     */
+    public static MethodFilter getterSetterFilter()
+    {
+        return new PatternFilter( GETTER_SETTER_PATTERN );
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public PatternFilter( String pattern )
+    {
+        this.pattern = pattern;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// MethodFilter Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public boolean accepts( Method method )
+    {
+        return method.getName().matches( pattern );
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/filter/ReturnTypeFilter.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/filter/ReturnTypeFilter.java
new file mode 100644
index 0000000..79894c7
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/filter/ReturnTypeFilter.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor.filter;
+
+import org.apache.commons.proxy.interceptor.MethodFilter;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Filters methods based on their return type.
+ * @author James Carman
+ * @since 1.0
+ */
+public class ReturnTypeFilter implements MethodFilter
+{
+    private final Set validReturnTypes = new HashSet();
+
+    public ReturnTypeFilter( Class[] validReturnTypes )
+    {
+        this( Arrays.asList( validReturnTypes ) );
+    }
+
+    public ReturnTypeFilter( Collection validReturnTypes )
+    {
+        this.validReturnTypes.addAll( validReturnTypes );
+    }
+
+    public boolean accepts( Method method )
+    {
+        return validReturnTypes.contains( method.getReturnType() );
+    }
+}
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/filter/SimpleFilter.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/filter/SimpleFilter.java
new file mode 100644
index 0000000..a91b0d4
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/interceptor/filter/SimpleFilter.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor.filter;
+
+import org.apache.commons.proxy.interceptor.MethodFilter;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A simple method filter implementation that merely returns true if the method's name is in a set of accepted names.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class SimpleFilter implements MethodFilter
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private final Set methodNames;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public SimpleFilter()
+    {
+        this.methodNames = new HashSet();
+    }
+    
+    public SimpleFilter( String[] methodNames )
+    {
+        this.methodNames = new HashSet( Arrays.asList( methodNames ) );
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// MethodFilter Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public boolean accepts( Method method )
+    {
+        return methodNames.contains( method.getName() );
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java
new file mode 100644
index 0000000..80c9aba
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java
@@ -0,0 +1,94 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one or more

+ * contributor license agreements.  See the NOTICE file distributed with

+ * this work for additional information regarding copyright ownership.

+ * The ASF licenses this file to You 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 org.apache.commons.proxy.invoker;

+

+import org.apache.commons.proxy.Invoker;

+import org.apache.commons.proxy.ObjectProvider;

+

+import java.lang.reflect.Method;

+

+/**

+ * An invoker which supports <a href="http://en.wikipedia.org/wiki/Duck_typing">&quot;duck typing&quot;</a>, meaning

+ * that it finds a matching method on the object returned from the target provider and invokes it.  This class is

+ * useful for adapting an existing class to an interface it does not implement.

+ * <p>

+ * <b>Example:</b>

+ * </p>

+ * <p>

+ * <pre>

+ * public class LegacyDuck // Does not implement interface!

+ * {

+ *   public void quack()

+ *   {

+ *     // Quacking logic...

+ *   }

+ * }

+ * <p/>

+ * public interface Duck

+ * {

+ *   public void quack();

+ * }

+ * <p/>

+ * ObjectProvider targetProvider = new ConstantProvider(new LegacyDuck()); // Always returns a "legacy" duck

+ * DuckTypingInvoker invoker = new DuckTypingInvoker(targetProvider);

+ * Duck duck = ( Duck )proxyFactory.createInvokerProxy( invoker, new Class[] { Duck.class } );

+ * </pre>

+ * </p>

+ */

+public class DuckTypingInvoker implements Invoker

+{

+//----------------------------------------------------------------------------------------------------------------------

+// Fields

+//----------------------------------------------------------------------------------------------------------------------

+

+    private final ObjectProvider targetProvider;

+

+//----------------------------------------------------------------------------------------------------------------------

+// Constructors

+//----------------------------------------------------------------------------------------------------------------------

+

+    public DuckTypingInvoker( final ObjectProvider targetProvider )

+    {

+        this.targetProvider = targetProvider;

+    }

+

+//----------------------------------------------------------------------------------------------------------------------

+// Interface Invoker

+//----------------------------------------------------------------------------------------------------------------------

+

+    public Object invoke( final Object proxy, final Method method, final Object[] arguments ) throws Throwable

+    {

+        final Object target = targetProvider.getObject();

+        final Class targetClass = target.getClass();

+        try

+        {

+            final Method targetMethod = targetClass.getMethod( method.getName(), method.getParameterTypes() );

+            if ( method.getReturnType().isAssignableFrom( targetMethod.getReturnType() ) )

+            {

+                return targetMethod.invoke( target, arguments );

+            }

+            throw new UnsupportedOperationException(

+                    "Target type " + targetClass.getName() + " method has incompatible return type." );

+        }

+        catch ( NoSuchMethodException e )

+        {

+            throw new UnsupportedOperationException(

+                    "Target type " + targetClass.getName() + " does not have a method matching " + method + "." );

+        }

+    }

+}

diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/invoker/InvocationHandlerAdapter.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/invoker/InvocationHandlerAdapter.java
new file mode 100644
index 0000000..4ae9b56
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/invoker/InvocationHandlerAdapter.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.invoker;
+
+import org.apache.commons.proxy.Invoker;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationHandler;
+
+/**
+ * An adapter class to adapt the JDK's {@link InvocationHandler} interface to Commons Proxy's
+ * {@link Invoker} interface.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class InvocationHandlerAdapter implements Invoker
+{
+    private final InvocationHandler invocationHandler;
+
+    public InvocationHandlerAdapter( InvocationHandler invocationHandler )
+    {
+        this.invocationHandler = invocationHandler;
+    }
+
+    public Object invoke( Object proxy, Method method, Object[] arguments ) throws Throwable
+    {
+        return invocationHandler.invoke( proxy, method, arguments );
+    }
+}
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/invoker/NullInvoker.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/invoker/NullInvoker.java
new file mode 100644
index 0000000..6bb032b
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/invoker/NullInvoker.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.invoker;
+
+import org.apache.commons.proxy.Invoker;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * An {@link Invoker} implementation which merely returns null for all method invocations.  This class is
+ * useful for scenarios where the "null object" design pattern is needed.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class NullInvoker implements Invoker
+{
+    private static Map primitiveValueMap = new HashMap();
+    static
+    {
+        primitiveValueMap.put( Integer.TYPE, new Integer( 0 ) );
+        primitiveValueMap.put( Long.TYPE, new Long( 0 ) );
+        primitiveValueMap.put( Short.TYPE, new Short( ( short )0 ) );
+        primitiveValueMap.put( Byte.TYPE, new Byte( ( byte )0 ) );
+        primitiveValueMap.put( Float.TYPE, new Float( 0.0f ) );
+        primitiveValueMap.put( Double.TYPE, new Double( 0.0 ) );
+        primitiveValueMap.put( Character.TYPE, new Character( ( char )0 ) );
+        primitiveValueMap.put( Boolean.TYPE, Boolean.FALSE );
+    }
+//----------------------------------------------------------------------------------------------------------------------
+// InvocationHandler Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
+    {
+        final Class returnType = method.getReturnType();
+        if( returnType.isPrimitive() )
+        {
+            return primitiveValueMap.get( returnType );
+        }
+        else
+        {
+            return null;
+        }
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/invoker/XmlRpcInvoker.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/invoker/XmlRpcInvoker.java
new file mode 100644
index 0000000..c0e0b70
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/invoker/XmlRpcInvoker.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.invoker;
+
+import org.apache.commons.proxy.Invoker;
+import org.apache.commons.proxy.exception.InvokerException;
+import org.apache.xmlrpc.XmlRpcException;
+import org.apache.xmlrpc.XmlRpcHandler;
+
+import java.lang.reflect.Method;
+import java.util.Vector;
+
+/**
+ * Uses <a href="http://ws.apache.org/xmlrpc/">Apache XML-RPC</a> to invoke methods on an XML-RPC service.
+ *
+ * <p>
+ * <b>Dependencies</b>:
+ * <ul>
+ *   <li>Apache XML-RPC version 2.0 or greater</li>
+ * </ul>
+ * </p>
+ * @author James Carman
+ * @since 1.0
+ */
+public class XmlRpcInvoker implements Invoker
+{
+    private final XmlRpcHandler handler;
+    private final String handlerName;
+
+    public XmlRpcInvoker( XmlRpcHandler handler, String handlerName )
+    {
+        this.handler = handler;
+        this.handlerName = handlerName;
+    }
+
+    public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
+    {
+        final Object returnValue = handler.execute( handlerName + "." + method.getName(), toArgumentVector( args ) );
+        if( returnValue instanceof XmlRpcException )
+        {
+            throw new InvokerException( "Unable to execute XML-RPC call.", ( XmlRpcException )returnValue );
+
+        }
+        return returnValue;
+    }
+
+    private Vector toArgumentVector( Object[] args )
+    {
+        final Vector v = new Vector();
+        for( int i = 0; i < args.length; i++ )
+        {
+            Object arg = args[i];
+            v.addElement( arg );
+        }
+        return v;
+    }
+}
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/BeanProvider.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/BeanProvider.java
new file mode 100644
index 0000000..6909ebf
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/BeanProvider.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider;
+
+import org.apache.commons.proxy.ObjectProvider;
+import org.apache.commons.proxy.exception.ObjectProviderException;
+
+/**
+ * Uses <code>Class.newInstance()</code> to instantiate an object.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class BeanProvider implements ObjectProvider
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private Class beanClass;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public BeanProvider()
+    {
+    }
+
+    public BeanProvider( Class beanClass )
+    {
+        this.beanClass = beanClass;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// ObjectProvider Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object getObject()
+    {
+        try
+        {
+            if( beanClass == null )
+            {
+                throw new ObjectProviderException( "No bean class provided." );
+            }
+            return beanClass.newInstance();
+        }
+        catch( InstantiationException e )
+        {
+            throw new ObjectProviderException( "Class " + beanClass.getName() + " is not concrete.", e );
+        }
+        catch( IllegalAccessException e )
+        {
+            throw new ObjectProviderException( "Constructor for class " + beanClass.getName() + " is not accessible.",
+                                               e );
+        }
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Getter/Setter Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    public void setBeanClass( Class beanClass )
+    {
+        this.beanClass = beanClass;
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/CloningProvider.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/CloningProvider.java
new file mode 100644
index 0000000..3a104de
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/CloningProvider.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider;
+
+import org.apache.commons.proxy.ObjectProvider;
+import org.apache.commons.proxy.ProxyUtils;
+import org.apache.commons.proxy.exception.ObjectProviderException;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Merely calls <code>clone()</code> (reflectively) on the given {@link Cloneable} object.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class CloningProvider implements ObjectProvider
+{
+    private final Cloneable cloneable;
+    private Method cloneMethod;
+
+    public CloningProvider( Cloneable cloneable )
+    {
+        this.cloneable = cloneable;
+    }
+
+    private synchronized Method getCloneMethod()
+    {
+        if( cloneMethod == null )
+        {
+            try
+            {
+                cloneMethod = cloneable.getClass().getMethod( "clone", ProxyUtils.EMPTY_ARGUMENT_TYPES );
+            }
+            catch( NoSuchMethodException e )
+            {
+                throw new ObjectProviderException(
+                        "Class " + cloneable.getClass().getName() + " does not have a public clone() method." );
+            }
+        }
+        return cloneMethod;
+    }
+
+    public Object getObject()
+    {
+        try
+        {
+            return getCloneMethod().invoke( cloneable, ProxyUtils.EMPTY_ARGUMENTS );
+        }
+        catch( IllegalAccessException e )
+        {
+            throw new ObjectProviderException(
+                    "Class " + cloneable.getClass().getName() + " does not have a public clone() method.", e );
+        }
+        catch( InvocationTargetException e )
+        {
+            throw new ObjectProviderException(
+                    "Attempt to clone object of type " + cloneable.getClass().getName() + " threw an exception.", e );
+        }
+    }
+
+}
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/ConstantProvider.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/ConstantProvider.java
new file mode 100644
index 0000000..d2bf0d6
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/ConstantProvider.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider;
+
+import org.apache.commons.proxy.ObjectProvider;
+
+/**
+ * Always returns the same object.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class ConstantProvider implements ObjectProvider
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private final Object constant;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public ConstantProvider( Object constant )
+    {
+        this.constant = constant;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// ObjectProvider Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object getObject()
+    {
+        return constant;
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/NullProvider.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/NullProvider.java
new file mode 100644
index 0000000..83d7b80
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/NullProvider.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider;
+
+/**
+ * Always returns null.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class NullProvider extends ConstantProvider
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public NullProvider()
+    {
+        super( null );
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/ProviderDecorator.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/ProviderDecorator.java
new file mode 100644
index 0000000..ef4bd6f
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/ProviderDecorator.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider;
+
+import org.apache.commons.proxy.ObjectProvider;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class ProviderDecorator implements ObjectProvider
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    protected ObjectProvider inner;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public ProviderDecorator( ObjectProvider inner )
+    {
+        this.inner = inner;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// ObjectProvider Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object getObject()
+    {
+        return inner.getObject();
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/SingletonProvider.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/SingletonProvider.java
new file mode 100644
index 0000000..f65306f
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/SingletonProvider.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider;
+
+import org.apache.commons.proxy.ObjectProvider;
+
+/**
+ * Wraps another object provider, making sure to only call it once, returning the value returned from the wrapped
+ * provider on all subsequent invocations.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class SingletonProvider extends ProviderDecorator
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private Object instance;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public SingletonProvider( ObjectProvider inner )
+    {
+        super( inner );
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// ObjectProvider Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object getObject()
+    {
+        synchronized( this )
+        {
+            if( instance == null )
+            {
+                instance = super.getObject();
+                inner = null; // Garbage collection
+            }
+        }
+        return instance;
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/BurlapProvider.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/BurlapProvider.java
new file mode 100644
index 0000000..1558d1b
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/BurlapProvider.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider.remoting;
+
+import com.caucho.burlap.client.BurlapProxyFactory;
+import org.apache.commons.proxy.ObjectProvider;
+import org.apache.commons.proxy.exception.ObjectProviderException;
+
+import java.net.MalformedURLException;
+
+/**
+ * Provides a burlap service object.
+ *
+ * <p>
+ * <b>Dependencies</b>:
+ * <ul>
+ *   <li>Burlap version 2.1.7 or greater</li>
+ * </ul>
+ * </p>
+ * @author James Carman
+ * @since 1.0
+ */
+public class BurlapProvider implements ObjectProvider
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private Class serviceInterface;
+    private String url;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public BurlapProvider()
+    {
+    }
+
+    public BurlapProvider( Class serviceInterface, String url )
+    {
+        this.serviceInterface = serviceInterface;
+        this.url = url;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// ObjectProvider Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object getObject()
+    {
+        try
+        {
+            return new BurlapProxyFactory().create( serviceInterface, url );
+        }
+        catch( MalformedURLException e )
+        {
+            throw new ObjectProviderException( "Invalid url given.", e );
+        }
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Getter/Setter Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    public void setServiceInterface( Class serviceInterface )
+    {
+        this.serviceInterface = serviceInterface;
+    }
+
+    public void setUrl( String url )
+    {
+        this.url = url;
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/HessianProvider.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/HessianProvider.java
new file mode 100644
index 0000000..608aa09
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/HessianProvider.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider.remoting;
+
+import com.caucho.hessian.client.HessianProxyFactory;
+import org.apache.commons.proxy.ObjectProvider;
+import org.apache.commons.proxy.exception.ObjectProviderException;
+
+import java.net.MalformedURLException;
+
+/**
+ * Provides a hessian service object.
+ *
+ * <p>
+ * <b>Dependencies</b>:
+ * <ul>
+ *   <li>Hessian version 3.0.1 or greater</li>
+ * </ul>
+ * </p>
+ * @author James Carman
+ * @since 1.0
+ */
+public class HessianProvider implements ObjectProvider
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private Class serviceInterface;
+    private String url;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public HessianProvider()
+    {
+    }
+
+    public HessianProvider( Class serviceInterface, String url )
+    {
+        this.serviceInterface = serviceInterface;
+        this.url = url;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// ObjectProvider Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object getObject()
+    {
+        try
+        {
+            return new HessianProxyFactory().create( serviceInterface, url );
+        }
+        catch( MalformedURLException e )
+        {
+            throw new ObjectProviderException( "Invalid url given.", e );
+        }
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Getter/Setter Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    public void setServiceInterface( Class serviceInterface )
+    {
+        this.serviceInterface = serviceInterface;
+    }
+
+    public void setUrl( String url )
+    {
+        this.url = url;
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/JaxRpcProvider.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/JaxRpcProvider.java
new file mode 100644
index 0000000..c946f87
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/JaxRpcProvider.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider.remoting;
+
+import org.apache.commons.proxy.ObjectProvider;
+import org.apache.commons.proxy.exception.ObjectProviderException;
+
+import javax.xml.namespace.QName;
+import javax.xml.rpc.Service;
+import javax.xml.rpc.ServiceException;
+import javax.xml.rpc.ServiceFactory;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Returns a proxy for a JAX-RPC-based service.
+ *
+ * <p>
+ * <b>Dependencies</b>:
+ * <ul>
+ *   <li>A JAX-RPC implementation</li>
+ * </ul>
+ * </p>
+ * @author James Carman
+ * @since 1.0
+ */
+public class JaxRpcProvider implements ObjectProvider
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private Class serviceInterface;
+    private String wsdlUrl;
+    private String serviceNamespaceUri;
+    private String serviceLocalPart;
+    private String servicePrefix;
+    private String portNamespaceUri;
+    private String portLocalPart;
+    private String portPrefix;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public JaxRpcProvider()
+    {
+    }
+
+    public JaxRpcProvider( Class serviceInterface )
+    {
+        this.serviceInterface = serviceInterface;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// ObjectProvider Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object getObject()
+    {
+        try
+        {
+            final Service service = ( wsdlUrl == null ?
+                                      ServiceFactory.newInstance().createService( getServiceQName() ) : ServiceFactory
+                    .newInstance().createService( new URL( wsdlUrl ), getServiceQName() ) );
+            final QName portQName = getPortQName();
+            return portQName == null ? service.getPort( serviceInterface ) :
+                   service.getPort( portQName, serviceInterface );
+        }
+        catch( ServiceException e )
+        {
+            throw new ObjectProviderException( "Unable to create JAX-RPC service proxy.", e );
+        }
+        catch( MalformedURLException e )
+        {
+            throw new ObjectProviderException( "Invalid URL given.", e );
+        }
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Getter/Setter Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    public void setPortLocalPart( String portLocalPart )
+    {
+        this.portLocalPart = portLocalPart;
+    }
+
+    public void setPortNamespaceUri( String portNamespaceUri )
+    {
+        this.portNamespaceUri = portNamespaceUri;
+    }
+
+    public void setPortPrefix( String portPrefix )
+    {
+        this.portPrefix = portPrefix;
+    }
+
+    public void setServiceInterface( Class serviceInterface )
+    {
+        this.serviceInterface = serviceInterface;
+    }
+
+    public void setServiceLocalPart( String serviceLocalPart )
+    {
+        this.serviceLocalPart = serviceLocalPart;
+    }
+
+    public void setServiceNamespaceUri( String serviceNamespaceUri )
+    {
+        this.serviceNamespaceUri = serviceNamespaceUri;
+    }
+
+    public void setServicePrefix( String servicePrefix )
+    {
+        this.servicePrefix = servicePrefix;
+    }
+
+    public void setWsdlUrl( String wsdlUrl )
+    {
+        this.wsdlUrl = wsdlUrl;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Other Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    private QName getPortQName()
+    {
+        return getQName( portNamespaceUri, portLocalPart, portPrefix );
+    }
+
+    private QName getQName( String namespaceUri, String localPart, String prefix )
+    {
+        if( namespaceUri != null && localPart != null && prefix != null )
+        {
+            return new QName( namespaceUri, localPart, prefix );
+        }
+        else if( namespaceUri != null && localPart != null )
+        {
+            return new QName( namespaceUri, localPart );
+        }
+        else if( localPart != null )
+        {
+            return new QName( localPart );
+        }
+        return null;
+    }
+
+    private QName getServiceQName()
+    {
+        return getQName( serviceNamespaceUri, serviceLocalPart, servicePrefix );
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/RmiProvider.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/RmiProvider.java
new file mode 100644
index 0000000..9320df3
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/RmiProvider.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider.remoting;
+
+import org.apache.commons.proxy.ObjectProvider;
+import org.apache.commons.proxy.exception.ObjectProviderException;
+
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.RMIClientSocketFactory;
+
+/**
+ * Provides an object by looking it up in an RMI registry.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class RmiProvider implements ObjectProvider
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private String host = "localhost";
+    private int port = Registry.REGISTRY_PORT;
+    private RMIClientSocketFactory clientSocketFactory;
+    private String name;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public RmiProvider()
+    {
+    }
+
+    public RmiProvider( String name )
+    {
+        setName( name );
+    }
+
+    public RmiProvider( String host, String name )
+    {
+        setHost( host );
+        setName( name );
+    }
+
+    public RmiProvider( String host, int port, String name )
+    {
+        setHost( host );
+        setName( name );
+        setPort( port );
+    }
+
+    public RmiProvider( String host, int port, RMIClientSocketFactory clientSocketFactory, String name )
+    {
+        setHost( host );
+        setPort( port );
+        setClientSocketFactory( clientSocketFactory );
+        setName( name );
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// ObjectProvider Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object getObject()
+    {
+        Registry reg = null;
+        try
+        {
+            reg = getRegistry();
+            return reg.lookup( name );
+        }
+        catch( NotBoundException e )
+        {
+            throw new ObjectProviderException( "Name " + name + " not found in registry at " + host + ":" + port + ".",
+                                               e );
+        }
+        catch( RemoteException e )
+        {
+            throw new ObjectProviderException(
+                    "Unable to lookup service named " + name + " in registry at " + host + ":" + port + ".", e );
+        }
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Getter/Setter Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    public void setClientSocketFactory( RMIClientSocketFactory clientSocketFactory )
+    {
+        this.clientSocketFactory = clientSocketFactory;
+    }
+
+    public void setHost( String host )
+    {
+        this.host = host;
+    }
+
+    public void setPort( int port )
+    {
+        this.port = port;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Other Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    private Registry getRegistry()
+    {
+        try
+        {
+            if( clientSocketFactory != null )
+            {
+                return LocateRegistry.getRegistry( host, port, clientSocketFactory );
+            }
+            else
+            {
+                return LocateRegistry.getRegistry( host, port );
+            }
+        }
+        catch( RemoteException e )
+        {
+            throw new ObjectProviderException( "Unable to locate registry at " + host + ":" + port + ".", e );
+        }
+    }
+}
+
diff --git a/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/SessionBeanProvider.java b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/SessionBeanProvider.java
new file mode 100644
index 0000000..901ab07
--- /dev/null
+++ b/proxy-1.0-work/src/main/java/org/apache/commons/proxy/provider/remoting/SessionBeanProvider.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider.remoting;
+
+import org.apache.commons.proxy.ObjectProvider;
+import org.apache.commons.proxy.ProxyUtils;
+import org.apache.commons.proxy.exception.ObjectProviderException;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.rmi.PortableRemoteObject;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Properties;
+
+/**
+ * Provides a reference to a session bean by looking up the home object and calling (via reflection) the no-argument
+ * create() method.  This will work for both local and remote session beans.
+ *
+ * @author James Carman
+ * @since 1.0
+ */
+public class SessionBeanProvider implements ObjectProvider
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+    private final String jndiName;
+    private final Class homeInterface;
+    private final Properties properties;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public SessionBeanProvider( String jndiName, Class homeInterface )
+    {
+        this.jndiName = jndiName;
+        this.homeInterface = homeInterface;
+        this.properties = null;
+    }
+
+    public SessionBeanProvider( String jndiName, Class homeInterface, Properties properties )
+    {
+        this.jndiName = jndiName;
+        this.homeInterface = homeInterface;
+        this.properties = properties;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// ObjectProvider Implementation
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object getObject()
+    {
+        try
+        {
+            final InitialContext initialContext = properties == null ? new InitialContext() :
+                                                  new InitialContext( properties );
+            Object homeObject = PortableRemoteObject.narrow( initialContext.lookup( jndiName ), homeInterface );
+            final Method createMethod = homeObject.getClass().getMethod( "create", ProxyUtils.EMPTY_ARGUMENT_TYPES );
+            return createMethod.invoke( homeObject, ProxyUtils.EMPTY_ARGUMENTS );
+        }
+        catch( NoSuchMethodException e )
+        {
+            throw new ObjectProviderException(
+                    "Unable to find no-arg create() method on home interface " + homeInterface.getName() + ".", e );
+        }
+        catch( IllegalAccessException e )
+        {
+            throw new ObjectProviderException(
+                    "No-arg create() method on home interface " + homeInterface.getName() + " is not accessible.",
+                    e ); // Should never happen!
+        }
+        catch( NamingException e )
+        {
+            throw new ObjectProviderException( "Unable to lookup EJB home object in JNDI.", e );
+        }
+        catch( InvocationTargetException e )
+        {
+            throw new ObjectProviderException(
+                    "No-arg create() method on home interface " + homeInterface.getName() + " threw an exception.", e );
+        }
+    }
+}
+
diff --git a/proxy-1.0-work/src/media/logo.xcf b/proxy-1.0-work/src/media/logo.xcf
new file mode 100644
index 0000000..4f4f865
--- /dev/null
+++ b/proxy-1.0-work/src/media/logo.xcf
Binary files differ
diff --git a/proxy-1.0-work/src/site/resources/images/logo.png b/proxy-1.0-work/src/site/resources/images/logo.png
new file mode 100644
index 0000000..7d377b4
--- /dev/null
+++ b/proxy-1.0-work/src/site/resources/images/logo.png
Binary files differ
diff --git a/proxy-1.0-work/src/site/site.xml b/proxy-1.0-work/src/site/site.xml
new file mode 100644
index 0000000..9120a7f
--- /dev/null
+++ b/proxy-1.0-work/src/site/site.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You 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.
+  -->
+<project name="Commons Proxy">
+  <bannerRight>
+    <name>Commons Proxy</name>
+    <src>images/logo.png</src>
+    <href>http://commons.apache.org/proxy/</href>
+  </bannerRight>
+  <body>
+    <menu name="Commons Proxy">
+      <item name="Overview" href="index.html"/>
+      <item name="Mailing lists" href="/mail-lists.html"/>
+      <item name="Team" href="/team-list.html"/>
+      <!--item name="Tasks" href="/tasks.html"/-->
+      <item name="SVN" href="http://svn.apache.org/viewvc/commons/proper/proxy/trunk/"/>
+      <item name="Javadoc (SVN latest)" href="apidocs/index.html"/>
+    </menu>
+  </body>
+</project>
diff --git a/proxy-1.0-work/src/site/xdoc/index.xml b/proxy-1.0-work/src/site/xdoc/index.xml
new file mode 100644
index 0000000..f287e22
--- /dev/null
+++ b/proxy-1.0-work/src/site/xdoc/index.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You 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.
+  -->
+<document>
+    <properties>
+        <title>Overview</title>
+        <author email="dev AT commons DOT apache DOT org">Apache Commons Development Team</author>
+        <author email="jcarman AT apache DOT org">James Carman</author>
+    </properties>
+
+    <body>
+        <section name="Commons Proxy: Dynamic Proxies Made Easy">
+            <p>
+                The <em>Proxy</em> design pattern (<a href="http://www.amazon.com/exec/obidos/tg/detail/-/0201633612/qid=1125413337/sr=1-1/ref=sr_1_1/104-0714405-6441551?v=glance&amp;s=books">GoF</a>)
+                allows you to provide &quot;a surrogate or placeholder for another object to control access to it&quot;.
+                Proxies can be used in many ways.  Some of which are:
+            </p>
+                <ul>
+                    <li><b>Deferred Initialization</b> - the proxy acts as a "stand-in" for the actual implementation allowing
+                    it to be instantiated only when absolutely necessary.</li>
+                    <li><b>Security</b> - the proxy object can verify that the user actually has the permission to execute
+                    the method (a la EJB).</li>
+                    <li><b>Logging</b> - the proxy can log evey method invocation, providing valuable debugging information.</li>
+                    <li><b>Performance Monitoring</b> - the proxy can log each method invocation to a performance monitor
+                    allowing system administrators to see what parts of the system are potentially bogged down.</li>
+                </ul>
+            <p>
+                <em>Commons Proxy</em> supports dynamic proxy generation using proxy factories, object providers, invokers, and
+                interceptors.
+            </p>
+            <section name="Proxy Factories">
+                <p>
+                    <a href="apidocs/org/apache/commons/proxy/ProxyFactory.html">Proxy factories</a>
+                    encapsulate all necessary proxying logic away from your code.  Switching proxying
+                    techniques/technologies is as simple as using a different proxy factory implementation class.
+                    Currently,  <em>Commons Proxy</em> provides proxy factory implementations using JDK proxies,
+                    <a href="http://cglib.sourceforge.net">CGLIB</a>, and
+                    <a href="http://www.jboss.org/products/javassist">Javassist</a>.  Proxy factories allow you to create
+                    three different types of proxy objects:
+            </p>
+                    <ul>
+                        <li><b>Delegator Proxies</b> - a proxy that merely delegates each method invocation to an
+                            object provided by an <a href="apidocs/org/apache/commons/proxy/ObjectProvider.html">object provider</a>.</li>
+                        <li><b>Interceptor Proxies</b> - a proxy that allows an <a href="apidocs/org/apache/commons/proxy/Interceptor.html">Interceptor</a> to intercept each
+                            method invocation as it makes its way to the target of the invocation.</li>
+                        <li><b>Invoker Proxies</b> - a proxy that uses an
+                            <a href="apidocs/org/apache/commons/proxy/Invoker.html">invoker</a> to handle all method
+                            invocations.</li>
+                    </ul>
+            </section>
+            <section name="Object Providers">
+                <p>
+                    <a href="apidocs/org/apache/commons/proxy/provider/package-summary.html">Object providers</a>
+                    provide the
+                    objects which will be the &quot;target&quot; of a proxy. There are two types of object providers:
+                    <subsection name="Core Object Providers">
+                        <p>
+                        A core object provider provides a core implementation object.  <em>Commons Proxy</em> supports
+                        many different implementations including:
+                        </p>
+                        <table border="0">
+                            <tr><td><b>Constant</b></td><td>Always returns a specific object</td></tr>
+                            <tr><td><b>Bean</b></td><td>Merely instantiates an object of a specified class each time</td></tr>
+                            <tr><td><b>Cloning</b></td><td>Reflectively calls the public clone() method on a Cloneable object</td></tr>
+                            <tr><td><b>Hessian</b></td><td>Returns a <a href="http://www.caucho.com/hessian/index.xtp">Hessian</a>-based service object</td></tr>
+                            <tr><td><b>Burlap</b></td><td>Returns a <a href="http://www.caucho.com/burlap/index.xtp">Burlap</a>-based service object</td></tr>
+                            <tr><td><b>JAX-RPC</b></td><td>Returns a <a href="http://java.sun.com/webservices/jaxrpc/index.jsp">JAX-RPC</a>-based service object</td></tr>
+                            <tr><td><b>Session Bean</b></td><td>Returns a reference to a Session EJB (stateless session beans only)</td></tr>
+                        </table>
+                    </subsection>
+                    <subsection name="Decorating Object Providers">
+                        <p>
+                        A decorating object provider decorates the object returned by another provider.
+                            <em>Commons Proxy</em> provides a few implementations including:
+                        </p>
+                        <table border="0">
+                            <tr><td><b>Singleton</b></td><td>Calls a nested provider at most once, returning that original value on all subsequent invocations</td></tr>
+                        </table>
+
+                    </subsection>
+
+                </p>
+            </section>
+            <section name="Invokers">
+                <p>
+                    An <a href="apidocs/org/apache/commons/proxy/Invoker.html">invoker</a> handles all
+                    method invocations using a single method.  <em>Commons Proxy</em> provides a few invoker implementations:
+                </p>
+                    <table border="0">
+                      <tr><td><b>Null</b></td><td>Always returns a null (useful for the "Null Object" pattern)</td></tr>
+                      <tr><td><b>Apache XML-RPC</b></td><td>Uses <a href="http://ws.apache.org/xmlrpc/">Apache XML-RPC</a> to fulfill the method invocation</td></tr>
+                        <tr><td><b>Duck Typing</b></td><td>Supports &quot;duck typing&quot; by adapting a class to an interface it does not implement.</td></tr>
+                      <tr><td><b>Invocation Handler Adapter</b></td><td>Adapts the JDK <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/reflect/InvocationHandler.html">InvocationHandler</a> interface
+                          to the <em>Commons Proxy</em> <a href="apidocs/org/apache/commons/proxy/Invoker.html">Invoker</a> interface.</td></tr>
+                    </table>
+
+            </section>
+            <section name="Interceptors">
+                <p>
+                    <em>Commons Proxy</em> allows you to &quot;intercept&quot; a method invocation using <a href="apidocs/org/apache/commons/proxy/Interceptor.html">Interceptors</a>.
+                    Interceptors provide <em>rudimentary</em> aspect-oriented
+                    programming support, allowing you to alter the results/effects of a method invocation without actually
+                    changing the implementation of the method itself.  <em>Commons Proxy</em> provides a few interceptor
+                    implementations including:
+                </p>
+                    <table border="0">
+                      <tr><td><b>Executor</b></td><td>Uses an
+                      <a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/Executor.html">Executor</a> to execute the method in possibly another thread (only void methods are supported).</td></tr>
+                      <tr><td><b>Logging</b></td><td>Logs all method invocations using the
+                      <a href="http://commons.apache.org/logging/">Apache Commons Logging</a> API</td></tr>
+                      <tr><td><b>Filtered</b></td><td>Optionally intercepts a method invocation based on a
+                      <a href="apidocs/org/apache/commons/proxy/interceptor/MethodFilter.html">method filter</a></td></tr>
+                      <tr><td><b>Method Interceptor Adapter</b></td><td>Adapts the AOP Alliance <a href="http://aopalliance.sourceforge.net/doc/org/aopalliance/intercept/MethodInterceptor.html">MethodInterceptor</a> interface to the
+                          <em>Commons Proxy</em> <a href="apidocs/org/apache/commons/proxy/Interceptor.html">Interceptor</a> interface.</td></tr>
+
+                      </table>
+            </section>
+        </section>
+
+        <section name="Status">
+                <ul>
+                    <li>The code is unreleased.</li>
+                    <li>Methods and classes can and will appear and disappear without warning.</li>
+                    <li>If you like the code and want to push it towards a release, join the mailing list!</li>
+                </ul>
+        </section>
+    </body>
+</document>
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/TestProxyFactory.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/TestProxyFactory.java
new file mode 100644
index 0000000..cbc395c
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/TestProxyFactory.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy;
+import org.apache.commons.proxy.factory.AbstractProxyFactoryTestCase;
+
+public class TestProxyFactory extends AbstractProxyFactoryTestCase
+{
+    public TestProxyFactory()
+    {
+        super( new ProxyFactory() );
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/TestProxyUtils.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/TestProxyUtils.java
new file mode 100644
index 0000000..19d4ea6
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/TestProxyUtils.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy;
+
+import junit.framework.TestCase;
+import org.apache.commons.proxy.factory.javassist.JavassistProxyFactory;
+import org.apache.commons.proxy.util.DuplicateEcho;
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.util.EchoImpl;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Properties;
+
+public class TestProxyUtils extends TestCase
+{
+    private Properties prevProperties;
+
+    protected void setUp() throws Exception
+    {
+        prevProperties = System.getProperties();
+        System.setProperties( new Properties() );
+    }
+
+    protected void tearDown() throws Exception
+    {
+        System.setProperties( prevProperties );
+    }
+
+    public void testCreateNullObject() throws Exception
+    {
+        final Echo nullEcho = ( Echo ) ProxyUtils
+                .createNullObject( new JavassistProxyFactory(), new Class[]{ Echo.class } );
+        assertNull( nullEcho.echoBack( "hello" ) );
+        assertNull( nullEcho.echoBack( "hello", "world" ) );
+        assertEquals( ( int ) 0, nullEcho.echoBack( 12345 ) );
+    }
+
+    public void testCreateNullObjectWithClassLoader() throws Exception
+    {
+        final Echo nullEcho = ( Echo ) ProxyUtils.createNullObject( new JavassistProxyFactory(),
+                                                                    Echo.class.getClassLoader(),
+                                                                    new Class[]{ Echo.class } );
+        assertNull( nullEcho.echoBack( "hello" ) );
+        assertNull( nullEcho.echoBack( "hello", "world" ) );
+        assertEquals( ( int ) 0, nullEcho.echoBack( 12345 ) );
+    }
+
+    public void testGetAllInterfaces()
+    {
+        assertNull( ProxyUtils.getAllInterfaces( null ) );
+        assertEquals( Arrays.asList( new Class[] { DuplicateEcho.class, Serializable.class, Echo.class } ), Arrays.asList( ProxyUtils.getAllInterfaces( EchoImpl.class ) ) );
+    }
+
+    public void testGetJavaClassName() throws Exception
+    {
+        assertEquals( "java.lang.Object[]", ProxyUtils.getJavaClassName( Object[].class ) );
+        assertEquals( "java.lang.Object[][]", ProxyUtils.getJavaClassName( Object[][].class ) );
+        assertEquals( "java.lang.String[][][]", ProxyUtils.getJavaClassName( String[][][].class ) );
+        assertEquals( "int", ProxyUtils.getJavaClassName( Integer.TYPE ) );
+        assertEquals( "float", ProxyUtils.getJavaClassName( Float.TYPE ) );
+        assertEquals( "long", ProxyUtils.getJavaClassName( Long.TYPE ) );
+        assertEquals( "double", ProxyUtils.getJavaClassName( Double.TYPE ) );
+        assertEquals( "short", ProxyUtils.getJavaClassName( Short.TYPE ) );
+        assertEquals( "byte", ProxyUtils.getJavaClassName( Byte.TYPE ) );
+        assertEquals( "char", ProxyUtils.getJavaClassName( Character.TYPE ) );
+        assertEquals( "boolean", ProxyUtils.getJavaClassName( Boolean.TYPE ) );
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/exception/AbstractExceptionClassTestCase.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/exception/AbstractExceptionClassTestCase.java
new file mode 100644
index 0000000..0e86c17
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/exception/AbstractExceptionClassTestCase.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.exception;
+
+import junit.framework.TestCase;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public abstract class AbstractExceptionClassTestCase extends TestCase
+{
+    private final Class exceptionClass;
+
+    public AbstractExceptionClassTestCase( Class exceptionClass )
+    {
+        this.exceptionClass = exceptionClass;
+    }
+
+    public void testNoArgConstructor() throws Exception
+    {
+        Exception e = ( Exception )exceptionClass.getConstructor( new Class[] {} ).newInstance( new Object[] {} );
+        assertNull( e.getMessage() );
+        assertNull( e.getCause() );
+    }
+
+    public void testMessageOnlyConstructor() throws Exception
+    {
+        final String message = "message";
+        Exception e = ( Exception )exceptionClass.getConstructor( new Class[] { String.class } ).newInstance( new Object[] { message } );
+        assertEquals( message, e.getMessage() );
+        assertNull( e.getCause() );
+    }
+
+    public void testCauseOnlyConstructor() throws Exception
+    {
+        final Exception cause = new Exception();
+        Exception e = ( Exception )exceptionClass.getConstructor( new Class[] { Throwable.class } ).newInstance( new Object[] { cause } );
+        assertEquals( cause.toString(), e.getMessage() );
+        assertEquals( cause, e.getCause() );
+    }
+
+    public void testMessageAndCauseConstructor() throws Exception
+    {
+        final Exception cause = new Exception();
+        final String message = "message";
+        Exception e = ( Exception )exceptionClass.getConstructor( new Class[] { String.class, Throwable.class } ).newInstance( new Object[] { message, cause } );
+        assertEquals( message, e.getMessage() );
+        assertEquals( cause, e.getCause() );
+    }
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/exception/TestDelegateProviderException.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/exception/TestDelegateProviderException.java
new file mode 100644
index 0000000..802ebda
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/exception/TestDelegateProviderException.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.exception;
+
+public class TestDelegateProviderException extends AbstractExceptionClassTestCase
+{
+    public TestDelegateProviderException()
+    {
+        super( ObjectProviderException.class );
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/exception/TestInvocationHandlerException.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/exception/TestInvocationHandlerException.java
new file mode 100644
index 0000000..0408acb
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/exception/TestInvocationHandlerException.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.exception;
+public class TestInvocationHandlerException extends AbstractExceptionClassTestCase
+{
+    public TestInvocationHandlerException()
+    {
+        super( InvokerException.class );
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/exception/TestProxyFactoryException.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/exception/TestProxyFactoryException.java
new file mode 100644
index 0000000..0651107
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/exception/TestProxyFactoryException.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.exception;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class TestProxyFactoryException extends AbstractExceptionClassTestCase
+{
+    public TestProxyFactoryException()
+    {
+        super( ProxyFactoryException.class );
+    }
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/AbstractProxyFactoryTestCase.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/AbstractProxyFactoryTestCase.java
new file mode 100644
index 0000000..d9bca77
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/AbstractProxyFactoryTestCase.java
@@ -0,0 +1,299 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory;
+
+import junit.framework.TestCase;
+import org.apache.commons.proxy.Interceptor;
+import org.apache.commons.proxy.Invocation;
+import org.apache.commons.proxy.Invoker;
+import org.apache.commons.proxy.ObjectProvider;
+import org.apache.commons.proxy.ProxyFactory;
+import org.apache.commons.proxy.provider.BeanProvider;
+import org.apache.commons.proxy.provider.ConstantProvider;
+import org.apache.commons.proxy.provider.SingletonProvider;
+import org.apache.commons.proxy.util.DuplicateEcho;
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.util.EchoImpl;
+import org.apache.commons.proxy.util.SuffixInterceptor;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public abstract class AbstractProxyFactoryTestCase extends TestCase
+{
+    protected final ProxyFactory factory;
+    private static final Class[] ECHO_ONLY = new Class[] { Echo.class };
+
+    protected AbstractProxyFactoryTestCase( ProxyFactory factory )
+    {
+        this.factory = factory;
+    }
+
+    public void testCanProxy()
+    {
+        assertTrue( factory.canProxy( ECHO_ONLY ) );
+        assertFalse( factory.canProxy( new Class[] { EchoImpl.class } ) );
+    }
+
+    public void testInterfaceHierarchies()
+    {
+        final SortedSet set = ( SortedSet ) factory.createDelegatorProxy( new ConstantProvider( new TreeSet() ), new Class[] { SortedSet.class } );
+        set.add( "Hello" );
+    }
+
+    public void testInvokerProxy() throws Exception
+    {
+        final InvokerTester tester = new InvokerTester();
+        final Echo echo = ( Echo )factory.createInvokerProxy( tester, ECHO_ONLY );
+        echo.echoBack( "hello" );
+        assertEquals( Echo.class.getMethod( "echoBack", new Class[] { String.class } ), tester.method );
+        assertSame( echo, tester.proxy );
+        assertNotNull( tester.args );
+        assertEquals( 1, tester.args.length );
+        assertEquals( "hello", tester.args[0] );
+    }
+
+    public void testDelegatingProxyInterfaceOrder()
+    {
+        final Echo echo = ( Echo ) factory.createDelegatorProxy( createSingletonEcho(), new Class[] { Echo.class, DuplicateEcho.class } );
+        final List expected = new LinkedList( Arrays.asList( new Class[] { Echo.class, DuplicateEcho.class } ) );
+        final List actual = new LinkedList( Arrays.asList( echo.getClass().getInterfaces() ) );
+        actual.retainAll( expected );  // Doesn't alter order!
+        assertEquals( expected, actual );
+    }
+
+    public void testCreateDelegatingProxy()
+    {
+        final Echo echo = ( Echo ) factory.createDelegatorProxy( createSingletonEcho(), ECHO_ONLY );
+        echo.echo();
+        assertEquals( "message", echo.echoBack( "message" ) );
+        assertEquals( "ab", echo.echoBack( "a", "b" ) );
+    }
+
+    public void testBooleanInterceptorParameter()
+    {
+        final Echo echo = ( Echo ) factory.createInterceptorProxy( new EchoImpl(), new  InterceptorTester(), ECHO_ONLY );
+        assertFalse( echo.echoBack( false ) );
+        assertTrue( echo.echoBack( true ) );
+
+    }
+    public void testPrimitiveParameter()
+    {
+        final Echo echo = ( Echo ) factory.createDelegatorProxy( createSingletonEcho(), ECHO_ONLY );
+        assertEquals( 1, echo.echoBack( 1 ) );
+    }
+
+    public void testCreateInterceptorProxy()
+    {
+        final Echo target = ( Echo ) factory.createDelegatorProxy( createSingletonEcho(), ECHO_ONLY );
+        final Echo proxy = ( Echo ) factory.createInterceptorProxy( target, new SuffixInterceptor( " suffix" ), ECHO_ONLY );
+        proxy.echo();
+        assertEquals( "message suffix", proxy.echoBack( "message" ) );
+    }
+
+    private ObjectProvider createSingletonEcho()
+    {
+        return new SingletonProvider( new BeanProvider( EchoImpl.class ) );
+    }
+
+    public void testMethodInvocationImplementation() throws Exception
+    {
+        final InterceptorTester tester = new InterceptorTester();
+        final EchoImpl target = new EchoImpl();
+        final Echo proxy = ( Echo ) factory.createInterceptorProxy( target, tester, ECHO_ONLY );
+        proxy.echo();
+        assertNotNull( tester.arguments );
+        assertEquals( 0, tester.arguments.length );
+        assertEquals( Echo.class.getMethod( "echo", new Class[] {} ), tester.method );
+        assertEquals( target, tester.proxy );
+        proxy.echoBack( "Hello" );
+        assertNotNull( tester.arguments );
+        assertEquals( 1, tester.arguments.length );
+        assertEquals( "Hello", tester.arguments[0] );
+        assertEquals( Echo.class.getMethod( "echoBack", new Class[] { String.class } ), tester.method );
+        proxy.echoBack( "Hello", "World" );
+        assertNotNull( tester.arguments );
+        assertEquals( 2, tester.arguments.length );
+        assertEquals( "Hello", tester.arguments[0] );
+        assertEquals( "World", tester.arguments[1] );
+        assertEquals( Echo.class.getMethod( "echoBack", new Class[] { String.class, String.class } ), tester.method );
+    }
+
+    public void testMethodInvocationDuplicateMethods() throws Exception
+    {
+        final InterceptorTester tester = new InterceptorTester();
+        final EchoImpl target = new EchoImpl();
+        final Echo proxy = ( Echo ) factory.createInterceptorProxy( target, tester, new Class[] { Echo.class, DuplicateEcho.class } );
+        proxy.echoBack( "hello" );
+        assertEquals( Echo.class.getMethod( "echoBack", new Class[] { String.class } ), tester.method );
+    }
+
+
+    public void testMethodInvocationClassCaching() throws Exception
+    {
+        final InterceptorTester tester = new InterceptorTester();
+        final EchoImpl target = new EchoImpl();
+        final Echo proxy1 = ( Echo ) factory.createInterceptorProxy( target, tester, ECHO_ONLY );
+        final Echo proxy2 = ( Echo ) factory.createInterceptorProxy( target, tester, new Class[] { Echo.class, DuplicateEcho.class } );
+        proxy1.echoBack( "hello1" );
+        final Class invocationClass1 = tester.invocationClass;
+        proxy2.echoBack( "hello2" );
+        assertEquals( invocationClass1, tester.invocationClass );
+    }
+
+    public void testDelegatingProxyClassCaching() throws Exception
+    {
+        final Echo proxy1 = ( Echo ) factory.createDelegatorProxy( new ConstantProvider( new EchoImpl() ), ECHO_ONLY );
+        final Echo proxy2 = ( Echo ) factory.createDelegatorProxy( new ConstantProvider( new EchoImpl() ), ECHO_ONLY );
+        assertEquals( proxy1.getClass(), proxy2.getClass() );
+    }
+
+    public void testInterceptingProxyClassCaching() throws Exception
+    {
+        final Echo proxy1 = ( Echo ) factory.createInterceptorProxy( new EchoImpl(), new NoOpMethodInterceptor(), ECHO_ONLY );
+        final Echo proxy2 = ( Echo ) factory.createInterceptorProxy( new EchoImpl(), new NoOpMethodInterceptor(), ECHO_ONLY );
+        assertEquals( proxy1.getClass(), proxy2.getClass() );
+    }
+
+    public void testProxyWithCheckedException() throws Exception
+    {
+        final Echo proxy = ( Echo ) factory.createDelegatorProxy( new ConstantProvider( new EchoImpl() ), ECHO_ONLY );
+        try
+        {
+            proxy.ioException();
+            fail();
+        }
+        catch( IOException e )
+        {
+        }
+    }
+
+    public void testProxyWithUncheckedException() throws Exception
+    {
+        final Echo proxy = ( Echo ) factory.createDelegatorProxy( new ConstantProvider( new EchoImpl() ), ECHO_ONLY );
+        try
+        {
+            proxy.illegalArgument();
+            fail();
+        }
+        catch( IllegalArgumentException e )
+        {
+        }
+    }
+
+    public void testInterceptorProxyWithUncheckedException() throws Exception
+    {
+        final Echo proxy = ( Echo ) factory.createInterceptorProxy( new EchoImpl(), new NoOpMethodInterceptor(),  ECHO_ONLY );
+        try
+        {
+            proxy.illegalArgument();
+            fail();
+        }
+        catch( IllegalArgumentException e )
+        {
+        }
+    }
+
+    public void testInterceptorProxyWithCheckedException() throws Exception
+    {
+        final Echo proxy = ( Echo ) factory.createInterceptorProxy( new EchoImpl(), new NoOpMethodInterceptor(), ECHO_ONLY );
+        try
+        {
+            proxy.ioException();
+            fail();
+        }
+        catch( IOException e )
+        {
+        }
+    }
+
+    public void testWithNonAccessibleTargetType()
+    {
+        final Echo proxy = ( Echo ) factory.createInterceptorProxy( new PrivateEcho(), new NoOpMethodInterceptor(), ECHO_ONLY );
+        proxy.echo();
+
+    }
+
+    public void testChangingArguments()
+    {
+        final Echo proxy = ( Echo ) factory.createInterceptorProxy( new EchoImpl(), new ChangeArgumentInterceptor(), ECHO_ONLY );
+        assertEquals( "something different", proxy.echoBack( "whatever" ) );
+    }
+
+    private static class PrivateEcho extends EchoImpl
+    {
+    }
+
+    private static class ChangeArgumentInterceptor implements Interceptor
+    {
+        public Object intercept( Invocation methodInvocation ) throws Throwable
+        {
+            methodInvocation.getArguments()[0] = "something different";
+            return methodInvocation.proceed();
+        }
+    }
+
+    protected static class NoOpMethodInterceptor implements Interceptor
+    {
+        public Object intercept( Invocation methodInvocation ) throws Throwable
+        {
+            return methodInvocation.proceed();
+        }
+    }
+
+    private static class InvokerTester implements Invoker
+    {
+        private Object method;
+        private Object[] args;
+        private Object proxy;
+
+        public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
+        {
+            this.proxy = proxy;
+            this.method = method;
+            this.args = args;
+            return null;
+        }
+    }
+
+    private static class InterceptorTester implements Interceptor
+    {
+        private Object[] arguments;
+        private Method method;
+        private Object proxy;
+        private Class invocationClass;
+
+        public Object intercept( Invocation methodInvocation ) throws Throwable
+        {
+            arguments = methodInvocation.getArguments();
+            method = methodInvocation.getMethod();
+            proxy = methodInvocation.getProxy();
+            invocationClass = methodInvocation.getClass();
+            return methodInvocation.proceed();
+        }
+    }
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/AbstractSubclassingProxyFactoryTestCase.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/AbstractSubclassingProxyFactoryTestCase.java
new file mode 100644
index 0000000..078d967
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/AbstractSubclassingProxyFactoryTestCase.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory;
+
+import org.apache.commons.proxy.ProxyFactory;
+import org.apache.commons.proxy.exception.ProxyFactoryException;
+import org.apache.commons.proxy.invoker.NullInvoker;
+import org.apache.commons.proxy.provider.ConstantProvider;
+import org.apache.commons.proxy.util.AbstractEcho;
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.util.EchoImpl;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public abstract class AbstractSubclassingProxyFactoryTestCase extends AbstractProxyFactoryTestCase
+{
+    protected AbstractSubclassingProxyFactoryTestCase( ProxyFactory factory )
+    {
+        super( factory );
+    }
+
+    public void testWithAbstractSuperclass()
+    {
+        final Echo echo = ( Echo )factory.createDelegatorProxy( new ConstantProvider( new EchoImpl() ),  new Class[] { AbstractEcho.class } );
+        assertEquals( "hello", echo.echoBack( "hello" ) );
+        assertEquals( "helloworld", echo.echoBack( "hello", "world" ) );
+    }
+
+    public void testCanProxy()
+    {
+        assertTrue( factory.canProxy(  new Class[] { Echo.class } ) );
+        assertTrue( factory.canProxy(  new Class[] { EchoImpl.class } ) );
+        assertFalse( factory.canProxy(  new Class[] { FinalEcho.class } ) );
+        assertTrue( factory.canProxy(  new Class[] { FinalMethodEcho.class, Echo.class } ) );
+        assertFalse( factory.canProxy(  new Class[] { NoDefaultConstructorEcho.class } ) );
+        assertTrue( factory.canProxy(  new Class[] { ProtectedConstructorEcho.class } ) );
+        assertFalse( factory.canProxy(  new Class[] { InvisibleEcho.class } ) );
+        assertFalse( factory.canProxy(  new Class[] { Echo.class, EchoImpl.class, String.class } ) );
+    }
+
+    public void testDelegatorWithSuperclass()
+    {
+        final Echo echo = ( Echo ) factory
+                .createDelegatorProxy( new ConstantProvider( new EchoImpl() ),  new Class[] { Echo.class, EchoImpl.class } );
+        assertTrue( echo instanceof EchoImpl );
+    }
+
+    public void testInterceptorWithSuperclass()
+    {
+        final Echo echo = ( Echo ) factory
+                .createInterceptorProxy( new EchoImpl(), new NoOpMethodInterceptor(),  new Class[] { Echo.class, EchoImpl.class } );
+        assertTrue( echo instanceof EchoImpl );
+    }
+
+    public void testInvocationHandlerWithSuperclass()
+    {
+        final Echo echo = ( Echo ) factory
+                .createInvokerProxy( new NullInvoker(),  new Class[] { Echo.class, EchoImpl.class } );
+        assertTrue( echo instanceof EchoImpl );
+    }
+
+    public void testProxiesWithClashingFinalMethodInSuperclass()
+    {
+        final Class[] proxyClasses = new Class[]{Echo.class, FinalMethodEcho.class};
+        Echo proxy = ( Echo )factory.createDelegatorProxy( new ConstantProvider( new EchoImpl() ), proxyClasses );
+        assertEquals( "final", proxy.echoBack("echo") );
+
+        proxy = ( Echo )factory.createInterceptorProxy( new EchoImpl(), new NoOpMethodInterceptor(), proxyClasses );
+        assertEquals( "final", proxy.echoBack("echo") );
+
+        proxy = ( Echo )factory.createInvokerProxy( new NullInvoker(), proxyClasses );
+        assertEquals( "final", proxy.echoBack("echo") );
+    }
+
+    public void testDelegatorWithMultipleSuperclasses()
+    {
+        try
+        {
+            factory.createDelegatorProxy( new ConstantProvider( new EchoImpl() ),
+                                           new Class[] { EchoImpl.class, String.class } );
+            fail();
+        }
+        catch( ProxyFactoryException e )
+        {
+        }
+    }
+
+    public void testInterceptorWithMultipleSuperclasses()
+    {
+        try
+        {
+            factory.createInterceptorProxy( new EchoImpl(), new NoOpMethodInterceptor(),
+                                             new Class[] { EchoImpl.class, String.class } );
+            fail();
+        }
+        catch( ProxyFactoryException e )
+        {
+        }
+    }
+
+    public void testInvocationHandlerWithMultipleSuperclasses()
+    {
+        try
+        {
+            factory.createInvokerProxy( new NullInvoker(),
+                                                   new Class[] { EchoImpl.class, String.class } );
+            fail();
+        }
+        catch( ProxyFactoryException e )
+        {
+        }
+    }
+
+    public static final class FinalEcho extends EchoImpl
+    {
+    }
+
+    public static class FinalMethodEcho extends EchoImpl
+    {
+        public final String echoBack( String message )
+        {
+            return "final";
+        }
+    }
+
+    public static class NoDefaultConstructorEcho extends EchoImpl
+    {
+        public NoDefaultConstructorEcho( String param )
+        {
+        }
+    }
+
+    public static class ProtectedConstructorEcho extends EchoImpl
+    {
+        protected ProtectedConstructorEcho()
+        {
+        }
+    }
+
+    private static class InvisibleEcho extends EchoImpl
+    {
+    }
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/cglib/TestCglibProxyFactory.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/cglib/TestCglibProxyFactory.java
new file mode 100644
index 0000000..61dcadd
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/cglib/TestCglibProxyFactory.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory.cglib;
+
+import org.apache.commons.proxy.factory.AbstractProxyFactoryTestCase;
+import org.apache.commons.proxy.factory.AbstractSubclassingProxyFactoryTestCase;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class TestCglibProxyFactory extends AbstractSubclassingProxyFactoryTestCase
+{
+    public TestCglibProxyFactory()
+    {
+        super( new CglibProxyFactory() );
+    }
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/javassist/TestJavassistProxyFactory.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/javassist/TestJavassistProxyFactory.java
new file mode 100644
index 0000000..66b74d3
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/javassist/TestJavassistProxyFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory.javassist;
+
+import org.apache.commons.proxy.factory.AbstractProxyFactoryTestCase;
+import org.apache.commons.proxy.factory.AbstractSubclassingProxyFactoryTestCase;
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.util.DuplicateEcho;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.LinkedList;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class TestJavassistProxyFactory extends AbstractSubclassingProxyFactoryTestCase
+{
+    public TestJavassistProxyFactory()
+    {
+        super( new JavassistProxyFactory() );
+    }
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/util/TestMethodSignature.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/util/TestMethodSignature.java
new file mode 100644
index 0000000..a92b6bc
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/factory/util/TestMethodSignature.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.factory.util;
+import junit.framework.TestCase;
+import org.apache.commons.proxy.util.DuplicateEcho;
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.factory.util.MethodSignature;
+
+public class TestMethodSignature extends TestCase
+{
+    public void testEquals() throws Exception
+    {
+        final MethodSignature sig = new MethodSignature( Echo.class.getMethod( "echoBack",  new Class[] { String.class } ) );
+        assertTrue( sig.equals( sig ) );
+        assertFalse( sig.equals( "echoBack" ) );
+        assertEquals( sig, new MethodSignature( Echo.class.getMethod( "echoBack",  new Class[] { String.class } ) ) );
+        assertEquals( sig, new MethodSignature( DuplicateEcho.class.getMethod( "echoBack",  new Class[] { String.class } ) ) );
+        assertFalse( sig.equals( new MethodSignature( Echo.class.getMethod( "echoBack",  new Class[] { String.class, String.class } ) ) ) );
+        assertFalse( sig.equals( new MethodSignature( Echo.class.getMethod( "echo",  new Class[] {} ) ) ) );
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestExecutorInterceptor.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestExecutorInterceptor.java
new file mode 100644
index 0000000..c92be5b
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestExecutorInterceptor.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor;
+
+import junit.framework.TestCase;
+import org.apache.commons.proxy.factory.cglib.CglibProxyFactory;
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.util.EchoImpl;
+import EDU.oswego.cs.dl.util.concurrent.Executor;
+import EDU.oswego.cs.dl.util.concurrent.CountDown;
+
+public class TestExecutorInterceptor extends TestCase
+{
+    public void testVoidMethod() throws Exception
+    {
+        final ExecutedEcho impl = new ExecutedEcho();
+        final OneShotExecutor executor = new OneShotExecutor();
+        final Echo proxy = ( Echo ) new CglibProxyFactory()
+                .createInterceptorProxy( impl, new ExecutorInterceptor( executor ), new Class[] { Echo.class } );
+        proxy.echo();
+        executor.getLatch().acquire();
+        assertEquals( executor.getThread(), impl.getExecutionThread() );
+    }
+
+    public void testNonVoidMethod() throws Exception
+    {
+        final ExecutedEcho impl = new ExecutedEcho();
+        final OneShotExecutor executor = new OneShotExecutor();
+        final Echo proxy = ( Echo ) new CglibProxyFactory()
+                .createInterceptorProxy( impl, new ExecutorInterceptor( executor ), new Class[] { Echo.class } );
+        try
+        {
+            proxy.echoBack( "hello" );
+            fail();
+        }
+        catch( IllegalArgumentException e )
+        {
+        }
+    }
+
+    public static class ExecutedEcho extends EchoImpl
+    {
+        private Thread executionThread;
+
+        public void echo()
+        {
+            executionThread = Thread.currentThread();
+        }
+
+        public Thread getExecutionThread()
+        {
+            return executionThread;
+        }
+    }
+
+    private static class OneShotExecutor implements Executor
+    {
+        private Thread thread;
+        private CountDown latch = new CountDown( 1 );
+
+        public void execute( final Runnable command )
+        {
+            thread = new Thread( new Runnable()
+            {
+                public void run()
+                {
+                    try
+                    {
+                        command.run();
+                    }
+                    finally
+                    {
+                        latch.release();
+                    }
+                }
+            } );
+            thread.start();
+        }
+
+        public Thread getThread()
+        {
+            return thread;
+        }
+
+        public CountDown getLatch()
+        {
+            return latch;
+        }
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestFilteredInterceptor.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestFilteredInterceptor.java
new file mode 100644
index 0000000..7e3f0f6
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestFilteredInterceptor.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor;
+
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.util.EchoImpl;
+import org.apache.commons.proxy.util.SuffixInterceptor;
+import org.apache.commons.proxy.factory.cglib.CglibProxyFactory;
+import org.apache.commons.proxy.interceptor.filter.SimpleFilter;
+import org.apache.commons.proxy.Interceptor;
+import junit.framework.TestCase;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class TestFilteredInterceptor extends TestCase
+{
+    public void testFilterAccepts()
+    {
+        Echo echo = ( Echo ) new InterceptorChain( new Interceptor[] { new FilteredInterceptor( new SuffixInterceptor( "a" ), new SimpleFilter( new String[] { "echoBack" } ) ) } ).createProxyProvider( new CglibProxyFactory(), new EchoImpl() ).getObject();
+        assertEquals( "messagea", echo.echoBack( "message" ) );
+    }
+
+    public void testFilterDenies()
+    {
+        Echo echo = ( Echo ) new InterceptorChain( new Interceptor[] { new FilteredInterceptor( new SuffixInterceptor( "a" ), new SimpleFilter() ) } ).createProxyProvider( new CglibProxyFactory(), new EchoImpl() ).getObject();
+        assertEquals( "message", echo.echoBack( "message" ) );
+    }
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestInterceptorChain.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestInterceptorChain.java
new file mode 100644
index 0000000..f736929
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestInterceptorChain.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor;
+
+import junit.framework.TestCase;
+import org.apache.commons.proxy.Interceptor;
+import org.apache.commons.proxy.factory.cglib.CglibProxyFactory;
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.util.EchoImpl;
+import org.apache.commons.proxy.util.SuffixInterceptor;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class TestInterceptorChain extends TestCase
+{
+    public void testWithSingleInterceptor()
+    {
+        Echo echo = ( Echo ) new InterceptorChain( new Interceptor[] { new SuffixInterceptor( "a" ) } ).createProxyProvider( new CglibProxyFactory(), new EchoImpl(),  new Class[] { Echo.class } ).getObject();
+        assertEquals( "messagea", echo.echoBack( "message" ) );
+    }
+
+    public void testWithMultipleInterceptors()
+    {
+        Echo echo = ( Echo ) new InterceptorChain( new Interceptor[] { new SuffixInterceptor( "a" ), new SuffixInterceptor( "b" ) } ).createProxyProvider( new CglibProxyFactory(), new EchoImpl(),  new Class[] { Echo.class } ).getObject();
+        assertEquals( "messageba", echo.echoBack( "message" ) );
+    }
+}
+
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestLoggingInterceptor.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestLoggingInterceptor.java
new file mode 100644
index 0000000..57aa138
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestLoggingInterceptor.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.proxy.factory.cglib.CglibProxyFactory;
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.util.EchoImpl;
+import org.jmock.Mock;
+import org.jmock.MockObjectTestCase;
+
+import java.io.IOException;
+
+public class TestLoggingInterceptor extends MockObjectTestCase
+{
+    private Mock logMock;
+    private Echo echo;
+
+    protected void setUp() throws Exception
+    {
+        logMock = mock( Log.class );
+        echo = ( Echo ) new CglibProxyFactory()
+                .createInterceptorProxy( new EchoImpl(), new LoggingInterceptor( ( Log ) logMock.proxy() ),
+                                         new Class[]{ Echo.class } );
+    }
+
+    public void testWhenLoggingDisabled()
+    {
+        logMock = mock( Log.class );
+        echo = ( Echo ) new CglibProxyFactory()
+                .createInterceptorProxy( new EchoImpl(), new LoggingInterceptor( ( Log ) logMock.proxy() ),
+                                         new Class[]{ Echo.class } );
+        logMock.expects( once() ).method( "isDebugEnabled" ).will( returnValue( false ) );
+        echo.echoBack( "Hello" );
+
+    }
+
+    public void testWithArrayParameter()
+    {
+        logMock.expects( once() ).method( "isDebugEnabled" ).will( returnValue( true ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "BEGIN echoBack((java.lang.String[]){Hello, World})" ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "END echoBack() [HelloWorld]" ) );
+        echo.echoBack( new String[] { "Hello", "World" } );
+    }
+
+    public void testMultipleParameters()
+    {
+        logMock.expects( once() ).method( "isDebugEnabled" ).will( returnValue( true ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "BEGIN echoBack(Hello, World)" ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "END echoBack() [HelloWorld]" ) );
+        echo.echoBack( "Hello", "World" );
+    }
+
+    public void testNullReturnValue()
+    {
+        logMock.expects( once() ).method( "isDebugEnabled" ).will( returnValue( true ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "BEGIN echoBack(<null>)" ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "END echoBack() [<null>]" ) );
+        echo.echoBack( ( String )null );
+    }
+
+    public void testNonVoidMethod()
+    {
+        logMock.expects( once() ).method( "isDebugEnabled" ).will( returnValue( true ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "BEGIN echoBack(Hello)" ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "END echoBack() [Hello]" ) );
+        echo.echoBack( "Hello" );
+    }
+
+    public void testException()
+    {
+        logMock.expects( once() ).method( "isDebugEnabled" ).will( returnValue( true ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "BEGIN ioException()" ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "EXCEPTION ioException() -- java.io.IOException" ), isA( IOException.class ) );
+        try
+        {
+            echo.ioException();
+            fail();
+        }
+        catch( IOException e )
+        {
+
+        }
+    }
+
+    public void testRuntimeException()
+    {
+        logMock.expects( once() ).method( "isDebugEnabled" ).will( returnValue( true ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "BEGIN illegalArgument()" ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "EXCEPTION illegalArgument() -- java.lang.IllegalArgumentException" ), isA( IllegalArgumentException.class ) );
+        try
+        {
+            echo.illegalArgument();
+            fail();
+        }
+        catch( IllegalArgumentException e )
+        {
+
+        }
+    }
+
+    public void testVoidMethod()
+    {
+        logMock.expects( once() ).method( "isDebugEnabled" ).will( returnValue( true ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "BEGIN echo()" ) );
+        logMock.expects( once() ).method( "debug" ).with( eq( "END echo()" ) );
+        echo.echo();
+    }
+
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestMethodInterceptorAdapter.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestMethodInterceptorAdapter.java
new file mode 100644
index 0000000..0062818
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestMethodInterceptorAdapter.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.commons.proxy.ProxyUtils;
+import org.apache.commons.proxy.factory.javassist.JavassistProxyFactory;
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.util.EchoImpl;
+
+public class TestMethodInterceptorAdapter extends TestCase
+{
+    public void testMethodInterception()
+    {
+        final Echo proxy = ( Echo ) new JavassistProxyFactory().createInterceptorProxy( new EchoImpl(),
+                                                                                         new MethodInterceptorAdapter( new SuffixMethodInterceptor(
+                                                                                                 " suffix" ) ),
+                                                                                         new Class[]{ Echo.class } );
+        assertEquals( "message suffix", proxy.echoBack( "message" ) );
+    }
+
+    public void testMethodInvocationImplementation() throws Exception
+    {
+        final InterceptorTester tester = new InterceptorTester();
+        final EchoImpl target = new EchoImpl();
+        final Echo proxy = ( Echo ) new JavassistProxyFactory().createInterceptorProxy( target, new MethodInterceptorAdapter( tester ), new Class[] { Echo.class } );
+        proxy.echo();
+        assertNotNull( tester.invocation.getArguments() );
+        assertEquals( 0, tester.invocation.getArguments().length );
+        assertEquals( Echo.class.getMethod( "echo", new Class[] {} ), tester.invocation.getMethod() );
+        assertEquals( Echo.class.getMethod( "echo", new Class[] {} ), tester.invocation.getStaticPart() );
+        assertEquals( target, tester.invocation.getThis() );
+        proxy.echoBack( "Hello" );
+        assertNotNull( tester.invocation.getArguments() );
+        assertEquals( 1, tester.invocation.getArguments().length );
+        assertEquals( "Hello", tester.invocation.getArguments()[0] );
+        assertEquals( Echo.class.getMethod( "echoBack", new Class[] { String.class } ), tester.invocation.getMethod() );
+        assertEquals( Echo.class.getMethod( "echoBack", new Class[] { String.class } ), tester.invocation.getStaticPart() );
+        proxy.echoBack( "Hello", "World" );
+        assertNotNull( tester.invocation.getArguments() );
+        assertEquals( 2, tester.invocation.getArguments().length );
+        assertEquals( "Hello", tester.invocation.getArguments()[0] );
+        assertEquals( "World", tester.invocation.getArguments()[1] );
+        assertEquals( Echo.class.getMethod( "echoBack", new Class[] { String.class, String.class } ), tester.invocation.getMethod() );
+        assertEquals( Echo.class.getMethod( "echoBack", new Class[] { String.class, String.class } ), tester.invocation.getStaticPart() );
+    }
+    private static class InterceptorTester implements MethodInterceptor
+    {
+        private MethodInvocation invocation;
+
+        public Object invoke( MethodInvocation methodInvocation ) throws Throwable
+        {
+            this.invocation = methodInvocation;
+            return methodInvocation.proceed();
+        }
+    }
+    private class SuffixMethodInterceptor implements MethodInterceptor
+    {
+        private final String suffix;
+
+        public SuffixMethodInterceptor( String suffix )
+        {
+            this.suffix = suffix;
+        }
+
+        public Object invoke( MethodInvocation methodInvocation ) throws Throwable
+        {
+            return methodInvocation.proceed() + suffix;
+        }
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestSerializingInterceptor.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestSerializingInterceptor.java
new file mode 100644
index 0000000..76d43f0
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/TestSerializingInterceptor.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor;
+
+import junit.framework.TestCase;
+import org.apache.commons.proxy.ProxyFactory;
+
+import java.io.ByteArrayOutputStream;
+
+public class TestSerializingInterceptor extends TestCase
+{
+    public void testWithSerializableParametersAndReturn()
+    {
+        final ObjectEchoImpl target = new ObjectEchoImpl();
+        ObjectEcho echo =
+                (ObjectEcho) new ProxyFactory().createInterceptorProxy(target,
+                        new SerializingInterceptor(),
+                        new Class[]{ObjectEcho.class});
+        final Object originalParameter = "Hello, World!";
+        final Object returnValue = echo.echoBack(originalParameter);
+        assertNotSame(originalParameter, target.parameter);
+        assertNotSame(originalParameter, returnValue);
+        assertNotSame(returnValue, target.parameter);
+    }
+
+    public void testWithInvalidParameterType()
+    {
+        try
+        {
+            final ObjectEchoImpl target = new ObjectEchoImpl();
+            ObjectEcho echo =
+                    (ObjectEcho) new ProxyFactory().createInterceptorProxy(target,
+                            new SerializingInterceptor(),
+                            new Class[]{ObjectEcho.class});
+            final Object originalParameter = new ByteArrayOutputStream();
+            echo.echoBack(originalParameter);
+            fail("Should not be able to call method with non-serializable parameter type.");
+        }
+        catch (RuntimeException e)
+        {
+
+        }
+
+    }
+
+    public static interface ObjectEcho
+    {
+        public Object echoBack(Object object);
+    }
+
+    public static class ObjectEchoImpl implements ObjectEcho
+    {
+        private Object parameter;
+
+        public Object echoBack(Object object)
+        {
+            this.parameter = object;
+            return object;
+        }
+    }
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/filter/TestPatternFilter.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/filter/TestPatternFilter.java
new file mode 100644
index 0000000..d865e16
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/filter/TestPatternFilter.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor.filter;
+
+import junit.framework.TestCase;
+
+import java.util.Date;
+
+import org.apache.commons.proxy.interceptor.MethodFilter;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class TestPatternFilter extends TestCase
+{
+    public void testAccepts() throws Exception
+    {
+        final MethodFilter filter = PatternFilter.getterSetterFilter();
+        assertTrue( filter.accepts( Date.class.getMethod( "getSeconds", new Class[] {} ) ) );
+        assertTrue( filter.accepts( Date.class.getMethod( "getMinutes",  new Class[] {} ) ) );
+        assertTrue( filter.accepts( Date.class.getMethod( "setSeconds",  new Class[] { Integer.TYPE } ) ) );
+        assertTrue( filter.accepts( Date.class.getMethod( "setMinutes",  new Class[] { Integer.TYPE } ) ) );
+        assertFalse( filter.accepts( Date.class.getMethod( "toString",  new Class[] {} ) ) );
+        assertFalse( filter.accepts( Date.class.getMethod( "hashCode",  new Class[] {} ) ) );
+    }
+
+
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/filter/TestReturnTypeFilter.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/filter/TestReturnTypeFilter.java
new file mode 100644
index 0000000..0df58ad
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/filter/TestReturnTypeFilter.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor.filter;
+import junit.framework.TestCase;
+
+public class TestReturnTypeFilter extends TestCase
+{
+    public void testAcceptsMethod() throws Exception
+    {
+        final ReturnTypeFilter filter = new ReturnTypeFilter(  new Class[] { String.class, Integer.TYPE } );
+        assertTrue( filter.accepts( Object.class.getMethod( "toString",  new Class[] {} ) ) );
+        assertTrue( filter.accepts( Object.class.getMethod( "hashCode",  new Class[] {} ) ) );
+        assertFalse( filter.accepts( Object.class.getMethod( "equals",  new Class[] { Object.class } ) ) );
+    }
+
+
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/filter/TestSimpleFilter.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/filter/TestSimpleFilter.java
new file mode 100644
index 0000000..d0590cb
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/interceptor/filter/TestSimpleFilter.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.interceptor.filter;
+
+import junit.framework.TestCase;
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.util.EchoImpl;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class TestSimpleFilter extends TestCase
+{
+    public void testAccepts() throws Exception
+    {
+        final SimpleFilter filter = new SimpleFilter( new String[] { "echoBack" } );
+        assertTrue( filter.accepts( Echo.class.getMethod( "echoBack", new Class[] { String.class } ) ) );
+        assertFalse( filter.accepts( EchoImpl.class.getMethod( "hashCode",  new Class[] {} ) ) );
+    }
+
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java
new file mode 100644
index 0000000..9a77995
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java
@@ -0,0 +1,140 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one or more

+ * contributor license agreements.  See the NOTICE file distributed with

+ * this work for additional information regarding copyright ownership.

+ * The ASF licenses this file to You 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 org.apache.commons.proxy.invoker;

+

+import junit.framework.TestCase;

+import org.apache.commons.proxy.ObjectProvider;

+import org.apache.commons.proxy.ProxyFactory;

+import org.apache.commons.proxy.provider.ConstantProvider;

+

+import java.io.Serializable;

+

+/**

+ *

+ */

+public class TestDuckTypingInvoker extends TestCase

+{

+//----------------------------------------------------------------------------------------------------------------------

+// Other Methods

+//----------------------------------------------------------------------------------------------------------------------

+

+    public void testExactSignatureMatch()

+    {

+        final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );

+        final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );

+        final Duck duck = ( Duck ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{ Duck.class } );

+        assertEquals( "Quack!", duck.sayQuack() );

+    }

+

+    public void testNoMatchingMethod()

+    {

+        final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );

+        final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );

+        final Goose goose = ( Goose ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{ Goose.class } );

+        try

+        {

+            goose.sayHonk();

+            fail( "No matching method should be found." );

+        }

+        catch ( UnsupportedOperationException e )

+        {

+            // Do nothing, expected behavior!

+        }

+    }

+

+    public void testMismatchingParameterType()

+    {

+        final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );

+        final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );

+        final ParameterizedDuck parameterizedDuck = ( ParameterizedDuck ) new ProxyFactory()

+                .createInvokerProxy( invoker, new Class[]{ ParameterizedDuck.class } );

+        try

+        {

+            parameterizedDuck.sayQuack("Elmer");

+            fail( "No matching method should be found." );

+        }

+        catch ( UnsupportedOperationException e )

+        {

+            // Do nothing, expected behavior!

+        }

+    }

+

+    public void testTargetHasCompatibleReturnType()

+    {

+        final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );

+        final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );

+        final SerializableDuck duck = ( SerializableDuck ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{

+                SerializableDuck.class } );

+        assertEquals("Quack!", duck.sayQuack() );

+

+    }

+

+    public void testMismatchingReturnType()

+    {

+        final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );

+        final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );

+        final VoidReturnDuck voidDuck = ( VoidReturnDuck ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{

+                VoidReturnDuck.class } );

+        try

+        {

+            voidDuck.sayQuack();

+            fail( "No matching method should be found." );

+        }

+        catch ( UnsupportedOperationException e )

+        {

+            // Do nothing, expected behavior!

+        }

+    }

+

+//----------------------------------------------------------------------------------------------------------------------

+// Inner Classes

+//----------------------------------------------------------------------------------------------------------------------

+

+    public static class LegacyDuck

+    {

+        public String sayQuack()

+        {

+            return "Quack!";

+        }

+    }

+

+    public interface Duck

+    {

+        public String sayQuack();

+    }

+

+    public interface SerializableDuck

+    {

+        public Serializable sayQuack();

+    }

+    

+    public interface ParameterizedDuck

+    {

+        public String sayQuack( String recipient );

+    }

+

+    public interface VoidReturnDuck

+    {

+        public void sayQuack();

+    }

+

+    public interface Goose

+    {

+        public void sayHonk();

+    }

+}

diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/invoker/TestInvocationHandlerAdapter.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/invoker/TestInvocationHandlerAdapter.java
new file mode 100644
index 0000000..2e6f46c
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/invoker/TestInvocationHandlerAdapter.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.invoker;
+import junit.framework.TestCase;
+import org.apache.commons.proxy.factory.javassist.JavassistProxyFactory;
+import org.apache.commons.proxy.util.Echo;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class TestInvocationHandlerAdapter extends TestCase
+{
+    public void testMethodInvocation() throws Exception
+    {
+        InvocationHandlerTester tester = new InvocationHandlerTester();
+        final Echo echo = ( Echo ) new JavassistProxyFactory().createInvokerProxy( new InvocationHandlerAdapter( tester ), new Class[] { Echo.class } );
+        echo.echoBack( "hello" );
+        assertEquals( Echo.class.getMethod( "echoBack", new Class[] { String.class } ), tester.method );
+        assertSame( echo, tester.proxy );
+        assertNotNull( tester.arguments );
+        assertEquals( 1, tester.arguments.length );
+        assertEquals( "hello", tester.arguments[0] );
+    }
+
+    private class InvocationHandlerTester implements InvocationHandler
+    {
+        private Object proxy;
+        private Method method;
+        private Object[] arguments;
+
+        public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
+        {
+            this.proxy = proxy;
+            this.method = method;
+            this.arguments = args;
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/invoker/TestNullInvoker.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/invoker/TestNullInvoker.java
new file mode 100644
index 0000000..74233ac
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/invoker/TestNullInvoker.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.invoker;
+import junit.framework.TestCase;
+import org.apache.commons.proxy.ProxyUtils;
+import org.apache.commons.proxy.factory.cglib.CglibProxyFactory;
+
+public class TestNullInvoker extends TestCase
+{
+    public void testReturnValues()
+    {
+        final Tester tester = ( Tester )ProxyUtils.createNullObject( new CglibProxyFactory(), new Class[] { Tester.class } );
+        assertEquals( 0, tester.intMethod() );
+        assertEquals( 0L, tester.longMethod() );
+        assertEquals( ( short )0, tester.shortMethod() );
+        assertEquals( ( byte )0, tester.byteMethod() );
+        assertEquals( ( char )0, tester.charMethod() );
+        assertEquals( 0.0f, tester.floatMethod(), 0.0f );
+        assertEquals( 0.0, tester.doubleMethod(), 0.0f );
+        assertFalse( tester.booleanMethod() );
+        assertNull( tester.stringMethod() );
+    }
+
+    public static interface Tester
+    {
+        public int intMethod();
+        public long longMethod();
+        public short shortMethod();
+        public byte byteMethod();
+        public char charMethod();
+        public double doubleMethod();
+        public float floatMethod();
+        public String stringMethod();
+        public boolean booleanMethod();
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/invoker/TestXmlRpcInvoker.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/invoker/TestXmlRpcInvoker.java
new file mode 100644
index 0000000..2ee007a
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/invoker/TestXmlRpcInvoker.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.invoker;
+
+import junit.extensions.TestSetup;
+import junit.framework.Protectable;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+import org.apache.commons.proxy.exception.InvokerException;
+import org.apache.commons.proxy.factory.cglib.CglibProxyFactory;
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.util.EchoImpl;
+import org.apache.xmlrpc.WebServer;
+import org.apache.xmlrpc.XmlRpcClient;
+import org.apache.xmlrpc.XmlRpcClientLite;
+
+/**
+ * @author James Carman
+ */
+public class TestXmlRpcInvoker extends TestCase
+{
+    private static WebServer server;
+    private static XmlRpcClient client;
+
+    public static Test suite()
+    {
+        return new TestSetup( new TestSuite( TestXmlRpcInvoker.class ) )
+        {
+            public void run( final TestResult testResult )
+            {
+                Protectable p = new Protectable()
+                {
+                    public void protect() throws Throwable
+                    {
+                        try
+                        {
+                            setUp();
+                            basicRun( testResult );
+                        }
+                        finally
+                        {
+                            tearDown();
+                        }
+                    }
+                };
+                testResult.runProtected( this, p );
+            }
+
+            protected void setUp() throws Exception
+            {
+                server = new WebServer( 9999 );
+                server.addHandler( "echo", new EchoImpl() );
+                server.start();
+                client = new XmlRpcClientLite( "http://localhost:9999/RPC2" );
+            }
+
+            protected void tearDown() throws Exception
+            {
+                server.shutdown();
+            }
+        };
+    }
+
+    public void testInvalidHandlerName()
+    {
+        final XmlRpcInvoker handler = new XmlRpcInvoker( client, "invalid" );
+        final Echo echo = ( Echo ) new CglibProxyFactory()
+                .createInvokerProxy( handler, new Class[]{ Echo.class } );
+        try
+        {
+            echo.echoBack( "Hello" );
+            fail();
+        }
+        catch( InvokerException e )
+        {
+        }
+    }
+
+    public void testValidInvocation() throws Exception
+    {
+        final XmlRpcInvoker handler = new XmlRpcInvoker( client, "echo" );
+        final Echo echo = ( Echo ) new CglibProxyFactory()
+                .createInvokerProxy( handler, new Class[]{ Echo.class } );
+        assertEquals( "Hello", echo.echoBack( "Hello" ) );
+
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/CountingProvider.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/CountingProvider.java
new file mode 100644
index 0000000..f7b0621
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/CountingProvider.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider;
+
+import org.apache.commons.proxy.ObjectProvider;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class CountingProvider extends ProviderDecorator
+{
+    private int count = 0;
+
+    public CountingProvider( ObjectProvider inner )
+    {
+        super( inner );
+    }
+
+    public synchronized Object getObject()
+    {
+        count++;
+        return super.getObject();
+    }
+
+    public synchronized int getCount()
+    {
+        return count;
+    }
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/TestBeanProvider.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/TestBeanProvider.java
new file mode 100644
index 0000000..08c1062
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/TestBeanProvider.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider;
+
+import junit.framework.TestCase;
+import org.apache.commons.proxy.exception.ObjectProviderException;
+
+public class TestBeanProvider extends TestCase
+{
+    public void testWithNullBeanClass()
+    {
+        try
+        {
+            final BeanProvider p = new BeanProvider();
+            p.getObject();
+            fail();
+        }
+        catch( ObjectProviderException e )
+        {
+        }
+    }
+    public void testAbstractBeanClass()
+    {
+        try
+        {
+            final BeanProvider p = new BeanProvider();
+            p.setBeanClass( Number.class );
+            p.getObject();
+            fail();
+        }
+        catch( ObjectProviderException e )
+        {
+
+        }
+    }
+
+    public void testNonAccessibleConstructor()
+    {
+        try
+        {
+            new BeanProvider( MyBean.class ).getObject();
+            fail();
+        }
+        catch( ObjectProviderException e )
+        {
+
+        }
+    }
+
+    public static class MyBean
+    {
+        private MyBean()
+        {
+
+        }
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/TestCloningProvider.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/TestCloningProvider.java
new file mode 100644
index 0000000..6de4b4d
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/TestCloningProvider.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider;
+
+import junit.framework.TestCase;
+import org.apache.commons.proxy.exception.ObjectProviderException;
+
+import java.util.Date;
+
+public class TestCloningProvider extends TestCase
+{
+    public void testValidCloneable()
+    {
+        final Date now = new Date();
+        final CloningProvider provider = new CloningProvider( now );
+        final Date clone1 = ( Date ) provider.getObject();
+        assertEquals( now, clone1 );
+        assertNotSame( now, clone1 );
+        final Date clone2 = ( Date )provider.getObject();
+        assertEquals( now, clone2 );
+        assertNotSame( now, clone2 );
+        assertNotSame( clone2, clone1 );
+    }
+
+    public void testWithPrivateCloneMethod()
+    {
+        final CloningProvider provider = new CloningProvider( new PrivateCloneable() );
+        try
+        {
+            provider.getObject();
+            fail();
+        }
+        catch( ObjectProviderException e )
+        {
+        }
+    }
+    
+    public void testWithInvalidCloneable()
+    {
+        final CloningProvider provider = new CloningProvider( new InvalidCloneable() );
+        try
+        {
+            provider.getObject();
+            fail();
+        }
+        catch( ObjectProviderException e )
+        {
+        }
+    }
+
+    public void testWithExceptionThrown()
+    {
+        final CloningProvider provider = new CloningProvider( new ExceptionCloneable() );
+        try
+        {
+            provider.getObject();
+            fail();
+        }
+        catch( ObjectProviderException e )
+        {
+        }
+    }
+
+    public static class InvalidCloneable implements Cloneable
+    {
+    }
+
+    public static class PrivateCloneable implements Cloneable
+    {
+        protected Object clone()
+        {
+            return this;
+        }
+    }
+    
+    public static class ExceptionCloneable implements Cloneable
+    {
+        public Object clone()
+        {
+            throw new RuntimeException( "No clone for you!" );
+        }
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/TestConstantProvider.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/TestConstantProvider.java
new file mode 100644
index 0000000..4a0a4a4
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/TestConstantProvider.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider;
+
+import junit.framework.TestCase;
+
+/**
+ * @since 1.0
+ */
+public class TestConstantProvider extends TestCase
+{
+    public void testGetObject() throws Exception
+    {
+        final String s = "Hello, World!";
+        final ConstantProvider provider = new ConstantProvider( s );
+        assertSame( s, provider.getObject() );
+    }
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/TestNullProvider.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/TestNullProvider.java
new file mode 100644
index 0000000..451566d
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/TestNullProvider.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider;
+
+import junit.framework.TestCase;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class TestNullProvider extends TestCase
+{
+    public void testGetObject()
+    {
+        final NullProvider provider = new NullProvider();
+        assertNull( provider.getObject() );
+    }
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/remoting/TestBurlapProvider.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/remoting/TestBurlapProvider.java
new file mode 100644
index 0000000..e34f81c
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/remoting/TestBurlapProvider.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider.remoting;
+import junit.framework.TestCase;
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.exception.ObjectProviderException;
+import org.apache.commons.proxy.provider.remoting.BurlapProvider;
+
+public class TestBurlapProvider extends TestCase
+{
+    public void testWithMalformedUrl()
+    {
+        try
+        {
+            final BurlapProvider p = new BurlapProvider( Echo.class, "a malformed URL" );
+            p.getObject();
+            fail();
+        }
+        catch( ObjectProviderException e )
+        {
+        }
+    }
+
+    public void testWithMalformedUrlBean()
+    {
+        try
+        {
+            final BurlapProvider p = new BurlapProvider();
+            p.setServiceInterface( Echo.class );
+            p.setUrl( "a malformed URL" );
+            p.getObject();
+            fail();
+        }
+        catch( ObjectProviderException e )
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/remoting/TestHessianProvider.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/remoting/TestHessianProvider.java
new file mode 100644
index 0000000..4255f12
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/provider/remoting/TestHessianProvider.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.provider.remoting;
+
+import junit.framework.TestCase;
+import org.apache.commons.proxy.exception.ObjectProviderException;
+import org.apache.commons.proxy.util.Echo;
+import org.apache.commons.proxy.provider.remoting.HessianProvider;
+
+public class TestHessianProvider extends TestCase
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Other Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    public void testWithMalformedUrlBean()
+    {
+        try
+        {
+            final HessianProvider p = new HessianProvider();
+            p.setServiceInterface( Echo.class );
+            p.setUrl( "a malformed URL" );
+            p.getObject();
+            fail();
+        }
+        catch( ObjectProviderException e )
+        {
+        }
+    }
+
+    public void testWithMalformedUrl()
+    {
+        try
+        {
+            final HessianProvider p = new HessianProvider( Echo.class, "a malformed URL" );
+            p.getObject();
+            fail();
+        }
+        catch( ObjectProviderException e )
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/AbstractEcho.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/AbstractEcho.java
new file mode 100644
index 0000000..89ca7bb
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/AbstractEcho.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.util;
+
+import java.io.Serializable;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public abstract class AbstractEcho implements Echo, Serializable
+{
+    public String echoBack( String message )
+    {
+        return message;
+    }
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/DuplicateEcho.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/DuplicateEcho.java
new file mode 100644
index 0000000..e22a18c
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/DuplicateEcho.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.util;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public interface DuplicateEcho
+{
+    public String echoBack( String message );
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/Echo.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/Echo.java
new file mode 100644
index 0000000..1a71112
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/Echo.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.util;
+
+import java.io.IOException;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public interface Echo
+{
+    public String echoBack( String message );
+    public String echoBack( String message1, String message2 );
+    public String echoBack( String[] messages );
+    public int echoBack( int i );
+    public boolean echoBack( boolean b );
+    public void echo();
+
+    public void ioException() throws IOException;
+    public void illegalArgument();
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/EchoImpl.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/EchoImpl.java
new file mode 100644
index 0000000..50f3d22
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/EchoImpl.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.util;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class EchoImpl extends AbstractEcho implements DuplicateEcho, Serializable
+{
+    private static final long serialVersionUID = -4844873352607521103L;
+
+    public boolean echoBack( boolean b )
+    {
+        return b;
+    }
+
+    public String echoBack( String message1, String message2 )
+    {
+        return message1 + message2;
+    }
+
+    public String echoBack( String[] messages )
+    {
+        final StringBuffer sb = new StringBuffer();
+        for( int i = 0; i < messages.length; i++ )
+        {
+            String message = messages[i];
+            sb.append( message );
+        }
+        return sb.toString();
+    }
+
+    public int echoBack( int i )
+    {
+        return i;
+    }
+
+    public void echo()
+    {
+    }
+
+    public void ioException() throws IOException
+    {
+        throw new IOException( "dummy message" );
+    }
+
+    public void illegalArgument()
+    {
+        throw new IllegalArgumentException( "dummy message" );
+    }
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/QuoteService.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/QuoteService.java
new file mode 100644
index 0000000..8ebd681
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/QuoteService.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.util;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public interface QuoteService extends Remote
+{
+    public float getQuote( String symbol ) throws RemoteException;
+}
diff --git a/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/SuffixInterceptor.java b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/SuffixInterceptor.java
new file mode 100644
index 0000000..b80e017
--- /dev/null
+++ b/proxy-1.0-work/src/test/java/org/apache/commons/proxy/util/SuffixInterceptor.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.proxy.util;
+
+import org.apache.commons.proxy.Invocation;
+import org.apache.commons.proxy.Interceptor;
+
+/**
+ * @author James Carman
+ * @since 1.0
+ */
+public class SuffixInterceptor implements Interceptor
+{
+    private final String suffix;
+
+    public SuffixInterceptor( String suffix )
+    {
+        this.suffix = suffix;
+    }
+
+    public Object intercept( Invocation methodInvocation ) throws Throwable
+    {
+        return methodInvocation.proceed() + suffix;
+    }
+}
diff --git a/proxy-1.0-work/src/test/resources/log4j.properties b/proxy-1.0-work/src/test/resources/log4j.properties
new file mode 100644
index 0000000..b981287
--- /dev/null
+++ b/proxy-1.0-work/src/test/resources/log4j.properties
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+log4j.rootLogger=DEBUG, console
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{MM-dd@HH:mm:ss} %-5p (%c{1}) %3x - %m%n
\ No newline at end of file