You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by rf...@apache.org on 2009/07/31 03:59:17 UTC

svn commit: r799486 - in /tuscany/java/sca/modules: extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/ extensibility-equinox/src/test/java/org/apache/tuscany/sca/extensibility/equinox/ extensibility/src/main/java/org/apac...

Author: rfeng
Date: Fri Jul 31 01:59:16 2009
New Revision: 799486

URL: http://svn.apache.org/viewvc?rev=799486&view=rev
Log:
Enhance the service discovery by testing the types
Add more test cases
Improve the syntax parsing for service declarations

Added:
    tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclarationParser.java   (with props)
    tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ServiceDiscoveryTestCase.java   (with props)
    tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/
    tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/DummyImpl.java   (with props)
    tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/Test2Impl.java   (with props)
    tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestImpl.java   (with props)
    tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestInterface.java   (with props)
    tuscany/java/sca/modules/extensibility/src/test/resources/
    tuscany/java/sca/modules/extensibility/src/test/resources/META-INF/
    tuscany/java/sca/modules/extensibility/src/test/resources/META-INF/services/
    tuscany/java/sca/modules/extensibility/src/test/resources/META-INF/services/org.apache.tuscany.sca.extensibility.test.TestInterface
Modified:
    tuscany/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java
    tuscany/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoveryActivator.java
    tuscany/java/sca/modules/extensibility-equinox/src/test/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscovererTestCase.java
    tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ContextClassLoaderServiceDiscoverer.java
    tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java
    tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java

Modified: tuscany/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java?rev=799486&r1=799485&r2=799486&view=diff
==============================================================================
--- tuscany/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java (original)
+++ tuscany/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java Fri Jul 31 01:59:16 2009
@@ -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.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 @@
             return bundle;
         }
 
+        public boolean isAssignableTo(Class<?> serviceType) {
+            try {
+                loadClass();
+            } catch (ClassNotFoundException e) {
+                // Ignore 
+            }
+            return (javaClass != null && serviceType.isAssignableFrom(javaClass));
+        }
+
     }
 
     /**
@@ -156,40 +166,6 @@
 
     }
 
-    /**
-     * 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 @@
                                 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 @@
                                     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

Modified: tuscany/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoveryActivator.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoveryActivator.java?rev=799486&r1=799485&r2=799486&view=diff
==============================================================================
--- tuscany/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoveryActivator.java (original)
+++ tuscany/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoveryActivator.java Fri Jul 31 01:59:16 2009
@@ -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 @@
  * @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 {

Modified: tuscany/java/sca/modules/extensibility-equinox/src/test/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscovererTestCase.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility-equinox/src/test/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscovererTestCase.java?rev=799486&r1=799485&r2=799486&view=diff
==============================================================================
--- tuscany/java/sca/modules/extensibility-equinox/src/test/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscovererTestCase.java (original)
+++ tuscany/java/sca/modules/extensibility-equinox/src/test/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscovererTestCase.java Fri Jul 31 01:59:16 2009
@@ -108,6 +108,7 @@
         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 @@
                 Object reg = m.invoke(cls);
                 System.out.println(reg);
             }
+            */
         }
     }
 

Modified: tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ContextClassLoaderServiceDiscoverer.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ContextClassLoaderServiceDiscoverer.java?rev=799486&r1=799485&r2=799486&view=diff
==============================================================================
--- tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ContextClassLoaderServiceDiscoverer.java (original)
+++ tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ContextClassLoaderServiceDiscoverer.java Fri Jul 31 01:59:16 2009
@@ -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.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 boolean isAssignableTo(Class<?> serviceType) {
+            try {
+                loadClass();
+            } catch (ClassNotFoundException e) {
+                // Ignore 
+            }
+            return (javaClass != null && serviceType.isAssignableFrom(javaClass));
+        }
     }
 
     private WeakReference<ClassLoader> classLoaderReference;
@@ -126,41 +135,6 @@
         }
     }
 
-    /**
-     * 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 @@
                         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 @@
                             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 @@
                                 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

Modified: tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java?rev=799486&r1=799485&r2=799486&view=diff
==============================================================================
--- tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java (original)
+++ tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java Fri Jul 31 01:59:16 2009
@@ -50,8 +50,19 @@
      */
     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);

Added: tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclarationParser.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclarationParser.java?rev=799486&view=auto
==============================================================================
--- tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclarationParser.java (added)
+++ tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclarationParser.java Fri Jul 31 01:59:16 2009
@@ -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;
+        }
+
+    }
+
+}

Propchange: tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclarationParser.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclarationParser.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java?rev=799486&r1=799485&r2=799486&view=diff
==============================================================================
--- tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java (original)
+++ tuscany/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java Fri Jul 31 01:59:16 2009
@@ -24,7 +24,9 @@
 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 @@
     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 @@
      * 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> {

Added: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ServiceDiscoveryTestCase.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ServiceDiscoveryTestCase.java?rev=799486&view=auto
==============================================================================
--- tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ServiceDiscoveryTestCase.java (added)
+++ tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ServiceDiscoveryTestCase.java Fri Jul 31 01:59:16 2009
@@ -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());
+    }
+}

Propchange: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ServiceDiscoveryTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/ServiceDiscoveryTestCase.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/DummyImpl.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/DummyImpl.java?rev=799486&view=auto
==============================================================================
--- tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/DummyImpl.java (added)
+++ tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/DummyImpl.java Fri Jul 31 01:59:16 2009
@@ -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);
+    }
+
+}

Propchange: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/DummyImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/DummyImpl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/Test2Impl.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/Test2Impl.java?rev=799486&view=auto
==============================================================================
--- tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/Test2Impl.java (added)
+++ tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/Test2Impl.java Fri Jul 31 01:59:16 2009
@@ -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);
+    }
+
+}

Propchange: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/Test2Impl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/Test2Impl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestImpl.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestImpl.java?rev=799486&view=auto
==============================================================================
--- tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestImpl.java (added)
+++ tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestImpl.java Fri Jul 31 01:59:16 2009
@@ -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);
+    }
+
+}

Propchange: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestImpl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestInterface.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestInterface.java?rev=799486&view=auto
==============================================================================
--- tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestInterface.java (added)
+++ tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestInterface.java Fri Jul 31 01:59:16 2009
@@ -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);
+}

Propchange: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestInterface.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tuscany/java/sca/modules/extensibility/src/test/java/org/apache/tuscany/sca/extensibility/test/TestInterface.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: tuscany/java/sca/modules/extensibility/src/test/resources/META-INF/services/org.apache.tuscany.sca.extensibility.test.TestInterface
URL: http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility/src/test/resources/META-INF/services/org.apache.tuscany.sca.extensibility.test.TestInterface?rev=799486&view=auto
==============================================================================
--- tuscany/java/sca/modules/extensibility/src/test/resources/META-INF/services/org.apache.tuscany.sca.extensibility.test.TestInterface (added)
+++ tuscany/java/sca/modules/extensibility/src/test/resources/META-INF/services/org.apache.tuscany.sca.extensibility.test.TestInterface Fri Jul 31 01:59:16 2009
@@ -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