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ö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ö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 "flavors" 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">"duck typing"</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&s=books">GoF</a>)
+ allows you to provide "a surrogate or placeholder for another object to control access to it".
+ 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 "target" 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 "duck typing" 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 "intercept" 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