You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by zo...@apache.org on 2011/02/27 19:31:59 UTC
svn commit: r1075107 [1/2] - in /aries/tags/testsupport-0.1-incubating: ./
testsupport-unit/ testsupport-unit/src/ testsupport-unit/src/main/
testsupport-unit/src/main/java/ testsupport-unit/src/main/java/org/
testsupport-unit/src/main/java/org/apache/...
Author: zoe
Date: Sun Feb 27 18:31:58 2011
New Revision: 1075107
URL: http://svn.apache.org/viewvc?rev=1075107&view=rev
Log:
Restore testsupport 0.1
Added:
aries/tags/testsupport-0.1-incubating/
aries/tags/testsupport-0.1-incubating/LICENSE
aries/tags/testsupport-0.1-incubating/NOTICE
aries/tags/testsupport-0.1-incubating/pom.xml
aries/tags/testsupport-0.1-incubating/testsupport-unit/
aries/tags/testsupport-0.1-incubating/testsupport-unit/pom.xml
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/BundleContextMock.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/BundleMock.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/MockInitialContextFactoryBuilder.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/fixture/
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/fixture/ArchiveFixture.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/junit/
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/junit/Assert.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/DefaultInvocationHandler.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/DefaultMethodCallHandlers.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/DefaultReturnTypeHandlers.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/ExceptionListener.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/MethodCall.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/MethodCallHandler.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/ReturnTypeHandler.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/Skeleton.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/annotations/
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/annotations/InjectSkeleton.java
aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/annotations/Singleton.java
Added: aries/tags/testsupport-0.1-incubating/LICENSE
URL: http://svn.apache.org/viewvc/aries/tags/testsupport-0.1-incubating/LICENSE?rev=1075107&view=auto
==============================================================================
--- aries/tags/testsupport-0.1-incubating/LICENSE (added)
+++ aries/tags/testsupport-0.1-incubating/LICENSE Sun Feb 27 18:31:58 2011
@@ -0,0 +1,203 @@
+
+ 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.
+
Added: aries/tags/testsupport-0.1-incubating/NOTICE
URL: http://svn.apache.org/viewvc/aries/tags/testsupport-0.1-incubating/NOTICE?rev=1075107&view=auto
==============================================================================
--- aries/tags/testsupport-0.1-incubating/NOTICE (added)
+++ aries/tags/testsupport-0.1-incubating/NOTICE Sun Feb 27 18:31:58 2011
@@ -0,0 +1,8 @@
+
+Apache Aries
+Copyright 2009-2010 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+
Added: aries/tags/testsupport-0.1-incubating/pom.xml
URL: http://svn.apache.org/viewvc/aries/tags/testsupport-0.1-incubating/pom.xml?rev=1075107&view=auto
==============================================================================
--- aries/tags/testsupport-0.1-incubating/pom.xml (added)
+++ aries/tags/testsupport-0.1-incubating/pom.xml Sun Feb 27 18:31:58 2011
@@ -0,0 +1,48 @@
+<!--
+ 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">
+
+ <parent>
+ <groupId>org.apache.aries</groupId>
+ <artifactId>java5-parent</artifactId>
+ <version>0.1-incubating</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.aries.testsupport</groupId>
+ <artifactId>testsupport</artifactId>
+ <name>Apache Aries Test Support</name>
+ <version>0.1-incubating</version>
+ <packaging>pom</packaging>
+
+ <description>
+ Test Support for OSGi
+ </description>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/incubator/aries/tags/testsupport-0.1-incubating</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/incubator/aries/tags/testsupport-0.1-incubating</developerConnection>
+ <url>http://svn.apache.org/viewvc/incubator/aries/tags/testsupport-0.1-incubating</url>
+ </scm>
+
+ <modules>
+ <module>testsupport-unit</module>
+ </modules>
+
+</project>
Added: aries/tags/testsupport-0.1-incubating/testsupport-unit/pom.xml
URL: http://svn.apache.org/viewvc/aries/tags/testsupport-0.1-incubating/testsupport-unit/pom.xml?rev=1075107&view=auto
==============================================================================
--- aries/tags/testsupport-0.1-incubating/testsupport-unit/pom.xml (added)
+++ aries/tags/testsupport-0.1-incubating/testsupport-unit/pom.xml Sun Feb 27 18:31:58 2011
@@ -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.
+ -->
+<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.aries.testsupport</groupId>
+ <artifactId>testsupport</artifactId>
+ <version>0.1-incubating</version>
+ </parent>
+
+ <artifactId>org.apache.aries.testsupport.unit</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Aries Unit Test Support</name>
+ <description>
+ This bundle provides unit test support.
+ </description>
+
+ <properties>
+ <aries.osgi.export.pkg>
+ org.apache.aries.*
+ </aries.osgi.export.pkg>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+</project>
Added: aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/BundleContextMock.java
URL: http://svn.apache.org/viewvc/aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/BundleContextMock.java?rev=1075107&view=auto
==============================================================================
--- aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/BundleContextMock.java (added)
+++ aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/BundleContextMock.java Sun Feb 27 18:31:58 2011
@@ -0,0 +1,763 @@
+/*
+ * 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.aries.mocks;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.jar.Attributes;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+
+import junit.framework.AssertionFailedError;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+import org.apache.aries.unittest.mocks.Skeleton;
+
+/**
+ *
+ */
+/**
+ * This class is a partial implementation of BundleContext. Its main function
+ * is to provide a service registry implementation
+ */
+public class BundleContextMock
+{
+ /** The service registry */
+ private static Map<String, List<ServiceData>> registry = new HashMap<String, List<ServiceData>>();
+ /** A list of bundles installed into the runtime */
+ private static List<Bundle> bundles = new ArrayList<Bundle>();
+ /** A list of service listeners */
+ private static List<ServiceListener> listeners = new ArrayList<ServiceListener>();
+ /** The next service id to be assigned */
+ private static long nextId = 0;
+
+ private static class MockServiceFactory implements ServiceFactory
+ {
+ private final Object service;
+
+ public MockServiceFactory(Object obj)
+ {
+ service = obj;
+ }
+
+ public Object getService(Bundle arg0, ServiceRegistration arg1)
+ {
+ return service;
+ }
+
+ public void ungetService(Bundle arg0, ServiceRegistration arg1, Object arg2)
+ {
+ }
+ }
+
+ private static class FilteredServiceListener implements ServiceListener
+ {
+ private Filter filter;
+ private final ServiceListener listener;
+
+ public FilteredServiceListener(String f, ServiceListener l)
+ {
+ listener = l;
+
+ if (f != null) {
+ try {
+ filter = FrameworkUtil.createFilter(f);
+ } catch (InvalidSyntaxException e) {
+ AssertionFailedError err = new AssertionFailedError("The filter " + f + " is invalid");
+ err.initCause(e);
+
+ throw err;
+ }
+ }
+ }
+
+ public void serviceChanged(ServiceEvent arg0)
+ {
+ if (matches(arg0)) listener.serviceChanged(arg0);
+ }
+
+ private boolean matches(ServiceEvent arg0)
+ {
+ if (filter == null) return true;
+
+ ServiceReference ref = arg0.getServiceReference();
+
+ if (Skeleton.isSkeleton(ref)) {
+ Object template = Skeleton.getSkeleton(ref).getTemplateObject();
+
+ if (template instanceof ServiceData) {
+ return filter.match(((ServiceData)template).getProperties());
+ }
+ }
+
+ return filter.match(ref);
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null) return false;
+ else if (obj instanceof FilteredServiceListener) {
+ return listener.equals(((FilteredServiceListener)obj).listener);
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return listener.hashCode();
+ }
+ }
+
+ /**
+ * This class represents the information registered about a service. It also
+ * implements part of the ServiceRegistration and ServiceReference interfaces.
+ */
+ private class ServiceData implements Comparable<ServiceReference>
+ {
+ /** The service that was registered */
+ private ServiceFactory serviceImpl;
+ /** the service properties */
+ @SuppressWarnings("unused")
+ private final Hashtable<String, Object> serviceProps = new Hashtable<String, Object>();
+ /** The interfaces the service publishes with */
+ private String[] interfaceNames;
+ /** The bundle that defines this service */
+ private Bundle registeringBundle;
+
+ /**
+ * This method unregisters the service from the registry.
+ */
+ public void unregister()
+ {
+ for (String interfaceName : interfaceNames) {
+ List<ServiceData> list = registry.get(interfaceName);
+ if (list != null) {
+ list.remove(this);
+ if (list.isEmpty()) {
+ registry.remove(interfaceName);
+ }
+ }
+ }
+ notifyAllListeners(ServiceEvent.UNREGISTERING);
+ registeringBundle = null;
+ }
+
+ /**
+ * This method is used to register the service data in the registry
+ */
+ public void register()
+ {
+ for (String interfaceName : interfaceNames) {
+ List<ServiceData> list = registry.get(interfaceName);
+ if (list == null) {
+ list = new ArrayList<ServiceData>();
+ registry.put(interfaceName, list);
+ }
+ list.add(this);
+ }
+ notifyAllListeners(ServiceEvent.REGISTERED);
+ }
+
+ private void notifyAllListeners(int eventType) {
+ List<ServiceListener> copy = new ArrayList<ServiceListener>(listeners.size());
+ copy.addAll(listeners);
+ for(ServiceListener listener : copy) {
+ listener.serviceChanged(new ServiceEvent(eventType, Skeleton.newMock(this, ServiceReference.class)));
+ }
+ }
+
+ /**
+ * Change the service properties
+ * @param newProps
+ */
+ public void setProperties(Dictionary<String,Object> newProps)
+ {
+ // make sure we don't overwrite framework properties
+ newProps.put(Constants.OBJECTCLASS, serviceProps.get(Constants.OBJECTCLASS));
+ newProps.put(Constants.SERVICE_ID, serviceProps.get(Constants.SERVICE_ID));
+
+ Enumeration<String> keys = newProps.keys();
+
+ serviceProps.clear();
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ serviceProps.put(key, newProps.get(key));
+ }
+
+ notifyAllListeners(ServiceEvent.MODIFIED);
+ }
+
+ /**
+ * This implements the isAssignableTo method from ServiceReference.
+ *
+ * @param b
+ * @param className
+ * @return true if the referenced service can be assigned to the requested
+ * class name.
+ */
+ public boolean isAssignableTo(Bundle b, String className)
+ {
+ boolean result = false;
+
+ for (String iName : interfaceNames)
+ {
+ result = iName.equals(className);
+
+ if (result) break;
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the requested service property.
+ * @param key the property to return.
+ * @return the property value.
+ */
+ public Object getProperty(String key)
+ {
+ return serviceProps.get(key);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if(o == null) return false;
+
+ if(o == this) return true;
+
+ if (o instanceof ServiceData) {
+ ServiceData other = (ServiceData) o;
+ return serviceImpl == other.serviceImpl;
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return serviceImpl.hashCode();
+ }
+
+ /**
+ * @return the keys of all the service properties.
+ */
+ public String[] getPropertyKeys()
+ {
+ Enumeration<String> e = serviceProps.keys();
+
+ String[] toReturn = new String[serviceProps.size()];
+
+ for(int i = 0 ; i < serviceProps.size(); i++)
+ toReturn[i] = e.nextElement();
+
+ return toReturn;
+ }
+
+ /**
+ * @return the bundle this service reference was registered against.
+ */
+ public Bundle getBundle()
+ {
+ return registeringBundle;
+ }
+
+ /**
+ * @return a service reference for this service registration.
+ */
+ public ServiceReference getReference()
+ {
+ return Skeleton.newMock(this, ServiceReference.class);
+ }
+
+ public Hashtable<String, Object> getProperties()
+ {
+ return new Hashtable<String, Object>(serviceProps);
+ }
+
+ /**
+ * Implement the standard behaviour of the registry
+ */
+ public int compareTo(ServiceReference o) {
+ Integer rank = (Integer) serviceProps.get(Constants.SERVICE_RANKING);
+ if(rank == null)
+ rank = 0;
+
+ Integer otherRank = (Integer) o.getProperty(Constants.SERVICE_RANKING);
+ if(otherRank == null)
+ otherRank = 0;
+ //Higher rank = higher order
+ int result = rank.compareTo(otherRank);
+
+ if(result == 0) {
+ Long id = (Long) serviceProps.get(Constants.SERVICE_ID);
+ Long otherId = (Long) o.getProperty(Constants.SERVICE_ID);
+ //higher id = lower order
+ return otherId.compareTo(id);
+ }
+ return result;
+ }
+ }
+
+ /** The bundle associated with this bundle context */
+ private Bundle bundle;
+
+ /**
+ * Default constructor, widely used in the tests.
+ */
+ public BundleContextMock()
+ {
+ bundle = Skeleton.newMock(new BundleMock("test." + new Random(System.currentTimeMillis()).nextInt(),
+ new Hashtable<Object, Object>()), Bundle.class);
+ }
+
+ /**
+ * Constructor used by BundleMock, it ensures the bundle and its context are wired together correctly.
+ *
+ * TODO We have to many Bundle mocks objects for a single OSGi bundle, we need to update this.
+ *
+ * @param b
+ */
+ public BundleContextMock(Bundle b)
+ {
+ bundle = b;
+ }
+
+ /**
+ * This checks that we have at least one service with this interface name.
+ *
+ * @param interfaceName the name of the interface.
+ */
+ public static void assertServiceExists(String interfaceName)
+ {
+ assertTrue("No service registered with interface " + interfaceName + ". Services found: " + registry.keySet(), registry.containsKey(interfaceName));
+ }
+
+ /**
+ * This checks that we have at no services with this interface name.
+ *
+ * @param interfaceName the name of the interface.
+ */
+ public static void assertNoServiceExists(String interfaceName)
+ {
+ assertFalse("Services registered with interface " + interfaceName + ". Services found: " + registry.keySet(), registry.containsKey(interfaceName));
+ }
+
+ /**
+ * This implements the registerService method from BundleContext.
+ *
+ * @param interFace
+ * @param service
+ * @param properties
+ * @return the ServiceRegistration object for this service.
+ */
+ public ServiceRegistration registerService(String interFace, final Object service, Dictionary<String, Object> properties)
+ {
+ // validate that the service implements interFace
+ try {
+ Class<?> clazz = Class.forName(interFace, false, service.getClass().getClassLoader());
+
+ if (!!!clazz.isInstance(service) && !!!(service instanceof ServiceFactory)) {
+ throw new AssertionFailedError("The service " + service + " does not implement " + interFace);
+ }
+ } catch (ClassNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ ServiceFactory factory = new MockServiceFactory(service);
+ return registerService(new String[] {interFace}, factory, properties);
+ }
+
+ /**
+ * This implements the registerService method from BundleContext.
+ *
+ * @param interfaces
+ * @param service
+ * @param properties
+ * @return the ServiceRegistration object for this service.
+ */
+ public ServiceRegistration registerService(String[] interfaces, Object service, Dictionary<String, Object> properties)
+ {
+ if (properties == null) properties = new Hashtable<String, Object>();
+
+ ServiceData data = new ServiceData();
+ // cast the service to a service factory because in our framework we only ever register
+ // a service factory. If we every put a non-service factory object in that is a failure.
+ properties.put(Constants.OBJECTCLASS, interfaces);
+ properties.put(Constants.SERVICE_ID, nextId++);
+ if (service instanceof ServiceFactory) {
+ data.serviceImpl = (ServiceFactory)service;
+ } else {
+ data.serviceImpl = new MockServiceFactory(service);
+ }
+ data.interfaceNames = interfaces;
+ data.registeringBundle = bundle;
+
+ Enumeration<String> keys = properties.keys();
+
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ data.serviceProps.put(key, properties.get(key));
+ }
+
+ data.register();
+
+ return Skeleton.newMock(data, ServiceRegistration.class);
+ }
+
+ /**
+ * This helper method is used to get the service from the registry with the
+ * given interface name.
+ *
+ * <p>This should really return multiple services.
+ * </p>
+ *
+ * @param interfaceName the interface name.
+ * @param bundle the bundle name.
+ * @return the registered service.
+ */
+ public static Object getService(String interfaceName, Bundle bundle)
+ {
+ List<ServiceData> datum = registry.get(interfaceName);
+
+ if (datum == null) return null;
+ else if (datum.isEmpty()) return null;
+ // this is safe for now, but may not be when we do other scoped components.
+ else {
+ ServiceRegistration reg = Skeleton.newMock(ServiceRegistration.class);
+ return datum.iterator().next().serviceImpl.getService(bundle, reg);
+ }
+ }
+
+ /**
+ * A mock implementation of the getServiceReferences method. It does not currently
+ * process the filter, this is probably a bit hard, so we might cheat when we do.
+ *
+ * <p>Note this does not check that the service classes are visible to the
+ * caller as OSGi does. It is equivalent to getAllServiceReferences.
+ * </p>
+ *
+ * @param className the name of the class the lookup is for.
+ * @param filter
+ * @return an array of matching service references.
+ * @throws InvalidSyntaxException
+ */
+ public ServiceReference[] getServiceReferences(String className, String filter) throws InvalidSyntaxException
+ {
+ List<ServiceData> data = new ArrayList<ServiceData>();
+
+ if (className != null) {
+ List<ServiceData> tmpData = registry.get(className);
+ if (tmpData != null) data.addAll(tmpData);
+ } else {
+ data = new ArrayList<ServiceData>();
+ for (List<ServiceData> value : registry.values())
+ data.addAll(value);
+ }
+
+ ServiceReference[] refs;
+
+ if (data == null) {
+ refs = null;
+ } else {
+
+ if (filter != null) {
+ Filter f = FrameworkUtil.createFilter(filter);
+
+ Iterator<ServiceData> it = data.iterator();
+
+ while (it.hasNext()) {
+ ServiceData sd = it.next();
+
+ if (!!!f.match(sd.getProperties())) it.remove();
+ }
+ }
+
+ if (data.isEmpty()) return null;
+
+ refs = new ServiceReference[data.size()];
+ for (int i = 0; i < refs.length; i++) {
+ refs[i] = Skeleton.newMock(data.get(i), ServiceReference.class);
+ }
+ }
+
+ return refs;
+ }
+
+ /**
+ * Gets the first matching service reference.
+ *
+ * @param className the class name wanted.
+ * @return the matchine service, or null if one cannot be found.
+ */
+ public ServiceReference getServiceReference(String className)
+ {
+ ServiceReference[] refs;
+ try {
+ refs = getServiceReferences(className, null);
+ if (refs != null) return refs[0];
+
+ return null;
+ } catch (InvalidSyntaxException e) {
+ // should never happen.
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * This method finds all the service references in the registry with the
+ * matching class name and filter.
+ *
+ * @param className
+ * @param filter
+ * @return the matching service references.
+ * @throws InvalidSyntaxException
+ */
+ public ServiceReference[] getAllServiceReferences(String className, String filter) throws InvalidSyntaxException
+ {
+ return getServiceReferences(className, filter);
+ }
+
+ /**
+ * Retrieve a service from the registry.
+ * @param ref the service reference.
+ * @return the returned service.
+ */
+ public Object getService(ServiceReference ref)
+ {
+ ServiceData data = (ServiceData)Skeleton.getSkeleton(ref).getTemplateObject();
+
+ return data.serviceImpl.getService(getBundle(), Skeleton.newMock(data, ServiceRegistration.class));
+ }
+
+ /**
+ * This method implements the installBundle method from BundleContext. It
+ * makes use of the java.util.jar package to parse the manifest from the input
+ * stream.
+ *
+ * @param location the location of the bundle.
+ * @param is the input stream to read from.
+ * @return the created bundle.
+ * @throws BundleException
+ */
+ public Bundle installBundle(String location, InputStream is) throws BundleException
+ {
+ Bundle b;
+ JarInputStream jis;
+ try {
+ jis = new JarInputStream(is);
+
+ Manifest man = jis.getManifest();
+
+ b = createBundle(man, null);
+
+ } catch (IOException e) {
+ throw new BundleException(e.getMessage(), e);
+ }
+
+ return b;
+ }
+
+ /**
+ * Create a mock bundle correctly configured using the supplied manifest and
+ * location.
+ *
+ * @param man the manifest to load.
+ * @param location the location on disk.
+ * @return the created bundle
+ * @throws MalformedURLException
+ */
+ private Bundle createBundle(Manifest man, String location) throws MalformedURLException
+ {
+ Attributes attribs = man.getMainAttributes();
+ String symbolicName = attribs.getValue(Constants.BUNDLE_SYMBOLICNAME);
+
+ Hashtable<Object, Object> attribMap = new Hashtable<Object, Object>();
+
+ for (Map.Entry<Object, Object> entry : attribs.entrySet()) {
+ Attributes.Name name = (Attributes.Name)entry.getKey();
+ attribMap.put(name.toString(), entry.getValue());
+ }
+
+ BundleMock mock = new BundleMock(symbolicName, attribMap, location);
+
+ mock.addToClassPath(new File("build/unittest/classes").toURL());
+
+ Bundle b = Skeleton.newMock(mock, Bundle.class);
+
+ bundles.add(b);
+
+ return b;
+ }
+
+ /**
+ * Asks to install an OSGi bundle from the given location.
+ *
+ * @param location the location of the bundle on the file system.
+ * @return the installed bundle.
+ * @throws BundleException
+ */
+ public Bundle installBundle(String location) throws BundleException
+ {
+ try {
+ URI uri = new URI(location.replaceAll(" ", "%20"));
+
+ File baseDir = new File(uri);
+ Manifest man = null;
+ //check if it is a directory
+ if (baseDir.isDirectory()){
+ man = new Manifest(new FileInputStream(new File(baseDir, "META-INF/MANIFEST.MF")));
+ }
+ //if it isn't assume it is a jar file
+ else{
+ InputStream is = new FileInputStream(baseDir);
+ JarInputStream jis = new JarInputStream(is);
+ man = jis.getManifest();
+ jis.close();
+ if (man == null){
+ throw new BundleException("Null manifest");
+ }
+ }
+
+ return createBundle(man, location);
+ } catch (IOException e) {
+ throw new BundleException(e.getMessage(), e);
+ } catch (URISyntaxException e) {
+ // TODO Auto-generated catch block
+ throw new BundleException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * @return all the bundles in the system
+ */
+ public Bundle[] getBundles()
+ {
+ return bundles.toArray(new Bundle[bundles.size()]);
+ }
+
+ /**
+ * Add a service listener.
+ *
+ * @param listener
+ * @param filter
+ */
+ public void addServiceListener(ServiceListener listener, String filter)
+ {
+ listeners.add(new FilteredServiceListener(filter, listener));
+ }
+
+ /**
+ * Add a service listener.
+ *
+ * @param listener
+ */
+ public void addServiceListener(ServiceListener listener)
+ {
+ listeners.add(listener);
+ }
+
+ /**
+ * Remove a service listener
+ * @param listener
+ */
+ public void removeServiceListener(ServiceListener listener)
+ {
+ listeners.remove(new FilteredServiceListener(null, listener));
+ }
+
+ public String getProperty(String name)
+ {
+ if (Constants.FRAMEWORK_VERSION.equals(name)) {
+ return "4.1";
+ }
+ /*added System.getProperty so that tests can set a system property
+ * but it is retrieved via the BundleContext.
+ * This allows tests to emulate different properties being set on the
+ * context, helpful for the feature pack launcher/kernel relationship
+ */
+ else if (System.getProperty(name) != null){
+ return System.getProperty(name);
+ }
+
+ return "";
+ }
+
+ /**
+ * @return the bundle associated with this bundle context (if we created one).
+ */
+ public Bundle getBundle()
+ {
+ return bundle;
+ }
+
+ /**
+ * This method clears the service registry.
+ */
+ public static void clear()
+ {
+ registry.clear();
+ bundles.clear();
+ listeners.clear();
+ nextId = 0;
+ }
+
+ public static List<ServiceListener> getServiceListeners()
+ {
+ return listeners;
+ }
+
+ public void addBundle(Bundle b)
+ {
+ bundles.add(b);
+ }
+}
\ No newline at end of file
Added: aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/BundleMock.java
URL: http://svn.apache.org/viewvc/aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/BundleMock.java?rev=1075107&view=auto
==============================================================================
--- aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/BundleMock.java (added)
+++ aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/BundleMock.java Sun Feb 27 18:31:58 2011
@@ -0,0 +1,391 @@
+/*
+ * 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.aries.mocks;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Vector;
+import java.util.regex.Pattern;
+
+import junit.framework.AssertionFailedError;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleReference;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+
+import org.apache.aries.unittest.mocks.MethodCall;
+import org.apache.aries.unittest.mocks.MethodCallHandler;
+import org.apache.aries.unittest.mocks.Skeleton;
+import org.apache.aries.unittest.mocks.annotations.Singleton;
+
+@Singleton
+public class BundleMock
+{
+ private final String symbolicName;
+ private final Dictionary<?, ?> headers;
+ private final BundleContext bc;
+ private String location;
+ private BundleClassLoader cl;
+
+ private class BundleClassLoader extends URLClassLoader implements BundleReference
+ {
+ List<Bundle> otherBundlesToCheck = new ArrayList<Bundle>();
+
+ public BundleClassLoader(URL[] urls)
+ {
+ super(urls);
+ }
+
+ public BundleClassLoader(URL[] urls, ClassLoader parent)
+ {
+ super(urls, parent);
+ }
+
+ public void addBundle(Bundle ... otherBundles)
+ {
+ otherBundlesToCheck.addAll(Arrays.asList(otherBundles));
+ }
+
+ public Bundle[] getBundles()
+ {
+ return otherBundlesToCheck.toArray(new Bundle[otherBundlesToCheck.size()]);
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException
+ {
+ Class<?> result = null;
+ for (Bundle b : otherBundlesToCheck) {
+ try {
+ result = b.loadClass(name);
+ } catch (ClassNotFoundException e) {
+ // do nothing here.
+ }
+
+ if (result != null) return result;
+ }
+
+ return super.findClass(name);
+ }
+
+ public Bundle getBundle()
+ {
+ return Skeleton.newMock(BundleMock.this, Bundle.class);
+ }
+ }
+
+ public BundleMock(String name, Dictionary<?, ?> bundleHeaders)
+ {
+ symbolicName = name;
+ headers = bundleHeaders;
+ bc = Skeleton.newMock(new BundleContextMock(Skeleton.newMock(this, Bundle.class)), BundleContext.class);
+
+ cl = AccessController.doPrivileged(new PrivilegedAction<BundleClassLoader>() {
+
+ public BundleClassLoader run()
+ {
+ return new BundleClassLoader(new URL[0], this.getClass().getClassLoader());
+ }
+ });
+ }
+
+ public BundleMock(String name, Dictionary<?,?> bundleHeaders, boolean dummy)
+ {
+ this(name, bundleHeaders);
+
+ cl = null;
+ }
+
+ public BundleMock(String name, Dictionary<?, ?> bundleHeaders, String location)
+ {
+ this(name, bundleHeaders);
+ this.location = location;
+
+ if (location != null) {
+ String cp = (String)bundleHeaders.get(Constants.BUNDLE_CLASSPATH);
+
+ if (cp == null) cp = ".";
+
+ String[] cpEntries = cp.split(",");
+
+ final List<URL> urls = new ArrayList<URL>();
+
+ try {
+ for (String cpEntry : cpEntries) {
+ if (".".equals(cpEntry.trim())) {
+ urls.add(new URL(location));
+ } else {
+ urls.add(new URL(location + "/" + cpEntry));
+ }
+ }
+
+ cl = AccessController.doPrivileged(new PrivilegedAction<BundleClassLoader>() {
+ public BundleClassLoader run()
+ {
+ return new BundleClassLoader(urls.toArray(new URL[urls.size()]));
+ }
+ });
+ } catch (MalformedURLException e) {
+ Error err = new AssertionFailedError("The location was not a valid url");
+ err.initCause(e);
+ throw err;
+ }
+ }
+ }
+
+ private static class PrivateDataFileHandler implements MethodCallHandler
+ {
+ private final File location;
+
+ public PrivateDataFileHandler(File f)
+ {
+ this.location = f;
+ }
+
+ public Object handle(MethodCall call, Skeleton parent)
+ {
+ File privateStorage = new File(location.getAbsolutePath(), "_private");
+ if (!!!privateStorage.exists())
+ privateStorage.mkdirs();
+
+ return new File(privateStorage, (String) call.getArguments()[0]);
+ }
+ }
+
+ public BundleMock(String name, Dictionary<?, ?> properties, File location) throws Exception
+ {
+ this(name,properties,location.toURL().toExternalForm());
+
+ Skeleton bcSkel = Skeleton.getSkeleton(bc);
+ bcSkel.registerMethodCallHandler(
+ new MethodCall(BundleContext.class,"getDataFile", new Object[] { String.class }),
+ new PrivateDataFileHandler(location)
+ );
+ }
+
+ public String getSymbolicName()
+ {
+ return symbolicName;
+ }
+
+ public Dictionary<?, ?> getHeaders()
+ {
+ return headers;
+ }
+
+ public Enumeration<URL> findEntries(String baseDir, String matchRule, boolean recurse)
+ {
+ System.err.println("findEntries: " + baseDir + ", " + matchRule + ", " + recurse);
+ File base;
+ try {
+ base = new File(new File(new URL(location.replaceAll(" ", "%20")).toURI()), baseDir);
+ System.err.println("Base dir: " + base);
+ } catch (Exception e) {
+ Error err = new AssertionFailedError("Unable to findEntries from " + location);
+ err.initCause(e);
+ throw err;
+ }
+
+ if (matchRule.equals("*.xml")) matchRule = ".*\\.xml";
+ else matchRule = matchRule.replaceAll("\\*", ".*");
+
+ System.err.println("matchrule: " + matchRule);
+
+ final Pattern p = Pattern.compile(matchRule);
+
+ File[] files = base.listFiles(new FileFilter(){
+ public boolean accept(File pathname)
+ {
+ return pathname.isFile() &&
+ p.matcher(pathname.getName()).matches();
+ }
+ });
+
+ Vector<URL> v = new Vector<URL>();
+
+ if (files != null) {
+ for (File f : files) {
+ try {
+ v.add(f.toURL());
+ } catch (MalformedURLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ } else {
+ System.err.println("no matching files");
+ }
+
+ if (v.isEmpty()) {
+ return null;
+ } else {
+ System.err.println(v);
+ return v.elements();
+ }
+ }
+
+ public URL getResource(String name)
+ {
+ if (cl != null) return cl.getResource(name);
+
+ try {
+ File f = new File(name);
+ if(f.exists() || "Entities.jar".equals(name)) return f.toURL();
+ else return null;
+ } catch (MalformedURLException e) {
+ Error err = new AssertionFailedError("The resource " + name + " could not be found.");
+ err.initCause(e);
+ throw err;
+ }
+ }
+
+ public Enumeration<URL> getResources(String name)
+ {
+ if (cl != null)
+ {
+ try {
+ return cl.getResources(name);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ else {
+ final URL resource = getResource(name);
+
+ if(resource != null) {
+ return new Enumeration<URL>() {
+
+ boolean hasMore = true;
+ public boolean hasMoreElements()
+ {
+ return hasMore;
+ }
+
+ public URL nextElement()
+ {
+ hasMore = false;
+ return resource;
+ }
+
+ };
+ }
+ }
+ return new Enumeration<URL>(){
+ public URL nextElement()
+ {
+ return null;
+ }
+
+ public boolean hasMoreElements()
+ {
+ return false;
+ }
+ };
+
+ }
+
+ public Class<?> loadClass(String name) throws ClassNotFoundException
+ {
+ if (cl != null) return Class.forName(name, false, cl);
+
+ throw new ClassNotFoundException("Argh, things went horribly wrong trying to load " + name);
+ }
+
+ public String getLocation()
+ {
+ try {
+ return (location == null) ? new File(symbolicName + ".jar").toURL().toString() : location;
+ } catch (MalformedURLException e) {
+ Error err = new AssertionFailedError("We could not generate a valid url for the bundle");
+ err.initCause(e);
+ throw err;
+ }
+ }
+
+ public BundleContext getBundleContext()
+ {
+ return bc;
+ }
+
+ public Version getVersion()
+ {
+ String res = (String) headers.get("Bundle-Version");
+ if (res != null)
+ return new Version(res);
+ else
+ return new Version("0.0.0");
+ }
+
+ public int getState()
+ {
+ return Bundle.ACTIVE;
+ }
+
+ public void addToClassPath(URL ... urls)
+ {
+ if (cl != null) {
+ URL[] existingURLs = cl.getURLs();
+ final URL[] mergedURLs = new URL[urls.length + existingURLs.length];
+ int i = 0;
+ for (; i < existingURLs.length; i++) {
+ mergedURLs[i] = existingURLs[i];
+ }
+
+ for (int j = 0; j < urls.length; j++, i++) {
+ mergedURLs[i] = urls[j];
+ }
+
+ BundleClassLoader newCl = AccessController.doPrivileged(new PrivilegedAction<BundleClassLoader>() {
+
+ public BundleClassLoader run()
+ {
+ return new BundleClassLoader(mergedURLs, cl.getParent());
+ }
+
+ });
+ newCl.addBundle(cl.getBundles());
+ cl = newCl;
+ }
+ }
+
+ public void addBundleToClassPath(Bundle ... bundles) {
+ if (cl != null) {
+ cl.addBundle(bundles);
+ }
+ }
+
+ public ClassLoader getClassLoader()
+ {
+ return cl;
+ }
+}
\ No newline at end of file
Added: aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/MockInitialContextFactoryBuilder.java
URL: http://svn.apache.org/viewvc/aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/MockInitialContextFactoryBuilder.java?rev=1075107&view=auto
==============================================================================
--- aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/MockInitialContextFactoryBuilder.java (added)
+++ aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/mocks/MockInitialContextFactoryBuilder.java Sun Feb 27 18:31:58 2011
@@ -0,0 +1,56 @@
+/*
+ * 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.aries.mocks;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+import javax.naming.spi.InitialContextFactoryBuilder;
+import javax.naming.spi.NamingManager;
+
+import org.apache.aries.unittest.mocks.MethodCall;
+import org.apache.aries.unittest.mocks.Skeleton;
+
+public class MockInitialContextFactoryBuilder implements InitialContextFactoryBuilder
+{
+ private static InitialContextFactory icf;
+
+ public InitialContextFactory createInitialContextFactory(Hashtable<?, ?> environment)
+ throws NamingException
+ {
+ return icf;
+ }
+
+ public static void start(Context ctx) throws NamingException
+ {
+ if (icf == null) {
+ NamingManager.setInitialContextFactoryBuilder(new MockInitialContextFactoryBuilder());
+ }
+
+ icf = Skeleton.newMock(InitialContextFactory.class);
+ getSkeleton().setReturnValue(new MethodCall(InitialContextFactory.class, "getInitialContext", Hashtable.class), ctx);
+ }
+
+ public static Skeleton getSkeleton()
+ {
+ return Skeleton.getSkeleton(icf);
+ }
+}
\ No newline at end of file
Added: aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/fixture/ArchiveFixture.java
URL: http://svn.apache.org/viewvc/aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/fixture/ArchiveFixture.java?rev=1075107&view=auto
==============================================================================
--- aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/fixture/ArchiveFixture.java (added)
+++ aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/fixture/ArchiveFixture.java Sun Feb 27 18:31:58 2011
@@ -0,0 +1,473 @@
+/**
+ * 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.aries.unittest.fixture;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.osgi.framework.Constants;
+
+/**
+ * Utility class for creating archive-based fixtures such as EBA archives, jar files etc.
+ * This class provides a flow based api for defining such fixtures. For example, a simple EBA archive could
+ * be defined as such:
+ *
+ * <code>
+ * ArchiveFixtures.ZipFixture zip = ArchiveFixtures.newZip()
+ * .jar("test.jar")
+ * .manifest()
+ * .symbolicName("com.ibm.test")
+ * .version("2.0.0")
+ * .end()
+ * .file("random.txt", "Some text")
+ * .end();
+ * </code>
+ *
+ * This defines a zip archive containing a single jar file (hence no application manifest). The jar file itself has
+ * a manifest and a text file.
+ *
+ * To actually create the physical archive use the <code>writeOut</code> method on the archive fixture.
+ */
+public class ArchiveFixture
+{
+ /**
+ * Create a new zip file fixture
+ * @return
+ */
+ public static ZipFixture newZip() {
+ return new ZipFixture(null);
+ }
+
+ /**
+ * Create a new jar file fixture
+ * @return
+ */
+ public static JarFixture newJar() {
+ return new JarFixture(null);
+ }
+
+ /**
+ * Utility to copy an InputStream into an OutputStream. Closes the InputStream afterwards.
+ * @param in
+ * @param out
+ * @throws IOException
+ */
+ private static void copy(InputStream in, OutputStream out) throws IOException
+ {
+ try {
+ int len;
+ byte[] b = new byte[1024];
+ while ((len = in.read(b)) != -1)
+ out.write(b,0,len);
+ }
+ finally {
+ in.close();
+ }
+ }
+
+ /**
+ * Base interface for every fixture.
+ */
+ public interface Fixture {
+ /**
+ * Write the physical representation of the fixture to the given OutputStream
+ * @param out
+ * @throws IOException
+ */
+ void writeOut(OutputStream out) throws IOException;
+ }
+
+ /**
+ * Abstract base class for fixtures. Archive fixtures are by nature hierarchical.
+ */
+ public static abstract class AbstractFixture implements Fixture {
+ private ZipFixture parent;
+
+ protected AbstractFixture(ZipFixture parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Ends the current flow target and returns the parent flow target. For example, in the
+ * following code snippet the <code>end</code> after <code>.version("2.0.0")</code> marks
+ * the end of the manifest. Commands after that relate to the parent jar file of the manifest.
+ *
+ * <code>
+ * ArchiveFixtures.ZipFixture zip = ArchiveFixtures.newZip()
+ * .jar("test.jar")
+ * .manifest()
+ * .symbolicName("com.ibm.test")
+ * .version("2.0.0")
+ * .end()
+ * .file("random.txt", "Some text")
+ * .end();
+ * </code>
+ * @return
+ */
+ public ZipFixture end() {
+ return (parent == null) ? (ZipFixture) this : parent;
+ }
+ }
+
+ /**
+ * Simple fixture for text files.
+ */
+ public static class FileFixture extends AbstractFixture {
+ private StringBuffer text = new StringBuffer();
+
+ protected FileFixture(ZipFixture parent) {
+ super(parent);
+ }
+
+ /**
+ * Add a line to the file fixture. The EOL character is added automatically.
+ * @param line
+ * @return
+ */
+ public FileFixture line(String line) {
+ text.append(line);
+ text.append("\n");
+ return this;
+ }
+
+ public void writeOut(OutputStream out) throws IOException {
+ out.write(text.toString().getBytes());
+ }
+ }
+
+ public static class IStreamFixture extends AbstractFixture {
+ private byte[] bytes;
+
+ protected IStreamFixture(ZipFixture parent, InputStream input) throws IOException {
+ super(parent);
+
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ try {
+ copy(input, output);
+ } finally {
+ output.close();
+ }
+
+ bytes = output.toByteArray();
+ }
+
+ public void writeOut(OutputStream out) throws IOException {
+ copy(new ByteArrayInputStream(bytes), out);
+ }
+ }
+
+ /**
+ * Fixture for (bundle) manifests. By default, they contain the lines
+ *
+ * <code>
+ * Manifest-Version: 1
+ * Bundle-ManifestVersion: 2
+ * </code>
+ */
+ public static class ManifestFixture extends AbstractFixture {
+ private Manifest mf;
+
+ protected Manifest getManifest()
+ {
+ return mf;
+ }
+
+ protected ManifestFixture(ZipFixture parent) {
+ super(parent);
+ mf = new Manifest();
+ mf.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1");
+ mf.getMainAttributes().putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
+ }
+
+ /**
+ * Set the symbolic name of the bundle
+ * @param name
+ * @return
+ */
+ public ManifestFixture symbolicName(String name)
+ {
+ mf.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, name);
+ return this;
+ }
+
+ /**
+ * Set the version of the bundle
+ * @param version
+ * @return
+ */
+ public ManifestFixture version(String version)
+ {
+ mf.getMainAttributes().putValue(Constants.BUNDLE_VERSION, version);
+ return this;
+ }
+
+ /**
+ * Add a custom attribute to the manifest. Use the more specific methods for symbolic name and version.
+ * @param name
+ * @param value
+ * @return
+ */
+ public ManifestFixture attribute(String name, String value)
+ {
+ mf.getMainAttributes().putValue(name, value);
+ return this;
+ }
+
+ public void writeOut(OutputStream out) throws IOException
+ {
+ mf.write(out);
+ }
+ }
+
+ /**
+ * Fixture for a jar archive. It offers the same functionality as zip fixtures.
+ * The main difference is that in a jar archive the manifest will be output as the first file,
+ * regardless of when it is added.
+ */
+ public static class JarFixture extends ZipFixture {
+ private ManifestFixture mfFixture;
+
+ protected JarFixture(ZipFixture parent) {
+ super(parent);
+ }
+
+ @Override
+ public ManifestFixture manifest()
+ {
+ if (mfFixture != null)
+ throw new IllegalStateException("Only one manifest allowed, you dummy ;)");
+
+ mfFixture = new ManifestFixture(this);
+ return mfFixture;
+ }
+
+ @Override
+ public void writeOut(OutputStream out) throws IOException
+ {
+ if (bytes == null) {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ JarOutputStream jout;
+ if (mfFixture != null)
+ jout = new JarOutputStream(bout, mfFixture.getManifest());
+ else
+ jout = new JarOutputStream(bout);
+
+ try {
+ writeAllEntries(jout);
+ } finally {
+ jout.close();
+ }
+
+ bytes = bout.toByteArray();
+ }
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
+ copy(bin, out);
+ }
+ }
+
+ /**
+ * Base fixture for any kind of zip archive. Zip archives can contain any number of child archives
+ * given by an archive type and a path. The order in which these child archives are added is important
+ * because it will be the order in which they are added to the zip.
+ */
+ public static class ZipFixture extends AbstractFixture {
+ protected static class ChildFixture {
+ public String path;
+ public Fixture fixture;
+
+ public ChildFixture(String path, Fixture fixture)
+ {
+ this.path = path;
+ this.fixture = fixture;
+ }
+ }
+
+ protected List<ChildFixture> children = new ArrayList<ChildFixture>();
+ protected byte[] bytes = null;
+
+ protected ZipFixture(ZipFixture parent) {
+ super(parent);
+ }
+
+ /**
+ * Create a child zip fixture at the given target.
+ * @param path
+ * @return
+ */
+ public ZipFixture zip(String path) {
+ ZipFixture res = new ZipFixture(this);
+ children.add(new ChildFixture(path, res));
+
+ return res;
+ }
+
+ /**
+ * Create a child jar fixture at the given path.
+ * @param path
+ * @return
+ */
+ public ZipFixture jar(String path) {
+ JarFixture res = new JarFixture(this);
+ children.add(new ChildFixture(path, res));
+
+ return res;
+ }
+
+ /**
+ * Create a complete child file fixture at the given path and with the content.
+ * Note: this will return the current zip fixture and not the file fixture.
+ *
+ * @param path
+ * @param content
+ * @return
+ */
+ public ZipFixture file(String path, String content)
+ {
+ return file(path).line(content).end();
+ }
+
+ /**
+ * Create an empty file fixture at the given path.
+ *
+ * @param path
+ * @return
+ */
+ public FileFixture file(String path)
+ {
+ FileFixture res = new FileFixture(this);
+ children.add(new ChildFixture(path, res));
+
+ return res;
+ }
+
+ /**
+ * Create a binary file with the content from the input stream
+ * @param path
+ * @param input
+ * @return
+ */
+ public ZipFixture binary(String path, InputStream input) throws IOException {
+
+ if (input == null) throw new IllegalArgumentException("Provided input stream cannot be null");
+
+ IStreamFixture child = new IStreamFixture(this, input);
+ children.add(new ChildFixture(path, child));
+
+ return this;
+ }
+
+ /**
+ * Create a binary file that is populated from content on the classloader
+ * @param path
+ * @param resourcePath Path that the resource can be found in the current classloader
+ * @return
+ */
+ public ZipFixture binary(String path, String resourcePath) throws IOException {
+ return binary(path, getClass().getClassLoader().getResourceAsStream(resourcePath));
+ }
+
+ /**
+ * Create a manifest fixture at the given path.
+ * @return
+ */
+ public ManifestFixture manifest()
+ {
+ ManifestFixture res = new ManifestFixture(this);
+ children.add(new ChildFixture("META-INF/MANIFEST.MF", res));
+
+ return res;
+ }
+
+ /**
+ * Ensure that the necessary directory entries for the entry are available
+ * in the zip file. Newly created entries are added to the set of directories.
+ *
+ * @param zout
+ * @param entry
+ * @param existingDirs
+ * @throws IOException
+ */
+ private void mkDirs(ZipOutputStream zout, String entry, Set<String> existingDirs) throws IOException
+ {
+ String[] parts = entry.split("/");
+ String dirName = "";
+ for (int i=0;i<parts.length-1;i++) {
+ dirName += parts[i] + "/";
+ if (!!!existingDirs.contains(dirName)) {
+ ZipEntry ze = new ZipEntry(dirName);
+ zout.putNextEntry(ze);
+ zout.closeEntry();
+
+ existingDirs.add(dirName);
+ }
+ }
+ }
+
+ /**
+ * Add all entries to the ZipOutputStream
+ * @param zout
+ * @throws IOException
+ */
+ protected void writeAllEntries(ZipOutputStream zout) throws IOException
+ {
+ Set<String> dirs = new HashSet<String>();
+
+ for (ChildFixture child : children) {
+ mkDirs(zout, child.path, dirs);
+
+ ZipEntry ze = new ZipEntry(child.path);
+ zout.putNextEntry(ze);
+ child.fixture.writeOut(zout);
+ zout.closeEntry();
+ }
+ }
+
+ public void writeOut(OutputStream out) throws IOException
+ {
+ /*
+ * For better reuse this method delegate the writing to writeAllEntries, which
+ * can be reused by the JarFixture.
+ */
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ ZipOutputStream zout = new ZipOutputStream(bout);
+ try {
+ writeAllEntries(zout);
+ } finally {
+ zout.close();
+ }
+
+ bytes = bout.toByteArray();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
+ copy(bin, out);
+ }
+ }
+
+}
Added: aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/junit/Assert.java
URL: http://svn.apache.org/viewvc/aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/junit/Assert.java?rev=1075107&view=auto
==============================================================================
--- aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/junit/Assert.java (added)
+++ aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/junit/Assert.java Sun Feb 27 18:31:58 2011
@@ -0,0 +1,80 @@
+/*
+ * 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.aries.unittest.junit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * A library of useful assertion routines.
+ */
+public class Assert
+{
+ /**
+ * This method checks that the two objects have the same hashCode. If the
+ * equalsObjects parameter is true then the objects must also be .equals equal
+ * if the equalsObject parameter is false then they must not be .equals equal.
+ *
+ * @param <T>
+ * @param obj the first object.
+ * @param obj2 the second object.
+ * @param equalObjects whether the objects are also equal.
+ */
+ public static <T> void assertHashCodeEquals(T obj, T obj2, boolean equalObjects)
+ {
+ assertEquals("The hashCodes were different, bad, bad, bad", obj.hashCode(), obj2.hashCode());
+ assertEquals("The two objects are not equal", equalObjects, obj.equals(obj2));
+ }
+
+ /**
+ * This method makes sure that the hashCodes are not equal. And that they
+ * are not .equals. This is because two objects of the same type cannot be
+ * .equals if they have different hashCodes.
+ *
+ * @param <T>
+ * @param obj
+ * @param obj2
+ */
+ public static <T> void assertHashCodeNotEquals(T obj, T obj2)
+ {
+ assertFalse("The the two hashCodes should be different: " + obj.hashCode() + ", " + obj2.hashCode(), obj.hashCode() == obj2.hashCode());
+ assertFalse("The two objects not equal", obj.equals(obj2));
+ }
+
+ /**
+ * This method asserts that the equals contract is upheld by type T.
+ *
+ * @param <T>
+ * @param info an instance of T
+ * @param info2 a different instance of T that is .equal to info
+ * @param info3 an instance of T that is not equal to info
+ */
+ public static <T> void assertEqualsContract(T info, T info2, T info3)
+ {
+ Object other = new Object();
+ if (info.getClass() == Object.class) other = "A string";
+
+ assertEquals(info, info);
+ assertFalse(info.equals(null));
+ assertTrue("Equals should be commutative", info.equals(info2) == info2.equals(info) && info2.equals(info3) == info3.equals(info2));
+ assertTrue("If two objects are equal, then they must both be equal (or not equal) to a third", info.equals(info3) == info2.equals(info3));
+ assertFalse("An object should not equal an object of a disparate type", info.equals(other));
+ }
+}
\ No newline at end of file
Added: aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/DefaultInvocationHandler.java
URL: http://svn.apache.org/viewvc/aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/DefaultInvocationHandler.java?rev=1075107&view=auto
==============================================================================
--- aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/DefaultInvocationHandler.java (added)
+++ aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/DefaultInvocationHandler.java Sun Feb 27 18:31:58 2011
@@ -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.aries.unittest.mocks;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * <p>This invocation handler is used by the Skeleton when nothing else is
+ * matched. If the return type is an interface it creates a dynamic proxy
+ * backed by the associated skeleton for return, if it is a class with a
+ * default constructor that will be returned.
+ * </p>
+ */
+public class DefaultInvocationHandler implements InvocationHandler
+{
+ /** The skeleton this handler is associated with */
+ private Skeleton _s;
+
+ /* ------------------------------------------------------------------------ */
+ /* DefaultInvocationHandler constructor
+ /* ------------------------------------------------------------------------ */
+ /**
+ * Creates an instance called by the specified skeleton.
+ *
+ * @param s The caller.
+ */
+ public DefaultInvocationHandler(Skeleton s)
+ {
+ this._s = s;
+ }
+
+ /* ------------------------------------------------------------------------ */
+ /* invoke method
+ /* ------------------------------------------------------------------------ */
+ /**
+ * Invoked when no ReturnType or MethodCall Handlers are defined.
+ *
+ * @param target The target object that was invoked.
+ * @param method The method that was invoked.
+ * @param arguments The arguments that were passed.
+ * @return A proxy or null.
+ * @throws Throwable
+ */
+ public Object invoke(Object target, Method method, Object[] arguments)
+ throws Throwable
+ {
+ Class<?> returnType = method.getReturnType();
+ Object obj = null;
+
+ if (returnType.isInterface())
+ {
+ obj = createProxy(new Class[] { returnType });
+ }
+ else
+ {
+ try
+ {
+ obj = returnType.newInstance();
+ }
+ catch (Exception e)
+ {
+ // if this occurs then assume no default constructor was visible.
+ }
+ }
+
+ return obj;
+ }
+
+ /* ------------------------------------------------------------------------ */
+ /* createProxy method
+ /* ------------------------------------------------------------------------ */
+ /**
+ * Creates and returns a proxy backed by the associated skeleton, that
+ * implements the specified interfaces. Null is returned if the return
+ * type array contains non interfaces.
+ *
+ * @param returnTypes The classes.
+ * @return The proxy or null.
+ */
+ public Object createProxy(Class<?> ... returnTypes)
+ {
+ Object result = null;
+
+ boolean allInterfaces = true;
+ for(int i = 0; (allInterfaces && i<returnTypes.length); i++)
+ allInterfaces = returnTypes[i].isInterface();
+
+ if (allInterfaces)
+ {
+ result = _s.createMock(returnTypes);
+ }
+ return result;
+ }
+}
Added: aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/DefaultMethodCallHandlers.java
URL: http://svn.apache.org/viewvc/aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/DefaultMethodCallHandlers.java?rev=1075107&view=auto
==============================================================================
--- aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/DefaultMethodCallHandlers.java (added)
+++ aries/tags/testsupport-0.1-incubating/testsupport-unit/src/main/java/org/apache/aries/unittest/mocks/DefaultMethodCallHandlers.java Sun Feb 27 18:31:58 2011
@@ -0,0 +1,138 @@
+/*
+ * 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.aries.unittest.mocks;
+
+/**
+ * <p>This class contains method call handlers for some default method handling.
+ * </p>
+ *
+ * <p>This class provides handlers for the toString, equals and hashCode
+ * methods. They reproduce the default Object implementations for dynamic
+ * mock objects, these can be overridden.
+ * </p>
+ */
+public class DefaultMethodCallHandlers
+{
+ /** A MethodCall representing the equals method */
+ private static MethodCall _equals;
+ /** A MethodCall representing the toString method */
+ private static MethodCall _toString;
+ /** A MethodCall representing the hashCode method */
+ private static MethodCall _hashCode;
+
+ /* ------------------------------------------------------------------------ */
+ /* static initializer
+ /* ------------------------------------------------------------------------ */
+ static
+ {
+ _equals = new MethodCall(Object.class, "equals", new Object[] {Object.class});
+ _toString = new MethodCall(Object.class, "toString", new Object[0]);
+ _hashCode = new MethodCall(Object.class, "hashCode", new Object[0]);
+ }
+
+ /**
+ * The Default MethodCallHandler for the equals method, performs an == check.
+ */
+ public static final MethodCallHandler EQUALS_HANDLER = new MethodCallHandler()
+ {
+ public Object handle(MethodCall methodCall, Skeleton parent) throws Exception
+ {
+ Object obj = methodCall.getInvokedObject();
+ Object toObj = methodCall.getArguments()[0];
+
+ if (toObj == null) return false;
+
+ if(parent.getTemplateObject() != null){
+ try {
+ if(Skeleton.isSkeleton(toObj) &&Skeleton.getSkeleton(toObj).getTemplateObject() != null){
+ return parent.getTemplateObject().equals(Skeleton.getSkeleton(toObj).getTemplateObject());
+ } else {
+ return false;
+ }
+ } catch (IllegalArgumentException iae) {
+ return parent.getTemplateObject().equals(toObj);
+ }
+ }
+
+
+ return obj == toObj ? Boolean.TRUE : Boolean.FALSE;
+ }
+ };
+
+ /**
+ * The Default MethodCallHandler for the toString method, reproduces
+ * <classname>@<hashCode>
+ */
+ public static final MethodCallHandler TOSTRING_HANDLER = new MethodCallHandler()
+ {
+ public Object handle(MethodCall methodCall, Skeleton parent) throws Exception
+ {
+ if(parent.getTemplateObject() != null)
+ return parent.getTemplateObject().toString();
+ Object obj = methodCall.getInvokedObject();
+ return obj.getClass().getName() + "@" + System.identityHashCode(obj);
+ }
+ };
+
+ /**
+ * The Default MethodCallHandler for the hashCode method, returns the
+ * identity hashCode.
+ */
+ public static final MethodCallHandler HASHCODE_HANDLER = new MethodCallHandler()
+ {
+ public Object handle(MethodCall methodCall, Skeleton parent) throws Exception
+ {
+ if(parent.getTemplateObject() != null)
+ return parent.getTemplateObject().hashCode();
+
+ return Integer.valueOf(System.identityHashCode(methodCall.getInvokedObject()));
+ }
+ };
+
+ /* ------------------------------------------------------------------------ */
+ /* registerDefaultHandlers method
+ /* ------------------------------------------------------------------------ */
+ /**
+ * This method registers the DefaultMethodCall Handlers with the specified
+ * skeleton.
+ *
+ * @param s a skeleton
+ */
+ public static void registerDefaultHandlers(Skeleton s)
+ {
+ s.registerMethodCallHandler(_equals, EQUALS_HANDLER);
+ s.registerMethodCallHandler(_toString, TOSTRING_HANDLER);
+ s.registerMethodCallHandler(_hashCode, HASHCODE_HANDLER);
+ }
+
+ /* ------------------------------------------------------------------------ */
+ /* isDefaultMethodCall method
+ /* ------------------------------------------------------------------------ */
+ /**
+ * This method returns true if and only if the specified call represents a
+ * default method call.
+ *
+ * @param call the call
+ * @return see above.
+ */
+ public static boolean isDefaultMethodCall(MethodCall call)
+ {
+ return _toString.equals(call) || _equals.equals(call) || _hashCode.equals(call);
+ }
+}