summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68>2009-07-31 01:59:16 +0000
committerrfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68>2009-07-31 01:59:16 +0000
commit12b7cae9bf154e509f3769404f090ce15d1e3b77 (patch)
tree977637aa0761eab5fc3f4725157d430dc3c310d0
parent3ed44524c6e7fa0646329412ac04fa9bef3fd942 (diff)
Enhance the service discovery by testing the types
Add more test cases Improve the syntax parsing for service declarations git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@799486 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java50
-rw-r--r--java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoveryActivator.java6
-rw-r--r--java/sca/modules/extensibility-equinox/src/test/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscovererTestCase.java2
-rw-r--r--java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ContextClassLoaderServiceDiscoverer.java52
-rw-r--r--java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java11
-rw-r--r--java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclarationParser.java264
-rw-r--r--java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java47
-rw-r--r--java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ServiceDiscoveryTestCase.java68
-rw-r--r--java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/DummyImpl.java31
-rw-r--r--java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/Test2Impl.java34
-rw-r--r--java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestImpl.java34
-rw-r--r--java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestInterface.java27
-rw-r--r--java/sca/modules/extensibility/src/test/resources/META-INF/services/org.apache.tuscany.sca.extensibility.test.TestInterface19
13 files changed, 560 insertions, 85 deletions
diff --git a/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java b/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java
index 930b308dfc..61bba30719 100644
--- a/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java
+++ b/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java
@@ -19,6 +19,8 @@
package org.apache.tuscany.sca.extensibility.equinox;
+import static org.apache.tuscany.sca.extensibility.ServiceDeclarationParser.parseDeclaration;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@@ -35,7 +37,6 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
-import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -122,6 +123,15 @@ public class EquinoxServiceDiscoverer implements ServiceDiscoverer {
return bundle;
}
+ public boolean isAssignableTo(Class<?> serviceType) {
+ try {
+ loadClass();
+ } catch (ClassNotFoundException e) {
+ // Ignore
+ }
+ return (javaClass != null && serviceType.isAssignableFrom(javaClass));
+ }
+
}
/**
@@ -156,40 +166,6 @@ public class EquinoxServiceDiscoverer implements ServiceDiscoverer {
}
- /**
- * 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 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 ServiceDeclaration getServiceDeclaration(String name) throws IOException {
Collection<ServiceDeclaration> declarations = getServiceDeclarations(name);
@@ -285,7 +261,7 @@ public class EquinoxServiceDiscoverer implements ServiceDiscoverer {
attributes.put(key, value);
attributes.put("uri", key);
}
- attributes.put("class", value);
+ attributes.putAll(parseDeclaration(value));
ServiceDeclarationImpl descriptor = new ServiceDeclarationImpl(bundle, url, value, attributes);
descriptors.add(descriptor);
}
@@ -306,7 +282,7 @@ public class EquinoxServiceDiscoverer implements ServiceDiscoverer {
logger.fine("Registering service provider: " + reg);
}
- Map<String, String> attributes = parseServiceDeclaration(reg);
+ Map<String, String> attributes = parseDeclaration(reg);
String className = attributes.get("class");
if (className == null) {
// Add a unique class name to prevent equals() from returning true
diff --git a/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoveryActivator.java b/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoveryActivator.java
index d5d7b92022..a9a0d6d3f6 100644
--- a/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoveryActivator.java
+++ b/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoveryActivator.java
@@ -19,8 +19,6 @@
package org.apache.tuscany.sca.extensibility.equinox;
-import java.util.logging.Logger;
-
import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
@@ -31,12 +29,12 @@ import org.osgi.framework.BundleContext;
* @version $Rev$ $Date$
*/
public class EquinoxServiceDiscoveryActivator implements BundleActivator {
- private static final Logger logger = Logger.getLogger(EquinoxServiceDiscoveryActivator.class.getName());
+ // private static final Logger logger = Logger.getLogger(EquinoxServiceDiscoveryActivator.class.getName());
public void start(BundleContext context) throws Exception {
EquinoxServiceDiscoverer discoverer = new EquinoxServiceDiscoverer(context);
ServiceDiscovery.getInstance().setServiceDiscoverer(discoverer);
- logger.info("Equinox-based service discoverer is now configured.");
+ // logger.info("Equinox-based service discoverer is now configured.");
}
public void stop(BundleContext context) throws Exception {
diff --git a/java/sca/modules/extensibility-equinox/src/test/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscovererTestCase.java b/java/sca/modules/extensibility-equinox/src/test/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscovererTestCase.java
index 2ed3cfd82c..deb4221f4f 100644
--- a/java/sca/modules/extensibility-equinox/src/test/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscovererTestCase.java
+++ b/java/sca/modules/extensibility-equinox/src/test/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscovererTestCase.java
@@ -108,6 +108,7 @@ public class EquinoxServiceDiscovererTestCase {
for (Bundle b : bundles) {
b.start();
System.out.println("Started "+b.getSymbolicName() + " [" + getState(b) + "]");
+ /*
// Get the Platform.getExtensionRegistry()
if ("org.eclipse.core.runtime".equals(b.getSymbolicName())) {
// The Platform class loaded by the bundle is different that the one
@@ -117,6 +118,7 @@ public class EquinoxServiceDiscovererTestCase {
Object reg = m.invoke(cls);
System.out.println(reg);
}
+ */
}
}
diff --git a/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ContextClassLoaderServiceDiscoverer.java b/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ContextClassLoaderServiceDiscoverer.java
index 13f967c053..3d733d042e 100644
--- a/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ContextClassLoaderServiceDiscoverer.java
+++ b/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ContextClassLoaderServiceDiscoverer.java
@@ -19,6 +19,8 @@
package org.apache.tuscany.sca.extensibility;
+import static org.apache.tuscany.sca.extensibility.ServiceDeclarationParser.parseDeclaration;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@@ -37,7 +39,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
-import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -104,6 +105,14 @@ public class ContextClassLoaderServiceDiscoverer implements ServiceDiscoverer {
});
}
+ public boolean isAssignableTo(Class<?> serviceType) {
+ try {
+ loadClass();
+ } catch (ClassNotFoundException e) {
+ // Ignore
+ }
+ return (javaClass != null && serviceType.isAssignableFrom(javaClass));
+ }
}
private WeakReference<ClassLoader> classLoaderReference;
@@ -126,41 +135,6 @@ public class ContextClassLoaderServiceDiscoverer implements ServiceDiscoverer {
}
}
- /**
- * 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 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 ServiceDeclaration getServiceDeclaration(String name) throws IOException {
Collection<ServiceDeclaration> declarations = getServiceDeclarations(name);
if (declarations.isEmpty()) {
@@ -212,7 +186,7 @@ public class ContextClassLoaderServiceDiscoverer implements ServiceDiscoverer {
String key = (String)e.getKey();
String value = (String)e.getValue();
// Unfortunately, the xalan file only has the classname
- if ("".equals(value)) {
+ if (value == null || "".equals(value)) {
value = key;
key = "";
}
@@ -220,7 +194,7 @@ public class ContextClassLoaderServiceDiscoverer implements ServiceDiscoverer {
attributes.put(key, value);
attributes.put("uri", key);
}
- attributes.put("class", value);
+ attributes.putAll(parseDeclaration(value));
ServiceDeclarationImpl descriptor = new ServiceDeclarationImpl(url, value, attributes);
descriptors.add(descriptor);
}
@@ -241,7 +215,7 @@ public class ContextClassLoaderServiceDiscoverer implements ServiceDiscoverer {
logger.fine("Registering service provider: " + reg);
}
- Map<String, String> attributes = parseServiceDeclaration(reg);
+ Map<String, String> attributes = parseDeclaration(reg);
String className = attributes.get("class");
if (className == null) {
// Add a unique class name to prevent equals() from returning true
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 d7ac8b449f..209a30b08e 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
@@ -50,8 +50,19 @@ public interface ServiceDeclaration {
*/
Map<String, String> getAttributes();
+ /**
+ * Check if the service implementation class is a type of the service
+ * @param serviceType The java class of the service SPI
+ * @return true if the implementation class is a type of the service
+ */
+ boolean isAssignableTo(Class<?> serviceType);
+
URL getLocation();
+ /**
+ * Return the class name for the service provider
+ * @return
+ */
String getClassName();
URL getResource(String name);
diff --git a/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclarationParser.java b/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclarationParser.java
new file mode 100644
index 0000000000..537aac2e64
--- /dev/null
+++ b/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclarationParser.java
@@ -0,0 +1,264 @@
+/*
+ * 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.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Parser for the service descriptors. The syntax of the service declaration is similar with the OSGi
+ * headers with the following exceptions:
+ * <ul>
+ * <li>Tuscany uses , and ; as the separator for attibutes
+ * <li>Tuscany
+ */
+public class ServiceDeclarationParser {
+
+ // private static final String PATH_SEPARATOR = ","; // OSGi style
+ private static final String PATH_SEPARATOR = "|";
+
+ // private static final String SEGMENT_SEPARATOR = ";"; // OSGi style
+ private static final String SEGMENT_SEPARATOR = ";,";
+
+ private static final String ATTRIBUTE_SEPARATOR = "=";
+ private static final String DIRECTIVE_SEPARATOR = ":=";
+
+ private static final char QUOTE_CHAR = '"';
+ private static final String QUOTE = "\"";
+
+ // Like this: path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2,
+ // path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
+ public static List<Descriptor> parse(String header) {
+
+ if (header != null) {
+ if (header.length() == 0) {
+ throw new IllegalArgumentException("A header cannot be an empty string.");
+ }
+
+ String[] clauseStrings = parseDelimitedString(header, PATH_SEPARATOR);
+
+ List<Descriptor> completeList = new ArrayList<Descriptor>();
+ for (int i = 0; (clauseStrings != null) && (i < clauseStrings.length); i++) {
+ completeList.add(parseClause(clauseStrings[i]));
+ }
+
+ return completeList;
+ }
+
+ return null;
+
+ }
+
+ /**
+ * Parse the declaration into a map of name/value pairs. The class name is added under "class"
+ * and directives are added using @<directiveName> as the key.
+ * @param declaration
+ * @return A map of attributes
+ */
+ public static Map<String, String> parseDeclaration(String declaration) {
+ List<Descriptor> descriptors = parse(declaration);
+ Descriptor descriptor = descriptors.get(0);
+ Map<String, String> map = new HashMap<String, String>();
+ map.putAll(descriptor.getAttributes());
+ map.put("class", descriptor.getValue());
+ for (Map.Entry<String, String> e : descriptor.getDirectives().entrySet()) {
+ // For directives, add @ as the prefix for the key
+ map.put("@" + e.getKey(), e.getValue());
+ }
+ return map;
+ }
+
+ // Like this: path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
+ private static Descriptor parseClause(String clauseString) throws IllegalArgumentException {
+ // Break string into semi-colon delimited pieces.
+ String[] pieces = parseDelimitedString(clauseString, SEGMENT_SEPARATOR);
+
+ // Count the number of different paths; paths
+ // will not have an '=' in their string. This assumes
+ // that paths come first, before directives and
+ // attributes.
+ int pathCount = 0;
+ for (int pieceIdx = 0; pieceIdx < pieces.length; pieceIdx++) {
+ if (pieces[pieceIdx].indexOf('=') >= 0) {
+ break;
+ }
+ pathCount++;
+ }
+
+ // Create an array of paths.
+ String[] paths = new String[pathCount];
+ System.arraycopy(pieces, 0, paths, 0, pathCount);
+
+ // Parse the directives/attributes.
+ Map<String, String> dirsMap = new HashMap<String, String>();
+ Map<String, String> attrsMap = new HashMap<String, String>();
+ int idx = -1;
+ String sep = null;
+ for (int pieceIdx = pathCount; pieceIdx < pieces.length; pieceIdx++) {
+ // Check if it is a directive.
+ if ((idx = pieces[pieceIdx].indexOf(DIRECTIVE_SEPARATOR)) >= 0) {
+ sep = DIRECTIVE_SEPARATOR;
+ }
+ // Check if it is an attribute.
+ else if ((idx = pieces[pieceIdx].indexOf(ATTRIBUTE_SEPARATOR)) >= 0) {
+ sep = ATTRIBUTE_SEPARATOR;
+ }
+ // It is an error.
+ else {
+ throw new IllegalArgumentException("Not a directive/attribute: " + clauseString);
+ }
+
+ String key = pieces[pieceIdx].substring(0, idx).trim();
+ String value = pieces[pieceIdx].substring(idx + sep.length()).trim();
+
+ // Remove quotes, if value is quoted.
+ if (value.startsWith(QUOTE) && value.endsWith(QUOTE)) {
+ value = value.substring(1, value.length() - 1);
+ }
+
+ // Save the directive/attribute in the appropriate array.
+ if (sep.equals(DIRECTIVE_SEPARATOR)) {
+ // Check for duplicates.
+ if (dirsMap.get(key) != null) {
+ throw new IllegalArgumentException("Duplicate directive: " + key);
+ }
+ dirsMap.put(key, value);
+ } else {
+ // Check for duplicates.
+ if (attrsMap.get(key) != null) {
+ throw new IllegalArgumentException("Duplicate attribute: " + key);
+ }
+ attrsMap.put(key, value);
+ }
+ }
+
+ StringBuffer path = new StringBuffer();
+ for (int i = 0; i < paths.length; i++) {
+ path.append(paths[i]);
+ if (i != paths.length - 1) {
+ path.append(';');
+ }
+ }
+
+ Descriptor descriptor = new Descriptor();
+ descriptor.text = clauseString;
+ descriptor.value = path.toString();
+ descriptor.valueComponents = paths;
+ descriptor.attributes = attrsMap;
+ descriptor.directives = dirsMap;
+
+ return descriptor;
+ }
+
+ /**
+ * Parses delimited string and returns an array containing the tokens. This
+ * parser obeys quotes, so the delimiter character will be ignored if it is
+ * inside of a quote. This method assumes that the quote character is not
+ * included in the set of delimiter characters.
+ * @param value the delimited string to parse.
+ * @param delim the characters delimiting the tokens.
+ * @return an array of string tokens or null if there were no tokens.
+ **/
+ private static String[] parseDelimitedString(String value, String delim) {
+ if (value == null) {
+ value = "";
+ }
+
+ List<String> list = new ArrayList<String>();
+
+ int CHAR = 1;
+ int DELIMITER = 2;
+ int STARTQUOTE = 4;
+ int ENDQUOTE = 8;
+
+ StringBuffer sb = new StringBuffer();
+
+ int expecting = (CHAR | DELIMITER | STARTQUOTE);
+
+ for (int i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+
+ boolean isDelimiter = (delim.indexOf(c) >= 0);
+ boolean isQuote = (c == QUOTE_CHAR);
+
+ if (isDelimiter && ((expecting & DELIMITER) > 0)) {
+ list.add(sb.toString().trim());
+ sb.delete(0, sb.length());
+ expecting = (CHAR | DELIMITER | STARTQUOTE);
+ } else if (isQuote && ((expecting & STARTQUOTE) > 0)) {
+ sb.append(c);
+ expecting = CHAR | ENDQUOTE;
+ } else if (isQuote && ((expecting & ENDQUOTE) > 0)) {
+ sb.append(c);
+ expecting = (CHAR | STARTQUOTE | DELIMITER);
+ } else if ((expecting & CHAR) > 0) {
+ sb.append(c);
+ } else {
+ throw new IllegalArgumentException("Invalid delimited string: " + value);
+ }
+ }
+
+ if (sb.length() > 0) {
+ list.add(sb.toString().trim());
+ }
+
+ return (String[])list.toArray(new String[list.size()]);
+ }
+
+ public static class Descriptor {
+ private String text;
+ private String value;
+ private String[] valueComponents;
+ private Map<String, String> attributes;
+ private Map<String, String> directives;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public String[] getValueComponents() {
+ return valueComponents;
+ }
+
+ public void setValueComponents(String[] valueComponents) {
+ this.valueComponents = valueComponents;
+ }
+
+ public Map<String, String> getAttributes() {
+ return attributes;
+ }
+
+ public Map<String, String> getDirectives() {
+ return directives;
+ }
+
+ public String toString() {
+ return text;
+ }
+
+ }
+
+}
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 081693b02b..ec95aba7e1 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
@@ -24,7 +24,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Iterator;
import java.util.List;
+import java.util.logging.Level;
import java.util.logging.Logger;
/**
@@ -44,6 +46,7 @@ public final class ServiceDiscovery implements ServiceDiscoverer {
private ServiceDiscovery() {
super();
}
+
/**
* Get an instance of Service discovery, one instance is created per
* ClassLoader that this class is loaded from
@@ -112,19 +115,53 @@ public final class ServiceDiscovery implements ServiceDiscoverer {
* be returned.
*/
public ServiceDeclaration getServiceDeclaration(final String name) throws IOException {
- // ServiceDeclaration service = getServiceDiscoverer().getFirstServiceDeclaration(name);
- // return service;
Collection<ServiceDeclaration> declarations = getServiceDeclarations(name, true);
if (!declarations.isEmpty()) {
- List<ServiceDeclaration> declarationList = new ArrayList<ServiceDeclaration>(declarations);
- Collections.sort(declarationList, ServiceComparator.DESCENDING_ORDER);
- return declarationList.get(0);
+ // List<ServiceDeclaration> declarationList = new ArrayList<ServiceDeclaration>(declarations);
+ // Collections.sort(declarationList, ServiceComparator.DESCENDING_ORDER);
+ return declarations.iterator().next();
} else {
return null;
}
}
/**
+ * Get service declarations that are filtered by the service type. In an OSGi runtime, there
+ * might be different versions of the services
+ * @param serviceType
+ * @return
+ * @throws IOException
+ */
+ public Collection<ServiceDeclaration> getServiceDeclarations(Class<?> serviceType, boolean byRanking)
+ throws IOException {
+ Collection<ServiceDeclaration> sds = getServiceDeclarations(serviceType.getName(), byRanking);
+ for (Iterator<ServiceDeclaration> i = sds.iterator(); i.hasNext();) {
+ ServiceDeclaration sd = i.next();
+ if (!sd.isAssignableTo(serviceType)) {
+ logger.log(Level.WARNING, "Service provider {0} is not a type of {1}", new Object[] {
+ sd,
+ serviceType
+ .getName()});
+ i.remove();
+ }
+ }
+ return sds;
+ }
+
+ public Collection<ServiceDeclaration> getServiceDeclarations(Class<?> serviceType) throws IOException {
+ return getServiceDeclarations(serviceType, false);
+ }
+
+ public ServiceDeclaration getServiceDeclaration(Class<?> serviceType) throws IOException {
+ Collection<ServiceDeclaration> sds = getServiceDeclarations(serviceType, true);
+ if (sds.isEmpty()) {
+ return null;
+ } else {
+ return sds.iterator().next();
+ }
+ }
+
+ /**
* Compare service declarations by ranking
*/
private static class ServiceComparator implements Comparator<ServiceDeclaration> {
diff --git a/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ServiceDiscoveryTestCase.java b/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ServiceDiscoveryTestCase.java
new file mode 100644
index 0000000000..7d0413ef17
--- /dev/null
+++ b/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ServiceDiscoveryTestCase.java
@@ -0,0 +1,68 @@
+/*
+ * 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.Collection;
+import java.util.Iterator;
+
+import org.apache.tuscany.sca.extensibility.test.TestInterface;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class ServiceDiscoveryTestCase {
+ private static final String NAME = "org.apache.tuscany.sca.extensibility.test.TestInterface";
+
+ @Test
+ public void testRanking() throws Exception {
+ ServiceDeclaration sd = ServiceDiscovery.getInstance().getServiceDeclaration(NAME);
+ Assert.assertEquals("org.apache.tuscany.sca.extensibility.test.Test2Impl", sd.getClassName());
+
+ Collection<ServiceDeclaration> sds = ServiceDiscovery.getInstance().getServiceDeclarations(NAME);
+ Assert.assertEquals(3, sds.size());
+
+ sds = ServiceDiscovery.getInstance().getServiceDeclarations(NAME, true);
+ Assert.assertEquals(3, sds.size());
+ Iterator<ServiceDeclaration> it = sds.iterator();
+ ServiceDeclaration sd1 = it.next();
+ ServiceDeclaration sd2 = it.next();
+ Assert.assertEquals("org.apache.tuscany.sca.extensibility.test.Test2Impl", sd1.getClassName());
+ Assert.assertEquals("org.apache.tuscany.sca.extensibility.test.TestImpl", sd2.getClassName());
+ }
+
+ @Test
+ public void testServiceType() throws Exception {
+ ServiceDeclaration sd = ServiceDiscovery.getInstance().getServiceDeclaration(TestInterface.class);
+ Assert.assertEquals("org.apache.tuscany.sca.extensibility.test.Test2Impl", sd.getClassName());
+
+ Collection<ServiceDeclaration> sds = ServiceDiscovery.getInstance().getServiceDeclarations(TestInterface.class);
+ Assert.assertEquals(2, sds.size());
+
+ sds = ServiceDiscovery.getInstance().getServiceDeclarations(TestInterface.class, true);
+ Assert.assertEquals(2, sds.size());
+ Iterator<ServiceDeclaration> it = sds.iterator();
+ ServiceDeclaration sd1 = it.next();
+ ServiceDeclaration sd2 = it.next();
+ Assert.assertEquals("org.apache.tuscany.sca.extensibility.test.Test2Impl", sd1.getClassName());
+ Assert.assertEquals("org.apache.tuscany.sca.extensibility.test.TestImpl", sd2.getClassName());
+ }
+}
diff --git a/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/DummyImpl.java b/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/DummyImpl.java
new file mode 100644
index 0000000000..f1ed50c5f2
--- /dev/null
+++ b/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/DummyImpl.java
@@ -0,0 +1,31 @@
+/*
+ * 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.test;
+
+/**
+ *
+ */
+public class DummyImpl {
+
+ public void test(String str) {
+ System.out.println("Test: " + str);
+ }
+
+}
diff --git a/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/Test2Impl.java b/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/Test2Impl.java
new file mode 100644
index 0000000000..49bc0d022e
--- /dev/null
+++ b/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/Test2Impl.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.test;
+
+/**
+ *
+ */
+public class Test2Impl implements TestInterface {
+
+ /* (non-Javadoc)
+ * @see org.apache.tuscany.sca.extensibility.test.TestInterface#test(java.lang.String)
+ */
+ public void test(String str) {
+ System.out.println("Test 2: " + str);
+ }
+
+}
diff --git a/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestImpl.java b/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestImpl.java
new file mode 100644
index 0000000000..c925bf07c0
--- /dev/null
+++ b/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestImpl.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.test;
+
+/**
+ *
+ */
+public class TestImpl implements TestInterface {
+
+ /* (non-Javadoc)
+ * @see org.apache.tuscany.sca.extensibility.test.TestInterface#test(java.lang.String)
+ */
+ public void test(String str) {
+ System.out.println("Test: " + str);
+ }
+
+}
diff --git a/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestInterface.java b/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestInterface.java
new file mode 100644
index 0000000000..a1897d86c0
--- /dev/null
+++ b/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestInterface.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.extensibility.test;
+
+/**
+ *
+ */
+public interface TestInterface {
+ void test(String str);
+}
diff --git a/java/sca/modules/extensibility/src/test/resources/META-INF/services/org.apache.tuscany.sca.extensibility.test.TestInterface b/java/sca/modules/extensibility/src/test/resources/META-INF/services/org.apache.tuscany.sca.extensibility.test.TestInterface
new file mode 100644
index 0000000000..3d5f9d1857
--- /dev/null
+++ b/java/sca/modules/extensibility/src/test/resources/META-INF/services/org.apache.tuscany.sca.extensibility.test.TestInterface
@@ -0,0 +1,19 @@
+# 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.
+org.apache.tuscany.sca.extensibility.test.TestImpl;ranking=10
+org.apache.tuscany.sca.extensibility.test.Test2Impl;ranking=20
+org.apache.tuscany.sca.extensibility.test.DummyImpl \ No newline at end of file