I think there are some issues with this change. I'll have to dig some more and post more details later (don't have time right now) ... but in short I'm seeing the following:

- AriesTrader is behaving very badly after this change.
- From within a jsp we use jndi lookup to find an osgi service.
- After this change I get a failure in my jsp with a CNFE. This despite the fact that I can see the package is imported on the web bundle and appears to be wired correctly. - Even more strange: I notice that the application service I was looking for is listed as being used by the pax-web jsp bundle. So it seems like we might be using the wrong bundle context at some point.


Joe



[email protected] wrote:
Author: not
Date: Mon Mar  1 23:53:18 2010
New Revision: 917809

URL: http://svn.apache.org/viewvc?rev=917809&view=rev
Log:
ARIES-128 Implement OSGi spec url lookup scheme

Added:
    
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiName.java
      - copied, changed from r910238, 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryName.java
    
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiNameParser.java
      - copied, changed from r910238, 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryNameParser.java
    
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryListContext.java
    
incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/OsgiNameParserTest.java
      - copied, changed from r917002, 
incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/ServiceRegistryNameParserTest.java
Removed:
    
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryName.java
    
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryNameParser.java
    
incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/ServiceHelperTest.java
    
incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/ServiceRegistryNameParserTest.java
Modified:
    incubator/aries/trunk/jndi/jndi-url/pom.xml
    
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/services/ServiceHelper.java
    
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/Activator.java
    
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiURLContextFactory.java
    
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryContext.java
    
incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/ServiceRegistryContextTest.java

Modified: incubator/aries/trunk/jndi/jndi-url/pom.xml
URL: 
http://svn.apache.org/viewvc/incubator/aries/trunk/jndi/jndi-url/pom.xml?rev=917809&r1=917808&r2=917809&view=diff
==============================================================================
--- incubator/aries/trunk/jndi/jndi-url/pom.xml (original)
+++ incubator/aries/trunk/jndi/jndi-url/pom.xml Mon Mar  1 23:53:18 2010
@@ -33,6 +33,10 @@
<dependencies>
       <dependency>
+       <groupId>org.apache.aries</groupId>
+       <artifactId>org.apache.aries.util</artifactId>
+      </dependency>
+      <dependency>
           <groupId>org.osgi</groupId>
           <artifactId>org.osgi.core</artifactId>
           <scope>provided</scope>

Modified: 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/services/ServiceHelper.java
URL: 
http://svn.apache.org/viewvc/incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/services/ServiceHelper.java?rev=917809&r1=917808&r2=917809&view=diff
==============================================================================
--- 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/services/ServiceHelper.java
 (original)
+++ 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/services/ServiceHelper.java
 Mon Mar  1 23:53:18 2010
@@ -18,18 +18,30 @@
  */
 package org.apache.aries.jndi.services;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import javax.naming.NamingException;
+
+import org.apache.aries.util.BundleToClassLoaderAdapter;
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleReference;
 import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceException;
 import org.osgi.framework.ServiceReference;
