summaryrefslogtreecommitdiffstats
path: root/java/sca/modules/extensibility
diff options
context:
space:
mode:
authorrfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68>2008-07-08 23:10:31 +0000
committerrfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68>2008-07-08 23:10:31 +0000
commit2410d8844182e057fd59ea4139b9a7d61413bbea (patch)
treebf16f0379149936193778e805a2d88c3cad69959 /java/sca/modules/extensibility
parent755737f1cef0f827f6c87c3d55560adebdb776f0 (diff)
Make the ServiceDiscovery pluggable and add support for OSGi-based service discoverer
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@675040 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/sca/modules/extensibility')
-rw-r--r--java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ClasspathServiceDiscover.java237
-rw-r--r--java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java118
-rw-r--r--java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscoverer.java34
-rw-r--r--java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java273
-rw-r--r--java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ClasspathServiceDiscovererTestCase.java61
5 files changed, 427 insertions, 296 deletions
diff --git a/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ClasspathServiceDiscover.java b/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ClasspathServiceDiscover.java
new file mode 100644
index 0000000000..c83a7d9172
--- /dev/null
+++ b/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ClasspathServiceDiscover.java
@@ -0,0 +1,237 @@
+/*
+ * 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.tuscany.sca.extensibility;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.ref.WeakReference;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ */
+public class ClasspathServiceDiscover implements ServiceDiscoverer {
+
+ public class ServiceDeclarationImpl implements ServiceDeclaration {
+ private URL url;
+ private String className;
+ private Class<?> javaClass;
+ private Map<String, String> attributes;
+
+ public ServiceDeclarationImpl(URL url, String className, Map<String, String> attributes) {
+ super();
+ this.url = url;
+ this.className = className;
+ this.attributes = attributes;
+ }
+
+ public Map<String, String> getAttributes() {
+ return attributes;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public URL getLocation() {
+ return url;
+ }
+
+ public Class<?> loadClass() throws ClassNotFoundException {
+ if (className == null) {
+ return null;
+ }
+ if (javaClass == null) {
+ javaClass = loadClass(className);
+ }
+ return javaClass;
+ }
+
+ public Class<?> loadClass(String className) throws ClassNotFoundException {
+ return getClassLoader().loadClass(className);
+ }
+
+ private ClasspathServiceDiscover getOuterType() {
+ return ClasspathServiceDiscover.this;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("ClassLoader: ").append(getClassLoader());
+ sb.append(" Attributes: ").append(attributes);
+ return sb.toString();
+ }
+
+ public URL getResource(final String name) {
+ return AccessController.doPrivileged(new PrivilegedAction<URL>() {
+ public URL run() {
+ return getClassLoader().getResource(name);
+ }
+ });
+ }
+
+ }
+
+ private WeakReference<ClassLoader> classLoaderReference;
+ private static final Logger logger = Logger.getLogger(ClasspathServiceDiscover.class.getName());
+
+ public ClasspathServiceDiscover() {
+ // ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ ClassLoader classLoader = ClasspathServiceDiscover.class.getClassLoader();
+ this.classLoaderReference = new WeakReference<ClassLoader>(classLoader);
+ }
+
+ public ClasspathServiceDiscover(ClassLoader classLoader) {
+ this.classLoaderReference = new WeakReference<ClassLoader>(classLoader);
+ }
+
+ protected List<URL> getResources(final String name) throws IOException {
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<List<URL>>() {
+ public List<URL> run() throws IOException {
+ return Collections.list(getClassLoader().getResources(name));
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw (IOException)e.getException();
+ }
+ }
+
+ private ClassLoader getClassLoader() {
+ return classLoaderReference.get();
+ }
+
+ /**
+ * Parse a service declaration in the form class;attr=value,attr=value and
+ * return a map of attributes
+ *
+ * @param declaration
+ * @return a map of attributes
+ */
+ protected static Map<String, String> parseServiceDeclaration(String declaration) {
+ Map<String, String> attributes = new HashMap<String, String>();
+ int index = declaration.indexOf(';');
+ if (index != -1) {
+ attributes.put("class", declaration.substring(0, index).trim());
+ declaration = declaration.substring(index);
+ } else {
+ int j = declaration.indexOf('=');
+ if (j == -1) {
+ attributes.put("class", declaration.trim());
+ return attributes;
+ } else {
+ declaration = ";" + declaration;
+ }
+ }
+ StringTokenizer tokens = new StringTokenizer(declaration);
+ for (; tokens.hasMoreTokens();) {
+ String key = tokens.nextToken("=").substring(1).trim();
+ if (key == null)
+ break;
+ String value = tokens.nextToken(",").substring(1).trim();
+ if (value == null)
+ break;
+ attributes.put(key, value);
+ }
+ return attributes;
+ }
+
+ public Set<ServiceDeclaration> discover(String serviceName) {
+ Set<ServiceDeclaration> descriptors = new HashSet<ServiceDeclaration>();
+
+ String name = "META-INF/services/" + serviceName;
+ boolean debug = logger.isLoggable(Level.FINE);
+ try {
+ for (final URL url : getResources(name)) {
+ if (debug) {
+ logger.fine("Reading service provider file: " + url.toExternalForm());
+ }
+
+ // Allow privileged access to open URL stream. Add FilePermission to added to security
+ // policy file.
+ InputStream is;
+ try {
+ is = AccessController.doPrivileged(new PrivilegedExceptionAction<InputStream>() {
+ public InputStream run() throws IOException {
+ return url.openStream();
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw (IOException)e.getException();
+ }
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(is));
+ int count = 0;
+ while (true) {
+ String line = reader.readLine();
+ if (line == null)
+ break;
+ line = line.trim();
+ if (!line.startsWith("#") && !"".equals(line)) {
+ String reg = line.trim();
+ if (debug) {
+ logger.fine("Registering service provider: " + reg);
+ }
+
+ Map<String, String> attributes = parseServiceDeclaration(reg);
+ String className = attributes.get("class");
+ if (className == null) {
+ // Add a unique class name to prevent equals() from returning true
+ className = "_class_" + count;
+ count++;
+ }
+ ServiceDeclarationImpl descriptor = new ServiceDeclarationImpl(url, className, attributes);
+ descriptors.add(descriptor);
+ }
+ }
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ logger.log(Level.SEVERE, e.getMessage(), e);
+ }
+ return descriptors;
+
+ }
+
+}
diff --git a/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java b/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java
index 4b25f2adc2..403b6aa7a7 100644
--- a/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java
+++ b/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java
@@ -19,7 +19,6 @@
package org.apache.tuscany.sca.extensibility;
-import java.lang.ref.WeakReference;
import java.net.URL;
import java.util.Map;
@@ -30,107 +29,40 @@ import java.util.Map;
*
* @version $Rev$ $Date$
*/
-public class ServiceDeclaration {
-
- private WeakReference<ClassLoader> classLoader;
-
- private String className;
-
- private Map<String, String> attributes;
-
- /**
- * Service declaration constructor
- *
- * @param className Service implementation class name
- * @param classLoader ClassLoader corresponding to this service
- * implementation
- * @param attributes Optional attributes for this service declaration
- */
- public ServiceDeclaration(String className, ClassLoader classLoader, Map<String, String> attributes) {
-
- this.className = className;
- this.classLoader = new WeakReference<ClassLoader>(classLoader);
- this.attributes = attributes;
- }
-
+public interface ServiceDeclaration {
/**
- * Load this service implementation class
- *
- * @return Class
+ * Load a java class in the same context as the service definition
+ * @param className The class name
+ * @return The loaded class
* @throws ClassNotFoundException
*/
- @SuppressWarnings("unchecked")
- public Class<?> loadClass() throws ClassNotFoundException {
-
- return Class.forName(className, true, classLoader.get());
- }
-
+ Class<?> loadClass(String className) throws ClassNotFoundException;
/**
- * Load another class using the ClassLoader of this service implementation
- *
- * @param anotherClassName
- * @return Class
- * @throws ClassNotFoundException
+ * Get the java class for the service impl
+ * @return The java class
*/
- public Class<?> loadClass(String anotherClassName) throws ClassNotFoundException {
-
- return Class.forName(anotherClassName, true, classLoader.get());
- }
-
- /**
- * Return the resource corresponding to this service implementation class
- *
- * @return resource URL
- */
- public URL getResource() {
- return classLoader.get().getResource(className);
- }
-
+ Class<?> loadClass() throws ClassNotFoundException;
/**
- * ClassLoader associated with this service declaration
- *
- * @return ClassLoader
+ * Get all attributes (name=value pairs) defined for the given entry
+ * @return All attributes keyed by name
*/
- public ClassLoader getClassLoader() {
- return classLoader.get();
- }
-
+ Map<String, String> getAttributes();
+
+ URL getLocation();
+
+ String getClassName();
+
+ URL getResource(String name);
+
/**
- * Service implementation class corresponding to this declaration
- *
- * @return The Service implementation class corresponding to this declaration
+ * The service descriptor might be hashed
+ * @param obj Another object
+ * @return
*/
- public String getClassName() {
- return className;
- }
-
+ boolean equals(Object obj);
/**
- * Attributes specified for this declaration
- *
- * @return attributes
+ * The service descriptor might be hashed
+ * @return
*/
- public Map<String, String> getAttributes() {
- return attributes;
- }
-
- /**
- * Equals method used to ensure that each service declaration is stored only
- * once in a set of declarations.
- */
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof ServiceDeclaration))
- return false;
- ServiceDeclaration s = (ServiceDeclaration)o;
- if (!className.equals(s.className))
- return false;
- else if (!classLoader.equals(s.classLoader))
- return false;
- else if (attributes == null)
- return s.attributes == null;
- else
- return attributes.equals(s.attributes);
-
- }
-
+ int hashCode();
}
diff --git a/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscoverer.java b/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscoverer.java
new file mode 100644
index 0000000000..31f2cf600e
--- /dev/null
+++ b/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscoverer.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.tuscany.sca.extensibility;
+
+import java.util.Set;
+
+/**
+ *
+ */
+public interface ServiceDiscoverer {
+ /**
+ * Discover the service descriptors by name
+ * @param serviceName
+ * @return A set of service descriptors
+ */
+ Set<ServiceDeclaration> discover(String serviceName);
+}
diff --git a/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java b/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java
index 45a4494f24..412774c83b 100644
--- a/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java
+++ b/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java
@@ -19,23 +19,9 @@
package org.apache.tuscany.sca.extensibility;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Map;
import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.logging.Level;
import java.util.logging.Logger;
/**
@@ -50,9 +36,10 @@ import java.util.logging.Logger;
public class ServiceDiscovery {
private static final Logger logger = Logger.getLogger(ServiceDiscovery.class.getName());
- private static ServiceDiscovery instance;
+ private final static ServiceDiscovery instance = new ServiceDiscovery();
- private HashSet<ClassLoader> registeredClassLoaders;
+ private static ServiceDiscoverer discoverer;
+ private Set<ClassLoader> registeredClassLoaders = new HashSet<ClassLoader>();
/**
* Get an instance of Service discovery, one instance is created per
@@ -61,15 +48,29 @@ public class ServiceDiscovery {
* @return
*/
public static ServiceDiscovery getInstance() {
-
- if (instance == null) {
- instance = new ServiceDiscovery();
- instance.registeredClassLoaders = new HashSet<ClassLoader>();
- instance.registeredClassLoaders.add(ServiceDiscovery.class.getClassLoader());
- }
+//
+// if (instance == null) {
+// instance = new ServiceDiscovery();
+// instance.registeredClassLoaders = new HashSet<ClassLoader>();
+// instance.registeredClassLoaders.add(ServiceDiscovery.class.getClassLoader());
+// }
return instance;
}
-
+
+ public static ServiceDiscoverer getServiceDiscoverer() {
+ if (discoverer == null) {
+ discoverer = new ClasspathServiceDiscover();
+ }
+ return discoverer;
+ }
+
+ public static void setServiceDiscoverer(ServiceDiscoverer sd) {
+ if (discoverer != null) {
+ throw new IllegalStateException("The ServiceDiscoverer cannot be reset");
+ }
+ discoverer = sd;
+ }
+
/**
* Register a ClassLoader with this discovery mechanism. Tuscany extension
* ClassLoaders are registered here.
@@ -96,14 +97,10 @@ public class ServiceDiscovery {
* @return set of service declarations
* @throws IOException
*/
- public synchronized Set<ServiceDeclaration> getServiceDeclarations(String name) throws IOException {
-
- Set<ServiceDeclaration> classSet = new HashSet<ServiceDeclaration>();
-
- for (ClassLoader classLoader : registeredClassLoaders) {
- getServiceClasses(classLoader, name, classSet, true);
- }
- return classSet;
+ public Set<ServiceDeclaration> getServiceDeclarations(String name) throws IOException {
+ // Set<ServiceDeclaration> classSet = new HashSet<ServiceDeclaration>();
+ Set<ServiceDeclaration> services = getServiceDiscoverer().discover(name);
+ return services;
}
/**
@@ -126,185 +123,55 @@ public class ServiceDiscovery {
* @throws IOException
* @throws ClassNotFoundException
*/
- public synchronized Class<?> loadFirstServiceClass(Class<?> serviceInterface) throws IOException, ClassNotFoundException {
+ public Class<?> loadFirstServiceClass(Class<?> serviceInterface) throws IOException, ClassNotFoundException {
+ Set<ServiceDeclaration> services = getServiceDiscoverer().discover(serviceInterface.getName());
+ if(services.isEmpty()) {
+ return null;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- Set<ServiceDeclaration> classSet = new HashSet<ServiceDeclaration>();
- for (ClassLoader classLoader : registeredClassLoaders) {
- getServiceClasses(classLoader, serviceInterface.getName(), classSet, false);
- if (classSet.size() > 0)
- break;
- }
- if (classSet.size() > 0)
- return classSet.iterator().next().loadClass();
- else
- return null;
- }
- /**
- * Returns a unique list of resource URLs of name META-INF/services/<name>
- * Each URL is associated with the first ClassLoader that it was visible
- * from
- *
- * @param name Name of resource
- * @return Table of URLs with associated ClassLoaders
- * @throws IOException
- */
- public synchronized Hashtable<ClassLoader, Set<URL>> getServiceResources(final String name) throws IOException {
-
- Hashtable<ClassLoader, Set<URL>> resourceTable = new Hashtable<ClassLoader, Set<URL>>();
-
- HashSet<URL> allURLs = new HashSet<URL>();
- for (final ClassLoader classLoader : registeredClassLoaders) {
- HashSet<URL> urls = new HashSet<URL>();
- resourceTable.put(classLoader, urls);
- boolean debug = logger.isLoggable(Level.FINE);
- if (debug) {
- logger.fine("Discovering service resources using class loader " + classLoader);
- }
- // Allow privileged access to read META-INF/services/*. Add FilePermission to added to security policy file.
- ArrayList<URL> urlList;
- try {
- // FIXME J2 Security - promote this to callers of this method
- urlList = AccessController.doPrivileged(new PrivilegedExceptionAction<ArrayList<URL>>() {
- public ArrayList<URL> run() throws IOException {
- return Collections.list(classLoader.getResources("META-INF/services/" + name));
- }
- });
- } catch (PrivilegedActionException e) {
- throw (IOException)e.getException();
- }
-
- for (URL url : urlList) {
- if (allURLs.contains(url))
- continue;
- urls.add(url);
- }
- allURLs.addAll(urls);
- }
- return resourceTable;
- }
- /**
- * Parse a service declaration in the form class;attr=value,attr=value and
- * return a map of attributes
- *
- * @param declaration
- * @return a map of attributes
- */
- private Map<String, String> parseServiceDeclaration(String declaration) {
- Map<String, String> attributes = new HashMap<String, String>();
- int index = declaration.indexOf(';');
- if (index != -1) {
- attributes.put("class", declaration.substring(0, index).trim());
- declaration = declaration.substring(index);
- } else {
- int j = declaration.indexOf('=');
- if (j == -1) {
- attributes.put("class", declaration.trim());
- return attributes;
- } else {
- declaration = ";" + declaration;
- }
- }
- StringTokenizer tokens = new StringTokenizer(declaration);
- for (; tokens.hasMoreTokens();) {
- String key = tokens.nextToken("=").substring(1).trim();
- if (key == null)
- break;
- String value = tokens.nextToken(",").substring(1).trim();
- if (value == null)
- break;
- attributes.put(key, value);
- }
- return attributes;
- }
- /**
- * Load the service class whose name specified in a configuration file
- *
- * @param classLoader
- * @param name The name of the service class
- * @param classSet Populate this set with classes extends/implements the
- * service class
- * @throws IOException
- */
- private void getServiceClasses(final ClassLoader classLoader,
- final String name,
- Set<ServiceDeclaration> classSet,
- boolean findAllClasses) throws IOException {
-
- boolean debug = logger.isLoggable(Level.FINE);
- if (debug) {
- logger.fine("Discovering service providers using class loader " + classLoader);
- }
- // Allow privileged access to read META-INF/services/*. Add FilePermission to added to
- // security policy file.
- ArrayList<URL> urlList;
- try {
- urlList = AccessController.doPrivileged(new PrivilegedExceptionAction<ArrayList<URL>>() {
- public ArrayList<URL> run() throws IOException {
- return Collections.list(classLoader.getResources("META-INF/services/" + name));
- }
- });
- } catch (PrivilegedActionException e) {
- throw (IOException)e.getException();
- }
-
- for (final URL url : urlList) {
- if (debug) {
- logger.fine("Reading service provider file: " + url.toExternalForm());
- }
-
- // Allow privileged access to open URL stream. Add FilePermission to added to security
- // policy file.
- InputStream is;
- try {
- is = AccessController.doPrivileged(new PrivilegedExceptionAction<InputStream>() {
- public InputStream run() throws IOException {
- return url.openStream();
- }
- });
- } catch (PrivilegedActionException e) {
- throw (IOException)e.getException();
- }
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new InputStreamReader(is));
- while (true) {
- String line = reader.readLine();
- if (line == null)
- break;
- line = line.trim();
- if (!line.startsWith("#") && !"".equals(line)) {
- String reg = line.trim();
- if (debug) {
- logger.fine("Registering service provider: " + reg);
- }
-
- Map<String, String> attributes = parseServiceDeclaration(reg);
- String className = attributes.get("class");
- ServiceDeclaration serviceClass = new ServiceDeclaration(className, classLoader, attributes);
- classSet.add(serviceClass);
-
- if (!findAllClasses)
- break;
- }
- }
- } finally {
- if (reader != null)
- reader.close();
- if (is != null) {
- try {
- is.close();
- } catch (IOException ioe) {
- }
- }
- }
- if (!findAllClasses && classSet.size() > 0)
- break;
}
+ return services.iterator().next().loadClass();
}
}
diff --git a/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ClasspathServiceDiscovererTestCase.java b/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ClasspathServiceDiscovererTestCase.java
new file mode 100644
index 0000000000..cf203cce7a
--- /dev/null
+++ b/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ClasspathServiceDiscovererTestCase.java
@@ -0,0 +1,61 @@
+/*
+ * 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.tuscany.sca.extensibility;
+
+import java.util.Set;
+
+import junit.framework.Assert;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test Case for ClasspathServiceDiscover
+ */
+public class ClasspathServiceDiscovererTestCase {
+ private static ClasspathServiceDiscover discover;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ discover = new ClasspathServiceDiscover(ClasspathServiceDiscover.class.getClassLoader());
+ }
+
+ @Test
+ public void testDiscovery() {
+ Set<ServiceDeclaration> discriptors =
+ discover.discover("org.apache.tuscany.sca.core.ModuleActivatorExtensionPoint");
+ Assert.assertEquals(1, discriptors.size());
+ discriptors =
+ discover.discover("notthere");
+ Assert.assertEquals(0, discriptors.size());
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+}