/**
@@ -47,221 +59,206 @@
  */
 public final class ServiceHelper
 {
-  /** The bundle context used for service registry queries */
-  private static BundleContext context;
-  /** A cache of what service was returned last time the query was performed */
-  private static ConcurrentMap<ServiceKey, Set<ServiceReference>> cache = new 
ConcurrentHashMap<ServiceKey, Set<ServiceReference>>();
-
-  public static void setBundleContext(BundleContext ctx)
+  public static class StackFinder extends SecurityManager
   {
-    context = ctx;
+    public Class<?>[] getClassContext()
+    {
+      return super.getClassContext();
+    }
   }
- - /** - * This class is used as the key into the cache. It holds information to identify - * who performed the query, along with the className and filter used. The thread context
-   * class loader is used in the key, so two different modules will 
potentially get different
-   * services.
-   */
-  private static final class ServiceKey
+
+  private static class JNDIServiceDamper implements InvocationHandler
   {
-    /** The class loader of the invoking application */
-    private ClassLoader classLoader;
-    /** The name of the class being queried from the registry */
-    private String className;
-    /** the registry filter, this may be null */
+    private BundleContext ctx;
+    private ServicePair pair;
+    private String interfaceName;
     private String filter;
-    /** The cached hashCode */
-    private final int hashCode;
-
-    /**
-     * Boring unimportant comment.
- * - * @param cl
-     * @param cn
-     * @param f
-     */
-    public ServiceKey(ClassLoader cl, String cn, String f)
+    private boolean dynamic;
+ + public JNDIServiceDamper(BundleContext context, String i, String f, ServicePair service, boolean d)
     {
-      classLoader = cl;
-      className = cn;
+      ctx = context;
+      pair = service;
+      interfaceName = i;
       filter = f;
- - int classNameHash = (className == null) ? 0 : className.hashCode();
-      hashCode = System.identityHashCode(classLoader) * 1000003 + 
classNameHash;
+      dynamic = d;
     }
-
-    @Override
-    public int hashCode()
-    {
-      return hashCode;
-    }
-
-    @Override
-    public boolean equals(Object other)
+ + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
     {
-      if (other == this) return true;
-      if (other == null) return false;
-
-      if (other instanceof ServiceKey) {
-        ServiceKey otherKey = (ServiceKey) other;
-        if (hashCode != otherKey.hashCode) return false;
-
-        if (classLoader != otherKey.classLoader) return false;
-        if (!!!comparePossiblyNullObjects(className, otherKey.className)) 
return false;
-        return comparePossiblyNullObjects(filter, otherKey.filter);
-      }
-
-      return false;
-    }
- - /**
-     * Compares two objects where one or other (or both) may be null.
- * - * @param a the first object to compare.
-     * @param b the second object to compare.
-     * @return true if they are ==, both null or identity equals, false 
otherwise.
-     */
-    public boolean comparePossiblyNullObjects(Object a, Object b) {
-      if (a == b) return true;
-      else if (a == null) return false;
-      else return a.equals(b);
+      if (pair.ref.getBundle() == null) {
+        if (dynamic) pair = findService(ctx, interfaceName, filter);
+        else pair = null;
+      }
+ + if (pair == null) {
+        throw new ServiceException(interfaceName, 
ServiceException.UNREGISTERED);
+      }
+ + return method.invoke(pair.service, args);
     }
   }
-
-  /**
-   * This method is used to obtain a single instance of a desired service from 
the OSGi
-   * service registry. If the filter and class name identify multiple services 
the first
-   * one is returned. If no service is found null will be returned.
- * - * @param className The class name used to register the desired service. If null is provided
-   *                  then all services are eligible to be returned.
-   * @param filter    An RFC 1960 query into the properties of the registered 
services. e.g.
-   *                  (service.description=really useful)
-   * @return          The desired service
- * - * @throws IllegalArgumentException If the filter is not valid. See RFC 1960 to work out what - * it should be.
-   */
-  public static Object getService(String className, String filter) throws 
IllegalArgumentException
+ + private static class ServicePair
   {
-    Object service = null;
-    try {
-      BundleContext callerCtx = getBundleContext();
-      ServiceReference[] refs = callerCtx.getServiceReferences(className, 
filter);
- - if (refs != null) {
-        // we need to sort the references returned in case they are out of 
order
- // we need to sort in the reverse natural order, services with higher - // ranking or lower id should be processed first so should be earlier in the array.
-        Arrays.sort(refs, new Comparator<ServiceReference>() {
-          public int compare(ServiceReference o1, ServiceReference o2)
-          {
-            return o2.compareTo(o1);
-          }
-        });
- - for (ServiceReference ref : refs) {
-          List<Object> services = getServices(callerCtx, className, filter, 
ref);
-          if (!!!services.isEmpty()) {
-            service = services.get(0);
-            break;
-          }
-        }
- } - } catch (InvalidSyntaxException e) {
-      throw new IllegalArgumentException(e.getMessage(), e);
-    }
- - return service;
+    private ServiceReference ref;
+    private Object service;
   }
/**
-   * This method is used to obtain a list of service instances from the OSGi
-   * service registry. If no service is found an empty list will be returned.
- * - * @param className The class name used to register the desired service. If null is provided
-   *                  then all services are eligible to be returned.
-   * @param filter    An RFC 1960 query into the properties of the registered 
services. e.g.
-   *                  (service.description=really useful)
-   * @return          A list of matching services.
- * - * @throws IllegalArgumentException If the filter is not valid. See RFC 1960 to work out what - * it should be. + * @param env + * @return the bundle context for the caller. + * @throws NamingException */
-  public static List<?> getServices(String className, String filter)
-      throws IllegalArgumentException
+  public static BundleContext getBundleContext(Map<String, Object> env) throws 
NamingException
   {
-    List<Object> services;
-    try {
-      BundleContext callerCtx = getBundleContext();
-      ServiceReference[] refs = callerCtx.getAllServiceReferences(className, 
filter);
+    BundleContext result = null;
+ + Object bc = env.get("osgi.service.jndi.bundleContext"); + + if (bc != null && bc instanceof BundleContext) result = (BundleContext) bc;
+    else {
+      ClassLoader cl = AccessController.doPrivileged(new 
PrivilegedAction<ClassLoader>() {
+        public ClassLoader run()
+        {
+          return Thread.currentThread().getContextClassLoader();
+        }
+      });
- services = getServices(callerCtx, className, filter, refs);
-    } catch (InvalidSyntaxException e) {
-      throw new IllegalArgumentException(e.getMessage(), e);
+      result = getBundleContext(cl);
+    }
+ + if (result == null) {
+      StackTraceElement[] stackTrace = AccessController.doPrivileged(new 
PrivilegedAction<StackTraceElement[]>() {
+        public StackTraceElement[] run()
+        {
+          return Thread.currentThread().getStackTrace();
+        }
+      });
+ + StackFinder finder = new StackFinder();
+      Class<?>[] classStack = finder.getClassContext();
+ + boolean found = false;
+      boolean foundLookup = false;
+      int i = 0;
+      for (; i < stackTrace.length && !!!found; i++) {
+        if (!!!foundLookup && "lookup".equals(stackTrace[i].getMethodName())) {
+          foundLookup = true;
+        } else if (foundLookup && 
!!!(stackTrace[i].getClassName().startsWith("org.apache.aries.jndi") ||
+                                
stackTrace[i].getClassName().startsWith("javax.naming"))) {
+          found = true;
+        }
+      }
+ + if (found) {
+        Set<Integer> classLoadersChecked = new HashSet<Integer>();
+        for (; i < classStack.length && result == null; i++) {
+          ClassLoader cl = classStack[i].getClassLoader();
+          int hash = System.identityHashCode(cl);
+          if (!!!classLoadersChecked.contains(hash)) {
+            classLoadersChecked.add(hash);
+            result = getBundleContext(cl);
+          }
+        }
+        // Now we walk the stack looking for the BundleContext
+      }
     }
- return services;
+    if (result == null) throw new NamingException("Unable to find 
BundleContext");
+ + return result;
   }
- - /**
-   * @return the bundle context for the caller.
-   */
-  private static BundleContext getBundleContext()
+
+  private static BundleContext getBundleContext(ClassLoader cl)
   {
     BundleContext result = null;
-    ClassLoader cl = Thread.currentThread().getContextClassLoader();
     while (result == null && cl != null) {
       if (cl instanceof BundleReference) {
         result = ((BundleReference)cl).getBundle().getBundleContext();
       } else if (cl != null) {
         cl = cl.getParent();
       }
- } + } - if (result == null) result = context;
     return result;
   }
- /** - * This worker method obtains the requested service(s) and if the service(s) - * exist updates the cache and releases the previous service(s). - * - * @param callerCtx The caller context.
-   * @param className The class name used to query for the service.
-   * @param filter    The filter name used to query for the service.
-   * @param refs      The references to get.
-   * @return          The service, if one was found, or null.
-   */
-  private static List<Object> getServices(BundleContext callerCtx, String 
className, String filter, ServiceReference...refs)
+  public static Object getService(String interface1, String filter, String 
serviceName, boolean dynamicRebind, Map<String, Object> env) throws 
NamingException
   {
-    List<Object> data = new LinkedList<Object>();
+    Object result = null;
+ + BundleContext ctx = getBundleContext(env); + + ServicePair pair = findService(ctx, interface1, filter); - if (refs != null) {
-      Set<ServiceReference> refSet = new HashSet<ServiceReference>();
-      for (ServiceReference ref : refs) {
-        Object service = callerCtx.getService(ref);
-        if (service != null) {
-          data.add(service);
-          refSet.add(ref);
+    if (pair == null) {
+      interface1 = null;
+      filter = "(osgi.jndi.serviceName=" + serviceName + ")";
+      pair = findService(ctx, interface1, filter);
+    }
+ + if (pair != null) {
+      String[] interfaces = (String[]) pair.ref.getProperty("objectClass");
+ + List<Class<?>> clazz = new ArrayList<Class<?>>(interfaces.length); + + Bundle b = ctx.getBundle(); + + for (String interfaceName : interfaces) {
+        try {
+          clazz.add(b.loadClass(interfaceName));
+        } catch (ClassNotFoundException e) {
+          // TODO Auto-generated catch block
+          e.printStackTrace();
         }
       }
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
-      ServiceKey key = new ServiceKey(cl, className, filter);
+      if (clazz.isEmpty()) {
+        throw new IllegalArgumentException();
+      }
- // we do not need any synchronization around this. The map is concurrent
-      // and until here we do not touch any shared state.
-      refSet = cache.put(key, refSet);
+      InvocationHandler ih = new JNDIServiceDamper(ctx, interface1, filter, 
pair, dynamicRebind);
- if (refSet != null) {
-        for (ServiceReference ref : refSet) {
-          callerCtx.ungetService(ref);
+      result = Proxy.newProxyInstance(new BundleToClassLoaderAdapter(b), 
clazz.toArray(new Class<?>[clazz.size()]), ih);
+    }
+ + return result;
+  }
+
+  private static ServicePair findService(BundleContext ctx, String interface1, 
String filter)
+  {
+    ServicePair p = null;
+ + try {
+      ServiceReference[] refs = ctx.getServiceReferences(interface1, filter);
+ + if (refs != null) {
+        // natural order is the exact opposite of the order we desire.
+        Arrays.sort(refs, new Comparator<ServiceReference>() {
+          public int compare(ServiceReference o1, ServiceReference o2)
+          {
+            return o2.compareTo(o1);
+          }
+        });
+ + for (ServiceReference ref : refs) {
+          Object service = ctx.getService(ref);
+ + if (service != null) {
+            p = new ServicePair();
+            p.ref = ref;
+            p.service = service;
+            break;
+          }
         }
       }
+ + } catch (InvalidSyntaxException e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
     }
- return data;
+    return p;
   }
 }

Modified: 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/Activator.java
URL: 
http://svn.apache.org/viewvc/incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/Activator.java?rev=917809&r1=917808&r2=917809&view=diff
==============================================================================
--- 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/Activator.java
 (original)
+++ 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/Activator.java
 Mon Mar  1 23:53:18 2010
@@ -34,8 +34,6 @@
        
   public void start(BundleContext context)
   {
-    ServiceHelper.setBundleContext(context);
- Hashtable<Object, Object> props = new Hashtable<Object, Object>();
     props.put("osgi.jndi.urlScheme", new String[] {"osgi", "aries"} );
     reg = context.registerService(ObjectFactory.class.getName(), new 
OsgiURLContextFactory(), props);

Copied: 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiName.java
 (from r910238, 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryName.java)
URL: 
http://svn.apache.org/viewvc/incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiName.java?p2=incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiName.java&p1=incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryName.java&r1=910238&r2=917809&rev=917809&view=diff
==============================================================================
--- 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryName.java
 (original)
+++ 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiName.java
 Mon Mar  1 23:53:18 2010
@@ -21,28 +21,104 @@
 import java.util.Enumeration;
import javax.naming.CompositeName;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
/**
- * A composite name for the aries namespace. We only have this so that we can
- * provide a nicer toString()
+ * A composite name for the aries namespace. This provides useful utility 
methods
+ * for accessing the name.
+ * + * component 0: osgi:service, aries:services, osgi:servicelist
+ * component 1: interface
+ * component 2: filter
  */
-public final class ServiceRegistryName extends CompositeName
+public final class OsgiName extends CompositeName
 {
   /** The serial version UID */
   private static final long serialVersionUID = 6617580228852444656L;
+  public static final String OSGI_SCHEME = "osgi";
+  public static final String ARIES_SCHEME = "aries";
+  public static final String SERVICE_PATH = "service";
+  public static final String SERVICES_PATH = "services";
+  public static final String SERVICE_LIST_PATH = "servicelist";
+  public static final String FRAMEWORK_PATH = "framework";
- @Override
-  public String toString()
+  public OsgiName(String name) throws InvalidNameException
   {
-    StringBuilder buffer = new StringBuilder();
+    super(name);
+  }
+
+  public OsgiName(Name name) throws InvalidNameException
+  {
+    this(name.toString());
+  }
+
+  public boolean hasFilter()
+  {
+    return size() == 3;
+  }
+ + public boolean isServiceNameBased()
+  {
+    return size() > 3;
+  }
+ + public String getScheme()
+  {
+    String part0 = get(0);
+    int index = part0.indexOf(':');
+ + String result; + + if (index > 0) {
+      result = part0.substring(0, index);
+    } else {
+      result = null;
+    }
+ + return result;
+  }
+ + public String getSchemePath()
+  {
+    String part0 = get(0);
+    int index = part0.indexOf(':');
+ + String result; - buffer.append("aries:services");
-    Enumeration<String> components = getAll();
-    while (components.hasMoreElements()) {
-      buffer.append('/');
-      buffer.append(components.nextElement());
+    if (index > 0) {
+      result = part0.substring(index + 1);
+    } else {
+      result = null;
     }
- return buffer.toString();
+    return result;
+  }
+ + public String getInterface()
+  {
+    return get(1);
+  }
+ + public String getFilter()
+  {
+    return hasFilter() ? get(2) : null;
+  }
+ + public String getServiceName()
+  {
+    Enumeration<String> parts = getAll();
+    parts.nextElement();
+ + StringBuilder builder = new StringBuilder(); + + while (parts.hasMoreElements()) {
+      builder.append(parts.nextElement());
+      builder.append('/');
+    }
+ + builder.deleteCharAt(builder.length() - 1); + + return builder.toString();
   }
 }
\ No newline at end of file

Copied: 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiNameParser.java
 (from r910238, 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryNameParser.java)
URL: 
http://svn.apache.org/viewvc/incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiNameParser.java?p2=incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiNameParser.java&p1=incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryNameParser.java&r1=910238&r2=917809&rev=917809&view=diff
==============================================================================
--- 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryNameParser.java
 (original)
+++ 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiNameParser.java
 Mon Mar  1 23:53:18 2010
@@ -26,31 +26,40 @@
 /**
  * A parser for the aries namespace
  */
-public final class ServiceRegistryNameParser implements NameParser
+public final class OsgiNameParser implements NameParser
 {
-
+  private static final String OSGI_SCHEME = "osgi";
+  private static final String ARIES_SCHEME = "aries";
+  private static final String SERVICE_PATH = "service";
+  private static final String SERVICES_PATH = "services";
+  private static final String SERVICE_LIST_PATH = "servicelist";
+  private static final String FRAMEWORK_PATH = "framework";
+ public Name parse(String name) throws NamingException
   {
-    if (!!!name.startsWith("aries:services/") &&
-        !!!name.startsWith("osgi:services/")) throw new InvalidNameException("The 
JNDI name did not start with aries:, or osgi:");
+    OsgiName result = new OsgiName(name);
+ + if (result.size() < 2) throw new InvalidNameException(name); - name = name.substring(name.indexOf('/') + 1);
+    String urlScheme = result.getScheme();
+    String schemePath = result.getSchemePath();
- int slashIndex = name.indexOf('/');
-    String interfaceName = name;
-    String filter = null;
- - if (slashIndex != -1) {
-      interfaceName = name.substring(0, slashIndex);
-      filter = name.substring(slashIndex + 1);
+    if (!!!(OSGI_SCHEME.equals(urlScheme) || ARIES_SCHEME.equals(urlScheme))) {
+      throw new InvalidNameException(name);
     }
- if (interfaceName.length() == 0) throw new InvalidNameException("No interface name was specified");
+    if (ARIES_SCHEME.equals(urlScheme) && !!!SERVICES_PATH.equals(schemePath)) 
{
+      throw new InvalidNameException(name);
+    }
+ + if (OSGI_SCHEME.equals(urlScheme) && !!!( SERVICE_PATH.equals(schemePath) || + SERVICE_LIST_PATH.equals(schemePath) || + FRAMEWORK_PATH.equals(schemePath))) {
+      throw new InvalidNameException(name);
+    }
- Name result = new ServiceRegistryName();
-    result.add(interfaceName);
-    if (filter != null) {
-      result.add(filter);
+    if (result.getInterface() == null || result.getInterface().length() == 0) {
+      throw new InvalidNameException(name);
     }
return result;
@@ -59,7 +68,7 @@
   @Override
   public boolean equals(Object other)
   {
-    return other instanceof ServiceRegistryNameParser;
+    return other instanceof OsgiNameParser;
   }
@Override

Modified: 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiURLContextFactory.java
URL: 
http://svn.apache.org/viewvc/incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiURLContextFactory.java?rev=917809&r1=917808&r2=917809&view=diff
==============================================================================
--- 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiURLContextFactory.java
 (original)
+++ 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/OsgiURLContextFactory.java
 Mon Mar  1 23:53:18 2010
@@ -49,7 +49,7 @@
     } else if (obj instanceof String[]) {
       // Try each URL until either lookup succeeds or they all fail
       String[] urls = (String[])obj;
-      if (urls.length == 0) throw new 
ConfigurationException("ariesURLContextFactory: empty URL array");
+      if (urls.length == 0) throw new ConfigurationException("0");
       Context context = new ServiceRegistryContext(environment);
       try
       {

Modified: 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryContext.java
URL: 
http://svn.apache.org/viewvc/incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryContext.java?rev=917809&r1=917808&r2=917809&view=diff
==============================================================================
--- 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryContext.java
 (original)
+++ 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryContext.java
 Mon Mar  1 23:53:18 2010
@@ -42,9 +42,9 @@
 {
   private static final String ARIES_SERVICES = "aries:services/";
   /** The name parser for the service registry name space */
-  private NameParser parser = new ServiceRegistryNameParser();
+  private NameParser parser = new OsgiNameParser();
   /** The environment for this context */
-  private Map<Object, Object> env;
+  private Map<String, Object> env;
/** * Why Mr Java this class does indeed take a fine copy of the provided @@ -53,10 +53,11 @@ * * @param environment
    */
+  @SuppressWarnings("unchecked")
   public ServiceRegistryContext(Hashtable<?, ?> environment)
   {
-    env = new HashMap<Object, Object>();
-    env.putAll(environment);
+    env = new HashMap<String, Object>();
+    env.putAll((Map<? extends String, ? extends Object>) environment);
   }
public Object addToEnvironment(String propName, Object propVal) throws NamingException
@@ -153,7 +154,7 @@
public NamingEnumeration<NameClassPair> list(final Name name) throws NamingException
   {
-    throw new NamingException("Not a Context");
+    return new ServiceRegistryListContext(env, convert(name)).list("");
   }
public NamingEnumeration<NameClassPair> list(String name) throws NamingException
@@ -163,7 +164,7 @@
public NamingEnumeration<Binding> listBindings(final Name name) throws NamingException
   {
-    throw new NamingException("Not a Context");
+    return new ServiceRegistryListContext(env, convert(name)).listBindings("");
   }
public NamingEnumeration<Binding> listBindings(String name) throws NamingException
@@ -173,28 +174,43 @@
public Object lookup(Name name) throws NamingException
   {
-    int nameSize = validateName(name);
-    String className = name.get(0);
-
-    String filter = null;
+    Object result;
+ + OsgiName validName = convert(name); - if (nameSize == 2) {
-      filter = name.get(1);
+    String pathFragment = validName.getSchemePath();
+    String serviceName = validName.getServiceName();
+    String schemeName = validName.getScheme();
+ + if (OsgiName.FRAMEWORK_PATH.equals(pathFragment) && "bundleContext".equals(validName.getServiceName())) {
+      result = ServiceHelper.getBundleContext(env);
+    } else if ((OsgiName.SERVICE_PATH.equals(pathFragment) && 
OsgiName.OSGI_SCHEME.equals(schemeName)) ||
+               (OsgiName.SERVICES_PATH.equals(pathFragment) && 
OsgiName.ARIES_SCHEME.equals(schemeName))) {
+      result = ServiceHelper.getService(validName.getInterface(), 
validName.getFilter(), serviceName, true, env);
+    } else if (OsgiName.SERVICE_LIST_PATH.equals(pathFragment)) {
+      result = new ServiceRegistryListContext(env, validName);
+    } else {
+      result = null;
     }
- try {
-      Object result = ServiceHelper.getService(className, filter);
- - if (result == null) {
-        throw new NameNotFoundException("We couldn't find an object in the registry 
matching the query " + name);
-      }
- - return result;
-    } catch (IllegalArgumentException e) {
-      NamingException ne = new NamingException(e.getMessage());
-      ne.initCause(e);
-      throw ne;
+    if (result == null) {
+      throw new NameNotFoundException(name.toString());
+    }
+ + return result;
+  }
+
+  private OsgiName convert(Name name) throws InvalidNameException
+  {
+    OsgiName result;
+ + if (name instanceof OsgiName) {
+      result = (OsgiName) name;
+    } else {
+      result = new OsgiName(name);
     }
+ + return result;
   }
public Object lookup(String name) throws NamingException
@@ -246,27 +262,4 @@
   {
     throw new OperationNotSupportedException();
   }
- - /**
-   * Check that the name conforms to the expected format
-   * @param name
-   * @return the size of the name
-   * @throws InvalidNameException
-   */
-  private int validateName(final Name name) throws InvalidNameException
-  {
-    int nameSize = name.size();
-    if (nameSize == 0) {
-      throw new InvalidNameException("The provided name does not have any 
components" + name);
- } - - if ("aries:services".equals(name.get(0))) {
-      throw new InvalidNameException("The composite name should not start with 
aries:services");
-    }
- - if (nameSize > 2) {
-      throw new InvalidNameException("This JNDI context only expects 2 components, 
but it found " + nameSize);
-    }
-    return nameSize;
-  }
 }
\ No newline at end of file

Added: 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryListContext.java
URL: 
http://svn.apache.org/viewvc/incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryListContext.java?rev=917809&view=auto
==============================================================================
--- 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryListContext.java
 (added)
+++ 
incubator/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/url/ServiceRegistryListContext.java
 Mon Mar  1 23:53:18 2010
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.aries.jndi.url;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NameClassPair;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.OperationNotSupportedException;
+
+public class ServiceRegistryListContext implements Context
+{
+  private Map<String, Object> env;
+  /** The name parser for the service registry name space */
+  private NameParser parser = new OsgiNameParser();
+ + public ServiceRegistryListContext(Map<String, Object> env, OsgiName validName)
+  {
+    this.env = new HashMap<String, Object>(env);
+  }
+
+  public Object addToEnvironment(String propName, Object propVal) throws 
NamingException
+  {
+    return env.put(propName, propVal);
+  }
+
+  public void bind(Name name, Object obj) throws NamingException
+  {
+    throw new OperationNotSupportedException();
+  }
+
+  public void bind(String name, Object obj) throws NamingException
+  {
+    throw new OperationNotSupportedException();
+  }
+
+  public void close() throws NamingException
+  {
+    env = null;
+    parser = null;
+  }
+
+  public Name composeName(Name name, Name prefix) throws NamingException
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  public String composeName(String name, String prefix) throws NamingException
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  public Context createSubcontext(Name name) throws NamingException
+  {
+    throw new OperationNotSupportedException();
+  }
+
+  public Context createSubcontext(String name) throws NamingException
+  {
+    throw new OperationNotSupportedException();
+  }
+
+  public void destroySubcontext(Name name) throws NamingException
+  {
+    //No-op we don't support sub-contexts in our context
+  }
+
+  public void destroySubcontext(String name) throws NamingException
+  {
+    //No-op we don't support sub-contexts in our context
+  }
+
+  public Hashtable<?, ?> getEnvironment() throws NamingException
+  {
+    Hashtable<Object, Object> environment = new Hashtable<Object, Object>();
+    environment.putAll(env);
+    return environment;
+  }
+
+  public String getNameInNamespace() throws NamingException
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  public NameParser getNameParser(Name name) throws NamingException
+  {
+    return parser;
+  }
+
+  public NameParser getNameParser(String name) throws NamingException
+  {
+    return parser;
+  }
+
+  public NamingEnumeration<NameClassPair> list(Name name) throws 
NamingException
+  {
+    return list(name.toString());
+  }
+
+  public NamingEnumeration<NameClassPair> list(String name) throws 
NamingException
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  public NamingEnumeration<Binding> listBindings(Name name) throws 
NamingException
+  {
+    return listBindings(name.toString());
+  }
+
+  public NamingEnumeration<Binding> listBindings(String name) throws 
NamingException
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  public Object lookup(Name name) throws NamingException
+  {
+    return lookup(name.toString());
+  }
+
+  public Object lookup(String name) throws NamingException
+  {
+    return null;
+  }
+
+  public Object lookupLink(Name name) throws NamingException
+  {
+    throw new OperationNotSupportedException();
+  }
+
+  public Object lookupLink(String name) throws NamingException
+  {
+    throw new OperationNotSupportedException();
+  }
+
+  public void rebind(Name name, Object obj) throws NamingException
+  {
+    throw new OperationNotSupportedException();
+  }
+
+  public void rebind(String name, Object obj) throws NamingException
+  {
+    throw new OperationNotSupportedException();
+  }
+
+  public Object removeFromEnvironment(String propName) throws NamingException
+  {
+    return env.remove(propName);
+  }
+
+  public void rename(Name oldName, Name newName) throws NamingException
+  {
+    throw new OperationNotSupportedException();
+  }
+
+  public void rename(String oldName, String newName) throws NamingException
+  {
+    throw new OperationNotSupportedException();
+  }
+
+  public void unbind(Name name) throws NamingException
+  {
+    throw new OperationNotSupportedException();
+  }
+
+  public void unbind(String name) throws NamingException
+  {
+    throw new OperationNotSupportedException();
+  }
+}
\ No newline at end of file

Copied: 
incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/OsgiNameParserTest.java
 (from r917002, 
incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/ServiceRegistryNameParserTest.java)
URL: 
http://svn.apache.org/viewvc/incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/OsgiNameParserTest.java?p2=incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/OsgiNameParserTest.java&p1=incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/ServiceRegistryNameParserTest.java&r1=917002&r2=917809&rev=917809&view=diff
==============================================================================
--- 
incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/ServiceRegistryNameParserTest.java
 (original)
+++ 
incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/OsgiNameParserTest.java
 Mon Mar  1 23:53:18 2010
@@ -18,11 +18,11 @@
  */
 package org.apache.aries.jndi.url;
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import javax.naming.InvalidNameException;
-import javax.naming.Name;
 import javax.naming.NameParser;
 import javax.naming.NamingException;
@@ -31,10 +31,10 @@
 /**
  * This is where we test the service registry name parser.
  */
-public class ServiceRegistryNameParserTest
+public class OsgiNameParserTest
 {
   /** The parser we are going to use for testing */
-  private NameParser parser = new ServiceRegistryNameParser();
+  private NameParser parser = new OsgiNameParser();
/**
    * OK, so we check that we can call checkNames multiple times.
@@ -43,8 +43,14 @@
   @Test
   public void checkValidNames() throws NamingException
   {
-    checkName("aries:services/java.lang.Runnable/(a=b)");
-    checkName("aries:services/java.lang.Runnable");
+    checkName("aries","services","java.lang.Runnable","(a=b)");
+    checkName("aries","services","java.lang.Runnable");
+    checkName("osgi","service","java.lang.Runnable");
+    checkName("osgi","service","java.lang.Runnable", "(a=b)");
+    checkName("osgi","servicelist","java.lang.Runnable");
+    checkName("osgi","servicelist","java.lang.Runnable", "(a=b)");
+    checkName("osgi","servicelist","jdbc", "grok", "DataSource");
+    checkName("osgi", "framework", "bundleContext");
   }
/**
@@ -54,7 +60,7 @@
   @Test(expected=InvalidNameException.class)
   public void checkOutsideNamespace() throws NamingException
   {
-    checkName("java:comp/env/jms/cf");
+    checkName("java","comp","env","jms","cf");
   }
/**
@@ -64,7 +70,7 @@
   @Test(expected=InvalidNameException.class)
   public void checkMissingInterface() throws NamingException
   {
-    checkName("aries:services");
+    checkName("aries","services");
   }
/**
@@ -75,20 +81,64 @@
   @Test(expected=InvalidNameException.class)
   public void checkMissingInterface2() throws NamingException
   {
-    checkName("aries:services/");
+    checkName("aries","services", "");
   }
-
-  /**
-   * This method parses the name and then makes sure what was parsed was parsed
-   * correctly.
- * - * @param name
-   * @throws NamingException
-   */
-  private void checkName(String name) throws NamingException
+ + @Test(expected=InvalidNameException.class)
+  public void checkIncorrectPath() throws NamingException
+  {
+ checkName("osgi", "services", "java.lang.Runnable"); + } + + @Test(expected=InvalidNameException.class)
+  public void checkIllegalPath() throws NamingException
   {
-    Name n = parser.parse(name);
-    assertNotNull("We got a null name back, which is not allowed.", n);
-    assertEquals("The name's toString does not produce the original value", 
name, n.toString());
+ checkName("osgi", "wibble", "java.lang.Runnable"); + } + + private void checkName(String scheme, String path, String ... elements)
+    throws NamingException
+  {
+    StringBuilder builder = new StringBuilder();
+    StringBuilder serviceName = new StringBuilder();
+ + builder.append(scheme);
+    builder.append(':');
+    builder.append(path);
+
+    if (elements.length > 0) {
+      builder.append('/');
+ + for (String element : elements) {
+        serviceName.append(element);
+        serviceName.append('/');
+      }
+ + serviceName.deleteCharAt(serviceName.length() - 1); + + builder.append(serviceName);
+    }
+ + OsgiName n = (OsgiName) parser.parse(builder.toString()); + + assertEquals(scheme, n.getScheme());
+    assertEquals(path, n.getSchemePath());
+ + if (elements.length > 1) {
+      assertEquals(elements[0], n.getInterface());
+    }
+ + if (elements.length == 1) {
+      assertFalse(n.hasFilter());
+    }
+ + if (elements.length > 2) {
+      if (elements.length == 2) {
+        assertTrue(n.hasFilter());
+        assertEquals(elements[1], n.getFilter());
+      } else assertFalse(n.hasFilter());
+    }
+ + assertEquals(serviceName.toString(), n.getServiceName());
   }
 }
\ No newline at end of file

Modified: 
incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/ServiceRegistryContextTest.java
URL: 
http://svn.apache.org/viewvc/incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/ServiceRegistryContextTest.java?rev=917809&r1=917808&r2=917809&view=diff
==============================================================================
--- 
incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/ServiceRegistryContextTest.java
 (original)
+++ 
incubator/aries/trunk/jndi/jndi-url/src/test/java/org/apache/aries/jndi/url/ServiceRegistryContextTest.java
 Mon Mar  1 23:53:18 2010
@@ -21,7 +21,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
import java.lang.reflect.Field;
@@ -37,6 +36,12 @@
 import javax.naming.NamingException;
 import javax.naming.spi.ObjectFactory;
+import org.apache.aries.jndi.ContextHelper;
+import org.apache.aries.jndi.OSGiObjectFactoryBuilder;
+import org.apache.aries.mocks.BundleContextMock;
+import org.apache.aries.mocks.BundleMock;
+import org.apache.aries.unittest.mocks.MethodCall;
+import org.apache.aries.unittest.mocks.Skeleton;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -47,22 +52,13 @@
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
-import org.apache.aries.unittest.mocks.MethodCall;
-import org.apache.aries.unittest.mocks.Skeleton;
-import org.apache.aries.jndi.ContextHelper;
-import org.apache.aries.jndi.OSGiObjectFactoryBuilder;
-import org.apache.aries.jndi.services.ServiceHelper;
-import org.apache.aries.jndi.url.Activator;
-import org.apache.aries.mocks.BundleContextMock;
-import org.apache.aries.mocks.BundleMock;
-
 /**
  * Tests for our JNDI implementation for the service registry.
  */
 public class ServiceRegistryContextTest
 {
   /** The service we register by default */
-  private Thread service;
+  private Runnable service;
   /** The bundle context for the test */
   private BundleContext bc;
   /** The service registration for the service */
@@ -83,10 +79,7 @@
     new Activator().start(bc);
     new org.apache.aries.jndi.startup.Activator().start(bc);
- Field f = ServiceHelper.class.getDeclaredField("context");
-    f.setAccessible(true);
-    f.set(null, bc);
-    f = ContextHelper.class.getDeclaredField("context");
+    Field f = ContextHelper.class.getDeclaredField("context");
     f.setAccessible(true);
     f.set(null, bc);
     f = OSGiObjectFactoryBuilder.class.getDeclaredField("context");
@@ -94,7 +87,7 @@
     f.set(null, bc);
- service = new Thread();
+    service = Skeleton.newMock(Runnable.class);
registerService(service);
   }
@@ -104,7 +97,7 @@
* * @param service2 The service to register.
    */
-  private void registerService(Thread service2)
+  private void registerService(Runnable service2)
   {
     ServiceFactory factory = Skeleton.newMock(ServiceFactory.class);
     Skeleton skel = Skeleton.getSkeleton(factory);
@@ -159,11 +152,13 @@
Thread.currentThread().setContextClassLoader(mock.getClassLoader()); - Object s = ctx.lookup("aries:services/java.lang.Runnable");
+    Runnable s = (Runnable) ctx.lookup("aries:services/java.lang.Runnable");
assertNotNull("We didn't get a service back from our lookup :(", s); - assertEquals("The SR did not return the object we expected", service, s);
+    s.run();
+ + Skeleton.getSkeleton(service).assertCalledExactNumberOfTimes(new MethodCall(Runnable.class, "run"), 1); Skeleton skel = Skeleton.getSkeleton(mock.getBundleContext()); @@ -173,7 +168,7 @@ Thread.currentThread().setContextClassLoader(mock.getClassLoader()); - s = ctx.lookup("osgi:services/java.lang.Runnable");
+    s = (Runnable) ctx.lookup("osgi:service/java.lang.Runnable");
// Check we have the packages set correctly @@ -181,10 +176,11 @@ assertTrue(ctx.getEnvironment().containsValue(packages)); - assertNotNull("We didn't get a service back from our lookup :(", s);
+
+    s.run();
- assertEquals("The SR did not return the object we expected", service, s);
+    Skeleton.getSkeleton(service).assertCalledExactNumberOfTimes(new 
MethodCall(Runnable.class, "run"), 2);
skel = Skeleton.getSkeleton(mock.getBundleContext());
     skel.assertCalled(new MethodCall(BundleContext.class, "getServiceReferences", 
"java.lang.Runnable", null));
@@ -201,15 +197,21 @@
   @Test
   public void jndiLookupWithFilter() throws NamingException
   {
+    BundleMock mock = new BundleMock("scooby.doo", new Properties());
+ + Thread.currentThread().setContextClassLoader(mock.getClassLoader());
+
     InitialContext ctx = new InitialContext();
Object s = ctx.lookup("aries:services/java.lang.Runnable/(rubbish=smelly)"); assertNotNull("We didn't get a service back from our lookup :(", s); - assertEquals("The SR did not return the object we expected", service, s);
+    service.run();
- Skeleton.getSkeleton(bc).assertCalled(new MethodCall(BundleContext.class, "getServiceReferences", "java.lang.Runnable", "(rubbish=smelly)"));
+    Skeleton.getSkeleton(service).assertCalledExactNumberOfTimes(new 
MethodCall(Runnable.class, "run"), 1);
+
+    Skeleton.getSkeleton(mock.getBundleContext()).assertCalled(new MethodCall(BundleContext.class, 
"getServiceReferences", "java.lang.Runnable", "(rubbish=smelly)"));
   }
/**
@@ -222,6 +224,11 @@
   public void testLookupWhenServiceHasBeenRemoved() throws NamingException
   {
     reg.unregister();
+
+    BundleMock mock = new BundleMock("scooby.doo", new Properties());
+ + Thread.currentThread().setContextClassLoader(mock.getClassLoader());
+
     InitialContext ctx = new InitialContext();
ctx.lookup("aries:services/java.lang.Runnable");
@@ -236,6 +243,10 @@
   @Test(expected=NameNotFoundException.class)
   public void testLookupForServiceWeNeverHad() throws NamingException
   {
+    BundleMock mock = new BundleMock("scooby.doo", new Properties());
+ + Thread.currentThread().setContextClassLoader(mock.getClassLoader());
+
     InitialContext ctx = new InitialContext();
ctx.lookup("aries:services/java.lang.Integer");
@@ -271,14 +282,53 @@
   }
@Test
+  public void checkProxyDynamism() throws NamingException
+  {
+    BundleMock mock = new BundleMock("scooby.doo", new Properties());
+ + Thread.currentThread().setContextClassLoader(mock.getClassLoader());
+
+    InitialContext ctx = new InitialContext();
+ + String className = Runnable.class.getName(); + + Runnable t = Skeleton.newMock(Runnable.class);
+    Runnable t2 = Skeleton.newMock(Runnable.class);
+ + // we don't want the default service
+    reg.unregister();
+ + ServiceRegistration reg = bc.registerService(className, t, null);
+    bc.registerService(className, t2, null);
+ + Runnable r = (Runnable) ctx.lookup("osgi:service/java.lang.Runnable"); + + r.run(); + + Skeleton.getSkeleton(t).assertCalledExactNumberOfTimes(new MethodCall(Runnable.class, "run"), 1);
+    Skeleton.getSkeleton(t2).assertNotCalled(new MethodCall(Runnable.class, 
"run"));
+ + reg.unregister(); + + r.run(); + + Skeleton.getSkeleton(t).assertCalledExactNumberOfTimes(new MethodCall(Runnable.class, "run"), 1);
+    Skeleton.getSkeleton(t2).assertCalledExactNumberOfTimes(new 
MethodCall(Runnable.class, "run"), 1);
+ } +
+  @Test
   public void checkServiceOrderObserved() throws NamingException
   {
+    BundleMock mock = new BundleMock("scooby.doo", new Properties());
+ + Thread.currentThread().setContextClassLoader(mock.getClassLoader());
+
     InitialContext ctx = new InitialContext();
String className = Runnable.class.getName(); - Thread t = new Thread();
-    Thread t2 = new Thread();
+    Runnable t = Skeleton.newMock(Runnable.class);
+    Runnable t2 = Skeleton.newMock(Runnable.class);
// we don't want the default service
     reg.unregister();
@@ -286,9 +336,12 @@
     ServiceRegistration reg = bc.registerService(className, t, null);
     ServiceRegistration reg2 = bc.registerService(className, t2, null);
- Runnable r = (Runnable) ctx.lookup("osgi:services/java.lang.Runnable");
+    Runnable r = (Runnable) ctx.lookup("osgi:service/java.lang.Runnable");
- assertSame("The wrong runnable was returned", t, r);
+    r.run();
+ + Skeleton.getSkeleton(t).assertCalledExactNumberOfTimes(new MethodCall(Runnable.class, "run"), 1);
+    Skeleton.getSkeleton(t2).assertNotCalled(new MethodCall(Runnable.class, 
"run"));
reg.unregister();
     reg2.unregister();
@@ -296,12 +349,18 @@
     Hashtable<String, Object> props = new Hashtable<String, Object>();
     props.put(Constants.SERVICE_RANKING, 55);
+ t = Skeleton.newMock(Runnable.class);
+    t2 = Skeleton.newMock(Runnable.class);
+
     reg = bc.registerService(className, t, null);
     reg2 = bc.registerService(className, t2, props);
- r = (Runnable) ctx.lookup("osgi:services/java.lang.Runnable");
+    r = (Runnable) ctx.lookup("osgi:service/java.lang.Runnable");
+ + r.run(); - assertSame("The wrong runnable was returned", t2, r);
+    Skeleton.getSkeleton(t).assertNotCalled(new MethodCall(Runnable.class, 
"run"));
+    Skeleton.getSkeleton(t2).assertCalledExactNumberOfTimes(new 
MethodCall(Runnable.class, "run"), 1);
   }
/**





--
Joe

Reply via email to