[FELIX-4712] Upgrade connect to OSGi r5
Upgrade to Java 6
Add support for FrameworkStartLevel, StartLevel and PackageAdmin

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1642172 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/connect/pom.xml b/connect/pom.xml
index 10be23c..c48d887 100644
--- a/connect/pom.xml
+++ b/connect/pom.xml
@@ -49,17 +49,22 @@
             <name>Karl Pauls</name>
             <email>karlpauls@gmail.com</email>
         </developer>
+        <developer>
+            <id>gnodet</id>
+            <name>Guillaume Nodet</name>
+            <email>gnodet@gmail.com</email>
+        </developer>
     </developers>
     <dependencies>
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
-            <version>4.3.1</version>
+            <version>5.0.0</version>
         </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.compendium</artifactId>
-            <version>4.2.0</version>
+            <version>5.0.0</version>
         </dependency>
     </dependencies>
     <repositories/>
@@ -91,8 +96,8 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <target>1.5</target>
-                    <source>1.5</source>
+                    <target>1.6</target>
+                    <source>1.6</source>
                 </configuration>
             </plugin>
             <plugin>
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/Requirement.java b/connect/src/main/java/org/apache/felix/connect/BundleAware.java
similarity index 74%
rename from connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/Requirement.java
rename to connect/src/main/java/org/apache/felix/connect/BundleAware.java
index 0995898..98c1ccb 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/Requirement.java
+++ b/connect/src/main/java/org/apache/felix/connect/BundleAware.java
@@ -16,19 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.connect.felix.framework.capabilityset;
+package org.apache.felix.connect;
 
-import java.util.List;
+import org.osgi.framework.Bundle;
 
-public interface Requirement
+public interface BundleAware
 {
-    String getNamespace();
 
-    SimpleFilter getFilter();
+    void setBundle(Bundle bundle);
 
-    boolean isOptional();
-
-    Directive getDirective(String name);
-
-    List<Directive> getDirectives();
-}
\ No newline at end of file
+}
diff --git a/connect/src/main/java/org/apache/felix/connect/DirRevision.java b/connect/src/main/java/org/apache/felix/connect/DirRevision.java
index 29a8328..5b49c7d 100644
--- a/connect/src/main/java/org/apache/felix/connect/DirRevision.java
+++ b/connect/src/main/java/org/apache/felix/connect/DirRevision.java
@@ -23,7 +23,7 @@
 import java.net.URL;
 import java.util.Enumeration;
 
-class DirRevision extends Revision
+class DirRevision implements Revision
 {
     private final File m_file;
 
@@ -38,7 +38,8 @@
         return m_file.lastModified();
     }
 
-    public Enumeration getEntries()
+    @Override
+    public Enumeration<String> getEntries()
     {
         return new FileEntriesEnumeration(m_file);
     }
@@ -48,18 +49,20 @@
     {
         try
         {
-		    if (entryName != null) {
-            File file = (new File(m_file, (entryName.startsWith("/")) ? entryName.substring(1) : entryName));
-            if (file.exists()) {
-                return file.toURL();
-            } 
-			}
+            if (entryName != null)
+            {
+                File file = (new File(m_file, (entryName.startsWith("/")) ? entryName.substring(1) : entryName));
+                if (file.exists())
+                {
+                    return file.toURI().toURL();
+                }
+            }
         }
         catch (MalformedURLException e)
         {
             e.printStackTrace();
         }
-            return null;
+        return null;
 
     }
 
diff --git a/connect/src/main/java/org/apache/felix/connect/EntriesEnumeration.java b/connect/src/main/java/org/apache/felix/connect/EntriesEnumeration.java
index c5c4990..d6b753a 100644
--- a/connect/src/main/java/org/apache/felix/connect/EntriesEnumeration.java
+++ b/connect/src/main/java/org/apache/felix/connect/EntriesEnumeration.java
@@ -19,50 +19,62 @@
 package org.apache.felix.connect;
 
 import java.util.Enumeration;
+import java.util.NoSuchElementException;
 import java.util.zip.ZipEntry;
 
-class EntriesEnumeration implements Enumeration
+class EntriesEnumeration implements Enumeration<String>
 {
-    private final Enumeration m_enumeration;
-	private final String m_prefix;
-	private volatile Object current;
+    private final Enumeration<? extends ZipEntry> m_enumeration;
+    private final String m_prefix;
+    private volatile String current;
 
-    public EntriesEnumeration(Enumeration enumeration)
+    public EntriesEnumeration(Enumeration<? extends ZipEntry> enumeration)
     {
         this(enumeration, null);
     }
-	
-	public EntriesEnumeration(Enumeration enumeration, String prefix)
-	{
-	   m_enumeration = enumeration;
-	   m_prefix = prefix;
-	}
 
-    public boolean hasMoreElements() {
-				while ((current == null) && m_enumeration.hasMoreElements()) {
-					String result = (String) ((ZipEntry) m_enumeration.nextElement()).getName();
-					if (m_prefix != null){
-						if (result.startsWith(m_prefix)) {
-							current = result.substring(m_prefix.length());
-						}
-					}
-					else {
-						current = result;
-					}
-				}
-				return (current != null);
-			}
+    public EntriesEnumeration(Enumeration<? extends ZipEntry> enumeration, String prefix)
+    {
+        m_enumeration = enumeration;
+        m_prefix = prefix;
+    }
 
-			public Object nextElement() {
-				try {
-					if (hasMoreElements()) {
-						return current;
-					}
-					else {
-						return m_enumeration.nextElement();
-					}
-				} finally { 
-					current = null;
-				}
-			}
+    public boolean hasMoreElements()
+    {
+        while ((current == null) && m_enumeration.hasMoreElements())
+        {
+            String result = m_enumeration.nextElement().getName();
+            if (m_prefix != null)
+            {
+                if (result.startsWith(m_prefix))
+                {
+                    current = result.substring(m_prefix.length());
+                }
+            }
+            else
+            {
+                current = result;
+            }
+        }
+        return (current != null);
+    }
+
+    public String nextElement()
+    {
+        try
+        {
+            if (hasMoreElements())
+            {
+                return current;
+            }
+            else
+            {
+                throw new NoSuchElementException();
+            }
+        }
+        finally
+        {
+            current = null;
+        }
+    }
 }
\ No newline at end of file
diff --git a/connect/src/main/java/org/apache/felix/connect/EntryFilterEnumeration.java b/connect/src/main/java/org/apache/felix/connect/EntryFilterEnumeration.java
index 2e3de55..01c9d4d 100644
--- a/connect/src/main/java/org/apache/felix/connect/EntryFilterEnumeration.java
+++ b/connect/src/main/java/org/apache/felix/connect/EntryFilterEnumeration.java
@@ -40,8 +40,12 @@
     private final Set<String> m_dirEntries = new HashSet<String>();
     private final List<T> m_nextEntries = new ArrayList<T>(2);
 
-    public EntryFilterEnumeration(Revision rev, boolean includeFragments,
-            String path, String filePattern, boolean recurse,
+    public EntryFilterEnumeration(
+            Revision rev,
+            boolean includeFragments,
+            String path,
+            String filePattern,
+            boolean recurse,
             boolean isURLValues)
     {
         m_revision = rev;
@@ -52,8 +56,7 @@
         // Sanity check the parameters.
         if (path == null)
         {
-            throw new IllegalArgumentException(
-                    "The path for findEntries() cannot be null.");
+            throw new IllegalArgumentException("The path for findEntries() cannot be null.");
         }
         // Strip leading '/' if present.
         if ((path.length() > 0) && (path.charAt(0) == '/'))
@@ -170,8 +173,7 @@
                                                     : entryURL;
                                             try
                                             {
-                                                m_nextEntries.add((T) new URL(
-                                                        entryURL, "/" + dir));
+                                                m_nextEntries.add((T) new URL(entryURL, "/" + dir));
                                             }
                                             catch (MalformedURLException ex)
                                             {
@@ -199,8 +201,7 @@
                     // is a child (not a grandchild) of the initial path, then
                     // we need
                     // to check if it matches the file pattern.
-                    if (m_recurse || (dirSlashIdx < 0)
-                            || (dirSlashIdx == entryName.length() - 1))
+                    if (m_recurse || (dirSlashIdx < 0) || (dirSlashIdx == entryName.length() - 1))
                     {
                         // See if the file pattern matches the last element of
                         // the path.
diff --git a/connect/src/main/java/org/apache/felix/connect/ExportedPackageImpl.java b/connect/src/main/java/org/apache/felix/connect/ExportedPackageImpl.java
new file mode 100644
index 0000000..f769849
--- /dev/null
+++ b/connect/src/main/java/org/apache/felix/connect/ExportedPackageImpl.java
@@ -0,0 +1,90 @@
+/*
+ * 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.felix.connect;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.service.packageadmin.ExportedPackage;
+
+class ExportedPackageImpl implements ExportedPackage
+{
+    private final BundleCapability m_export;
+
+    public ExportedPackageImpl(BundleCapability export)
+    {
+        m_export = export;
+    }
+
+    public Bundle getExportingBundle()
+    {
+        return m_export.getRevision().getBundle();
+    }
+
+    public Bundle[] getImportingBundles()
+    {
+        // Create set for storing importing bundles.
+        Set<Bundle> result = new HashSet<Bundle>();
+        // Get all importers and requirers for all revisions of the bundle.
+        // The spec says that require-bundle should be returned with importers.
+        for (BundleWire wire : m_export.getRevision().getWiring().getProvidedWires(null))
+        {
+            if (wire.getCapability() == m_export
+                    || BundleNamespace.BUNDLE_NAMESPACE.equals(wire.getCapability().getNamespace()))
+            {
+                result.add( wire.getRequirer().getBundle() );
+            }
+        }
+        // Return the results.
+        return result.toArray(new Bundle[result.size()]);
+    }
+
+    public String getName()
+    {
+        return (String) m_export.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
+    }
+
+    public String getSpecificationVersion()
+    {
+        return getVersion().toString();
+    }
+
+    public Version getVersion()
+    {
+        return m_export.getAttributes().containsKey(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE)
+                ? (Version) m_export.getAttributes().get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE)
+                : Version.emptyVersion;
+    }
+
+    public boolean isRemovalPending()
+    {
+        return false;
+    }
+
+    public String toString()
+    {
+        return getName() + "; version=" + getVersion();
+    }
+}
\ No newline at end of file
diff --git a/connect/src/main/java/org/apache/felix/connect/FileEntriesEnumeration.java b/connect/src/main/java/org/apache/felix/connect/FileEntriesEnumeration.java
index ab9aa60..0208a37 100644
--- a/connect/src/main/java/org/apache/felix/connect/FileEntriesEnumeration.java
+++ b/connect/src/main/java/org/apache/felix/connect/FileEntriesEnumeration.java
@@ -22,7 +22,7 @@
 import java.util.Enumeration;
 import java.util.NoSuchElementException;
 
-class FileEntriesEnumeration implements Enumeration
+class FileEntriesEnumeration implements Enumeration<String>
 {
     private final File m_dir;
     private final File[] m_children;
@@ -39,7 +39,7 @@
         return (m_children != null) && (m_counter < m_children.length);
     }
 
-    public synchronized Object nextElement()
+    public synchronized String nextElement()
     {
         if ((m_children == null) || (m_counter >= m_children.length))
         {
@@ -52,7 +52,7 @@
 
         // Remove the leading path of the reference directory, since the
         // entry paths are supposed to be relative to the root.
-        StringBuffer sb = new StringBuffer(abs);
+        StringBuilder sb = new StringBuilder(abs);
         sb.delete(0, m_dir.getAbsolutePath().length() + 1);
         // Add a '/' to the end of directory entries.
         if (m_children[m_counter].isDirectory())
@@ -67,15 +67,14 @@
     {
         File[] children = dir.listFiles();
         File[] combined = children;
-        for (int i = 0; i < children.length; i++)
+        for (File aChildren : children)
         {
-            if (children[i].isDirectory())
+            if (aChildren.isDirectory())
             {
-                File[] grandchildren = listFilesRecursive(children[i]);
+                File[] grandchildren = listFilesRecursive(aChildren);
                 if (grandchildren.length > 0)
                 {
-                    File[] tmp = new File[combined.length
-                            + grandchildren.length];
+                    File[] tmp = new File[combined.length + grandchildren.length];
                     System.arraycopy(combined, 0, tmp, 0, combined.length);
                     System.arraycopy(grandchildren, 0, tmp, combined.length,
                             grandchildren.length);
diff --git a/connect/src/main/java/org/apache/felix/connect/JarRevision.java b/connect/src/main/java/org/apache/felix/connect/JarRevision.java
index aa8f442..61b6455 100644
--- a/connect/src/main/java/org/apache/felix/connect/JarRevision.java
+++ b/connect/src/main/java/org/apache/felix/connect/JarRevision.java
@@ -18,28 +18,29 @@
  */
 package org.apache.felix.connect;
 
-import java.io.*;
-import java.net.URLStreamHandler;
-import java.net.URLConnection;
+import java.io.IOException;
+import java.io.InputStream;
 import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
 import java.util.Enumeration;
-import java.util.jar.JarFile;
 import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
 
-class JarRevision extends Revision
+class JarRevision implements Revision
 {
     private final long m_lastModified;
     private final JarFile m_jar;
     private final URL m_url;
-	private final String m_urlString;
-	private final String m_prefix;
+    private final String m_urlString;
+    private final String m_prefix;
 
     public JarRevision(JarFile jar, URL url, String prefix, long lastModified)
     {
         m_jar = jar;
         m_url = url;
-		m_urlString =  m_url.toExternalForm();
-		m_prefix = prefix;
+        m_urlString = m_url.toExternalForm();
+        m_prefix = prefix;
         if (lastModified > 0)
         {
             m_lastModified = lastModified;
@@ -56,7 +57,7 @@
         return m_lastModified;
     }
 
-    public Enumeration getEntries()
+    public Enumeration<String> getEntries()
     {
         return new EntriesEnumeration(m_jar.entries(), m_prefix);
     }
@@ -66,61 +67,69 @@
     {
         try
         {
-		    if("/".equals(entryName) || "".equals(entryName) || " ".equals(entryName)) {
-			    return new URL("jar:" + m_urlString + "!/" + ((m_prefix == null) ? "" : m_prefix));
-			}
+            if ("/".equals(entryName) || "".equals(entryName) || " ".equals(entryName))
+            {
+                return new URL("jar:" + m_urlString + "!/" + ((m_prefix == null) ? "" : m_prefix));
+            }
             if (entryName != null)
-			{ 
-				final String target = ((entryName.startsWith("/")) ? entryName.substring(1) : entryName);
-				final JarEntry entry = m_jar.getJarEntry(((m_prefix == null) ? "" : m_prefix) + target);
-				if ( entry != null) {
-								URL result = new URL(null, "jar:" + m_urlString + "!/" + ((m_prefix == null) ? "" : m_prefix) + target, new URLStreamHandler() {
-									
-									
-									protected URLConnection openConnection(final URL u) throws IOException {
-										return new java.net.JarURLConnection(u) {
-											
-											public JarFile getJarFile() {
-											    return m_jar;
-											}
-											public void connect() throws IOException {
-												// TODO Auto-generated method stub
-												
-											}
-											
-											public InputStream getInputStream()
-													throws IOException {
-													
-												String extF = u.toExternalForm();
-												JarEntry targetEntry = entry;
-												if (!extF.endsWith(target)) {
-												    extF = extF.substring(extF.indexOf('!') + 2);
-												    if (m_prefix != null) {
-														if (!extF.startsWith(m_prefix)) {
-														    extF = m_prefix + extF;
-														}
-													}
-													targetEntry = m_jar.getJarEntry(extF);
-												}
-												return m_jar.getInputStream(targetEntry);
-											}
-										};
-									}
-								});
-								return result;
-							}
-							else {
-								if (entryName.endsWith("/")) {
-								     return new URL("jar:" + m_urlString + "!/" + ((m_prefix == null) ? "" : m_prefix) + target);
-								}
-							}
-			}
+            {
+                final String target = ((entryName.startsWith("/")) ? entryName.substring(1) : entryName);
+                final JarEntry entry = m_jar.getJarEntry(((m_prefix == null) ? "" : m_prefix) + target);
+                if (entry != null)
+                {
+                    URL result = new URL(null, "jar:" + m_urlString + "!/" + ((m_prefix == null) ? "" : m_prefix) + target, new URLStreamHandler()
+                    {
+                        protected URLConnection openConnection(final URL u) throws IOException
+                        {
+                            return new java.net.JarURLConnection(u)
+                            {
+
+                                public JarFile getJarFile()
+                                {
+                                    return m_jar;
+                                }
+
+                                public void connect() throws IOException
+                                {
+                                }
+
+                                public InputStream getInputStream() throws IOException
+                                {
+                                    String extF = u.toExternalForm();
+                                    JarEntry targetEntry = entry;
+                                    if (!extF.endsWith(target))
+                                    {
+                                        extF = extF.substring(extF.indexOf('!') + 2);
+                                        if (m_prefix != null)
+                                        {
+                                            if (!extF.startsWith(m_prefix))
+                                            {
+                                                extF = m_prefix + extF;
+                                            }
+                                        }
+                                        targetEntry = m_jar.getJarEntry(extF);
+                                    }
+                                    return m_jar.getInputStream(targetEntry);
+                                }
+                            };
+                        }
+                    });
+                    return result;
+                }
+                else
+                {
+                    if (entryName.endsWith("/"))
+                    {
+                        return new URL("jar:" + m_urlString + "!/" + ((m_prefix == null) ? "" : m_prefix) + target);
+                    }
+                }
+            }
         }
         catch (IOException e)
         {
             e.printStackTrace();
         }
-            return null;
+        return null;
 
     }
 
diff --git a/connect/src/main/java/org/apache/felix/connect/PojoSR.java b/connect/src/main/java/org/apache/felix/connect/PojoSR.java
index 0fcc480..960261e 100644
--- a/connect/src/main/java/org/apache/felix/connect/PojoSR.java
+++ b/connect/src/main/java/org/apache/felix/connect/PojoSR.java
@@ -19,16 +19,21 @@
 package org.apache.felix.connect;
 
 import java.io.File;
+import java.io.IOException;
 import java.net.JarURLConnection;
 import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Properties;
+import java.util.Set;
 
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -37,6 +42,7 @@
 import org.osgi.framework.Constants;
 import org.osgi.framework.Filter;
 import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
 import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceEvent;
@@ -44,6 +50,11 @@
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.framework.Version;
+import org.osgi.framework.VersionRange;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWiring;
 import org.osgi.service.packageadmin.ExportedPackage;
 import org.osgi.service.packageadmin.PackageAdmin;
 import org.osgi.service.packageadmin.RequiredBundle;
@@ -59,45 +70,41 @@
 public class PojoSR implements PojoServiceRegistry
 {
     private final BundleContext m_context;
-    private final ServiceRegistry m_reg = new ServiceRegistry(
+    private final ServiceRegistry m_registry = new ServiceRegistry(
             new ServiceRegistry.ServiceRegistryCallbacks()
             {
-
-                public void serviceChanged(ServiceEvent event,
-                        Dictionary oldProps)
+                public void serviceChanged(ServiceEvent event, Dictionary<String, ?> oldProps)
                 {
                     m_dispatcher.fireServiceEvent(event, oldProps, null);
                 }
             });
 
-    private final EventDispatcher m_dispatcher = new EventDispatcher(m_reg);
-    private final Map<Long, Bundle> m_bundles =new HashMap<Long, Bundle>();
-    private final Map<String, Bundle> m_symbolicNameToBundle = new HashMap<String, Bundle>();
-    private final Map bundleConfig;
-    public PojoSR(Map config) throws Exception
-    {
+    private final EventDispatcher m_dispatcher = new EventDispatcher(m_registry);
+    private final Map<Long, Bundle> m_bundles = new HashMap<Long, Bundle>();
+    private final Map<String, Object> bundleConfig;
+
+    public static BundleDescriptor createSystemBundle() {
         final Map<String, String> headers = new HashMap<String, String>();
-        headers.put(Constants.BUNDLE_SYMBOLICNAME,
-                "org.apache.felix.connect");
-        headers.put(Constants.BUNDLE_VERSION, "0.1.0-SNAPSHOT");
+        headers.put(Constants.BUNDLE_SYMBOLICNAME, "org.apache.felix.connect");
+        headers.put(Constants.BUNDLE_VERSION, "0.0.0");
         headers.put(Constants.BUNDLE_NAME, "System Bundle");
         headers.put(Constants.BUNDLE_MANIFESTVERSION, "2");
-		headers.put(Constants.BUNDLE_VENDOR, "Apache Software Foundation");
-        bundleConfig = new HashMap(config);
-        final Bundle b = new PojoSRBundle(new Revision()
-        {
+        headers.put(Constants.BUNDLE_VENDOR, "Apache Software Foundation");
 
+
+        Revision revision = new Revision()
+        {
+            final long lastModified = System.currentTimeMillis();
             @Override
             public long getLastModified()
             {
-                // TODO Auto-generated method stub
-                return System.currentTimeMillis();
+                return lastModified;
             }
 
             @Override
-            public Enumeration getEntries()
+            public Enumeration<String> getEntries()
             {
-                return new Properties().elements();
+                return Collections.emptyEnumeration();
             }
 
             @Override
@@ -105,26 +112,60 @@
             {
                 return getClass().getClassLoader().getResource(entryName);
             }
-        }, headers, new Version(0, 0, 1), "file:pojosr", m_reg, m_dispatcher,
-                null, 0, "org.apache.felix.connect", m_bundles, getClass()
-                        .getClassLoader(), bundleConfig)
-        {
-        	@Override
-        	public synchronized void start() throws BundleException {
-        		if (m_state != Bundle.RESOLVED) {
-        			return;
-        		}
-        		m_dispatcher.startDispatching();
-        		m_state = Bundle.STARTING;
+        };
+        Map<Class, Object> services = new HashMap<Class, Object>();
+        services.put(FrameworkStartLevel.class, new FrameworkStartLevelImpl());
+        return new BundleDescriptor(
+                PojoSR.class.getClassLoader(),
+                "felix-connect",
+                headers,
+                revision,
+                services
+                );
+    }
 
-                m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STARTING,
-                        this));
-                m_context = new PojoSRBundleContext(this, m_reg, m_dispatcher,
-                                m_bundles, bundleConfig);
+    public PojoSR(Map<String, ?> config) throws Exception
+    {
+        this(config, null);
+    }
+
+    public PojoSR(Map<String, ?> config, BundleDescriptor systemBundle) throws Exception
+    {
+        if (systemBundle == null) {
+            systemBundle = createSystemBundle();
+        }
+        bundleConfig = new HashMap<String, Object>(config);
+        final Bundle b = new PojoSRBundle(
+                        m_registry,
+                        m_dispatcher,
+                        m_bundles,
+                        systemBundle.getUrl(),
+                        0,
+                        "org.apache.felix.connect",
+                        new Version(0, 0, 1),
+                                systemBundle.getRevision(),
+                        systemBundle.getClassLoader(),
+                        systemBundle.getHeaders(),
+                        systemBundle.getServices(),
+                        bundleConfig)
+        {
+            @Override
+            public synchronized void start() throws BundleException
+            {
+                if (m_state != Bundle.RESOLVED)
+                {
+                    return;
+                }
+                m_dispatcher.startDispatching();
+                m_state = Bundle.STARTING;
+
+                m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STARTING, this));
+                m_context = new PojoSRBundleContext(this, m_registry, m_dispatcher, m_bundles, bundleConfig);
                 int i = 0;
-                for (Bundle b : m_bundles.values()) {
-                	i++;
-                	try
+                for (Bundle b : m_bundles.values())
+                {
+                    i++;
+                    try
                     {
                         if (b != this)
                         {
@@ -133,327 +174,223 @@
                     }
                     catch (Throwable t)
                     {
-                    	System.out.println("Unable to start bundle: " + i );
-                    	t.printStackTrace();
+                        System.out.println("Unable to start bundle: " + i);
+                        t.printStackTrace();
                     }
                 }
                 m_state = Bundle.ACTIVE;
-                m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STARTED,
-                        this));
+                m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STARTED, this));
 
                 m_dispatcher.fireFrameworkEvent(new FrameworkEvent(FrameworkEvent.STARTED, this, null));
-        		super.start();
-        	};
+                super.start();
+            }
+
             @Override
             public synchronized void stop() throws BundleException
             {
-            	if ((m_state == Bundle.STOPPING) || m_state == Bundle.RESOLVED) {
-            		return;
+                if ((m_state == Bundle.STOPPING) || m_state == Bundle.RESOLVED)
+                {
+                    return;
 
-            	}
-            	else if (m_state != Bundle.ACTIVE) {
-            		throw new BundleException("Can't stop pojosr because it is not ACTIVE");
-            	}
-            	final Bundle systemBundle = this;
-            	Runnable r = new Runnable() {
+                }
+                else if (m_state != Bundle.ACTIVE)
+                {
+                    throw new BundleException("Can't stop pojosr because it is not ACTIVE");
+                }
+                final Bundle systemBundle = this;
+                Runnable r = new Runnable()
+                {
 
-					public void run() {
-		                m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STOPPING,
-		                		systemBundle));
-		                for (Bundle b : m_bundles.values())
-		                {
-		                    try
-		                    {
-		                        if (b != systemBundle)
-		                        {
-		                            b.stop();
-		                        }
-		                    }
-		                    catch (Throwable t)
-		                    {
-		                        t.printStackTrace();
-		                    }
-		                }
-		                m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STOPPED,
-		                		systemBundle));
-		                m_state = Bundle.RESOLVED;
-		                m_dispatcher.stopDispatching();
-					}
-				};
-				m_state = Bundle.STOPPING;
-				if ("true".equalsIgnoreCase(System.getProperty("org.apache.felix.connect.events.sync"))) {
-					r.run();
-				}
-				else {
-					new Thread(r).start();
-				}
+                    public void run()
+                    {
+                        m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STOPPING, systemBundle));
+                        for (Bundle b : m_bundles.values())
+                        {
+                            try
+                            {
+                                if (b != systemBundle)
+                                {
+                                    b.stop();
+                                }
+                            }
+                            catch (Throwable t)
+                            {
+                                t.printStackTrace();
+                            }
+                        }
+                        m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STOPPED, systemBundle));
+                        m_state = Bundle.RESOLVED;
+                        m_dispatcher.stopDispatching();
+                    }
+                };
+                m_state = Bundle.STOPPING;
+                if ("true".equalsIgnoreCase(System.getProperty("org.apache.felix.connect.events.sync")))
+                {
+                    r.run();
+                }
+                else
+                {
+                    new Thread(r).start();
+                }
             }
         };
-        m_symbolicNameToBundle.put(b.getSymbolicName(), b);
+        m_bundles.put(0l, b);
         b.start();
-        b.getBundleContext().registerService(StartLevel.class.getName(),
-                new StartLevel()
-                {
+        b.getBundleContext().registerService(StartLevel.class.getName(), new StartLevelImpl(), null);
 
-                    public void setStartLevel(int startlevel)
-                    {
-                        // TODO Auto-generated method stub
-
-                    }
-
-                    public void setInitialBundleStartLevel(int startlevel)
-                    {
-                        // TODO Auto-generated method stub
-
-                    }
-
-                    public void setBundleStartLevel(Bundle bundle,
-                            int startlevel)
-                    {
-                        // TODO Auto-generated method stub
-
-                    }
-
-                    public boolean isBundlePersistentlyStarted(Bundle bundle)
-                    {
-                        // TODO Auto-generated method stub
-                        return true;
-                    }
-
-                    public boolean isBundleActivationPolicyUsed(Bundle bundle)
-                    {
-                        // TODO Auto-generated method stub
-                        return false;
-                    }
-
-                    public int getStartLevel()
-                    {
-                        // TODO Auto-generated method stub
-                        return 1;
-                    }
-
-                    public int getInitialBundleStartLevel()
-                    {
-                        // TODO Auto-generated method stub
-                        return 1;
-                    }
-
-                    public int getBundleStartLevel(Bundle bundle)
-                    {
-                        // TODO Auto-generated method stub
-                        return 1;
-                    }
-                }, null);
-
-        b.getBundleContext().registerService(PackageAdmin.class.getName(),
-                new PackageAdmin()
-                {
-
-                    public boolean resolveBundles(Bundle[] bundles)
-                    {
-                        // TODO Auto-generated method stub
-                        return true;
-                    }
-
-                    public void refreshPackages(Bundle[] bundles)
-                    {
-                        m_dispatcher.fireFrameworkEvent(new FrameworkEvent(
-                                FrameworkEvent.PACKAGES_REFRESHED, b, null));
-                    }
-
-                    public RequiredBundle[] getRequiredBundles(
-                            String symbolicName)
-                    {
-                        return null;
-                    }
-
-                    public Bundle[] getHosts(Bundle bundle)
-                    {
-                        // TODO Auto-generated method stub
-                        return null;
-                    }
-
-                    public Bundle[] getFragments(Bundle bundle)
-                    {
-                        // TODO Auto-generated method stub
-                        return null;
-                    }
-
-                    public ExportedPackage[] getExportedPackages(String name)
-                    {
-                        // TODO Auto-generated method stub
-                        return null;
-                    }
-
-                    public ExportedPackage[] getExportedPackages(Bundle bundle)
-                    {
-                        // TODO Auto-generated method stub
-                        return null;
-                    }
-
-                    public ExportedPackage getExportedPackage(String name)
-                    {
-                        // TODO Auto-generated method stub
-                        return null;
-                    }
-
-                    public Bundle[] getBundles(String symbolicName,
-                            String versionRange)
-                    {
-					    Bundle result = m_symbolicNameToBundle.get((symbolicName != null) ? symbolicName.trim() : symbolicName);
-						if (result != null) {
-							return new Bundle[] {result};
-						}
-						return null;
-                    }
-
-                    public int getBundleType(Bundle bundle)
-                    {
-                        return 0;
-                    }
-
-                    public Bundle getBundle(Class clazz)
-                    {
-                        return m_context.getBundle();
-                    }
-                }, null);
+        b.getBundleContext().registerService(PackageAdmin.class.getName(), new PackageAdminImpl(), null);
         m_context = b.getBundleContext();
 
-        List<BundleDescriptor> scan = (List<BundleDescriptor>) config
-                .get(PojoServiceRegistryFactory.BUNDLE_DESCRIPTORS);
+        Collection<BundleDescriptor> scan = (Collection<BundleDescriptor>) config.get(PojoServiceRegistryFactory.BUNDLE_DESCRIPTORS);
 
         if (scan != null)
         {
             startBundles(scan);
-		}
+        }
     }
 
-	public void startBundles(List<BundleDescriptor> scan) throws Exception {
-	 for (BundleDescriptor desc : scan)
+    public void startBundles(Collection<BundleDescriptor> scan) throws Exception
+    {
+        for (BundleDescriptor desc : scan)
+        {
+            Revision revision = desc.getRevision();
+            if (revision == null)
             {
-                URL u = new URL(desc.getUrl().toExternalForm()
-                        + "META-INF/MANIFEST.MF");
-                Revision r;
-                if (u.toExternalForm().startsWith("file:"))
+                revision = buildRevision(desc);
+            }
+            Map<String, String> bundleHeaders = desc.getHeaders();
+            Version osgiVersion;
+            try
+            {
+                osgiVersion = Version.parseVersion(bundleHeaders.get(Constants.BUNDLE_VERSION));
+            }
+            catch (Exception ex)
+            {
+                ex.printStackTrace();
+                osgiVersion = Version.emptyVersion;
+            }
+            String sym = bundleHeaders.get(Constants.BUNDLE_SYMBOLICNAME);
+            if (sym != null)
+            {
+                int idx = sym.indexOf(';');
+                if (idx > 0)
                 {
-                    File root = new File(URLDecoder.decode(desc.getUrl()
-                            .getFile(), "UTF-8"));
-                    u = root.toURL();
-                    r = new DirRevision(root);
+                    sym = sym.substring(0, idx);
                 }
-                else
-                {
-                    URLConnection uc = u.openConnection();
-                    if (uc instanceof JarURLConnection)
-                    {
-					    String target = ((JarURLConnection) uc).getJarFileURL().toExternalForm();
-						String prefix = null;
-						if (!("jar:" + target + "!/").equals(desc.getUrl().toExternalForm())) {
-						    prefix = desc.getUrl().toExternalForm().substring(("jar:" + target + "!/").length());
-						}
-                        r = new JarRevision(
-                                ((JarURLConnection) uc).getJarFile(),
-                                ((JarURLConnection) uc).getJarFileURL(),
-								prefix,
-                                uc.getLastModified());
-                    }
-                    else
-                    {
-                        r = new URLRevision(desc.getUrl(), desc.getUrl()
-                                .openConnection().getLastModified());
-                    }
-                }
-                Map<String, String> bundleHeaders = desc.getHeaders();
-				Version osgiVersion = null;
-				try {
-					osgiVersion = Version.parseVersion(bundleHeaders.get(Constants.BUNDLE_VERSION));
-				} catch (Exception ex) {
-					ex.printStackTrace();
-					osgiVersion = Version.emptyVersion;
-				}
-                String sym = bundleHeaders.get(Constants.BUNDLE_SYMBOLICNAME);
-                    if (sym != null)
-                    {
-                        int idx = sym.indexOf(';');
-                        if (idx > 0)
-                        {
-                            sym = sym.substring(0, idx);
-                        }
-						sym = sym.trim();
-                    }
-
-                if ((sym == null)
-                        || !m_symbolicNameToBundle.containsKey( sym ))
-                {
-                    // TODO: framework - support multiple versions
-                    Bundle bundle = new PojoSRBundle(r, bundleHeaders,
-                            osgiVersion, desc.getUrl().toExternalForm(), m_reg,
-                            m_dispatcher,
-                            bundleHeaders.get(Constants.BUNDLE_ACTIVATOR),
-                            m_bundles.size(),
-                            sym,
-                            m_bundles, desc.getClassLoader(), bundleConfig);
-                    if (sym != null)
-                    {
-                        m_symbolicNameToBundle.put(bundle.getSymbolicName(),
-                                bundle);
-                    }
-                }
-
+                sym = sym.trim();
             }
 
+            Bundle bundle = new PojoSRBundle(
+                    m_registry,
+                    m_dispatcher,
+                    m_bundles,
+                    desc.getUrl(),
+                    m_bundles.size(),
+                    sym,
+                    osgiVersion,
+                    revision,
+                    desc.getClassLoader(),
+                    bundleHeaders,
+                    desc.getServices(),
+                    bundleConfig);
+            m_bundles.put(bundle.getBundleId(), bundle);
+        }
 
-        for (long i = 1; i < m_bundles.size(); i++)
+
+        for (Bundle bundle : m_bundles.values())
         {
             try
             {
-                m_bundles.get(i).start();
+                bundle.start();
             }
             catch (Throwable e)
             {
-                System.out.println("Unable to start bundle: " + i);
+                System.out.println("Unable to start bundle: " + bundle);
                 e.printStackTrace();
             }
         }
 
-	}
+    }
+
+    private Revision buildRevision(BundleDescriptor desc) throws IOException
+    {
+        Revision r;
+        URL url = new URL(desc.getUrl());
+        URL u = new URL(desc.getUrl() + "META-INF/MANIFEST.MF");
+        if (u.toExternalForm().startsWith("file:"))
+        {
+            File root = new File(URLDecoder.decode(url.getFile(), "UTF-8"));
+            r = new DirRevision(root);
+        }
+        else
+        {
+            URLConnection uc = u.openConnection();
+            if (uc instanceof JarURLConnection)
+            {
+                String target = ((JarURLConnection) uc).getJarFileURL().toExternalForm();
+                String prefix = null;
+                if (!("jar:" + target + "!/").equals(desc.getUrl()))
+                {
+                    prefix = desc.getUrl().substring(("jar:" + target + "!/").length());
+                }
+                r = new JarRevision(
+                        ((JarURLConnection) uc).getJarFile(),
+                        ((JarURLConnection) uc).getJarFileURL(),
+                        prefix,
+                        uc.getLastModified());
+            }
+            else
+            {
+                r = new URLRevision(url, url.openConnection().getLastModified());
+            }
+        }
+        return r;
+    }
 
     public static void main(String[] args) throws Exception
     {
-    	Filter filter = null;
-    	Class main = null;
-    	for (int i = 0;(args != null) && (i < args.length) && (i < 2); i++) {
-	    	try {
-	    		filter = FrameworkUtil.createFilter(args[i]);
-	    	} catch (InvalidSyntaxException ie) {
-	    		try {
-	    			main = PojoSR.class.getClassLoader().loadClass(args[i]);
-	    		} catch (Exception ex) {
-	    			throw new IllegalArgumentException("Argument is neither a filter nor a class: " + args[i]);
-	    		}
-	    	}
-    	}
-        Map config = new HashMap();
+        Filter filter = null;
+        Class<?> main = null;
+        for (int i = 0; (args != null) && (i < args.length) && (i < 2); i++)
+        {
+            try
+            {
+                filter = FrameworkUtil.createFilter(args[i]);
+            }
+            catch (InvalidSyntaxException ie)
+            {
+                try
+                {
+                    main = PojoSR.class.getClassLoader().loadClass(args[i]);
+                }
+                catch (Exception ex)
+                {
+                    throw new IllegalArgumentException("Argument is neither a filter nor a class: " + args[i]);
+                }
+            }
+        }
+        Map<String, Object> config = new HashMap<String, Object>();
         config.put(
                 PojoServiceRegistryFactory.BUNDLE_DESCRIPTORS,
                 (filter != null) ? new ClasspathScanner()
                         .scanForBundles(filter.toString()) : new ClasspathScanner()
                         .scanForBundles());
         new PojoServiceRegistryFactoryImpl().newPojoServiceRegistry(config);
-        if (main != null) {
-        	int count = 0;
-        	if (filter != null) {
-        		count++;
-        	}
-        	if (main != null) {
-        		count++;
-        	}
-        	String[] newArgs = args;
-        	if (count > 0) {
-        		newArgs = new String[args.length - count];
-        		System.arraycopy(args, count, newArgs, 0, newArgs.length);
-        	}
-        	main.getMethod("main", String[].class).invoke(null, (Object) newArgs );
+        if (main != null)
+        {
+            int count = 0;
+            if (filter != null)
+            {
+                count++;
+            }
+            count++;
+            String[] newArgs = args;
+            if (count > 0)
+            {
+                newArgs = new String[args.length - count];
+                System.arraycopy(args, count, newArgs, 0, newArgs.length);
+            }
+            main.getMethod("main", String[].class).invoke(null, newArgs);
         }
     }
 
@@ -462,52 +399,281 @@
         return m_context;
     }
 
-    public void addServiceListener(ServiceListener listener, String filter)
-            throws InvalidSyntaxException
+    @Override
+    public void addServiceListener(ServiceListener listener, String filter) throws InvalidSyntaxException
     {
         m_context.addServiceListener(listener, filter);
     }
 
+    @Override
     public void addServiceListener(ServiceListener listener)
     {
         m_context.addServiceListener(listener);
     }
 
+    @Override
     public void removeServiceListener(ServiceListener listener)
     {
         m_context.removeServiceListener(listener);
     }
 
-    public ServiceRegistration registerService(String[] clazzes,
-            Object service, Dictionary properties)
+    @Override
+    public ServiceRegistration<?> registerService(String[] clazzes, Object service, Dictionary<String, ?> properties)
     {
         return m_context.registerService(clazzes, service, properties);
     }
 
-    public ServiceRegistration registerService(String clazz, Object service,
-            Dictionary properties)
+    @Override
+    public ServiceRegistration<?> registerService(String clazz, Object service, Dictionary<String, ?> properties)
     {
         return m_context.registerService(clazz, service, properties);
     }
 
-    public ServiceReference[] getServiceReferences(String clazz, String filter)
-            throws InvalidSyntaxException
+    @Override
+    public ServiceReference<?>[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException
     {
         return m_context.getServiceReferences(clazz, filter);
     }
 
-    public ServiceReference getServiceReference(String clazz)
+    @Override
+    public ServiceReference<?> getServiceReference(String clazz)
     {
         return m_context.getServiceReference(clazz);
     }
 
-    public Object getService(ServiceReference reference)
+    @Override
+    public <S> S getService(ServiceReference<S> reference)
     {
         return m_context.getService(reference);
     }
 
-    public boolean ungetService(ServiceReference reference)
+    @Override
+    public boolean ungetService(ServiceReference<?> reference)
     {
         return m_context.ungetService(reference);
     }
+
+    private static class FrameworkStartLevelImpl implements FrameworkStartLevel, BundleAware
+    {
+
+        private Bundle bundle;
+
+        @Override
+        public void setBundle(Bundle bundle)
+        {
+            this.bundle = bundle;
+        }
+
+        @Override
+        public int getStartLevel()
+        {
+            return 0;
+        }
+
+        @Override
+        public void setStartLevel(int startlevel, FrameworkListener... listeners)
+        {
+        }
+
+        @Override
+        public int getInitialBundleStartLevel()
+        {
+            return 0;
+        }
+
+        @Override
+        public void setInitialBundleStartLevel(int startlevel)
+        {
+        }
+
+        @Override
+        public Bundle getBundle()
+        {
+            return bundle;
+        }
+    }
+
+    private static class StartLevelImpl implements StartLevel
+    {
+        @Override
+        public void setStartLevel(int startlevel)
+        {
+            // TODO Auto-generated method stub
+        }
+
+        @Override
+        public void setInitialBundleStartLevel(int startlevel)
+        {
+            // TODO Auto-generated method stub
+        }
+
+        @Override
+        public void setBundleStartLevel(Bundle bundle, int startlevel)
+        {
+            // TODO Auto-generated method stub
+        }
+
+        @Override
+        public boolean isBundlePersistentlyStarted(Bundle bundle)
+        {
+            // TODO Auto-generated method stub
+            return true;
+        }
+
+        @Override
+        public boolean isBundleActivationPolicyUsed(Bundle bundle)
+        {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public int getStartLevel()
+        {
+            // TODO Auto-generated method stub
+            return 1;
+        }
+
+        @Override
+        public int getInitialBundleStartLevel()
+        {
+            // TODO Auto-generated method stub
+            return 1;
+        }
+
+        @Override
+        public int getBundleStartLevel(Bundle bundle)
+        {
+            // TODO Auto-generated method stub
+            return 1;
+        }
+    }
+
+    private class PackageAdminImpl implements PackageAdmin
+    {
+
+        @Override
+        public boolean resolveBundles(Bundle[] bundles)
+        {
+            return true;
+        }
+
+        @Override
+        public void refreshPackages(Bundle[] bundles)
+        {
+            FrameworkEvent event = new FrameworkEvent(FrameworkEvent.PACKAGES_REFRESHED, m_bundles.get(0l), null);
+            m_dispatcher.fireFrameworkEvent(event);
+        }
+
+        @Override
+        public RequiredBundle[] getRequiredBundles(String symbolicName)
+        {
+            List list = new ArrayList();
+            for (Bundle bundle : PojoSR.this.m_bundles.values())
+            {
+                if ((symbolicName == null) || (symbolicName.equals(bundle.getSymbolicName())))
+                {
+                    list.add(new RequiredBundleImpl(bundle));
+                }
+            }
+            return (list.isEmpty())
+                    ? null
+                    : (RequiredBundle[]) list.toArray(new RequiredBundle[list.size()]);
+        }
+
+        @Override
+        public Bundle[] getHosts(Bundle bundle)
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public Bundle[] getFragments(Bundle bundle)
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public ExportedPackage[] getExportedPackages(String name)
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public ExportedPackage[] getExportedPackages(Bundle bundle)
+        {
+            List<ExportedPackage> list = new ArrayList<ExportedPackage>();
+            // If a bundle is specified, then return its
+            // exported packages.
+            if (bundle != null)
+            {
+                getExportedPackages(bundle, list);
+            }
+            // Otherwise return all exported packages.
+            else
+            {
+                for (Bundle b : m_bundles.values())
+                {
+                    getExportedPackages(b, list);
+                }
+            }
+            return list.isEmpty() ? null : list.toArray(new ExportedPackage[list.size()]);
+        }
+
+        private void getExportedPackages(Bundle bundle, List<ExportedPackage> list)
+        {
+            // Since a bundle may have many revisions associated with it,
+            // one for each revision in the cache, search each revision
+            // to get all exports.
+            for (BundleCapability cap : bundle.adapt(BundleWiring.class).getCapabilities(null))
+            {
+                if (cap.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE))
+                {
+                    list.add(new ExportedPackageImpl(cap));
+                }
+            }
+        }
+
+        @Override
+        public ExportedPackage getExportedPackage(String name)
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public Bundle[] getBundles(String symbolicName, String versionRange)
+        {
+            Set<Bundle> result = new HashSet<Bundle>();
+            VersionRange range = versionRange != null ? new VersionRange(versionRange) : null;
+            for (Bundle bundle : m_bundles.values())
+            {
+                if (symbolicName != null && !bundle.getSymbolicName().equals(symbolicName))
+                {
+                    continue;
+                }
+                if (range != null && !range.includes(bundle.getVersion()))
+                {
+                    continue;
+                }
+                result.add(bundle);
+            }
+            return result.isEmpty() ? null : result.toArray(new Bundle[result.size()]);
+        }
+
+        @Override
+        public int getBundleType(Bundle bundle)
+        {
+            return bundle.adapt(BundleRevision.class).getTypes();
+        }
+
+        @Override
+        public Bundle getBundle(Class clazz)
+        {
+            return m_context.getBundle();
+        }
+    }
 }
diff --git a/connect/src/main/java/org/apache/felix/connect/PojoSRBundle.java b/connect/src/main/java/org/apache/felix/connect/PojoSRBundle.java
index 9c7a570..df26329 100644
--- a/connect/src/main/java/org/apache/felix/connect/PojoSRBundle.java
+++ b/connect/src/main/java/org/apache/felix/connect/PojoSRBundle.java
@@ -22,6 +22,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -29,7 +30,6 @@
 import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -51,21 +51,23 @@
 import org.osgi.framework.wiring.BundleRevisions;
 import org.osgi.framework.wiring.BundleWire;
 import org.osgi.framework.wiring.BundleWiring;
-
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Wire;
 
 import org.apache.felix.connect.felix.framework.ServiceRegistry;
 import org.apache.felix.connect.felix.framework.util.EventDispatcher;
 import org.apache.felix.connect.felix.framework.util.MapToDictionary;
 import org.apache.felix.connect.felix.framework.util.StringMap;
 
-class PojoSRBundle implements Bundle, BundleRevisions, BundleRevision
+class PojoSRBundle implements Bundle, BundleRevisions
 {
     private final Revision m_revision;
-    private final Map<String, String> m_manifest;
+    private final Map<String, String> m_headers;
     private final Version m_version;
     private final String m_location;
     private final Map<Long, Bundle> m_bundles;
-    private final ServiceRegistry m_reg;
+    private final ServiceRegistry m_registry;
     private final String m_activatorClass;
     private final long m_id;
     private final String m_symbolicName;
@@ -73,45 +75,62 @@
     volatile int m_state = Bundle.RESOLVED;
     volatile BundleContext m_context = null;
     private final EventDispatcher m_dispatcher;
-    private final ClassLoader m_loader;
+    private final ClassLoader m_classLoader;
+    private final Map<Class, Object> m_services;
     private final Map m_config;
 
-    Revision getRevision()
-    {
-        return m_revision;
-    }
-
-    public PojoSRBundle(Revision revision, Map<String, String> manifest,
-            Version version, String location, ServiceRegistry reg,
-            EventDispatcher dispatcher, String activatorClass, long id,
-            String symbolicName, Map<Long, Bundle> bundles, ClassLoader loader, Map config)
+    public PojoSRBundle(ServiceRegistry registry,
+                        EventDispatcher dispatcher,
+                        Map<Long, Bundle> bundles,
+                        String location,
+                        long id,
+                        String symbolicName,
+                        Version version,
+                        Revision revision,
+                        ClassLoader classLoader,
+                        Map<String, String> headers,
+                        Map<Class, Object> services,
+                        Map<? extends Object, ? extends Object> config)
     {
         m_revision = revision;
-        m_manifest = manifest;
+        m_headers = headers;
         m_version = version;
         m_location = location;
-        m_reg = reg;
+        m_registry = registry;
         m_dispatcher = dispatcher;
-        m_activatorClass = activatorClass;
+        m_activatorClass = headers.get(Constants.BUNDLE_ACTIVATOR);
         m_id = id;
         m_symbolicName = symbolicName;
-        bundles.put(m_id, this);
         m_bundles = bundles;
-        m_loader = loader;
+        m_classLoader = classLoader;
+        m_services = services;
         m_config = config;
+        if (classLoader instanceof BundleAware) {
+            ((BundleAware) classLoader).setBundle(this);
+        }
+        if (services != null) {
+            for (Object o : services.values()) {
+                if (o instanceof BundleAware) {
+                    ((BundleAware) o).setBundle(this);
+                }
+            }
+        }
     }
 
+    @Override
     public int getState()
     {
         return m_state;
     }
 
+    @Override
     public void start(int options) throws BundleException
     {
         // TODO: lifecycle - fix this
         start();
     }
 
+    @Override
     public synchronized void start() throws BundleException
     {
         if (m_state != Bundle.RESOLVED)
@@ -126,36 +145,33 @@
         {
             m_state = Bundle.STARTING;
 
-            m_context = new PojoSRBundleContext(this, m_reg, m_dispatcher,
-                    m_bundles, m_config);
-            m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STARTING,
-                    this));
+            m_context = new PojoSRBundleContext(this, m_registry, m_dispatcher, m_bundles, m_config);
+            m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STARTING, this));
             if (m_activatorClass != null)
             {
-                m_activator = (BundleActivator) m_loader.loadClass(
-                        m_activatorClass).newInstance();
+                m_activator = (BundleActivator) m_classLoader.loadClass(m_activatorClass).newInstance();
                 m_activator.start(m_context);
             }
             m_state = Bundle.ACTIVE;
-            m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STARTED,
-                    this));
+            m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STARTED, this));
         }
         catch (Throwable ex)
         {
             m_state = Bundle.RESOLVED;
             m_activator = null;
-            m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STOPPED,
-                    this));
+            m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STOPPED, this));
             throw new BundleException("Unable to start bundle", ex);
         }
     }
 
+    @Override
     public void stop(int options) throws BundleException
     {
         // TODO: lifecycle - fix this
         stop();
     }
 
+    @Override
     public synchronized void stop() throws BundleException
     {
         if (m_state != Bundle.ACTIVE)
@@ -182,7 +198,7 @@
         }
         finally
         {
-            m_reg.unregisterServices(this);
+            m_registry.unregisterServices(this);
             m_dispatcher.removeListeners(m_context);
             m_activator = null;
             m_context = null;
@@ -192,72 +208,83 @@
         }
     }
 
+    @Override
     public void update(InputStream input) throws BundleException
     {
         throw new BundleException("pojosr bundles can't be updated");
     }
 
+    @Override
     public void update() throws BundleException
     {
         throw new BundleException("pojosr bundles can't be updated");
     }
 
+    @Override
     public void uninstall() throws BundleException
     {
         throw new BundleException("pojosr bundles can't be uninstalled");
     }
 
-    public Dictionary getHeaders()
+    @Override
+    public Dictionary<String, String> getHeaders()
     {
         return getHeaders(Locale.getDefault().toString());
     }
 
+    @Override
     public long getBundleId()
     {
         return m_id;
     }
 
+    @Override
     public String getLocation()
     {
         return m_location;
     }
 
-    public ServiceReference[] getRegisteredServices()
+    @Override
+    public ServiceReference<?>[] getRegisteredServices()
     {
-        return m_reg.getRegisteredServices(this);
+        return m_registry.getRegisteredServices(this);
     }
 
-    public ServiceReference[] getServicesInUse()
+    @Override
+    public ServiceReference<?>[] getServicesInUse()
     {
-        return m_reg.getServicesInUse(this);
+        return m_registry.getServicesInUse(this);
     }
 
+    @Override
     public boolean hasPermission(Object permission)
     {
         // TODO: security - fix this
         return true;
     }
 
+    @Override
     public URL getResource(String name)
     {
         // TODO: module - implement this based on the revision
-        URL result = m_loader.getResource(name);
+        URL result = m_classLoader.getResource(name);
         return result;
     }
 
-    public Dictionary getHeaders(String locale)
+    @Override
+    public Dictionary<String, String> getHeaders(String locale)
     {
-        return new MapToDictionary(getCurrentLocalizedHeader(locale));
+        return new MapToDictionary<String, String>(getCurrentLocalizedHeader(locale));
     }
 
-    Map getCurrentLocalizedHeader(String locale)
+    Map<String, String> getCurrentLocalizedHeader(String locale)
     {
-        Map result = null;
+        Map<String, String> result = null;
 
         // Spec says empty local returns raw headers.
         if ((locale == null) || (locale.length() == 0))
         {
-            result = new StringMap(m_manifest, false);
+            result = new StringMap<String>(m_headers, false);
         }
 
         // If we have no result, try to get it from the cached headers.
@@ -270,7 +297,7 @@
                 // the time of uninstall, so just return that.
                 if (getState() == Bundle.UNINSTALLED)
                 {
-                    result = (Map) m_cachedHeaders.values().iterator().next();
+                    result = m_cachedHeaders.values().iterator().next();
                 }
                 // If the bundle has been updated, clear the cached headers.
                 else if (getLastModified() > m_cachedHeadersTimestamp)
@@ -280,12 +307,8 @@
                 // Otherwise, returned the cached headers if they exist.
                 else
                 {
-                    // Check if headers for this locale have already been
-                    // resolved
-                    if (m_cachedHeaders.containsKey(locale))
-                    {
-                        result = (Map) m_cachedHeaders.get(locale);
-                    }
+                    // Check if headers for this locale have already been resolved
+                    result = m_cachedHeaders.get(locale);
                 }
             }
         }
@@ -294,18 +317,18 @@
         if (result == null)
         {
             // Get a modifiable copy of the raw headers.
-            Map headers = new StringMap(m_manifest, false);
+            Map<String, String> headers = new StringMap<String>(m_headers, false);
             // Assume for now that this will be the result.
             result = headers;
 
             // Check to see if we actually need to localize anything
             boolean localize = false;
-            for (Iterator it = headers.values().iterator(); !localize
-                    && it.hasNext();)
+            for (String s : headers.values())
             {
-                if (((String) it.next()).startsWith("%"))
+                if ((s).startsWith("%"))
                 {
                     localize = true;
+                    break;
                 }
             }
 
@@ -319,31 +342,28 @@
             else
             {
                 // Do localization here and return the localized headers
-                String basename = (String) headers
-                        .get(Constants.BUNDLE_LOCALIZATION);
+                String basename = headers.get(Constants.BUNDLE_LOCALIZATION);
                 if (basename == null)
                 {
                     basename = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
                 }
 
                 // Create ordered list of files to load properties from
-                List resourceList = createLocalizationResourceList(basename,
-                        locale);
+                List<String> resourceList = createLocalizationResourceList(basename, locale);
 
                 // Create a merged props file with all available props for this
                 // locale
                 boolean found = false;
                 Properties mergedProperties = new Properties();
-                for (Iterator it = resourceList.iterator(); it.hasNext();)
+                for (String aResourceList : resourceList)
                 {
-                    URL temp = m_revision.getEntry(it.next() + ".properties");
+                    URL temp = m_revision.getEntry(aResourceList + ".properties");
                     if (temp != null)
                     {
                         found = true;
                         try
                         {
-                            mergedProperties.load(temp.openConnection()
-                                    .getInputStream());
+                            mergedProperties.load(temp.openConnection().getInputStream());
                         }
                         catch (IOException ex)
                         {
@@ -357,24 +377,20 @@
                 // return the default localization.
                 if (!found && !locale.equals(Locale.getDefault().toString()))
                 {
-                    result = getCurrentLocalizedHeader(Locale.getDefault()
-                            .toString());
+                    result = getCurrentLocalizedHeader(Locale.getDefault().toString());
                 }
                 // Otherwise, perform the localization based on the discovered
                 // properties and cache the result.
                 else
                 {
                     // Resolve all localized header entries
-                    for (Iterator it = headers.entrySet().iterator(); it
-                            .hasNext();)
+                    for (Map.Entry<String, String> entry : headers.entrySet())
                     {
-                        Map.Entry entry = (Map.Entry) it.next();
-                        String value = (String) entry.getValue();
+                        String value = entry.getValue();
                         if (value.startsWith("%"))
                         {
                             String newvalue;
-                            String key = value
-                                    .substring(value.indexOf("%") + 1);
+                            String key = value.substring(value.indexOf("%") + 1);
                             newvalue = mergedProperties.getProperty(key);
                             if (newvalue == null)
                             {
@@ -392,7 +408,7 @@
         return result;
     }
 
-    private void updateHeaderCache(String locale, Map localizedHeaders)
+    private void updateHeaderCache(String locale, Map<String, String> localizedHeaders)
     {
         synchronized (m_cachedHeaders)
         {
@@ -401,16 +417,15 @@
         }
     }
 
-    private final Map m_cachedHeaders = new HashMap();
+    private final Map<String, Map<String, String>> m_cachedHeaders = new HashMap<String, Map<String, String>>();
     private long m_cachedHeadersTimestamp;
 
-    private static List createLocalizationResourceList(String basename,
-            String locale)
+    private static List<String> createLocalizationResourceList(String basename, String locale)
     {
-        List result = new ArrayList(4);
+        List<String> result = new ArrayList<String>(4);
 
         StringTokenizer tokens;
-        StringBuffer tempLocale = new StringBuffer(basename);
+        StringBuilder tempLocale = new StringBuilder(basename);
 
         result.add(tempLocale.toString());
 
@@ -433,64 +448,73 @@
 
     public Class<?> loadClass(String name) throws ClassNotFoundException
     {
-        return m_loader.loadClass(name);
+        return m_classLoader.loadClass(name);
     }
 
+    @Override
     public Enumeration<URL> getResources(String name) throws IOException
     {
         // TODO: module - implement this based on the revision
-        return m_loader.getResources(name);
+        return m_classLoader.getResources(name);
     }
 
+    @Override
     public Enumeration<String> getEntryPaths(String path)
     {
         return new EntryFilterEnumeration<String>(m_revision, false, path, null, false,
                 false);
     }
 
+    @Override
     public URL getEntry(String path)
     {
         URL result = m_revision.getEntry(path);
         return result;
     }
 
+    @Override
     public long getLastModified()
     {
         return m_revision.getLastModified();
     }
 
-    public Enumeration<URL> findEntries(String path, String filePattern,
-            boolean recurse)
+    @Override
+    public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse)
     {
         // TODO: module - implement this based on the revision
-        return new EntryFilterEnumeration<URL>(m_revision, false, path, filePattern,
-                recurse, true);
+        return new EntryFilterEnumeration<URL>(m_revision, true, path, filePattern, recurse, true);
     }
 
+    @Override
     public BundleContext getBundleContext()
     {
         return m_context;
     }
 
-    public Map getSignerCertificates(int signersType)
+    @Override
+    public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(int signersType)
     {
         // TODO: security - fix this
-        return new HashMap();
+        return new HashMap<X509Certificate, List<X509Certificate>>();
     }
 
+    @Override
     public Version getVersion()
     {
         return m_version;
     }
 
-	public boolean equals(Object o)
-	{
-	     if (o instanceof PojoSRBundle) {
-		     return ((PojoSRBundle) o).m_id == m_id;
-		 }
-		 return false;
-	}
+    @Override
+    public boolean equals(Object o)
+    {
+        if (o instanceof PojoSRBundle)
+        {
+            return ((PojoSRBundle) o).m_id == m_id;
+        }
+        return false;
+    }
 
+    @Override
     public int compareTo(Bundle o)
     {
         long thisBundleId = this.getBundleId();
@@ -498,45 +522,28 @@
         return (thisBundleId < thatBundleId ? -1 : (thisBundleId == thatBundleId ? 0 : 1));
     }
 
+    @SuppressWarnings("unchecked")
     public <A> A adapt(Class<A> type)
     {
-        if (type == BundleStartLevel.class)
+        if (m_services != null && m_services.containsKey(type))
         {
-            return (A) new BundleStartLevel() {
-
-                public Bundle getBundle()
-                {
-                    return PojoSRBundle.this;
-                }
-
-                public int getStartLevel()
-                {
-                    // TODO Implement this?
-                    return 1;
-                }
-
-                public void setStartLevel(int startlevel)
-                {
-                    // TODO Implement this?
-                }
-
-                public boolean isPersistentlyStarted()
-                {
-                    return true;
-                }
-
-                public boolean isActivationPolicyUsed()
-                {
-                    return false;
-                }};
+            return (A) m_services.get(type);
         }
-        else if (type == BundleRevisions.class)
+        if (type.isInstance(this))
         {
             return (A) this;
         }
-        else if (type == BundleWiring.class)
+        if (type == BundleWiring.class)
         {
-            return (A) this.getWiring();
+            return (A) new BundleWiringImpl(this, m_classLoader);
+        }
+        if (type == BundleRevision.class)
+        {
+            return (A) new BundleRevisionImpl(this);
+        }
+        if (type == BundleStartLevel.class)
+        {
+            return (A) new BundleStartLevelImpl(this);
         }
         return null;
     }
@@ -551,109 +558,248 @@
         String sym = getSymbolicName();
         if (sym != null)
         {
-            return sym + " [" + getBundleId() +"]";
+            return sym + " [" + getBundleId() + "]";
         }
-        return "[" + getBundleId() +"]";
+        return "[" + getBundleId() + "]";
     }
 
+    @Override
+    public List<BundleRevision> getRevisions()
+    {
+        return Arrays.asList(adapt(BundleRevision.class));
+    }
+
+    @Override
     public Bundle getBundle()
     {
         return this;
     }
 
-    public List<BundleRevision> getRevisions()
-    {
-        return Arrays.asList((BundleRevision) this);
-    }
 
-    public List<BundleCapability> getDeclaredCapabilities(String namespace)
+    public static class BundleStartLevelImpl implements BundleStartLevel
     {
-        return Collections.emptyList();
-    }
+        private final Bundle bundle;
 
-    public List<BundleRequirement> getDeclaredRequirements(String namespace)
-    {
-        return Collections.emptyList();
-    }
-
-    public int getTypes()
-    {
-        if (getHeaders().get(Constants.FRAGMENT_HOST) != null) {
-            return BundleRevision.TYPE_FRAGMENT;
-        }
-        return 0;
-    }
-
-    public BundleWiring getWiring()
-    {
-        return new BundleWiring()
+        public BundleStartLevelImpl(Bundle bundle)
         {
+            this.bundle = bundle;
+        }
 
-            public Bundle getBundle()
-            {
-                return PojoSRBundle.this;
-            }
+        public int getStartLevel()
+        {
+            // TODO Implement this?
+            return 1;
+        }
 
-            public Collection<String> listResources(String path, String filePattern, int options)
-            {
-                Collection<String> result = new ArrayList<String>();
-                for (URL u : findEntries(path, filePattern, options))
-                {
-                    result.add(u.toString());
-                }
-                // TODO: implement this
-                return result;
-            }
+        public void setStartLevel(int startlevel)
+        {
+            // TODO Implement this?
+        }
 
-            public boolean isInUse()
-            {
-                return true;
-            }
+        public boolean isPersistentlyStarted()
+        {
+            return true;
+        }
 
-            public boolean isCurrent()
-            {
-                return true;
-            }
+        public boolean isActivationPolicyUsed()
+        {
+            return false;
+        }
 
-            public BundleRevision getRevision()
-            {
-                return PojoSRBundle.this;
-            }
-
-            public List<BundleRequirement> getRequirements(String namespace)
-            {
-                return getDeclaredRequirements(namespace);
-            }
-
-            public List<BundleWire> getRequiredWires(String namespace)
-            {
-                return Collections.emptyList();
-            }
-
-            public List<BundleWire> getProvidedWires(String namespace)
-            {
-                return Collections.emptyList();
-            }
-
-            public ClassLoader getClassLoader()
-            {
-                return getClass().getClassLoader();
-            }
-
-            public List<BundleCapability> getCapabilities(String namespace)
-            {
-                return Collections.emptyList();
-            }
-
-            public List<URL> findEntries(String path, String filePattern, int options)
-            {
-                List<URL> result = new ArrayList<URL>();
-                for (Enumeration<URL> e = PojoSRBundle.this.findEntries(path, filePattern, options == BundleWiring.FINDENTRIES_RECURSE); e.hasMoreElements();)
-                {
-                    result.add(e.nextElement());
-                }
-                return result;
-            }
-        };
+        @Override
+        public Bundle getBundle()
+        {
+            return bundle;
+        }
     }
+
+    public static class BundleRevisionImpl implements BundleRevision
+    {
+        private final Bundle bundle;
+
+        public BundleRevisionImpl(Bundle bundle)
+        {
+            this.bundle = bundle;
+        }
+
+        @Override
+        public String getSymbolicName()
+        {
+            return bundle.getSymbolicName();
+        }
+
+        @Override
+        public Version getVersion()
+        {
+            return bundle.getVersion();
+        }
+
+        @Override
+        public List<BundleCapability> getDeclaredCapabilities(String namespace)
+        {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<BundleRequirement> getDeclaredRequirements(String namespace)
+        {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public int getTypes()
+        {
+            if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null)
+            {
+                return BundleRevision.TYPE_FRAGMENT;
+            }
+            return 0;
+        }
+
+        @Override
+        public BundleWiring getWiring()
+        {
+            return bundle.adapt(BundleWiring.class);
+        }
+
+        @Override
+        public List<Capability> getCapabilities(String namespace)
+        {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<Requirement> getRequirements(String namespace)
+        {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public Bundle getBundle()
+        {
+            return bundle;
+        }
+    }
+
+    public static class BundleWiringImpl implements BundleWiring
+    {
+
+        private final Bundle bundle;
+        private final ClassLoader classLoader;
+
+        public BundleWiringImpl(Bundle bundle, ClassLoader classLoader)
+        {
+            this.bundle = bundle;
+            this.classLoader = classLoader;
+        }
+
+        @Override
+        public boolean isInUse()
+        {
+            return true;
+        }
+
+        @Override
+        public boolean isCurrent()
+        {
+            return true;
+        }
+
+        @Override
+        public BundleRevision getRevision()
+        {
+            return bundle.adapt(BundleRevision.class);
+        }
+
+        @Override
+        public List<BundleRequirement> getRequirements(String namespace)
+        {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<BundleWire> getRequiredWires(String namespace)
+        {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<BundleWire> getProvidedWires(String namespace)
+        {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public ClassLoader getClassLoader()
+        {
+            return classLoader;
+        }
+
+        @Override
+        public List<BundleCapability> getCapabilities(String namespace)
+        {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<Capability> getResourceCapabilities(String namespace)
+        {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<Requirement> getResourceRequirements(String namespace)
+        {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<Wire> getProvidedResourceWires(String namespace)
+        {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<Wire> getRequiredResourceWires(String namespace)
+        {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public BundleRevision getResource()
+        {
+            return getRevision();
+        }
+
+        @Override
+        public Bundle getBundle()
+        {
+            return bundle;
+        }
+
+        @Override
+        public List<URL> findEntries(String path, String filePattern, int options)
+        {
+            List<URL> result = new ArrayList<URL>();
+            for (Enumeration<URL> e = bundle.findEntries(path, filePattern, options == BundleWiring.FINDENTRIES_RECURSE); e.hasMoreElements(); )
+            {
+                result.add(e.nextElement());
+            }
+            return result;
+        }
+
+        @Override
+        public Collection<String> listResources(String path, String filePattern, int options)
+        {
+            // TODO: this is wrong, we should return the resource names
+            Collection<String> result = new ArrayList<String>();
+            for (URL u : findEntries(path, filePattern, options))
+            {
+                result.add(u.toString());
+            }
+            return result;
+        }
+
+    }
+
 }
diff --git a/connect/src/main/java/org/apache/felix/connect/PojoSRBundleContext.java b/connect/src/main/java/org/apache/felix/connect/PojoSRBundleContext.java
index e4e3b3c..864a818 100644
--- a/connect/src/main/java/org/apache/felix/connect/PojoSRBundleContext.java
+++ b/connect/src/main/java/org/apache/felix/connect/PojoSRBundleContext.java
@@ -25,8 +25,9 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Dictionary;
-import java.util.List;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -39,10 +40,13 @@
 import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.hooks.service.FindHook;
 
 import org.apache.felix.connect.felix.framework.ServiceRegistry;
 import org.apache.felix.connect.felix.framework.capabilityset.SimpleFilter;
 import org.apache.felix.connect.felix.framework.util.EventDispatcher;
+import org.apache.felix.connect.felix.framework.util.ShrinkableCollection;
+import org.apache.felix.connect.felix.framework.util.Util;
 
 class PojoSRBundleContext implements BundleContext
 {
@@ -50,10 +54,10 @@
     private final ServiceRegistry m_reg;
     private final EventDispatcher m_dispatcher;
     private final Map<Long, Bundle> m_bundles;
-    private final Map m_config;
+    private final Map<String, Object> m_config;
 
     public PojoSRBundleContext(Bundle bundle, ServiceRegistry reg,
-            EventDispatcher dispatcher, Map<Long, Bundle> bundles, Map config)
+                               EventDispatcher dispatcher, Map<Long, Bundle> bundles, Map<String, Object> config)
     {
         m_bundle = bundle;
         m_reg = reg;
@@ -70,7 +74,7 @@
     public void removeServiceListener(ServiceListener listener)
     {
         m_dispatcher.removeListener(this, ServiceListener.class,
-                    listener);
+                listener);
     }
 
     public void removeFrameworkListener(FrameworkListener listener)
@@ -85,14 +89,14 @@
     }
 
     public ServiceRegistration registerService(String clazz, Object service,
-            Dictionary properties)
+                                               Dictionary properties)
     {
-        return m_reg.registerService(m_bundle, new String[] { clazz }, service,
+        return m_reg.registerService(m_bundle, new String[]{clazz}, service,
                 properties);
     }
 
     public ServiceRegistration registerService(String[] clazzes,
-            Object service, Dictionary properties)
+                                               Object service, Dictionary properties)
     {
         return m_reg.registerService(m_bundle, clazzes, service, properties);
     }
@@ -109,17 +113,17 @@
         throw new BundleException("pojosr can't do that");
     }
 
-    public ServiceReference[] getServiceReferences(String clazz, String filter)
+    public ServiceReference<?>[] getServiceReferences(String clazz, String filter)
             throws InvalidSyntaxException
     {
-        return getAllServiceReferences(clazz, filter);
+        return getServiceReferences(clazz, filter, true);
     }
 
-    public ServiceReference getServiceReference(String clazz)
+    public ServiceReference<?> getServiceReference(String clazz)
     {
         try
         {
-            return getBestServiceReference(getAllServiceReferences(clazz, null));
+            return getBestServiceReference(getServiceReferences(clazz, null));
         }
         catch (InvalidSyntaxException e)
         {
@@ -127,7 +131,7 @@
         }
     }
 
-    private ServiceReference getBestServiceReference(ServiceReference[] refs)
+    private ServiceReference<?> getBestServiceReference(ServiceReference<?>[] refs)
     {
         if (refs == null)
         {
@@ -153,7 +157,7 @@
         return bestRef;
     }
 
-    public Object getService(ServiceReference reference)
+    public <S> S getService(ServiceReference<S> reference)
     {
         return m_reg.getService(m_bundle, reference);
     }
@@ -202,24 +206,90 @@
     }
 
     public ServiceReference[] getAllServiceReferences(String clazz,
-            String filter) throws InvalidSyntaxException
+                                                      String filter) throws InvalidSyntaxException
     {
-        SimpleFilter simple = null;
-        if (filter != null)
+        return getServiceReferences(clazz, filter, false);
+    }
+
+    /**
+     * Retrieves an array of {@link ServiceReference} objects based on calling bundle,
+     * service class name, and filter expression.  Optionally checks for isAssignable to
+     * make sure that the service can be cast to the
+     * @param className Service Classname or <code>null</code> for all
+     * @param expr Filter Criteria or <code>null</code>
+     * @return Array of ServiceReference objects that meet the criteria
+     * @throws InvalidSyntaxException
+     */
+    ServiceReference[] getServiceReferences(
+            final String className,
+            final String expr, final boolean checkAssignable)
+            throws InvalidSyntaxException
+    {
+        // Define filter if expression is not null.
+        SimpleFilter filter = null;
+        if (expr != null)
         {
             try
             {
-                simple = SimpleFilter.parse(filter);
+                filter = SimpleFilter.parse(expr);
             }
             catch (Exception ex)
             {
-                throw new InvalidSyntaxException(ex.getMessage(), filter);
+                throw new InvalidSyntaxException(ex.getMessage(), expr);
             }
         }
-        List<ServiceReference> result = m_reg.getServiceReferences(clazz,
-                simple);
-        return result.isEmpty() ? null : result
-                .toArray(new ServiceReference[result.size()]);
+
+        // Ask the service registry for all matching service references.
+        final Collection<ServiceReference<?>> refList = m_reg.getServiceReferences(className, filter);
+
+        // Filter on assignable references
+        if (checkAssignable)
+        {
+            for (Iterator<ServiceReference<?>> it = refList.iterator(); it.hasNext();)
+            {
+                // Get the current service reference.
+                ServiceReference ref = it.next();
+                // Now check for castability.
+                if (!Util.isServiceAssignable(m_bundle, ref))
+                {
+                    it.remove();
+                }
+            }
+        }
+
+        // activate findhooks
+        Set<ServiceReference<FindHook>> findHooks = m_reg.getHooks(org.osgi.framework.hooks.service.FindHook.class);
+        for (ServiceReference<org.osgi.framework.hooks.service.FindHook> sr : findHooks)
+        {
+            org.osgi.framework.hooks.service.FindHook fh = m_reg.getService(getBundle(0), sr);
+            if (fh != null)
+            {
+                try
+                {
+                    fh.find(this,
+                            className,
+                            expr,
+                            !checkAssignable,
+                            new ShrinkableCollection<ServiceReference<?>>(refList));
+                }
+                catch (Throwable th)
+                {
+                    System.err.println("Problem invoking service registry hook");
+                    th.printStackTrace();
+                }
+                finally
+                {
+                    m_reg.ungetService(getBundle(0), sr);
+                }
+            }
+        }
+
+        if (refList.size() > 0)
+        {
+            return refList.toArray(new ServiceReference[refList.size()]);
+        }
+
+        return null;
     }
 
     public Filter createFilter(String filter) throws InvalidSyntaxException
@@ -240,10 +310,10 @@
         }
     }
 
-     public void addServiceListener(final ServiceListener listener, String filter)
+    public void addServiceListener(final ServiceListener listener, String filter)
             throws InvalidSyntaxException
     {
-		 m_dispatcher.addListener(this, ServiceListener.class, listener,
+        m_dispatcher.addListener(this, ServiceListener.class, listener,
                 filter == null ? null : FrameworkUtil.createFilter(filter));
     }
 
@@ -259,18 +329,21 @@
                 .addListener(this, BundleListener.class, listener, null);
     }
 
+    @SuppressWarnings("unchecked")
     public <S> ServiceRegistration<S> registerService(Class<S> clazz, S service, Dictionary<String, ?> properties)
     {
         return (ServiceRegistration<S>) registerService(clazz.getName(), service, properties);
     }
 
+    @SuppressWarnings("unchecked")
     public <S> ServiceReference<S> getServiceReference(Class<S> clazz)
     {
         return (ServiceReference<S>) getServiceReference(clazz.getName());
     }
 
+    @SuppressWarnings("unchecked")
     public <S> Collection<ServiceReference<S>> getServiceReferences(Class<S> clazz, String filter)
-                    throws InvalidSyntaxException
+            throws InvalidSyntaxException
     {
         ServiceReference<S>[] refs = (ServiceReference<S>[]) getServiceReferences(clazz.getName(), filter);
         if (refs == null)
diff --git a/connect/src/main/java/org/apache/felix/connect/PojoServiceRegistryFactoryImpl.java b/connect/src/main/java/org/apache/felix/connect/PojoServiceRegistryFactoryImpl.java
index 5fdab63..6a05c40 100644
--- a/connect/src/main/java/org/apache/felix/connect/PojoServiceRegistryFactoryImpl.java
+++ b/connect/src/main/java/org/apache/felix/connect/PojoServiceRegistryFactoryImpl.java
@@ -22,9 +22,11 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.security.cert.X509Certificate;
 import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.osgi.framework.Bundle;
@@ -42,183 +44,227 @@
 import org.apache.felix.connect.launch.PojoServiceRegistry;
 import org.apache.felix.connect.launch.PojoServiceRegistryFactory;
 
-public class PojoServiceRegistryFactoryImpl implements
-		PojoServiceRegistryFactory, FrameworkFactory {
+public class PojoServiceRegistryFactoryImpl implements PojoServiceRegistryFactory, FrameworkFactory
+{
 
-	public PojoServiceRegistry newPojoServiceRegistry(Map configuration)
-			throws Exception {
-		return new PojoSR(configuration);
-	}
+    public PojoServiceRegistry newPojoServiceRegistry(Map<String, Object> configuration) throws Exception
+    {
+        return new PojoSR(configuration);
+    }
 
-	public Framework newFramework(Map configuration) {
-		return new FrameworkImpl((String) configuration.get("pojosr.filter"));
-	}
+    public Framework newFramework(Map<String, String> configuration)
+    {
+        return new FrameworkImpl(configuration.get("pojosr.filter"));
+    }
 
-	private static final class FrameworkImpl implements Framework {
-		private final String m_filter;
-		private volatile Bundle m_bundle = null;
-		private volatile PojoServiceRegistry m_reg = null;
+    private static final class FrameworkImpl implements Framework
+    {
+        private final String m_filter;
+        private volatile Bundle m_bundle = null;
+        private volatile PojoServiceRegistry m_reg = null;
 
-		public FrameworkImpl(String filter) {
-			m_filter = filter;
-		}
+        public FrameworkImpl(String filter)
+        {
+            m_filter = filter;
+        }
 
-		public void init() throws BundleException {
-			try {
-				m_reg = new PojoServiceRegistryFactoryImpl()
-				.newPojoServiceRegistry(new HashMap());
-				m_bundle = m_reg.getBundleContext()
-						.getBundle();
-			} catch (Exception ex) {
-				throw new BundleException("Unable to scan classpath", ex);
-			}
-		}
+        public void init() throws BundleException
+        {
+            try
+            {
+                m_reg = new PojoServiceRegistryFactoryImpl()
+                        .newPojoServiceRegistry(new HashMap<String, Object>());
+                m_bundle = m_reg.getBundleContext().getBundle();
+            }
+            catch (Exception ex)
+            {
+                throw new BundleException("Unable to scan classpath", ex);
+            }
+        }
 
-		public int getState() {
-			return (m_bundle == null) ? Bundle.INSTALLED : m_bundle.getState();
-		}
+        public int getState()
+        {
+            return (m_bundle == null) ? Bundle.INSTALLED : m_bundle.getState();
+        }
 
-		public void start(int options) throws BundleException {
-			start();
-		}
+        public void start(int options) throws BundleException
+        {
+            start();
+        }
 
-		public void start() throws BundleException {
-			try {
-				m_reg.startBundles((m_filter != null) ? new ClasspathScanner()
-					.scanForBundles(m_filter)
-					: new ClasspathScanner().scanForBundles());
-			} catch (Exception e) {
-				throw new BundleException("Error starting framework", e);
-			}
-		}
+        public void start() throws BundleException
+        {
+            try
+            {
+                m_reg.startBundles((m_filter != null) ? new ClasspathScanner()
+                        .scanForBundles(m_filter)
+                        : new ClasspathScanner().scanForBundles());
+            }
+            catch (Exception e)
+            {
+                throw new BundleException("Error starting framework", e);
+            }
+        }
 
-		public void stop(int options) throws BundleException {
-			m_bundle.stop(options);
-		}
+        public void stop(int options) throws BundleException
+        {
+            m_bundle.stop(options);
+        }
 
-		public void stop() throws BundleException {
-			m_bundle.stop();
-		}
+        public void stop() throws BundleException
+        {
+            m_bundle.stop();
+        }
 
-		public void update(InputStream input) throws BundleException {
-			m_bundle.update(input);
-		}
+        public void update(InputStream input) throws BundleException
+        {
+            m_bundle.update(input);
+        }
 
-		public void update() throws BundleException {
-			m_bundle.update();
-		}
+        public void update() throws BundleException
+        {
+            m_bundle.update();
+        }
 
-		public void uninstall() throws BundleException {
-			m_bundle.uninstall();
-		}
+        public void uninstall() throws BundleException
+        {
+            m_bundle.uninstall();
+        }
 
-		public Dictionary getHeaders() {
-			return m_bundle.getHeaders();
-		}
+        public Dictionary<String, String> getHeaders()
+        {
+            return m_bundle.getHeaders();
+        }
 
-		public long getBundleId() {
-			return m_bundle.getBundleId();
-		}
+        public long getBundleId()
+        {
+            return m_bundle.getBundleId();
+        }
 
-		public String getLocation() {
-			return m_bundle.getLocation();
-		}
+        public String getLocation()
+        {
+            return m_bundle.getLocation();
+        }
 
-		public ServiceReference[] getRegisteredServices() {
-			return m_bundle.getRegisteredServices();
-		}
+        public ServiceReference[] getRegisteredServices()
+        {
+            return m_bundle.getRegisteredServices();
+        }
 
-		public ServiceReference[] getServicesInUse() {
-			return m_bundle.getServicesInUse();
-		}
+        public ServiceReference[] getServicesInUse()
+        {
+            return m_bundle.getServicesInUse();
+        }
 
-		public boolean hasPermission(Object permission) {
-			return m_bundle.hasPermission(permission);
-		}
+        public boolean hasPermission(Object permission)
+        {
+            return m_bundle.hasPermission(permission);
+        }
 
-		public URL getResource(String name) {
-			return m_bundle.getResource(name);
-		}
+        public URL getResource(String name)
+        {
+            return m_bundle.getResource(name);
+        }
 
-		public Dictionary getHeaders(String locale) {
-			return m_bundle.getHeaders(locale);
-		}
+        public Dictionary<String, String> getHeaders(String locale)
+        {
+            return m_bundle.getHeaders(locale);
+        }
 
-		public String getSymbolicName() {
-			return m_bundle.getSymbolicName();
-		}
+        public String getSymbolicName()
+        {
+            return m_bundle.getSymbolicName();
+        }
 
-		public Class loadClass(String name) throws ClassNotFoundException {
-			return m_bundle.loadClass(name);
-		}
+        public Class loadClass(String name) throws ClassNotFoundException
+        {
+            return m_bundle.loadClass(name);
+        }
 
-		public Enumeration getResources(String name) throws IOException {
-			return m_bundle.getResources(name);
-		}
+        public Enumeration<URL> getResources(String name) throws IOException
+        {
+            return m_bundle.getResources(name);
+        }
 
-		public Enumeration getEntryPaths(String path) {
-			return m_bundle.getEntryPaths(path);
-		}
+        public Enumeration<String> getEntryPaths(String path)
+        {
+            return m_bundle.getEntryPaths(path);
+        }
 
-		public URL getEntry(String path) {
-			return m_bundle.getEntry(path);
-		}
+        public URL getEntry(String path)
+        {
+            return m_bundle.getEntry(path);
+        }
 
-		public long getLastModified() {
-			return m_bundle.getLastModified();
-		}
+        public long getLastModified()
+        {
+            return m_bundle.getLastModified();
+        }
 
-		public Enumeration findEntries(String path, String filePattern,
-				boolean recurse) {
-			return m_bundle.findEntries(path, filePattern, recurse);
-		}
+        public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse)
+        {
+            return m_bundle.findEntries(path, filePattern, recurse);
+        }
 
-		public BundleContext getBundleContext() {
-			return m_bundle.getBundleContext();
-		}
+        public BundleContext getBundleContext()
+        {
+            return m_bundle.getBundleContext();
+        }
 
-		public Map getSignerCertificates(int signersType) {
-			return m_bundle.getSignerCertificates(signersType);
-		}
+        public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(int signersType)
+        {
+            return m_bundle.getSignerCertificates(signersType);
+        }
 
-		public Version getVersion() {
-			return m_bundle.getVersion();
-		}
+        public Version getVersion()
+        {
+            return m_bundle.getVersion();
+        }
 
-		public FrameworkEvent waitForStop(long timeout)
-				throws InterruptedException {
-			final Object lock = new Object();
-			
-			m_bundle.getBundleContext().addBundleListener(new SynchronousBundleListener() {
-				
-				public void bundleChanged(BundleEvent event) {
-					if ((event.getBundle() == m_bundle) && (event.getType() == BundleEvent.STOPPED)) {
-						synchronized (lock) {
-							lock.notifyAll();
-						}
-					}
-				}
-			});
-			synchronized (lock) {
-				while (m_bundle.getState() != Bundle.RESOLVED) {
-					if (m_bundle.getState() == Bundle.STOPPING ) {
-						lock.wait(100);
-					}
-					else {
-						lock.wait();
-					}
-				}
-			}
-			return new FrameworkEvent(FrameworkEvent.STOPPED, m_bundle, null);
-		}
-		
-		public File getDataFile(String filename) {
-		    return m_bundle.getDataFile(filename);
-		}
+        public FrameworkEvent waitForStop(long timeout)
+                throws InterruptedException
+        {
+            final Object lock = new Object();
+
+            m_bundle.getBundleContext().addBundleListener(new SynchronousBundleListener()
+            {
+
+                public void bundleChanged(BundleEvent event)
+                {
+                    if ((event.getBundle() == m_bundle) && (event.getType() == BundleEvent.STOPPED))
+                    {
+                        synchronized (lock)
+                        {
+                            lock.notifyAll();
+                        }
+                    }
+                }
+            });
+            synchronized (lock)
+            {
+                while (m_bundle.getState() != Bundle.RESOLVED)
+                {
+                    if (m_bundle.getState() == Bundle.STOPPING)
+                    {
+                        lock.wait(100);
+                    }
+                    else
+                    {
+                        lock.wait();
+                    }
+                }
+            }
+            return new FrameworkEvent(FrameworkEvent.STOPPED, m_bundle, null);
+        }
+
+        public File getDataFile(String filename)
+        {
+            return m_bundle.getDataFile(filename);
+        }
 
         public int compareTo(Bundle o)
         {
-            if (o == this) 
+            if (o == this)
             {
                 return 0;
             }
@@ -230,5 +276,5 @@
             return m_bundle.adapt(type);
         }
 
-	}
+    }
 }
diff --git a/connect/src/main/java/org/apache/felix/connect/RequiredBundleImpl.java b/connect/src/main/java/org/apache/felix/connect/RequiredBundleImpl.java
new file mode 100644
index 0000000..50993b7
--- /dev/null
+++ b/connect/src/main/java/org/apache/felix/connect/RequiredBundleImpl.java
@@ -0,0 +1,79 @@
+/*
+ * 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.felix.connect;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.service.packageadmin.RequiredBundle;
+
+public class RequiredBundleImpl implements RequiredBundle
+{
+
+    private final Bundle m_bundle;
+
+    public RequiredBundleImpl(Bundle bundle)
+    {
+        m_bundle = bundle;
+    }
+
+    public String getSymbolicName()
+    {
+        return m_bundle.getSymbolicName();
+    }
+
+    public Bundle getBundle()
+    {
+        return m_bundle;
+    }
+
+    public Bundle[] getRequiringBundles()
+    {
+        Set<Bundle> set = new HashSet<Bundle>();
+        for (BundleWire wire : m_bundle.adapt(BundleWiring.class).getProvidedWires(null))
+        {
+            if (BundleNamespace.BUNDLE_NAMESPACE.equals(wire.getCapability().getNamespace()))
+            {
+                set.add(wire.getRequirer().getBundle());
+            }
+        }
+        return set.toArray(new Bundle[set.size()]);
+    }
+
+    public Version getVersion()
+    {
+        return m_bundle.getVersion();
+    }
+
+    public boolean isRemovalPending()
+    {
+        return false;
+    }
+
+    public String toString()
+    {
+        return m_bundle.getSymbolicName() + "; version=" + m_bundle.getVersion();
+    }
+
+}
diff --git a/connect/src/main/java/org/apache/felix/connect/Revision.java b/connect/src/main/java/org/apache/felix/connect/Revision.java
index cf4fd36..77b23bd 100644
--- a/connect/src/main/java/org/apache/felix/connect/Revision.java
+++ b/connect/src/main/java/org/apache/felix/connect/Revision.java
@@ -21,11 +21,11 @@
 import java.net.URL;
 import java.util.Enumeration;
 
-abstract class Revision
+public interface Revision
 {
-    public abstract long getLastModified();
+    public long getLastModified();
 
-    public abstract URL getEntry(String entryName);
+    public URL getEntry(String entryName);
 
-    public abstract Enumeration<String> getEntries();
+    public Enumeration<String> getEntries();
 }
\ No newline at end of file
diff --git a/connect/src/main/java/org/apache/felix/connect/URLRevision.java b/connect/src/main/java/org/apache/felix/connect/URLRevision.java
index efbe650..4cf45cb 100644
--- a/connect/src/main/java/org/apache/felix/connect/URLRevision.java
+++ b/connect/src/main/java/org/apache/felix/connect/URLRevision.java
@@ -20,10 +20,10 @@
 
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.Collections;
 import java.util.Enumeration;
-import java.util.Properties;
 
-class URLRevision extends Revision
+class URLRevision implements Revision
 {
     private final URL m_url;
     private final long m_lastModified;
@@ -47,9 +47,10 @@
         return m_lastModified;
     }
 
-    public Enumeration getEntries()
+    @Override
+    public Enumeration<String> getEntries()
     {
-        return new Properties().elements();
+        return Collections.emptyEnumeration();
     }
 
     @Override
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/ServiceRegistrationImpl.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/ServiceRegistrationImpl.java
index b29e587..2c401b0 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/ServiceRegistrationImpl.java
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/ServiceRegistrationImpl.java
@@ -18,17 +18,27 @@
  */
 package org.apache.felix.connect.felix.framework;
 
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Set;
 
-import org.osgi.framework.*;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceException;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRevision;
 
 import org.apache.felix.connect.felix.framework.util.MapToDictionary;
 import org.apache.felix.connect.felix.framework.util.StringMap;
 import org.apache.felix.connect.felix.framework.util.Util;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRevision;
 
-class ServiceRegistrationImpl implements ServiceRegistration
+class ServiceRegistrationImpl<T> implements ServiceRegistration<T>
 {
     // Service registry.
     private final ServiceRegistry m_registry;
@@ -41,16 +51,16 @@
     // Service object.
     private volatile Object m_svcObj;
     // Service factory interface.
-    private volatile ServiceFactory m_factory;
+    private volatile ServiceFactory<T> m_factory;
     // Associated property dictionary.
     private volatile Map m_propMap = new StringMap(false);
     // Re-usable service reference.
-    private final ServiceReferenceImpl m_ref;
+    private final ServiceReferenceImpl<T> m_ref;
     // Flag indicating that we are unregistering.
     private volatile boolean m_isUnregistering = false;
 
     public ServiceRegistrationImpl(ServiceRegistry registry, Bundle bundle,
-            String[] classes, Long serviceId, Object svcObj, Dictionary dict)
+                                   String[] classes, Long serviceId, Object svcObj, Dictionary dict)
     {
         m_registry = registry;
         m_bundle = bundle;
@@ -77,7 +87,7 @@
         m_svcObj = null;
     }
 
-    public synchronized ServiceReference getReference()
+    public synchronized ServiceReferenceImpl<T> getReference()
     {
         // Make sure registration is valid.
         if (!isValid())
@@ -152,7 +162,7 @@
      * itself.
      *
      * @return The service object associated with the registration.
-     **/
+     */
     Object getService()
     {
         return m_svcObj;
@@ -175,7 +185,7 @@
         }
     }
 
-    void ungetService(Bundle relBundle, Object svcObj)
+    void ungetService(Bundle relBundle, T svcObj)
     {
         // If the service object is a service factory, then
         // let it release the service object.
@@ -238,19 +248,24 @@
         }
         if (svcObj != null)
         {
-            for (int i = 0; i < m_classes.length; i++)
+            for (String className : m_classes)
             {
-                try {
-                if (!Class.forName(m_classes[i]).isAssignableFrom(svcObj.getClass()))
+                Class<?> clazz = Util.loadClassUsingClass(svcObj.getClass(), className);
+                if ((clazz == null) || !clazz.isAssignableFrom(svcObj.getClass()))
                 {
-                    throw new ServiceException(
-                            "Service cannot be cast: " + m_classes[i],
-                            ServiceException.FACTORY_ERROR);
+                    if (clazz == null)
+                    {
+                        throw new ServiceException(
+                                "Service cannot be cast due to missing class: " + className,
+                                ServiceException.FACTORY_ERROR);
+                    }
+                    else
+                    {
+                        throw new ServiceException(
+                                "Service cannot be cast: " + className,
+                                ServiceException.FACTORY_ERROR);
+                    }
                 }
-				} catch (ClassNotFoundException ex) {
-				   throw new ServiceException("Service is missing class: " + m_classes[i], ServiceException.FACTORY_ERROR);
-				}
-
             }
         }
         else
@@ -261,18 +276,17 @@
         return svcObj;
     }
 
-    private void ungetFactoryUnchecked(Bundle bundle, Object svcObj)
+    private void ungetFactoryUnchecked(Bundle bundle, T svcObj)
     {
         m_factory.ungetService(bundle, this, svcObj);
     }
 
 
-
     //
     // ServiceReference implementation
     //
 
-    class ServiceReferenceImpl implements ServiceReference, BundleCapability
+    class ServiceReferenceImpl<T> implements ServiceReference<T>, BundleCapability
     {
         private final ServiceReferenceMap m_map;
 
@@ -290,6 +304,13 @@
         // Capability methods.
         //
 
+
+        @Override
+        public BundleRevision getResource()
+        {
+            return getRevision();
+        }
+
         @Override
         public BundleRevision getRevision()
         {
@@ -305,30 +326,28 @@
         @Override
         public Map<String, String> getDirectives()
         {
-            return Collections.EMPTY_MAP;
+            return Collections.emptyMap();
         }
 
         @Override
-        public Map<String,Object> getAttributes()
+        public Map<String, Object> getAttributes()
         {
             return m_map;
         }
 
-        public List<String> getUses()
-        {
-            return Collections.EMPTY_LIST;
-        }
-
+        @Override
         public Object getProperty(String s)
         {
             return ServiceRegistrationImpl.this.getProperty(s);
         }
 
+        @Override
         public String[] getPropertyKeys()
         {
             return ServiceRegistrationImpl.this.getPropertyKeys();
         }
 
+        @Override
         public Bundle getBundle()
         {
             // The spec says that this should return null if
@@ -336,6 +355,7 @@
             return (isValid()) ? m_bundle : null;
         }
 
+        @Override
         public Bundle[] getUsingBundles()
         {
             return ServiceRegistrationImpl.this.getUsingBundles();
@@ -349,12 +369,15 @@
             {
                 oc = oc + ocs[i];
                 if (i < ocs.length - 1)
+                {
                     oc = oc + ", ";
+                }
             }
             oc = oc + "]";
             return oc;
         }
 
+        @Override
         public boolean isAssignableTo(Bundle requester, String className)
         {
             // Always return true if the requester is the same as the provider.
@@ -365,9 +388,8 @@
 
             // Boolean flag.
             boolean allow = true;
-            // Get the package.
-            String pkgName = Util.getClassPackage(className);
-            /*
+            /* // Get the package.
+             * String pkgName = Util.getClassPackage(className);
              * Module requesterModule = ((BundleImpl)
              * requester).getCurrentModule(); // Get package wiring from service
              * requester. Wire requesterWire = Util.getWire(requesterModule,
@@ -444,6 +466,7 @@
             return allow;
         }
 
+        @Override
         public int compareTo(Object reference)
         {
             ServiceReference other = (ServiceReference) reference;
@@ -485,66 +508,78 @@
         }
     }
 
-     private class ServiceReferenceMap implements Map
+    private class ServiceReferenceMap implements Map<String, Object>
     {
+        @Override
         public int size()
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
+        @Override
         public boolean isEmpty()
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
+        @Override
         public boolean containsKey(Object o)
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
+        @Override
         public boolean containsValue(Object o)
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
+        @Override
         public Object get(Object o)
         {
             return ServiceRegistrationImpl.this.getProperty((String) o);
         }
 
-        public Object put(Object k, Object v)
+        @Override
+        public Object put(String k, Object v)
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
+        @Override
         public Object remove(Object o)
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
-        public void putAll(Map map)
+        @Override
+        public void putAll(Map<? extends String, ? extends Object> map)
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
+        @Override
         public void clear()
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
-        public Set<Object> keySet()
+        @Override
+        public Set<String> keySet()
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
+        @Override
         public Collection<Object> values()
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
-        public Set<Entry<Object, Object>> entrySet()
+        @Override
+        public Set<Entry<String, Object>> entrySet()
         {
-            return Collections.EMPTY_SET;
+            return Collections.emptySet();
         }
     }
 }
\ No newline at end of file
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/ServiceRegistry.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/ServiceRegistry.java
index d46f613..a076b7f 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/ServiceRegistry.java
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/ServiceRegistry.java
@@ -18,80 +18,94 @@
  */
 package org.apache.felix.connect.felix.framework;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.WeakHashMap;
 
-import org.osgi.framework.*;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceException;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.wiring.BundleCapability;
 
 import org.apache.felix.connect.felix.framework.capabilityset.CapabilitySet;
 import org.apache.felix.connect.felix.framework.capabilityset.SimpleFilter;
-import org.osgi.framework.wiring.BundleCapability;
 
 public class ServiceRegistry
 {
     private long m_currentServiceId = 1L;
     // Maps bundle to an array of service registrations.
-    private final Map m_regsMap = Collections.synchronizedMap(new HashMap());
+    private final Map<Bundle, ServiceRegistration[]> m_regsMap = Collections.synchronizedMap(new HashMap<Bundle, ServiceRegistration[]>());
     // Capability set for all service registrations.
-    private final CapabilitySet m_regCapSet;
+    private final CapabilitySet<ServiceRegistrationImpl.ServiceReferenceImpl> m_regCapSet;
     // Maps registration to thread to keep track when a
     // registration is in use, which will cause other
     // threads to wait.
-    private final Map m_lockedRegsMap = new HashMap();
+    private final Map<ServiceRegistrationImpl, Thread> m_lockedRegsMap = new HashMap<ServiceRegistrationImpl, Thread>();
     // Maps bundle to an array of usage counts.
-    private final Map m_inUseMap = new HashMap();
+    private final Map<Bundle, UsageCount[]> m_inUseMap = new HashMap<Bundle, UsageCount[]>();
     private final ServiceRegistryCallbacks m_callbacks;
     private final WeakHashMap<ServiceReference, ServiceReference> m_blackList =
-        new WeakHashMap<ServiceReference, ServiceReference>();
+            new WeakHashMap<ServiceReference, ServiceReference>();
     private final static Class<?>[] m_hookClasses =
-    {
-        org.osgi.framework.hooks.bundle.FindHook.class,
-        org.osgi.framework.hooks.bundle.EventHook.class,
-        org.osgi.framework.hooks.service.EventHook.class,
-        org.osgi.framework.hooks.service.EventListenerHook.class,
-        org.osgi.framework.hooks.service.FindHook.class,
-        org.osgi.framework.hooks.service.ListenerHook.class,
-        org.osgi.framework.hooks.weaving.WeavingHook.class,
-        org.osgi.framework.hooks.resolver.ResolverHookFactory.class,
-        org.osgi.service.url.URLStreamHandlerService.class,
-        java.net.ContentHandler.class
-    };
+            {
+                    org.osgi.framework.hooks.bundle.FindHook.class,
+                    org.osgi.framework.hooks.bundle.EventHook.class,
+                    org.osgi.framework.hooks.service.EventHook.class,
+                    org.osgi.framework.hooks.service.EventListenerHook.class,
+                    org.osgi.framework.hooks.service.FindHook.class,
+                    org.osgi.framework.hooks.service.ListenerHook.class,
+                    org.osgi.framework.hooks.weaving.WeavingHook.class,
+                    org.osgi.framework.hooks.resolver.ResolverHookFactory.class,
+                    org.osgi.service.url.URLStreamHandlerService.class,
+                    java.net.ContentHandler.class
+            };
     private final Map<Class<?>, Set<ServiceReference<?>>> m_allHooks =
-        new HashMap<Class<?>, Set<ServiceReference<?>>>();
+            new HashMap<Class<?>, Set<ServiceReference<?>>>();
 
     public ServiceRegistry(ServiceRegistryCallbacks callbacks)
     {
         m_callbacks = callbacks;
 
-        List indices = new ArrayList();
-        indices.add(Constants.OBJECTCLASS);
-        m_regCapSet = new CapabilitySet(indices, false);
+        m_regCapSet = new CapabilitySet(Collections.singletonList(Constants.OBJECTCLASS), false);
     }
 
     public ServiceReference[] getRegisteredServices(Bundle bundle)
     {
-        ServiceRegistration[] regs = (ServiceRegistration[]) m_regsMap.get(bundle);
+        ServiceRegistration[] regs = m_regsMap.get(bundle);
         if (regs != null)
         {
-            List refs = new ArrayList(regs.length);
-            for (int i = 0; i < regs.length; i++)
+            List<ServiceReference> refs = new ArrayList<ServiceReference>(regs.length);
+            for (ServiceRegistration reg : regs)
             {
                 try
                 {
-                    refs.add(regs[i].getReference());
+                    refs.add(reg.getReference());
                 }
                 catch (IllegalStateException ex)
                 {
                     // Don't include the reference as it is not valid anymore
                 }
             }
-            return (ServiceReference[]) refs.toArray(new ServiceReference[refs.size()]);
+            return refs.toArray(new ServiceReference[refs.size()]);
         }
         return null;
     }
 
     // Caller is expected to fire REGISTERED event.
     public ServiceRegistration registerService(
-        Bundle bundle, String[] classNames, Object svcObj, Dictionary dict)
+            Bundle bundle, String[] classNames, Object svcObj, Dictionary dict)
     {
         ServiceRegistrationImpl reg = null;
 
@@ -99,7 +113,7 @@
         {
             // Create the service registration.
             reg = new ServiceRegistrationImpl(
-                this, bundle, classNames, new Long(m_currentServiceId++), svcObj, dict);
+                    this, bundle, classNames, m_currentServiceId++, svcObj, dict);
 
             // Keep track of registered hooks.
             addHooks(classNames, svcObj, reg.getReference());
@@ -107,19 +121,19 @@
             // Get the bundles current registered services.
             ServiceRegistration[] regs = (ServiceRegistration[]) m_regsMap.get(bundle);
             m_regsMap.put(bundle, addServiceRegistration(regs, reg));
-            m_regCapSet.addCapability((BundleCapability) reg.getReference());
+            m_regCapSet.addCapability(reg.getReference());
         }
 
         // Notify callback objects about registered service.
         if (m_callbacks != null)
         {
             m_callbacks.serviceChanged(new ServiceEvent(
-                ServiceEvent.REGISTERED, reg.getReference()), null);
+                    ServiceEvent.REGISTERED, reg.getReference()), null);
         }
         return reg;
     }
 
-    public void unregisterService(Bundle bundle, ServiceRegistration reg)
+    public void unregisterService(Bundle bundle, ServiceRegistrationImpl reg)
     {
         // If this is a hook, it should be removed.
         removeHook(reg.getReference());
@@ -133,16 +147,16 @@
             // new bundles will be able to look up the service.
 
             // Now remove the registered service.
-            ServiceRegistration[] regs = (ServiceRegistration[]) m_regsMap.get(bundle);
+            ServiceRegistration[] regs = m_regsMap.get(bundle);
             m_regsMap.put(bundle, removeServiceRegistration(regs, reg));
-            m_regCapSet.removeCapability((BundleCapability) reg.getReference());
+            m_regCapSet.removeCapability(reg.getReference());
         }
 
         // Notify callback objects about unregistering service.
         if (m_callbacks != null)
         {
             m_callbacks.serviceChanged(
-                new ServiceEvent(ServiceEvent.UNREGISTERING, reg.getReference()), null);
+                    new ServiceEvent(ServiceEvent.UNREGISTERING, reg.getReference()), null);
         }
 
         // Now forcibly unget the service object for all stubborn clients.
@@ -152,7 +166,9 @@
             for (int i = 0; (clients != null) && (i < clients.length); i++)
             {
                 while (ungetService(clients[i], reg.getReference()))
+                {
                     ; // Keep removing until it is no longer possible
+                }
             }
             ((ServiceRegistrationImpl) reg).invalidate();
         }
@@ -165,7 +181,6 @@
      * bundle.
      *
      * @param bundle the bundle whose services should be unregistered.
-     *
      */
     public void unregisterServices(Bundle bundle)
     {
@@ -173,7 +188,7 @@
         ServiceRegistration[] regs = null;
         synchronized (this)
         {
-            regs = (ServiceRegistration[]) m_regsMap.get(bundle);
+            regs = m_regsMap.get(bundle);
         }
 
         // Note, there is no race condition here with respect to the
@@ -197,7 +212,7 @@
         }
     }
 
-    public synchronized List getServiceReferences(String className, SimpleFilter filter)
+    public synchronized Collection<ServiceReference<?>> getServiceReferences(String className, SimpleFilter filter)
     {
         if ((className == null) && (filter == null))
         {
@@ -212,16 +227,16 @@
         else if ((className != null) && (filter != null))
         {
             // Return services matching the class name and filter.
-            List filters = new ArrayList(2);
+            List<Object> filters = new ArrayList<Object>(2);
             filters.add(new SimpleFilter(Constants.OBJECTCLASS, className, SimpleFilter.EQ));
             filters.add(filter);
             filter = new SimpleFilter(null, filters, SimpleFilter.AND);
         }
         // else just use the specified filter.
 
-        Set<BundleCapability> matches = m_regCapSet.match(filter, false);
+        Set<ServiceRegistrationImpl.ServiceReferenceImpl> matches = m_regCapSet.match(filter, false);
 
-        return new ArrayList(matches);
+        return (Collection) matches;
     }
 
     public synchronized ServiceReference[] getServicesInUse(Bundle bundle)
@@ -246,7 +261,7 @@
 
         // Get the service registration.
         ServiceRegistrationImpl reg =
-            ((ServiceRegistrationImpl.ServiceReferenceImpl) ref).getRegistration();
+                ((ServiceRegistrationImpl.ServiceReferenceImpl) ref).getRegistration();
 
         synchronized (this)
         {
@@ -258,9 +273,9 @@
                 if (o.equals(Thread.currentThread()))
                 {
                     throw new ServiceException(
-                        "ServiceFactory.getService() resulted in a cycle.",
-                        ServiceException.FACTORY_ERROR,
-                        null);
+                            "ServiceFactory.getService() resulted in a cycle.",
+                            ServiceException.FACTORY_ERROR,
+                            null);
                 }
 
                 // Otherwise, wait for it to be freed.
@@ -339,7 +354,7 @@
     {
         UsageCount usage = null;
         ServiceRegistrationImpl reg =
-            ((ServiceRegistrationImpl.ServiceReferenceImpl) ref).getRegistration();
+                ((ServiceRegistrationImpl.ServiceReferenceImpl) ref).getRegistration();
 
         synchronized (this)
         {
@@ -351,7 +366,7 @@
                 if (o.equals(Thread.currentThread()))
                 {
                     throw new IllegalStateException(
-                        "ServiceFactory.ungetService() resulted in a cycle.");
+                            "ServiceFactory.ungetService() resulted in a cycle.");
                 }
 
                 // Otherwise, wait for it to be freed.
@@ -385,7 +400,7 @@
             {
                 // Remove reference from usages array.
                 ((ServiceRegistrationImpl.ServiceReferenceImpl) ref)
-                    .getRegistration().ungetService(bundle, usage.m_svcObj);
+                        .getRegistration().ungetService(bundle, usage.m_svcObj);
             }
         }
         finally
@@ -423,14 +438,13 @@
      * specified bundle.
      *
      * @param bundle the bundle whose services are to be released.
-     *
      */
     public void ungetServices(Bundle bundle)
     {
         UsageCount[] usages;
         synchronized (this)
         {
-            usages = (UsageCount[]) m_inUseMap.get(bundle);
+            usages = m_inUseMap.get(bundle);
         }
 
         if (usages == null)
@@ -445,10 +459,10 @@
 
         // Remove each service object from the
         // service cache.
-        for (int i = 0; i < usages.length; i++)
+        for (UsageCount usage : usages)
         {
             // Keep ungetting until all usage count is zero.
-            while (ungetService(bundle, usages[i].m_ref))
+            while (ungetService(bundle, usage.m_ref))
             {
                 // Empty loop body.
             }
@@ -458,22 +472,18 @@
     public synchronized Bundle[] getUsingBundles(ServiceReference ref)
     {
         Bundle[] bundles = null;
-        for (Iterator iter = m_inUseMap.entrySet().iterator(); iter.hasNext();)
+        for (Map.Entry<Bundle, UsageCount[]> entry : m_inUseMap.entrySet())
         {
-            Map.Entry entry = (Map.Entry) iter.next();
-            Bundle bundle = (Bundle) entry.getKey();
-            UsageCount[] usages = (UsageCount[]) entry.getValue();
-            for (int useIdx = 0; useIdx < usages.length; useIdx++)
+            Bundle bundle = entry.getKey();
+            UsageCount[] usages = entry.getValue();
+            for (UsageCount usage : usages)
             {
-                if (usages[useIdx].m_ref.equals(ref))
+                if (usage.m_ref.equals(ref))
                 {
                     // Add the bundle to the array to be returned.
                     if (bundles == null)
                     {
-                        bundles = new Bundle[]
-                        {
-                            bundle
-                        };
+                        bundles = new Bundle[]{bundle};
                     }
                     else
                     {
@@ -494,19 +504,19 @@
         if (m_callbacks != null)
         {
             m_callbacks.serviceChanged(
-                new ServiceEvent(ServiceEvent.MODIFIED, reg.getReference()), oldProps);
+                    new ServiceEvent(ServiceEvent.MODIFIED, reg.getReference()), oldProps);
         }
     }
 
     private static ServiceRegistration[] addServiceRegistration(
-        ServiceRegistration[] regs, ServiceRegistration reg)
+            ServiceRegistration[] regs, ServiceRegistration reg)
     {
         if (regs == null)
         {
             regs = new ServiceRegistration[]
-            {
-                reg
-            };
+                    {
+                            reg
+                    };
         }
         else
         {
@@ -519,7 +529,7 @@
     }
 
     private static ServiceRegistration[] removeServiceRegistration(
-        ServiceRegistration[] regs, ServiceRegistration reg)
+            ServiceRegistration[] regs, ServiceRegistration reg)
     {
         for (int i = 0; (regs != null) && (i < regs.length); i++)
         {
@@ -538,7 +548,7 @@
                     if (i < newRegs.length)
                     {
                         System.arraycopy(
-                            regs, i + 1, newRegs, i, newRegs.length - i);
+                                regs, i + 1, newRegs, i, newRegs.length - i);
                     }
                     regs = newRegs;
                 }
@@ -552,9 +562,8 @@
      * specified service reference.
      *
      * @param bundle The bundle whose usage counts are being searched.
-     * @param ref The service reference to find in the bundle's usage counts.
+     * @param ref    The service reference to find in the bundle's usage counts.
      * @return The associated usage count or null if not found.
-     *
      */
     private UsageCount getUsageCount(Bundle bundle, ServiceReference ref)
     {
@@ -577,13 +586,11 @@
      * be incremented.
      *
      * @param bundle The bundle acquiring the service.
-     * @param ref The service reference of the acquired service.
-     * @param svcObj The service object of the acquired service.
-     *
+     * @param ref    The service reference of the acquired service.
      */
     private UsageCount addUsageCount(Bundle bundle, ServiceReference ref)
     {
-        UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+        UsageCount[] usages = m_inUseMap.get(bundle);
 
         UsageCount usage = new UsageCount();
         usage.m_ref = ref;
@@ -591,9 +598,9 @@
         if (usages == null)
         {
             usages = new UsageCount[]
-            {
-                usage
-            };
+                    {
+                            usage
+                    };
         }
         else
         {
@@ -618,8 +625,7 @@
      * usage count for the specified service reference.
      *
      * @param bundle The bundle whose usage count should be removed.
-     * @param ref The service reference whose usage count should be removed.
-     *
+     * @param ref    The service reference whose usage count should be removed.
      */
     private void flushUsageCount(Bundle bundle, ServiceReference ref)
     {
@@ -641,7 +647,7 @@
                     if (i < newUsages.length)
                     {
                         System.arraycopy(
-                            usages, i + 1, newUsages, i, newUsages.length - i);
+                                usages, i + 1, newUsages, i, newUsages.length - i);
                     }
                     usages = newUsages;
                 }
@@ -726,7 +732,7 @@
         // We maintain the hooks sorted, so if ranking has changed for example,
         // we need to ensure the order remains correct by resorting the hooks.
         Object svcObj = ((ServiceRegistrationImpl.ServiceReferenceImpl) ref)
-            .getRegistration().getService();
+                .getRegistration().getService();
         String[] classNames = (String[]) ref.getProperty(Constants.OBJECTCLASS);
 
         for (Class<?> hookClass : m_hookClasses)
@@ -750,7 +756,7 @@
     private void removeHook(ServiceReference ref)
     {
         Object svcObj = ((ServiceRegistrationImpl.ServiceReferenceImpl) ref)
-            .getRegistration().getService();
+                .getRegistration().getService();
         String[] classNames = (String[]) ref.getProperty(Constants.OBJECTCLASS);
 
         for (Class<?> hookClass : m_hookClasses)
@@ -777,25 +783,18 @@
     {
         synchronized (m_allHooks)
         {
-            Set<ServiceReference<?>> hooks = m_allHooks.get(hookClass);
+            @SuppressWarnings("unchecked")
+            Set<ServiceReference<S>> hooks = (Set) m_allHooks.get(hookClass);
             if (hooks != null)
             {
-                SortedSet sorted = new TreeSet<ServiceReference<?>>(Collections.reverseOrder());
+                SortedSet<ServiceReference<S>> sorted = new TreeSet<ServiceReference<S>>(Collections.reverseOrder());
                 sorted.addAll(hooks);
-                return asTypedSortedSet(sorted);
+                return sorted;
             }
-            return Collections.EMPTY_SET;
+            return Collections.emptySet();
         }
     }
 
-    private static <S> SortedSet<ServiceReference<S>> asTypedSortedSet(
-        SortedSet<ServiceReference<?>> ss)
-    {
-        return (SortedSet<ServiceReference<S>>) (SortedSet) ss;
-
-
-    }
-
     private static class UsageCount
     {
         public int m_count = 0;
@@ -805,6 +804,6 @@
 
     public interface ServiceRegistryCallbacks
     {
-        void serviceChanged(ServiceEvent event, Dictionary oldProps);
+        void serviceChanged(ServiceEvent event, Dictionary<String, ?> oldProps);
     }
 }
\ No newline at end of file
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/Attribute.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/Attribute.java
deleted file mode 100644
index ea8b01f..0000000
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/Attribute.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.felix.connect.felix.framework.capabilityset;
-
-public class Attribute
-{
-    private final String m_name;
-    private final Object m_value;
-    private final boolean m_isMandatory;
-
-    public Attribute(String name, Object value, boolean isMandatory)
-    {
-        m_name = name;
-        m_value = value;
-        m_isMandatory = isMandatory;
-    }
-
-    public String getName()
-    {
-        return m_name;
-    }
-
-    public Object getValue()
-    {
-        return m_value;
-    }
-
-    public boolean isMandatory()
-    {
-        return m_isMandatory;
-    }
-
-    public String toString()
-    {
-        return m_name + "=" + m_value;
-    }
-}
\ No newline at end of file
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/Capability.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/Capability.java
deleted file mode 100644
index 7c4e0f5..0000000
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/Capability.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.felix.connect.felix.framework.capabilityset;
-
-import java.util.List;
-
-public interface Capability
-{
-    static final String MODULE_NAMESPACE = "module";
-    static final String HOST_NAMESPACE = "host";
-    static final String PACKAGE_NAMESPACE = "package";
-    static final String SINGLETON_NAMESPACE = "singleton";
-
-    public static final String PACKAGE_ATTR = "package";
-    public static final String VERSION_ATTR = "version";
-
-    String getNamespace();
-
-    Directive getDirective(String name);
-
-    List<Directive> getDirectives();
-
-    Attribute getAttribute(String name);
-
-    List<Attribute> getAttributes();
-
-    List<String> getUses();
-}
\ No newline at end of file
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/CapabilitySet.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/CapabilitySet.java
index 895809b..cfeccef 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/CapabilitySet.java
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/CapabilitySet.java
@@ -31,33 +31,34 @@
 import java.util.Set;
 import java.util.TreeMap;
 
-import org.apache.felix.connect.felix.framework.util.StringComparator;
-import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.resource.Capability;
 
-public class CapabilitySet
+import org.apache.felix.connect.felix.framework.util.StringComparator;
+
+public class CapabilitySet<T extends Capability>
 {
-    private final Map<String, Map<Object, Set<BundleCapability>>> m_indices;
-    private final Set<BundleCapability> m_capSet = new HashSet<BundleCapability>();
+    private final Map<String, Map<Object, Set<T>>> m_indices;
+    private final Set<T> m_capSet = new HashSet<T>();
 
     public CapabilitySet(List<String> indexProps, boolean caseSensitive)
     {
         m_indices = (caseSensitive)
-            ? new TreeMap<String, Map<Object, Set<BundleCapability>>>()
-            : new TreeMap<String, Map<Object, Set<BundleCapability>>>(
-                        new StringComparator(false));
+                ? new TreeMap<String, Map<Object, Set<T>>>()
+                : new TreeMap<String, Map<Object, Set<T>>>(
+                new StringComparator(false));
         for (int i = 0; (indexProps != null) && (i < indexProps.size()); i++)
         {
             m_indices.put(
-                indexProps.get(i), new HashMap<Object, Set<BundleCapability>>());
+                    indexProps.get(i), new HashMap<Object, Set<T>>());
         }
     }
 
-    public void addCapability(BundleCapability cap)
+    public void addCapability(T cap)
     {
         m_capSet.add(cap);
 
         // Index capability.
-        for (Entry<String, Map<Object, Set<BundleCapability>>> entry : m_indices.entrySet())
+        for (Entry<String, Map<Object, Set<T>>> entry : m_indices.entrySet())
         {
             Object value = cap.getAttributes().get(entry.getKey());
             if (value != null)
@@ -67,7 +68,7 @@
                     value = convertArrayToList(value);
                 }
 
-                Map<Object, Set<BundleCapability>> index = entry.getValue();
+                Map<Object, Set<T>> index = entry.getValue();
 
                 if (value instanceof Collection)
                 {
@@ -86,22 +87,22 @@
     }
 
     private void indexCapability(
-        Map<Object, Set<BundleCapability>> index, BundleCapability cap, Object capValue)
+            Map<Object, Set<T>> index, T cap, Object capValue)
     {
-        Set<BundleCapability> caps = index.get(capValue);
+        Set<T> caps = index.get(capValue);
         if (caps == null)
         {
-            caps = new HashSet<BundleCapability>();
+            caps = new HashSet<T>();
             index.put(capValue, caps);
         }
         caps.add(cap);
     }
 
-    public void removeCapability(BundleCapability cap)
+    public void removeCapability(T cap)
     {
         if (m_capSet.remove(cap))
         {
-            for (Entry<String, Map<Object, Set<BundleCapability>>> entry : m_indices.entrySet())
+            for (Entry<String, Map<Object, Set<T>>> entry : m_indices.entrySet())
             {
                 Object value = cap.getAttributes().get(entry.getKey());
                 if (value != null)
@@ -111,7 +112,7 @@
                         value = convertArrayToList(value);
                     }
 
-                    Map<Object, Set<BundleCapability>> index = entry.getValue();
+                    Map<Object, Set<T>> index = entry.getValue();
 
                     if (value instanceof Collection)
                     {
@@ -131,9 +132,9 @@
     }
 
     private void deindexCapability(
-        Map<Object, Set<BundleCapability>> index, BundleCapability cap, Object value)
+            Map<Object, Set<T>> index, T cap, Object value)
     {
-        Set<BundleCapability> caps = index.get(value);
+        Set<T> caps = index.get(value);
         if (caps != null)
         {
             caps.remove(cap);
@@ -144,18 +145,18 @@
         }
     }
 
-   public Set<BundleCapability> match(SimpleFilter sf, boolean obeyMandatory)
+    public Set<T> match(SimpleFilter sf, boolean obeyMandatory)
     {
-        Set<BundleCapability> matches = match(m_capSet, sf);
-        return matches;
-       /* return (obeyMandatory)
+        Set<T> matches = match(m_capSet, sf);
+        return /* (obeyMandatory)
             ? matchMandatory(matches, sf)
-            : matches;*/
+            : */ matches;
     }
 
-    private Set<BundleCapability> match(Set<BundleCapability> caps, SimpleFilter sf)
+    @SuppressWarnings("unchecked")
+    private Set<T> match(Set<T> caps, SimpleFilter sf)
     {
-        Set<BundleCapability> matches = new HashSet<BundleCapability>();
+        Set<T> matches = new HashSet<T>();
 
         if (sf.getOperation() == SimpleFilter.MATCH_ALL)
         {
@@ -179,9 +180,9 @@
             // Evaluate each subfilter against the remaining capabilities.
             // For OR we calculate the union of each subfilter.
             List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
-            for (int i = 0; i < sfs.size(); i++)
+            for (SimpleFilter sf1 : sfs)
             {
-                matches.addAll(match(caps, sfs.get(i)));
+                matches.addAll(match(caps, sf1));
             }
         }
         else if (sf.getOperation() == SimpleFilter.NOT)
@@ -190,17 +191,17 @@
             // For OR we calculate the union of each subfilter.
             matches.addAll(caps);
             List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
-            for (int i = 0; i < sfs.size(); i++)
+            for (SimpleFilter sf1 : sfs)
             {
-                matches.removeAll(match(caps, sfs.get(i)));
+                matches.removeAll(match(caps, sf1));
             }
         }
         else
         {
-            Map<Object, Set<BundleCapability>> index = m_indices.get(sf.getName());
+            Map<Object, Set<T>> index = m_indices.get(sf.getName());
             if ((sf.getOperation() == SimpleFilter.EQ) && (index != null))
             {
-                Set<BundleCapability> existingCaps = index.get(sf.getValue());
+                Set<T> existingCaps = index.get(sf.getValue());
                 if (existingCaps != null)
                 {
                     matches.addAll(existingCaps);
@@ -209,9 +210,8 @@
             }
             else
             {
-                for (Iterator<BundleCapability> it = caps.iterator(); it.hasNext(); )
+                for (T cap : caps)
                 {
-                    BundleCapability cap = it.next();
                     Object lhs = cap.getAttributes().get(sf.getName());
                     if (lhs != null)
                     {
@@ -227,12 +227,13 @@
         return matches;
     }
 
-  /*  public static boolean matches(BundleCapability cap, SimpleFilter sf)
-    {
-        return matchesInternal(cap, sf) && matchMandatory(cap, sf);
-    }
-*/
-    private static boolean matchesInternal(BundleCapability cap, SimpleFilter sf)
+    /*  public static boolean matches(BundleCapability cap, SimpleFilter sf)
+      {
+          return matchesInternal(cap, sf) && matchMandatory(cap, sf);
+      }
+  */
+    @SuppressWarnings("unchecked")
+    private boolean matchesInternal(T cap, SimpleFilter sf)
     {
         boolean matched = true;
 
@@ -268,9 +269,9 @@
             // Evaluate each subfilter against the remaining capabilities.
             // For OR we calculate the union of each subfilter.
             List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
-            for (int i = 0; i < sfs.size(); i++)
+            for (SimpleFilter sf1 : sfs)
             {
-                matched = !(matchesInternal(cap, sfs.get(i)));
+                matched = !(matchesInternal(cap, sf1));
             }
         }
         else
@@ -286,12 +287,13 @@
         return matched;
     }
 
-   /* private static Set<BundleCapability> matchMandatory(
-        Set<BundleCapability> caps, SimpleFilter sf)
+    /*
+    private Set<T> matchMandatory(
+        Set<T> caps, SimpleFilter sf)
     {
-        for (Iterator<BundleCapability> it = caps.iterator(); it.hasNext(); )
+        for (Iterator<T> it = caps.iterator(); it.hasNext(); )
         {
-            BundleCapability cap = it.next();
+            T cap = it.next();
             if (!matchMandatory(cap, sf))
             {
                 it.remove();
@@ -300,12 +302,12 @@
         return caps;
     }
 
-    private static boolean matchMandatory(BundleCapability cap, SimpleFilter sf)
+    private boolean matchMandatory(T cap, SimpleFilter sf)
     {
         Map<String, Object> attrs = cap.getAttributes();
         for (Entry<String, Object> entry : attrs.entrySet())
         {
-            if (((BundleCapability) cap).isAttributeMandatory(entry.getKey())
+            if (((T) cap).isAttributeMandatory(entry.getKey())
                 && !matchMandatoryAttrbute(entry.getKey(), sf))
             {
                 return false;
@@ -314,7 +316,7 @@
         return true;
     }
 
-    private static boolean matchMandatoryAttrbute(String attrName, SimpleFilter sf)
+    private boolean matchMandatoryAttrbute(String attrName, SimpleFilter sf)
     {
         if ((sf.getName() != null) && sf.getName().equals(attrName))
         {
@@ -336,8 +338,9 @@
         return false;
     }*/
 
-    private static final Class<?>[] STRING_CLASS = new Class[] { String.class };
+    private static final Class<?>[] STRING_CLASS = new Class[]{String.class};
 
+    @SuppressWarnings("unchecked")
     private static boolean compare(Object lhs, Object rhsUnknown, int op)
     {
         if (lhs == null)
@@ -382,66 +385,42 @@
             switch (op)
             {
             case SimpleFilter.EQ:
-                    try
-                    {
-                return (((Comparable) lhs).compareTo(rhs) == 0);
-                    }
-                    catch (Exception ex)
-                    {
-                        return false;
-                    }
+                try
+                {
+                    return (((Comparable) lhs).compareTo(rhs) == 0);
+                }
+                catch (Exception ex)
+                {
+                    return false;
+                }
             case SimpleFilter.GTE:
-                    try
-                    {
-                return (((Comparable) lhs).compareTo(rhs) >= 0);
-                    }
-                    catch (Exception ex)
-                    {
-                        return false;
-                    }
+                try
+                {
+                    return (((Comparable) lhs).compareTo(rhs) >= 0);
+                }
+                catch (Exception ex)
+                {
+                    return false;
+                }
             case SimpleFilter.LTE:
-                    try
-                    {
-                return (((Comparable) lhs).compareTo(rhs) <= 0);
-                    }
-                    catch (Exception ex)
-                    {
-                        return false;
-                    }
+                try
+                {
+                    return (((Comparable) lhs).compareTo(rhs) <= 0);
+                }
+                catch (Exception ex)
+                {
+                    return false;
+                }
             case SimpleFilter.APPROX:
-                return compareApproximate(((Comparable) lhs), rhs);
+                return compareApproximate(lhs, rhs);
             case SimpleFilter.SUBSTRING:
-                    return SimpleFilter.compareSubstring((List<String>) rhs, (String) lhs);
+                return SimpleFilter.compareSubstring((List<String>) rhs, (String) lhs);
             default:
-                    throw new RuntimeException(
+                throw new RuntimeException(
                         "Unknown comparison operator: " + op);
             }
         }
-        // Booleans do not implement comparable, so special case them.
-        else if (lhs instanceof Boolean)
-        {
-            Object rhs;
-            try
-            {
-                rhs = coerceType(lhs, (String) rhsUnknown);
-            }
-            catch (Exception ex)
-            {
-                return false;
-            }
 
-            switch (op)
-            {
-            case SimpleFilter.EQ:
-            case SimpleFilter.GTE:
-            case SimpleFilter.LTE:
-            case SimpleFilter.APPROX:
-                return (lhs.equals(rhs));
-            default:
-                    throw new RuntimeException(
-                        "Unknown comparison operator: " + op);
-            }
-        }
 
         // If the LHS is not a comparable or boolean, check if it is an
         // array. If so, convert it to a list so we can treat it as a
@@ -455,9 +434,9 @@
         // of the collection until a match is found.
         if (lhs instanceof Collection)
         {
-            for (Iterator iter = ((Collection) lhs).iterator(); iter.hasNext();)
+            for (Object o : ((Collection) lhs))
             {
-                if (compare(iter.next(), rhsUnknown, op))
+                if (compare(o, rhsUnknown, op))
                 {
                     return true;
                 }
@@ -467,7 +446,7 @@
         }
 
         // Spec says SUBSTRING is false for all types other than string.
-        if ((op == SimpleFilter.SUBSTRING) && !(lhs instanceof String))
+        if (op == SimpleFilter.SUBSTRING)
         {
             return false;
         }
@@ -489,19 +468,19 @@
         if (rhs instanceof String)
         {
             return removeWhitespace((String) lhs)
-                .equalsIgnoreCase(removeWhitespace((String) rhs));
+                    .equalsIgnoreCase(removeWhitespace((String) rhs));
         }
         else if (rhs instanceof Character)
         {
             return Character.toLowerCase(((Character) lhs))
-                == Character.toLowerCase(((Character) rhs));
+                    == Character.toLowerCase(((Character) rhs));
         }
         return lhs.equals(rhs);
     }
 
     private static String removeWhitespace(String s)
     {
-        StringBuffer sb = new StringBuffer(s.length());
+        StringBuilder sb = new StringBuilder(s.length());
         for (int i = 0; i < s.length(); i++)
         {
             if (!Character.isWhitespace(s.charAt(i)))
@@ -523,14 +502,14 @@
 
         // Try to convert the RHS type to the LHS type by using
         // the string constructor of the LHS class, if it has one.
-        Object rhs = null;
+        Object rhs;
         try
         {
             // The Character class is a special case, since its constructor
             // does not take a string, so handle it separately.
             if (lhs instanceof Character)
             {
-                rhs = new Character(rhsString.charAt(0));
+                rhs = rhsString.charAt(0);
             }
             else
             {
@@ -541,16 +520,16 @@
                 }
                 Constructor ctor = lhs.getClass().getConstructor(STRING_CLASS);
                 ctor.setAccessible(true);
-                rhs = ctor.newInstance(new Object[] { rhsString });
+                rhs = ctor.newInstance(rhsString);
             }
         }
         catch (Exception ex)
         {
             throw new Exception(
-                "Could not instantiate class "
-                    + lhs.getClass().getName()
-                    + " from string constructor with argument '"
-                    + rhsString + "' because " + ex);
+                    "Could not instantiate class "
+                            + lhs.getClass().getName()
+                            + " from string constructor with argument '"
+                            + rhsString + "' because " + ex);
         }
 
         return rhs;
@@ -561,14 +540,13 @@
      * array of primitive wrapper objects. This method simplifies processing
      * LDAP filters since the special case of primitive arrays can be ignored.
      *
-     * @param array
-     *            An array of primitive types.
+     * @param array An array of primitive types.
      * @return An corresponding array using pritive wrapper objects.
-     **/
-    private static List convertArrayToList(Object array)
+     */
+    private static List<Object> convertArrayToList(Object array)
     {
         int len = Array.getLength(array);
-        List list = new ArrayList(len);
+        List<Object> list = new ArrayList<Object>(len);
         for (int i = 0; i < len; i++)
         {
             list.add(Array.get(array, i));
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/Directive.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/Directive.java
deleted file mode 100644
index 9c6963d..0000000
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/Directive.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.felix.connect.felix.framework.capabilityset;
-
-public class Directive
-{
-    private final String m_name;
-    private final Object m_value;
-
-    public Directive(String name, Object value)
-    {
-        m_name = name;
-        m_value = value;
-    }
-
-    public String getName()
-    {
-        return m_name;
-    }
-
-    public Object getValue()
-    {
-        return m_value;
-    }
-
-    public String toString()
-    {
-        return m_name + "=" + m_value;
-    }
-}
\ No newline at end of file
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/SimpleFilter.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/SimpleFilter.java
index 22f57cf..c8f0310 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/SimpleFilter.java
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/capabilityset/SimpleFilter.java
@@ -60,6 +60,7 @@
         return m_op;
     }
 
+    @SuppressWarnings("unchecked")
     public String toString()
     {
         String s = null;
@@ -84,8 +85,7 @@
             s = "(" + m_name + ">=" + toEncodedString(m_value) + ")";
             break;
         case SUBSTRING:
-            s = "(" + m_name + "=" + unparseSubstring((List<String>) m_value)
-                    + ")";
+            s = "(" + m_name + "=" + unparseSubstring((List<String>) m_value) + ")";
             break;
         case PRESENT:
             s = "(" + m_name + "=*)";
@@ -97,19 +97,19 @@
         return s;
     }
 
-    private static String toString(List list)
+    private static String toString(List<?> list)
     {
-        StringBuffer sb = new StringBuffer();
-        for (int i = 0; i < list.size(); i++)
+        StringBuilder sb = new StringBuilder();
+        for (Object aList : list)
         {
-            sb.append(list.get(i).toString());
+            sb.append(aList.toString());
         }
         return sb.toString();
     }
 
     private static String toDecodedString(String s, int startIdx, int endIdx)
     {
-        StringBuffer sb = new StringBuffer(endIdx - startIdx);
+        StringBuilder sb = new StringBuilder(endIdx - startIdx);
         boolean escaped = false;
         for (int i = 0; i < (endIdx - startIdx); i++)
         {
@@ -133,7 +133,7 @@
         if (o instanceof String)
         {
             String s = (String) o;
-            StringBuffer sb = new StringBuffer();
+            StringBuilder sb = new StringBuilder();
             for (int i = 0; i < s.length(); i++)
             {
                 char c = s.charAt(i);
@@ -150,6 +150,7 @@
         return o.toString();
     }
 
+    @SuppressWarnings("unchecked")
     public static SimpleFilter parse(String filter)
     {
         int idx = skipWhitespace(filter, 0);
@@ -166,7 +167,7 @@
         }
 
         SimpleFilter sf = null;
-        List stack = new ArrayList();
+        List<Object> stack = new ArrayList<Object>();
         boolean isEscaped = false;
         while (idx < filter.length())
         {
@@ -192,7 +193,7 @@
                     }
                     else
                     {
-                        stack.add(0, new Integer(idx));
+                        stack.add(0, idx);
                     }
                 }
                 else if (filter.charAt(idx) == '|')
@@ -206,7 +207,7 @@
                     }
                     else
                     {
-                        stack.add(0, new Integer(idx));
+                        stack.add(0, idx);
                     }
                 }
                 else if (filter.charAt(idx) == '!')
@@ -220,12 +221,12 @@
                     }
                     else
                     {
-                        stack.add(0, new Integer(idx));
+                        stack.add(0, idx);
                     }
                 }
                 else
                 {
-                    stack.add(0, new Integer(idx));
+                    stack.add(0, idx);
                 }
             }
             else if (!isEscaped && (filter.charAt(idx) == ')'))
@@ -233,36 +234,28 @@
                 Object top = stack.remove(0);
                 if (top instanceof SimpleFilter)
                 {
-                    if (!stack.isEmpty()
-                            && (stack.get(0) instanceof SimpleFilter))
+                    if (!stack.isEmpty() && (stack.get(0) instanceof SimpleFilter))
                     {
-                        ((List) ((SimpleFilter) stack.get(0)).m_value).add(top);
+                        ((List<Object>) ((SimpleFilter) stack.get(0)).m_value).add(top);
                     }
                     else
                     {
                         sf = (SimpleFilter) top;
                     }
                 }
-                else if (!stack.isEmpty()
-                        && (stack.get(0) instanceof SimpleFilter))
+                else if (!stack.isEmpty() && (stack.get(0) instanceof SimpleFilter))
                 {
-                    ((List) ((SimpleFilter) stack.get(0)).m_value)
-                            .add(SimpleFilter.subfilter(filter,
-                                    ((Integer) top).intValue(), idx));
+                    ((List<Object>) ((SimpleFilter) stack.get(0)).m_value)
+                            .add(SimpleFilter.subfilter(filter, (Integer) top, idx));
                 }
                 else
                 {
-                    sf = SimpleFilter.subfilter(filter,
-                            ((Integer) top).intValue(), idx);
+                    sf = SimpleFilter.subfilter(filter, (Integer) top, idx);
                 }
             }
-            else if (!isEscaped && (filter.charAt(idx) == '\\'))
-            {
-                isEscaped = true;
-            }
             else
             {
-                isEscaped = false;
+                isEscaped = !isEscaped && (filter.charAt(idx) == '\\');
             }
 
             idx = skipWhitespace(filter, idx + 1);
@@ -270,15 +263,14 @@
 
         if (sf == null)
         {
-            throw new IllegalArgumentException("Missing closing parenthesis: "
-                    + filter);
+            throw new IllegalArgumentException("Missing closing parenthesis: " + filter);
         }
 
         return sf;
     }
 
     private static SimpleFilter subfilter(String filter, int startIdx,
-            int endIdx)
+                                          int endIdx)
     {
         final String opChars = "=<>~";
 
@@ -307,7 +299,7 @@
         startIdx = skipWhitespace(filter, attrEndIdx);
 
         // Determine the operator type.
-        int op = -1;
+        int op;
         switch (filter.charAt(startIdx))
         {
         case '=':
@@ -372,8 +364,8 @@
 
     public static List<String> parseSubstring(String value)
     {
-        List<String> pieces = new ArrayList();
-        StringBuffer ss = new StringBuffer();
+        List<String> pieces = new ArrayList<String>();
+        StringBuilder ss = new StringBuilder();
         // int kind = SIMPLE; // assume until proven otherwise
         boolean wasStar = false; // indicates last piece was a star
         boolean leftstar = false; // track if the initial piece is a star
@@ -383,7 +375,7 @@
 
         // We assume (sub)strings can contain leading and trailing blanks
         boolean escaped = false;
-        loop: for (;;)
+        for (; ; )
         {
             if (idx >= value.length())
             {
@@ -401,7 +393,7 @@
                     // the string "" (!=null)
                 }
                 ss.setLength(0);
-                break loop;
+                break;
             }
 
             // Read the next character and account for escapes.
@@ -460,7 +452,7 @@
 
     public static String unparseSubstring(List<String> pieces)
     {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         for (int i = 0; i < pieces.size(); i++)
         {
             if (i > 0)
@@ -495,7 +487,7 @@
 
         int index = 0;
 
-        loop: for (int i = 0; i < len; i++)
+        for (int i = 0; i < len; i++)
         {
             String piece = pieces.get(i);
 
@@ -506,7 +498,7 @@
                 if (!s.startsWith(piece))
                 {
                     result = false;
-                    break loop;
+                    break;
                 }
             }
 
@@ -514,15 +506,8 @@
             // string ends with it.
             if (i == len - 1)
             {
-                if (s.endsWith(piece))
-                {
-                    result = true;
-                }
-                else
-                {
-                    result = false;
-                }
-                break loop;
+                result = s.endsWith(piece);
+                break;
             }
 
             // If this is neither the first or last piece, then
@@ -533,7 +518,7 @@
                 if (index < 0)
                 {
                     result = false;
-                    break loop;
+                    break;
                 }
             }
 
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/EventDispatcher.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/EventDispatcher.java
index ffd59b5..e2002ac 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/EventDispatcher.java
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/EventDispatcher.java
@@ -20,10 +20,16 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Dictionary;
 import java.util.EventListener;
 import java.util.EventObject;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
 
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -36,27 +42,23 @@
 import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.SynchronousBundleListener;
+import org.osgi.framework.hooks.bundle.EventHook;
+import org.osgi.framework.hooks.service.EventListenerHook;
 import org.osgi.framework.hooks.service.ListenerHook;
 import org.osgi.framework.launch.Framework;
 
 import org.apache.felix.connect.felix.framework.ServiceRegistry;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
 
 public class EventDispatcher
 {
     private final ServiceRegistry m_registry;
-    private Map<BundleContext, List<ListenerInfo>> m_fwkListeners = Collections.EMPTY_MAP;
-    private Map<BundleContext, List<ListenerInfo>> m_bndlListeners = Collections.EMPTY_MAP;
-    private Map<BundleContext, List<ListenerInfo>> m_syncBndlListeners = Collections.EMPTY_MAP;
-    private Map<BundleContext, List<ListenerInfo>> m_svcListeners = Collections.EMPTY_MAP;
+    private Map<BundleContext, List<ListenerInfo>> m_fwkListeners = Collections.emptyMap();
+    private Map<BundleContext, List<ListenerInfo>> m_bndlListeners = Collections.emptyMap();
+    private Map<BundleContext, List<ListenerInfo>> m_syncBndlListeners = Collections.emptyMap();
+    private Map<BundleContext, List<ListenerInfo>> m_svcListeners = Collections.emptyMap();
     // A single thread is used to deliver events for all dispatchers.
     private static Thread m_thread = null;
-    private final static String m_threadLock = new String("thread lock");
+    private final static String m_threadLock = "thread lock";
     private static int m_references = 0;
     private static volatile boolean m_stopping = false;
     // List of requests.
@@ -66,7 +68,7 @@
 
     private static final boolean m_sync = "true".equalsIgnoreCase(System
             .getProperty("org.apache.felix.connect.events.sync"));
-    
+
     public EventDispatcher(ServiceRegistry registry)
     {
         m_registry = registry;
@@ -153,6 +155,7 @@
                 }
                 catch (InterruptedException ex)
                 {
+                    // Ignore
                 }
             }
         }
@@ -167,8 +170,7 @@
         }
         else if (!clazz.isInstance(l))
         {
-            throw new IllegalArgumentException(
-                "Listener not of type " + clazz.getName());
+            throw new IllegalArgumentException("Listener not of type " + clazz.getName());
         }
 
         // See if we can simply update the listener, if so then
@@ -192,7 +194,7 @@
                 // Bundle context is no longer valid, so just return.
             }
 
-            Map<BundleContext, List<ListenerInfo>> listeners = null;
+            Map<BundleContext, List<ListenerInfo>> listeners;
             Object acc = null;
 
             if (clazz == FrameworkListener.class)
@@ -231,7 +233,7 @@
 
             // Add listener.
             ListenerInfo info =
-                new ListenerInfo(bc.getBundle(), bc, clazz, l, filter, acc, false);
+                    new ListenerInfo(bc.getBundle(), bc, clazz, l, filter, acc, false);
             listeners = addListenerInfo(listeners, info);
 
             if (clazz == FrameworkListener.class)
@@ -258,7 +260,7 @@
     }
 
     public ListenerHook.ListenerInfo removeListener(
-        BundleContext bc, Class clazz, EventListener l)
+            BundleContext bc, Class clazz, EventListener l)
     {
         ListenerHook.ListenerInfo returnInfo = null;
 
@@ -270,13 +272,13 @@
         else if (!clazz.isInstance(l))
         {
             throw new IllegalArgumentException(
-                "Listener not of type " + clazz.getName());
+                    "Listener not of type " + clazz.getName());
         }
 
         // Lock the object to remove the listener.
         synchronized (this)
         {
-            Map<BundleContext, List<ListenerInfo>> listeners = null;
+            Map<BundleContext, List<ListenerInfo>> listeners;
 
             if (clazz == FrameworkListener.class)
             {
@@ -311,8 +313,8 @@
                 {
                     ListenerInfo info = infos.get(i);
                     if (info.getBundleContext().equals(bc)
-                        && (info.getListenerClass() == clazz)
-                        && (info.getListener() == l))
+                            && (info.getListenerClass() == clazz)
+                            && (info.getListener() == l))
                     {
                         // For service listeners, we must return some info about
                         // the listener for the ListenerHook callback.
@@ -405,19 +407,19 @@
                 {
                     ListenerInfo info = infos.get(i);
                     if (info.getBundleContext().equals(bc)
-                        && (info.getListenerClass() == clazz)
-                        && (info.getListener() == l))
+                            && (info.getListenerClass() == clazz)
+                            && (info.getListener() == l))
                     {
                         // The spec says to update the filter in this case.
                         Filter oldFilter = info.getParsedFilter();
                         ListenerInfo newInfo = new ListenerInfo(
-                            info.getBundle(),
-                            info.getBundleContext(),
-                            info.getListenerClass(),
-                            info.getListener(),
-                            filter,
-                            info.getSecurityContext(),
-                            info.isRemoved());
+                                info.getBundle(),
+                                info.getBundleContext(),
+                                info.getListenerClass(),
+                                info.getListener(),
+                                filter,
+                                info.getSecurityContext(),
+                                info.isRemoved());
                         m_svcListeners = updateListenerInfo(m_svcListeners, i, newInfo);
                         return oldFilter;
                     }
@@ -429,15 +431,14 @@
     }
 
     /**
-     * Returns all existing service listener information into a collection of
+     * Returns all existing service listener information into a List of
      * ListenerHook.ListenerInfo objects. This is used the first time a listener
      * hook is registered to synchronize it with the existing set of listeners.
      *
      * @return Returns all existing service listener information into a
-     * collection of ListenerHook.ListenerInfo objects
-     *
+     * List of ListenerHook.ListenerInfo objects
      */
-    public Collection<ListenerHook.ListenerInfo> getAllServiceListeners()
+    public List<ListenerHook.ListenerInfo> getAllServiceListeners()
     {
         List<ListenerHook.ListenerInfo> listeners = new ArrayList<ListenerHook.ListenerInfo>();
         synchronized (this)
@@ -453,7 +454,7 @@
     public void fireFrameworkEvent(FrameworkEvent event)
     {
         // Take a snapshot of the listener array.
-        Map<BundleContext, List<ListenerInfo>> listeners = null;
+        Map<BundleContext, List<ListenerInfo>> listeners;
         synchronized (this)
         {
             listeners = m_fwkListeners;
@@ -466,8 +467,8 @@
     public void fireBundleEvent(BundleEvent event)
     {
         // Take a snapshot of the listener array.
-        Map<BundleContext, List<ListenerInfo>> listeners = null;
-        Map<BundleContext, List<ListenerInfo>> syncListeners = null;
+        Map<BundleContext, List<ListenerInfo>> listeners;
+        Map<BundleContext, List<ListenerInfo>> syncListeners;
         synchronized (this)
         {
             listeners = m_bndlListeners;
@@ -477,14 +478,13 @@
         // Create a whitelist of bundle context for bundle listeners,
         // if we have hooks.
         Set<BundleContext> whitelist = createWhitelistFromHooks(event, event.getBundle(),
-            listeners, syncListeners, org.osgi.framework.hooks.bundle.EventHook.class);
+                listeners.keySet(), syncListeners.keySet());
 
         // If we have a whitelist, then create copies of only the whitelisted
         // listeners.
         if (whitelist != null)
         {
-            Map<BundleContext, List<ListenerInfo>> copy =
-                new HashMap<BundleContext, List<ListenerInfo>>();
+            Map<BundleContext, List<ListenerInfo>> copy = new HashMap<BundleContext, List<ListenerInfo>>();
             for (BundleContext bc : whitelist)
             {
                 List<ListenerInfo> infos = listeners.get(bc);
@@ -507,188 +507,54 @@
         }
 
         // Fire synchronous bundle listeners immediately on the calling thread.
-        fireEventImmediately(
-            this, Request.BUNDLE_EVENT, syncListeners, event, null);
+        fireEventImmediately(this, Request.BUNDLE_EVENT, syncListeners, event, null);
 
         // The spec says that asynchronous bundle listeners do not get events
         // of types STARTING, STOPPING, or LAZY_ACTIVATION.
         if ((event.getType() != BundleEvent.STARTING)
-            && (event.getType() != BundleEvent.STOPPING)
-            && (event.getType() != BundleEvent.LAZY_ACTIVATION))
+                && (event.getType() != BundleEvent.STOPPING)
+                && (event.getType() != BundleEvent.LAZY_ACTIVATION))
         {
             // Fire asynchronous bundle listeners on a separate thread.
-            fireEventAsynchronously(
-                this, Request.BUNDLE_EVENT, listeners, event);
+            fireEventAsynchronously(this, Request.BUNDLE_EVENT, listeners, event);
         }
     }
 
-    public void fireServiceEvent(
-        final ServiceEvent event, final Dictionary oldProps, final Framework felix)
-    {
-        // Take a snapshot of the listener array.
-        Map<BundleContext, List<ListenerInfo>> listeners = null;
-        synchronized (this)
-        {
-            listeners = m_svcListeners;
-        }
-
-        // Use service registry hooks to filter target listeners.
-        listeners = filterListenersUsingHooks(event, felix, listeners);
-
-        // Fire all service events immediately on the calling thread.
-        fireEventImmediately(
-            this, Request.SERVICE_EVENT, listeners, event, oldProps);
-    }
-
-// TODO: OSGi R4.3 - This is ugly and inefficient.
-    private Map<BundleContext, List<ListenerInfo>> filterListenersUsingHooks(
-        ServiceEvent event, Framework felix, Map<BundleContext, List<ListenerInfo>> listeners)
-    {
-        Set<ServiceReference<org.osgi.framework.hooks.service.EventHook>> ehs =
-            m_registry.getHooks(org.osgi.framework.hooks.service.EventHook.class);
-        if ((ehs != null) && !ehs.isEmpty())
-        {
-            // Create a whitelist of bundle context for bundle listeners,
-            // if we have hooks.
-            Set<BundleContext> whitelist = createWhitelistFromHooks(event, felix,
-                listeners, null, org.osgi.framework.hooks.service.EventHook.class);
-
-            // If we have a whitelist, then create copies of only the whitelisted
-            // listeners.
-            if (whitelist != null)
-            {
-                Map<BundleContext, List<ListenerInfo>> copy =
-                    new HashMap<BundleContext, List<ListenerInfo>>();
-                for (BundleContext bc : whitelist)
-                {
-                    copy.put(bc, listeners.get(bc));
-                }
-                listeners = copy;
-            }
-        }
-
-        Set<ServiceReference<org.osgi.framework.hooks.service.EventListenerHook>> elhs =
-            m_registry.getHooks(org.osgi.framework.hooks.service.EventListenerHook.class);
-        if ((elhs != null) && !elhs.isEmpty())
-        {
-            // Create shrinkable map with shrinkable collections.
-            Map<BundleContext, Collection<ListenerHook.ListenerInfo>> shrinkableMap =
-                new HashMap<BundleContext, Collection<ListenerHook.ListenerInfo>>();
-            for (Entry<BundleContext, List<ListenerInfo>> entry : listeners.entrySet())
-            {
-                Collection shrinkableCollection =
-                    new ShrinkableCollection(new ArrayList(entry.getValue()));
-                shrinkableMap.put(
-                    entry.getKey(),
-                    (Collection<ListenerHook.ListenerInfo>) shrinkableCollection);
-            }
-            shrinkableMap =
-                new ShrinkableMap<BundleContext, Collection<ListenerHook.ListenerInfo>>(shrinkableMap);
-            for (ServiceReference<org.osgi.framework.hooks.service.EventListenerHook> sr : elhs)
-            {
-                if (felix != null)
-                {
-                    org.osgi.framework.hooks.service.EventListenerHook elh = null;
-                    try
-                    {
-                        elh = m_registry.getService(felix, sr);
-                    }
-                    catch (Exception ex)
-                    {
-                        // If we can't get the hook, then ignore it.
-                    }
-                    if (elh != null)
-                    {
-                        try
-                        {
-                            elh.event(event, shrinkableMap);
-                        }
-                        catch (Throwable th)
-                        {
-                            System.out.println("Problem invoking event hook");
-                            th.printStackTrace();
-                        }
-                        finally
-                        {
-                            m_registry.ungetService(felix, sr);
-                        }
-                    }
-                }
-            }
-// TODO: OSGi R4.3 - Should check and only do this if there was a change.
-//       Also, it is inefficient to have to create new lists for the values.
-            Map<BundleContext, List<ListenerInfo>> newMap =
-                new HashMap<BundleContext, List<ListenerInfo>>();
-            for (Entry entry : shrinkableMap.entrySet())
-            {
-                if (!((Collection) entry.getValue()).isEmpty())
-                {
-                    newMap.put((BundleContext) entry.getKey(),
-                        new ArrayList<ListenerInfo>((Collection) entry.getValue()));
-                }
-            }
-            listeners = newMap;
-        }
-
-        return listeners;
-    }
-
     private <T> Set<BundleContext> createWhitelistFromHooks(
-        EventObject event, Bundle bundle,
-        Map<BundleContext, List<ListenerInfo>> listeners1,
-        Map<BundleContext, List<ListenerInfo>> listeners2,
-        Class<T> hookClass)
+            BundleEvent event,
+            Bundle bundle,
+            Set<BundleContext> listeners1,
+            Set<BundleContext> listeners2)
     {
+        if (bundle == null)
+        {
+            return null;
+        }
         // Create a whitelist of bundle context, if we have hooks.
         Set<BundleContext> whitelist = null;
-        Set<ServiceReference<T>> hooks = m_registry.getHooks(hookClass);
+        Set<ServiceReference<EventHook>> hooks = m_registry.getHooks(EventHook.class);
         if ((hooks != null) && !hooks.isEmpty())
         {
             whitelist = new HashSet<BundleContext>();
-            for (Entry<BundleContext, List<ListenerInfo>> entry : listeners1.entrySet())
-            {
-                whitelist.add(entry.getKey());
-            }
-            if (listeners2 != null)
-            {
-                for (Entry<BundleContext, List<ListenerInfo>> entry : listeners2.entrySet())
-                {
-                    whitelist.add(entry.getKey());
-                }
-            }
+            whitelist.addAll(listeners1);
+            whitelist.addAll(listeners2);
 
             int originalSize = whitelist.size();
-            ShrinkableCollection<BundleContext> shrinkable =
-                new ShrinkableCollection<BundleContext>(whitelist);
-            for (ServiceReference<T> sr : hooks)
+            ShrinkableCollection<BundleContext> shrinkable = new ShrinkableCollection<BundleContext>(whitelist);
+            for (ServiceReference<EventHook> sr : hooks)
             {
-                if (bundle != null)
+                try
                 {
-                    T eh = null;
-                    try
-                    {
-                        eh = m_registry.getService(bundle, sr);
-                    }
-                    catch (Exception ex)
-                    {
-                        // If we can't get the hook, then ignore it.
-                    }
+                    EventHook eh = m_registry.getService(bundle, sr);
                     if (eh != null)
                     {
                         try
                         {
-                            if (eh instanceof org.osgi.framework.hooks.service.EventHook)
-                            {
-                                ((org.osgi.framework.hooks.service.EventHook) eh).event((ServiceEvent) event, shrinkable);
-                            }
-                            else if (eh instanceof org.osgi.framework.hooks.bundle.EventHook)
-                            {
-                                ((org.osgi.framework.hooks.bundle.EventHook) eh).event((BundleEvent) event, shrinkable);
-                            }
+                            eh.event(event, shrinkable);
                         }
                         catch (Throwable th)
                         {
-                            System.out.println("Problem invoking event hook");
+                            System.out.println("Problem invoking bundle hook");
                             th.printStackTrace();
                         }
                         finally
@@ -697,6 +563,10 @@
                         }
                     }
                 }
+                catch (Throwable th)
+                {
+                    // If we can't get the hook, then ignore it.
+                }
             }
             // If the whitelist hasn't changed, then null it to avoid having
             // to do whitelist lookups during event delivery.
@@ -708,16 +578,130 @@
         return whitelist;
     }
 
+    public void fireServiceEvent(final ServiceEvent event, final Dictionary<String, ?> oldProps, final Framework felix)
+    {
+        // Take a snapshot of the listener array.
+        Map<BundleContext, List<ListenerInfo>> listeners;
+        synchronized (this)
+        {
+            listeners = m_svcListeners;
+        }
+
+        // Use service registry hooks to filter target listeners.
+        listeners = filterListenersUsingHooks(event, felix, listeners);
+
+        // Fire all service events immediately on the calling thread.
+        fireEventImmediately(this, Request.SERVICE_EVENT, listeners, event, oldProps);
+    }
+
+    private Map<BundleContext, List<ListenerInfo>> filterListenersUsingHooks(
+            ServiceEvent event, Framework felix, Map<BundleContext, List<ListenerInfo>> listeners)
+    {
+        if (felix == null)
+        {
+            return listeners;
+        }
+
+        Set<ServiceReference<org.osgi.framework.hooks.service.EventHook>> ehs =
+                m_registry.getHooks(org.osgi.framework.hooks.service.EventHook.class);
+        Set<ServiceReference<EventListenerHook>> elhs =
+                m_registry.getHooks(EventListenerHook.class);
+
+        if ((ehs == null || ehs.isEmpty()) && (elhs == null || elhs.isEmpty()))
+        {
+            return listeners;
+        }
+
+        // Create a shrinkable copy of the map
+        Map<BundleContext, List<ListenerInfo>> shrinkableMap = new HashMap<BundleContext, List<ListenerInfo>>();
+        for (Entry<BundleContext, List<ListenerInfo>> entry : listeners.entrySet())
+        {
+            List<ListenerInfo> shrinkableList =
+                    new ShrinkableList<ListenerInfo>(
+                            new ArrayList<ListenerInfo>(entry.getValue()));
+            shrinkableMap.put(entry.getKey(), shrinkableList);
+        }
+        shrinkableMap = new ShrinkableMap<BundleContext, List<ListenerInfo>>(shrinkableMap);
+
+        // Go through service EventHook
+        if (ehs != null && !ehs.isEmpty())
+        {
+            Set<BundleContext> shrink = shrinkableMap.keySet();
+            for (ServiceReference<org.osgi.framework.hooks.service.EventHook> sr : ehs)
+            {
+                try
+                {
+                    org.osgi.framework.hooks.service.EventHook eh = m_registry.getService(felix, sr);
+                    if (eh != null)
+                    {
+                        try
+                        {
+                            eh.event(event, shrink);
+                        }
+                        catch (Throwable th)
+                        {
+                            System.out.println("Problem invoking event hook");
+                            th.printStackTrace();
+                        }
+                        finally
+                        {
+                            m_registry.ungetService(felix, sr);
+                        }
+                    }
+                }
+                catch (Throwable th)
+                {
+                    // Ignore
+                }
+            }
+        }
+
+        // Go through EventListenerHook
+        if (elhs != null && !elhs.isEmpty())
+        {
+            @SuppressWarnings("unchecked")
+            Map<BundleContext, Collection<ListenerHook.ListenerInfo>> shrink =
+                    (Map<BundleContext, Collection<ListenerHook.ListenerInfo>>) (Map) shrinkableMap;
+            for (ServiceReference<EventListenerHook> sr : elhs)
+            {
+                try
+                {
+                    EventListenerHook elh = m_registry.getService(felix, sr);
+                    if (elh != null)
+                    {
+                        try
+                        {
+                            elh.event(event, shrink);
+                        }
+                        catch (Throwable th)
+                        {
+                            System.out.println("Problem invoking event hook");
+                            th.printStackTrace();
+                        }
+                        finally
+                        {
+                            m_registry.ungetService(felix, sr);
+                        }
+                    }
+                }
+                catch (Throwable th)
+                {
+                    // Ignore
+                }
+            }
+        }
+
+        return shrinkableMap;
+    }
+
     private static void fireEventAsynchronously(
-        EventDispatcher dispatcher, int type,
-        Map<BundleContext, List<ListenerInfo>> listeners,
-        EventObject event)
+            EventDispatcher dispatcher, int type,
+            Map<BundleContext, List<ListenerInfo>> listeners,
+            EventObject event)
     {
         if (!m_sync)
         {
-            // TODO: should possibly check this within thread lock, seems to be
-            // ok
-            // though without
+            // TODO: should possibly check this within thread lock, seems to be ok though without
             // If dispatch thread is stopped, then ignore dispatch request.
             if (m_stopping || m_thread == null)
             {
@@ -725,7 +709,7 @@
             }
 
             // First get a request from the pool or create one if necessary.
-            Request req = null;
+            Request req;
             synchronized (m_requestPool)
             {
                 if (m_requestPool.size() > 0)
@@ -760,9 +744,9 @@
     }
 
     private static void fireEventImmediately(
-        EventDispatcher dispatcher, int type,
-        Map<BundleContext, List<ListenerInfo>> listeners,
-        EventObject event, Dictionary oldProps)
+            EventDispatcher dispatcher, int type,
+            Map<BundleContext, List<ListenerInfo>> listeners,
+            EventObject event, Dictionary<String, ?> oldProps)
     {
         if (!listeners.isEmpty())
         {
@@ -788,19 +772,17 @@
                         }
                         else if (type == Request.SERVICE_EVENT)
                         {
-                            invokeServiceListenerCallback(
-                                bundle, l, filter, acc, event, oldProps);
+                            invokeServiceListenerCallback(bundle, l, filter, acc, event, oldProps);
                         }
                     }
                     catch (Throwable th)
                     {
                         if ((type != Request.FRAMEWORK_EVENT)
-                            || (((FrameworkEvent) event).getType() != FrameworkEvent.ERROR))
+                                || (((FrameworkEvent) event).getType() != FrameworkEvent.ERROR))
                         {
                             System.out.println("EventDispatcher: Error during dispatch.");
                             th.printStackTrace();
-                            dispatcher.fireFrameworkEvent(
-                                new FrameworkEvent(FrameworkEvent.ERROR, bundle, th));
+                            dispatcher.fireFrameworkEvent(new FrameworkEvent(FrameworkEvent.ERROR, bundle, th));
                         }
                     }
                 }
@@ -809,13 +791,12 @@
     }
 
     private static void invokeFrameworkListenerCallback(
-        Bundle bundle, final EventListener l, final EventObject event)
+            Bundle bundle, final EventListener l, final EventObject event)
     {
         // The spec says only active bundles receive asynchronous events,
         // but we will include starting bundles too otherwise
         // it is impossible to see everything.
-        if ((bundle.getState() == Bundle.STARTING)
-            || (bundle.getState() == Bundle.ACTIVE))
+        if ((bundle.getState() == Bundle.STARTING) || (bundle.getState() == Bundle.ACTIVE))
         {
             ((FrameworkListener) l).frameworkEvent((FrameworkEvent) event);
 
@@ -823,7 +804,7 @@
     }
 
     private static void invokeBundleListenerCallback(
-        Bundle bundle, final EventListener l, final EventObject event)
+            Bundle bundle, final EventListener l, final EventObject event)
     {
         // A bundle listener is either synchronous or asynchronous.
         // If the bundle listener is synchronous, then deliver the
@@ -831,25 +812,25 @@
         // ACTIVE. If the listener is asynchronous, then deliver the
         // event only to bundles that are STARTING or ACTIVE.
         if (((SynchronousBundleListener.class.isAssignableFrom(l.getClass()))
-            && ((bundle.getState() == Bundle.STARTING)
-            || (bundle.getState() == Bundle.STOPPING)
-            || (bundle.getState() == Bundle.ACTIVE)))
-            || ((bundle.getState() == Bundle.STARTING)
-            || (bundle.getState() == Bundle.ACTIVE)))
+                && ((bundle.getState() == Bundle.STARTING)
+                || (bundle.getState() == Bundle.STOPPING)
+                || (bundle.getState() == Bundle.ACTIVE)))
+                || ((bundle.getState() == Bundle.STARTING)
+                || (bundle.getState() == Bundle.ACTIVE)))
         {
             ((BundleListener) l).bundleChanged((BundleEvent) event);
         }
     }
 
     private static void invokeServiceListenerCallback(Bundle bundle,
-        final EventListener l, Filter filter, Object acc,
-        final EventObject event, final Dictionary oldProps)
+                                                      final EventListener l, Filter filter, Object acc,
+                                                      final EventObject event, final Dictionary<String, ?> oldProps)
     {
         // Service events should be delivered to STARTING,
         // STOPPING, and ACTIVE bundles.
         if ((bundle.getState() != Bundle.STARTING)
-            && (bundle.getState() != Bundle.STOPPING)
-            && (bundle.getState() != Bundle.ACTIVE))
+                && (bundle.getState() != Bundle.STOPPING)
+                && (bundle.getState() != Bundle.ACTIVE))
         {
             return;
         }
@@ -864,12 +845,11 @@
         {
             // Dispatch according to the filter.
             boolean matched = (filter == null)
-                || filter.match(((ServiceEvent) event).getServiceReference());
+                    || filter.match(((ServiceEvent) event).getServiceReference());
 
             if (matched)
             {
-                ((ServiceListener) l)
-                    .serviceChanged((ServiceEvent) event);
+                ((ServiceListener) l).serviceChanged((ServiceEvent) event);
             }
             // We need to send an MODIFIED_ENDMATCH event if the listener
             // matched previously.
@@ -878,8 +858,8 @@
                 if (filter.match(oldProps))
                 {
                     final ServiceEvent se = new ServiceEvent(
-                        ServiceEvent.MODIFIED_ENDMATCH,
-                        ((ServiceEvent) event).getServiceReference());
+                            ServiceEvent.MODIFIED_ENDMATCH,
+                            ((ServiceEvent) event).getServiceReference());
                     ((ServiceListener) l).serviceChanged(se);
 
                 }
@@ -888,11 +868,11 @@
     }
 
     private static Map<BundleContext, List<ListenerInfo>> addListenerInfo(
-        Map<BundleContext, List<ListenerInfo>> listeners, ListenerInfo info)
+            Map<BundleContext, List<ListenerInfo>> listeners, ListenerInfo info)
     {
         // Make a copy of the map, since we will be mutating it.
         Map<BundleContext, List<ListenerInfo>> copy =
-            new HashMap<BundleContext, List<ListenerInfo>>(listeners);
+                new HashMap<BundleContext, List<ListenerInfo>>(listeners);
         // Remove the affected entry and make a copy so we can modify it.
         List<ListenerInfo> infos = copy.remove(info.getBundleContext());
         if (infos == null)
@@ -911,32 +891,32 @@
     }
 
     private static Map<BundleContext, List<ListenerInfo>> updateListenerInfo(
-        Map<BundleContext, List<ListenerInfo>> listeners, int idx,
-        ListenerInfo info)
+            Map<BundleContext, List<ListenerInfo>> listeners, int idx,
+            ListenerInfo info)
     {
         // Make a copy of the map, since we will be mutating it.
         Map<BundleContext, List<ListenerInfo>> copy =
-            new HashMap<BundleContext, List<ListenerInfo>>(listeners);
+                new HashMap<BundleContext, List<ListenerInfo>>(listeners);
         // Remove the affected entry and make a copy so we can modify it.
         List<ListenerInfo> infos = copy.remove(info.getBundleContext());
         if (infos != null)
         {
-            infos = new ArrayList<ListenerInfo>(infos);
+            List<ListenerInfo> copylist = new ArrayList<ListenerInfo>(infos);
             // Update the new listener info.
-            infos.set(idx, info);
+            copylist.set(idx, info);
             // Put the listeners back into the copy of the map and return it.
-            copy.put(info.getBundleContext(), infos);
+            copy.put(info.getBundleContext(), copylist);
             return copy;
         }
         return listeners;
     }
 
     private static Map<BundleContext, List<ListenerInfo>> removeListenerInfo(
-        Map<BundleContext, List<ListenerInfo>> listeners, BundleContext bc, int idx)
+            Map<BundleContext, List<ListenerInfo>> listeners, BundleContext bc, int idx)
     {
         // Make a copy of the map, since we will be mutating it.
         Map<BundleContext, List<ListenerInfo>> copy =
-            new HashMap<BundleContext, List<ListenerInfo>>(listeners);
+                new HashMap<BundleContext, List<ListenerInfo>>(listeners);
         // Remove the affected entry and make a copy so we can modify it.
         List<ListenerInfo> infos = copy.remove(bc);
         if (infos != null)
@@ -955,11 +935,11 @@
     }
 
     private static Map<BundleContext, List<ListenerInfo>> removeListenerInfos(
-        Map<BundleContext, List<ListenerInfo>> listeners, BundleContext bc)
+            Map<BundleContext, List<ListenerInfo>> listeners, BundleContext bc)
     {
         // Make a copy of the map, since we will be mutating it.
         Map<BundleContext, List<ListenerInfo>> copy =
-            new HashMap<BundleContext, List<ListenerInfo>>(listeners);
+                new HashMap<BundleContext, List<ListenerInfo>>(listeners);
         // Remove the affected entry and return the copy.
         copy.remove(bc);
         return copy;
@@ -967,11 +947,10 @@
 
     /**
      * This is the dispatching thread's main loop.
-     *
      */
     private static void run()
     {
-        Request req = null;
+        Request req;
         while (true)
         {
             // Lock the request list so we can try to get a
@@ -1012,8 +991,8 @@
             // the invoked method shields us from exceptions by
             // catching Throwables when it invokes callbacks.
             fireEventImmediately(
-                req.m_dispatcher, req.m_type, req.m_listeners,
-                req.m_event, null);
+                    req.m_dispatcher, req.m_type, req.m_listeners,
+                    req.m_event, null);
 
             // Put dispatch request in cache.
             synchronized (m_requestPool)
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ListenerHookInfoImpl.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ListenerHookInfoImpl.java
deleted file mode 100644
index 86dbffd..0000000
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ListenerHookInfoImpl.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.felix.connect.felix.framework.util;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.hooks.service.ListenerHook;
-
-public class ListenerHookInfoImpl implements ListenerHook.ListenerInfo
-{
-    private final BundleContext m_context;
-    private final ServiceListener m_listener;
-    private final String m_filter;
-    private boolean m_removed;
-
-    public ListenerHookInfoImpl(BundleContext context,
-            ServiceListener listener, String filter, boolean removed)
-    {
-        m_context = context;
-        m_listener = listener;
-        m_filter = filter;
-        m_removed = removed;
-    }
-
-    public BundleContext getBundleContext()
-    {
-        return m_context;
-    }
-
-    public String getFilter()
-    {
-        return m_filter;
-    }
-
-    public boolean isRemoved()
-    {
-        return m_removed;
-    }
-
-    public boolean equals(Object obj)
-    {
-        if (obj == this)
-        {
-            return true;
-        }
-
-        if (!(obj instanceof ListenerHookInfoImpl))
-        {
-            return false;
-        }
-
-        ListenerHookInfoImpl other = (ListenerHookInfoImpl) obj;
-        return other.m_listener == m_listener
-                && (m_filter == null ? other.m_filter == null : m_filter
-                        .equals(other.m_filter));
-    }
-
-    public int hashCode()
-    {
-        int rc = 17;
-
-        rc = 37 * rc + m_listener.hashCode();
-        if (m_filter != null)
-        {
-            rc = 37 * rc + m_filter.hashCode();
-        }
-        return rc;
-    }
-}
\ No newline at end of file
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ListenerInfo.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ListenerInfo.java
index 3e5bb59..e0aa933 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ListenerInfo.java
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ListenerInfo.java
@@ -19,6 +19,7 @@
 package org.apache.felix.connect.felix.framework.util;
 
 import java.util.EventListener;
+
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Filter;
@@ -36,8 +37,8 @@
     private final boolean m_removed;
 
     public ListenerInfo(
-        Bundle bundle, BundleContext context, Class listenerClass, EventListener listener,
-        Filter filter, Object acc, boolean removed)
+            Bundle bundle, BundleContext context, Class listenerClass, EventListener listener,
+            Filter filter, Object acc, boolean removed)
     {
         // Technically, we could get the bundle from the bundle context, but
         // there are some corner cases where the bundle context might become
@@ -121,10 +122,10 @@
 
         ListenerInfo other = (ListenerInfo) obj;
         return (other.m_bundle == m_bundle)
-            && (other.m_context == m_context)
-            && (other.m_listenerClass == m_listenerClass)
-            && (other.m_listener == m_listener)
-            && (m_filter == null ? other.m_filter == null : m_filter.equals(other.m_filter));
+                && (other.m_context == m_context)
+                && (other.m_listenerClass == m_listenerClass)
+                && (other.m_listener == m_listener)
+                && (m_filter == null ? other.m_filter == null : m_filter.equals(other.m_filter));
     }
 
     @Override
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/MapToDictionary.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/MapToDictionary.java
index a882def..bd33969 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/MapToDictionary.java
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/MapToDictionary.java
@@ -18,20 +18,23 @@
  */
 package org.apache.felix.connect.felix.framework.util;
 
-import java.util.*;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Map;
 
 /**
  * This is a simple class that implements a <tt>Dictionary</tt> from a
  * <tt>Map</tt>. The resulting dictionary is immutable.
- **/
-public class MapToDictionary extends Dictionary
+ */
+public class MapToDictionary<K, V> extends Dictionary<K, V>
 {
     /**
      * Map source.
-     **/
-    private Map m_map = null;
+     */
+    private Map<K, V> m_map = null;
 
-    public MapToDictionary(Map map)
+    public MapToDictionary(Map<K, V> map)
     {
         if (map == null)
         {
@@ -40,12 +43,12 @@
         m_map = map;
     }
 
-    public Enumeration elements()
+    public Enumeration<V> elements()
     {
         return Collections.enumeration(m_map.values());
     }
 
-    public Object get(Object key)
+    public V get(Object key)
     {
         return m_map.get(key);
     }
@@ -55,17 +58,17 @@
         return m_map.isEmpty();
     }
 
-    public Enumeration keys()
+    public Enumeration<K> keys()
     {
         return Collections.enumeration(m_map.keySet());
     }
 
-    public Object put(Object key, Object value)
+    public V put(K key, V value)
     {
         throw new UnsupportedOperationException();
     }
 
-    public Object remove(Object key)
+    public V remove(Object key)
     {
         throw new UnsupportedOperationException();
     }
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ShrinkableCollection.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ShrinkableCollection.java
index cc62168..04ae94c 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ShrinkableCollection.java
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ShrinkableCollection.java
@@ -18,13 +18,14 @@
  */
 package org.apache.felix.connect.felix.framework.util;
 
+import java.util.AbstractCollection;
 import java.util.Collection;
 import java.util.Iterator;
 
 /**
  * A collection wrapper that only permits clients to shrink the collection.
-**/
-public class ShrinkableCollection<T> implements Collection<T>
+ */
+public class ShrinkableCollection<T> extends AbstractCollection<T>
 {
     private final Collection<T> m_delegate;
 
@@ -33,80 +34,16 @@
         m_delegate = delegate;
     }
 
-    public boolean add(T o)
-    {
-        throw new UnsupportedOperationException();
-    }
-
-    public boolean addAll(Collection<? extends T> c)
-    {
-        throw new UnsupportedOperationException();
-    }
-
-    public void clear()
-    {
-        m_delegate.clear();
-    }
-
-    public boolean contains(Object o)
-    {
-        return m_delegate.contains(o);
-    }
-
-    public boolean containsAll(Collection<?> c)
-    {
-        return m_delegate.containsAll(c);
-    }
-
     @Override
-    public boolean equals(Object o)
-    {
-        return m_delegate.equals(o);
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return m_delegate.hashCode();
-    }
-
-    public boolean isEmpty()
-    {
-        return m_delegate.isEmpty();
-    }
-
-    public Iterator iterator()
+    public Iterator<T> iterator()
     {
         return m_delegate.iterator();
     }
 
-    public boolean remove(Object o)
-    {
-        return m_delegate.remove(o);
-    }
-
-    public boolean removeAll(Collection<?> c)
-    {
-        return m_delegate.removeAll(c);
-    }
-
-    public boolean retainAll(Collection<?> c)
-    {
-        return m_delegate.retainAll(c);
-    }
-
+    @Override
     public int size()
     {
         return m_delegate.size();
     }
 
-    public Object[] toArray()
-    {
-        return m_delegate.toArray();
-    }
-
-    public <A> A[] toArray(A[] a)
-    {
-        return m_delegate.toArray(a);
-    }
 }
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ShrinkableList.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ShrinkableList.java
new file mode 100644
index 0000000..6f4aed7
--- /dev/null
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ShrinkableList.java
@@ -0,0 +1,54 @@
+/*
+ * 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.felix.connect.felix.framework.util;
+
+import java.util.AbstractList;
+import java.util.List;
+
+/**
+ * A collection wrapper that only permits clients to shrink the collection.
+ */
+public class ShrinkableList<T> extends AbstractList<T>
+{
+    private final List<T> m_delegate;
+
+    public ShrinkableList(List<T> delegate)
+    {
+        m_delegate = delegate;
+    }
+
+    @Override
+    public T get(int index)
+    {
+        return m_delegate.get(index);
+    }
+
+    @Override
+    public int size()
+    {
+        return m_delegate.size();
+    }
+
+    @Override
+    public T remove(int index)
+    {
+        return m_delegate.remove(index);
+    }
+
+}
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ShrinkableMap.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ShrinkableMap.java
index 7235bde..dbaac0b 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ShrinkableMap.java
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/ShrinkableMap.java
@@ -18,11 +18,11 @@
  */
 package org.apache.felix.connect.felix.framework.util;
 
-import java.util.Collection;
+import java.util.AbstractMap;
 import java.util.Map;
 import java.util.Set;
 
-public class ShrinkableMap<K, V> implements Map<K, V>
+public class ShrinkableMap<K, V> extends AbstractMap<K, V>
 {
     private final Map<K, V> m_delegate;
 
@@ -31,63 +31,10 @@
         m_delegate = delegate;
     }
 
-    public int size()
-    {
-        return m_delegate.size();
-    }
-
-    public boolean isEmpty()
-    {
-        return m_delegate.isEmpty();
-    }
-
-    public boolean containsKey(Object o)
-    {
-        return m_delegate.containsKey(o);
-    }
-
-    public boolean containsValue(Object o)
-    {
-        return m_delegate.containsValue(o);
-    }
-
-    public V get(Object o)
-    {
-        return m_delegate.get(o);
-    }
-
-    public V put(K k, V v)
-    {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    public V remove(Object o)
-    {
-        return m_delegate.remove(o);
-    }
-
-    public void putAll(Map<? extends K, ? extends V> map)
-    {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    public void clear()
-    {
-        m_delegate.clear();
-    }
-
-    public Set<K> keySet()
-    {
-        return m_delegate.keySet();
-    }
-
-    public Collection<V> values()
-    {
-        return m_delegate.values();
-    }
-
+    @Override
     public Set<Entry<K, V>> entrySet()
     {
         return m_delegate.entrySet();
     }
+
 }
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/StringComparator.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/StringComparator.java
index 25030b7..2a34eda 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/StringComparator.java
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/StringComparator.java
@@ -20,7 +20,7 @@
 
 import java.util.Comparator;
 
-public class StringComparator implements Comparator
+public class StringComparator implements Comparator<String>
 {
     private final boolean m_isCaseSensitive;
 
@@ -29,15 +29,16 @@
         m_isCaseSensitive = b;
     }
 
-    public int compare(Object o1, Object o2)
+    @Override
+    public int compare(String o1, String o2)
     {
         if (m_isCaseSensitive)
         {
-            return o1.toString().compareTo(o2.toString());
+            return o1.compareTo(o2);
         }
         else
         {
-            return o1.toString().compareToIgnoreCase(o2.toString());
+            return o1.compareToIgnoreCase(o2);
         }
     }
 
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/StringMap.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/StringMap.java
index 09709ea..f472782 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/StringMap.java
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/StringMap.java
@@ -18,7 +18,10 @@
  */
 package org.apache.felix.connect.felix.framework.util;
 
-import java.util.*;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
 
 /**
  * Simple utility class that creates a map for string-based keys. This map can
@@ -26,10 +29,10 @@
  * for the key. Any keys put into this map will be converted to a
  * <tt>String</tt> using the <tt>toString()</tt> method, since it is only
  * intended to compare strings.
- **/
-public class StringMap implements Map
+ */
+public class StringMap<T> implements Map<String, T>
 {
-    private TreeMap m_map;
+    private TreeMap<String, T> m_map;
 
     public StringMap()
     {
@@ -38,10 +41,10 @@
 
     public StringMap(boolean caseSensitive)
     {
-        m_map = new TreeMap(new StringComparator(caseSensitive));
+        m_map = new TreeMap<String, T>(new StringComparator(caseSensitive));
     }
 
-    public StringMap(Map map, boolean caseSensitive)
+    public StringMap(Map<? extends String, ? extends T> map, boolean caseSensitive)
     {
         this(caseSensitive);
         putAll(map);
@@ -56,72 +59,83 @@
     {
         if (isCaseSensitive() != b)
         {
-            TreeMap map = new TreeMap(new StringComparator(b));
+            TreeMap<String, T> map = new TreeMap<String, T>(new StringComparator(b));
             map.putAll(m_map);
             m_map = map;
         }
     }
 
+    @Override
     public int size()
     {
         return m_map.size();
     }
 
+    @Override
     public boolean isEmpty()
     {
         return m_map.isEmpty();
     }
 
+    @Override
     public boolean containsKey(Object arg0)
     {
         return m_map.containsKey(arg0);
     }
 
+    @Override
     public boolean containsValue(Object arg0)
     {
         return m_map.containsValue(arg0);
     }
 
-    public Object get(Object arg0)
+    @Override
+    public T get(Object arg0)
     {
         return m_map.get(arg0);
     }
 
-    public Object put(Object key, Object value)
+    @Override
+    public T put(String key, T value)
     {
-        return m_map.put(key.toString(), value);
+        return m_map.put(key, value);
     }
 
-    public void putAll(Map map)
+    @Override
+    public void putAll(Map<? extends String, ? extends T> map)
     {
-        for (Iterator it = map.entrySet().iterator(); it.hasNext();)
+        for (Entry<? extends String, ? extends T> entry : map.entrySet())
         {
-            Map.Entry entry = (Map.Entry) it.next();
             put(entry.getKey(), entry.getValue());
         }
     }
 
-    public Object remove(Object arg0)
+    @Override
+    public T remove(Object arg0)
     {
         return m_map.remove(arg0);
     }
 
+    @Override
     public void clear()
     {
         m_map.clear();
     }
 
-    public Set keySet()
+    @Override
+    public Set<String> keySet()
     {
         return m_map.keySet();
     }
 
-    public Collection values()
+    @Override
+    public Collection<T> values()
     {
         return m_map.values();
     }
 
-    public Set entrySet()
+    @Override
+    public Set<Entry<String, T>> entrySet()
     {
         return m_map.entrySet();
     }
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/Util.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/Util.java
index 1bebffa..565287e 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/Util.java
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/Util.java
@@ -36,7 +36,7 @@
 {
     /**
      * The default name used for the default configuration properties file.
-     **/
+     */
     private static final String DEFAULT_PROPERTIES_FILE = "default.properties";
 
     public static String getDefaultProperty(String name)
@@ -66,7 +66,9 @@
                 try
                 {
                     if (is != null)
+                    {
                         is.close();
+                    }
                 }
                 catch (IOException ex2)
                 {
@@ -83,7 +85,7 @@
      * Converts a module identifier to a bundle identifier. Module IDs are
      * typically <tt>&lt;bundle-id&gt;.&lt;revision&gt;</tt>; this method
      * returns only the portion corresponding to the bundle ID.
-     **/
+     */
     public static long getBundleIdFromModuleId(String id)
     {
         try
@@ -102,7 +104,7 @@
      * Converts a module identifier to a bundle identifier. Module IDs are
      * typically <tt>&lt;bundle-id&gt;.&lt;revision&gt;</tt>; this method
      * returns only the portion corresponding to the revision.
-     **/
+     */
     public static int getModuleRevisionFromModuleId(String id)
     {
         try
@@ -196,13 +198,11 @@
      * from the service object's class loader, but from the class loaders of any
      * interfaces it implements and the class loaders of all super classes.
      * </p>
-     * 
-     * @param svcObj
-     *            the class that is the root of the search.
-     * @param name
-     *            the name of the class to load.
+     *
+     * @param svcObj the class that is the root of the search.
+     * @param name   the name of the class to load.
      * @return the loaded class or <tt>null</tt> if it could not be loaded.
-     **/
+     */
     public static Class loadClassUsingClass(Class clazz, String name)
     {
         Class loadedClass = null;
@@ -248,16 +248,14 @@
      * This method determines if the requesting bundle is able to cast the
      * specified service reference based on class visibility rules of the
      * underlying modules.
-     * 
-     * @param requester
-     *            The bundle requesting the service.
-     * @param ref
-     *            The service in question.
+     *
+     * @param requester The bundle requesting the service.
+     * @param ref       The service in question.
      * @return <tt>true</tt> if the requesting bundle is able to case the
-     *         service object to a known type.
-     **/
+     * service object to a known type.
+     */
     public static boolean isServiceAssignable(Bundle requester,
-            ServiceReference ref)
+                                              ServiceReference ref)
     {
         // Boolean flag.
         boolean allow = true;
@@ -280,22 +278,22 @@
         return allow;
     }
 
-    private static final byte encTab[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
+    private static final byte encTab[] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
             0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
             0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62,
             0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d,
             0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
             0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
-            0x39, 0x2b, 0x2f };
+            0x39, 0x2b, 0x2f};
 
-    private static final byte decTab[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    private static final byte decTab[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1,
             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
             62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
             -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
             14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
             -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
-            42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 };
+            42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1};
 
     public static String base64Encode(String s) throws IOException
     {
@@ -304,12 +302,10 @@
 
     /**
      * Encode a raw byte array to a Base64 String.
-     * 
-     * @param in
-     *            Byte array to encode.
-     * @param len
-     *            Length of Base64 lines. 0 means no line breaks.
-     **/
+     *
+     * @param in  Byte array to encode.
+     * @param len Length of Base64 lines. 0 means no line breaks.
+     */
     public static String encode(byte[] in, int len) throws IOException
     {
         ByteArrayOutputStream baos = null;
@@ -409,23 +405,18 @@
      * as nested variable placeholders, which are substituted from inner most to
      * outer most. Configuration properties override system properties.
      * </p>
-     * 
-     * @param val
-     *            The string on which to perform property substitution.
-     * @param currentKey
-     *            The key of the property being evaluated used to detect cycles.
-     * @param cycleMap
-     *            Map of variable references used to detect nested cycles.
-     * @param configProps
-     *            Set of configuration properties.
+     *
+     * @param val         The string on which to perform property substitution.
+     * @param currentKey  The key of the property being evaluated used to detect cycles.
+     * @param cycleMap    Map of variable references used to detect nested cycles.
+     * @param configProps Set of configuration properties.
      * @return The value of the specified string after system property
-     *         substitution.
-     * @throws IllegalArgumentException
-     *             If there was a syntax error in the property placeholder
-     *             syntax or a recursive variable reference.
-     **/
+     * substitution.
+     * @throws IllegalArgumentException If there was a syntax error in the property placeholder
+     *                                  syntax or a recursive variable reference.
+     */
     public static String substVars(String val, String currentKey, Map cycleMap,
-            Properties configProps) throws IllegalArgumentException
+                                   Properties configProps) throws IllegalArgumentException
     {
         // If there is currently no cycle map, then create
         // one for detecting cycles for this invocation.
diff --git a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/VersionRange.java b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/VersionRange.java
index a13b0a7..7971840 100644
--- a/connect/src/main/java/org/apache/felix/connect/felix/framework/util/VersionRange.java
+++ b/connect/src/main/java/org/apache/felix/connect/felix/framework/util/VersionRange.java
@@ -30,7 +30,7 @@
             Version.emptyVersion, true, null, true);
 
     public VersionRange(Version low, boolean isLowInclusive, Version high,
-            boolean isHighInclusive)
+                        boolean isHighInclusive)
     {
         m_floor = low;
         m_isFloorInclusive = isLowInclusive;
diff --git a/connect/src/main/java/org/apache/felix/connect/launch/BundleDescriptor.java b/connect/src/main/java/org/apache/felix/connect/launch/BundleDescriptor.java
index 68b849e..0a2b1cc 100644
--- a/connect/src/main/java/org/apache/felix/connect/launch/BundleDescriptor.java
+++ b/connect/src/main/java/org/apache/felix/connect/launch/BundleDescriptor.java
@@ -18,21 +18,34 @@
  */
 package org.apache.felix.connect.launch;
 
-import java.net.URL;
 import java.util.Map;
 
+import org.apache.felix.connect.Revision;
+
 public class BundleDescriptor
 {
     private final ClassLoader m_loader;
-    private final URL m_url;
+    private final String m_url;
     private final Map<String, String> m_headers;
+    private final Revision m_revision;
+    private final Map<Class, Object> m_services;
 
-    public BundleDescriptor(ClassLoader loader, URL url,
-            Map<String, String> headers)
+    public BundleDescriptor(ClassLoader loader, String url,
+                            Map<String, String> headers)
+    {
+        this(loader, url, headers, null, null);
+    }
+
+    public BundleDescriptor(ClassLoader loader, String url,
+                            Map<String, String> headers,
+                            Revision revision,
+                            Map<Class, Object> services)
     {
         m_loader = loader;
         m_url = url;
         m_headers = headers;
+        m_revision = revision;
+        m_services = services;
     }
 
     public ClassLoader getClassLoader()
@@ -40,18 +53,28 @@
         return m_loader;
     }
 
-    public URL getUrl()
+    public String getUrl()
     {
         return m_url;
     }
 
     public String toString()
     {
-        return m_url.toExternalForm();
+        return m_url;
     }
 
     public Map<String, String> getHeaders()
     {
         return m_headers;
     }
+
+    public Revision getRevision()
+    {
+        return m_revision;
+    }
+
+    public Map<Class, Object> getServices()
+    {
+        return m_services;
+    }
 }
diff --git a/connect/src/main/java/org/apache/felix/connect/launch/ClasspathScanner.java b/connect/src/main/java/org/apache/felix/connect/launch/ClasspathScanner.java
index e1f794e..da19f9f 100644
--- a/connect/src/main/java/org/apache/felix/connect/launch/ClasspathScanner.java
+++ b/connect/src/main/java/org/apache/felix/connect/launch/ClasspathScanner.java
@@ -50,7 +50,7 @@
     }
 
     public List<BundleDescriptor> scanForBundles(String filterString, ClassLoader loader)
-        throws Exception
+            throws Exception
     {
         Filter filter = (filterString != null) ? FrameworkUtil
                 .createFilter(filterString) : null;
@@ -58,105 +58,106 @@
         loader = (loader != null) ? loader : getClass().getClassLoader();
 
         List<BundleDescriptor> bundles = new ArrayList<BundleDescriptor>();
-		byte[] bytes = new byte[1024 * 1024 * 2];
+        byte[] bytes = new byte[1024 * 1024 * 2];
         for (Enumeration<URL> e = loader.getResources(
-                "META-INF/MANIFEST.MF"); e.hasMoreElements();)
+                "META-INF/MANIFEST.MF"); e.hasMoreElements(); )
         {
             URL manifestURL = e.nextElement();
             InputStream input = null;
             try
             {
                 input = manifestURL.openStream();
-				int size = 0;
-				for (int i = input.read(bytes); i != -1; i = input.read(bytes, size, bytes.length - size)) {
-					size += i;
-					if (size == bytes.length) {
-					     byte[] tmp = new byte[size * 2];
-						 System.arraycopy(bytes, 0, tmp, 0, bytes.length);
-						 bytes = tmp;
-					}
-				}
+                int size = 0;
+                for (int i = input.read(bytes); i != -1; i = input.read(bytes, size, bytes.length - size))
+                {
+                    size += i;
+                    if (size == bytes.length)
+                    {
+                        byte[] tmp = new byte[size * 2];
+                        System.arraycopy(bytes, 0, tmp, 0, bytes.length);
+                        bytes = tmp;
+                    }
+                }
 
-				// Now parse the main attributes. The idea is to do that
-				// without creating new byte arrays. Therefore, we read through
-				// the manifest bytes inside the bytes array and write them back into
-				// the same array unless we don't need them (e.g., \r\n and \n are skipped).
-				// That allows us to create the strings from the bytes array without the skipped
-				// chars. We stopp as soon as we see a blankline as that denotes that the main
-				//attributes part is finished.
-				String key = null;
-				int last = 0;
-				int current = 0;
+                // Now parse the main attributes. The idea is to do that
+                // without creating new byte arrays. Therefore, we read through
+                // the manifest bytes inside the bytes array and write them back into
+                // the same array unless we don't need them (e.g., \r\n and \n are skipped).
+                // That allows us to create the strings from the bytes array without the skipped
+                // chars. We stopp as soon as we see a blankline as that denotes that the main
+                //attributes part is finished.
+                String key = null;
+                int last = 0;
+                int current = 0;
 
                 Map<String, String> headers = new HashMap<String, String>();
-				for (int i = 0; i < size; i++)
-				{
-					// skip \r and \n if it is follows by another \n
-					// (we catch the blank line case in the next iteration)
-					if (bytes[i] == '\r')
-					{
-						if ((i + 1 < size) && (bytes[i + 1] == '\n'))
-						{
-							continue;
-						}
-					}
-					if (bytes[i] == '\n')
-					{
-						if ((i + 1 < size) && (bytes[i + 1] == ' '))
-						{
-							i++;
-							continue;
-						}
-					}
-					// If we don't have a key yet and see the first : we parse it as the key
-					// and skip the :<blank> that follows it.
-					if ((key == null) && (bytes[i] == ':'))
-					{
-						key = new String(bytes, last, (current - last), "UTF-8");
-						if ((i + 1 < size) && (bytes[i + 1] == ' '))
-						{
-							last = current + 1;
-							continue;
-						}
-						else
-						{
-							throw new Exception(
-								"Manifest error: Missing space separator - " + key);
-						}
-					}
-					// if we are at the end of a line
-					if (bytes[i] == '\n')
-					{
-						// and it is a blank line stop parsing (main attributes are done)
-						if ((last == current) && (key == null))
-						{
-							break;
-						}
-						// Otherwise, parse the value and add it to the map (we throw an
-						// exception if we don't have a key or the key already exist.
-						String value = new String(bytes, last, (current - last), "UTF-8");
-						if (key == null)
-						{
-							throw new Exception("Manifst error: Missing attribute name - " + value);
-						}
-						else if (headers.put(key, value) != null)
-						{
-							throw new Exception("Manifst error: Duplicate attribute name - " + key);
-						}
-						last = current;
-						key = null;
-					}
-					else
-					{
-						// write back the byte if it needs to be included in the key or the value.
-						bytes[current++] = bytes[i];
-					}
-				}
-                if ((filter == null)
-                        || filter.match(new MapToDictionary(headers)))
+                for (int i = 0; i < size; i++)
                 {
-                    bundles.add(new BundleDescriptor(loader, getParentURL(manifestURL),
-                            headers));
+                    // skip \r and \n if it is follows by another \n
+                    // (we catch the blank line case in the next iteration)
+                    if (bytes[i] == '\r')
+                    {
+                        if ((i + 1 < size) && (bytes[i + 1] == '\n'))
+                        {
+                            continue;
+                        }
+                    }
+                    if (bytes[i] == '\n')
+                    {
+                        if ((i + 1 < size) && (bytes[i + 1] == ' '))
+                        {
+                            i++;
+                            continue;
+                        }
+                    }
+                    // If we don't have a key yet and see the first : we parse it as the key
+                    // and skip the :<blank> that follows it.
+                    if ((key == null) && (bytes[i] == ':'))
+                    {
+                        key = new String(bytes, last, (current - last), "UTF-8");
+                        if ((i + 1 < size) && (bytes[i + 1] == ' '))
+                        {
+                            last = current + 1;
+                            continue;
+                        }
+                        else
+                        {
+                            throw new Exception(
+                                    "Manifest error: Missing space separator - " + key);
+                        }
+                    }
+                    // if we are at the end of a line
+                    if (bytes[i] == '\n')
+                    {
+                        // and it is a blank line stop parsing (main attributes are done)
+                        if ((last == current) && (key == null))
+                        {
+                            break;
+                        }
+                        // Otherwise, parse the value and add it to the map (we throw an
+                        // exception if we don't have a key or the key already exist.
+                        String value = new String(bytes, last, (current - last), "UTF-8");
+                        if (key == null)
+                        {
+                            throw new Exception("Manifst error: Missing attribute name - " + value);
+                        }
+                        else if (headers.put(key, value) != null)
+                        {
+                            throw new Exception("Manifst error: Duplicate attribute name - " + key);
+                        }
+                        last = current;
+                        key = null;
+                    }
+                    else
+                    {
+                        // write back the byte if it needs to be included in the key or the value.
+                        bytes[current++] = bytes[i];
+                    }
+                }
+                if ((filter == null)
+                        || filter.match(new MapToDictionary<String, String>(headers)))
+                {
+                    bundles.add(new BundleDescriptor(loader, getParentURL(manifestURL).toExternalForm(), headers));
                 }
             }
             finally
diff --git a/connect/src/main/java/org/apache/felix/connect/launch/PojoServiceRegistry.java b/connect/src/main/java/org/apache/felix/connect/launch/PojoServiceRegistry.java
index 2da7807..a63421b 100644
--- a/connect/src/main/java/org/apache/felix/connect/launch/PojoServiceRegistry.java
+++ b/connect/src/main/java/org/apache/felix/connect/launch/PojoServiceRegistry.java
@@ -18,8 +18,9 @@
  */
 package org.apache.felix.connect.launch;
 
+import java.util.Collection;
 import java.util.Dictionary;
-import java.util.List;
+
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceListener;
@@ -29,28 +30,24 @@
 public interface PojoServiceRegistry
 {
     public BundleContext getBundleContext();
-	
-	public void startBundles(List<BundleDescriptor> bundles) throws Exception;
 
-    public void addServiceListener(ServiceListener listener, String filter)
-            throws InvalidSyntaxException;
+    public void startBundles(Collection<BundleDescriptor> bundles) throws Exception;
+
+    public void addServiceListener(ServiceListener listener, String filter) throws InvalidSyntaxException;
 
     public void addServiceListener(ServiceListener listener);
 
     public void removeServiceListener(ServiceListener listener);
 
-    public ServiceRegistration registerService(String[] clazzes,
-            Object service, @SuppressWarnings("rawtypes") Dictionary properties);
+    public ServiceRegistration<?> registerService(String[] clazzes, Object service, Dictionary<String, ?> properties);
 
-    public ServiceRegistration registerService(String clazz, Object service,
-            @SuppressWarnings("rawtypes") Dictionary properties);
+    public ServiceRegistration<?> registerService(String clazz, Object service, Dictionary<String, ?> properties);
 
-    public ServiceReference[] getServiceReferences(String clazz, String filter)
-            throws InvalidSyntaxException;
+    public ServiceReference<?>[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException;
 
-    public ServiceReference getServiceReference(String clazz);
+    public ServiceReference<?> getServiceReference(String clazz);
 
-    public Object getService(ServiceReference reference);
+    public <S> S getService(ServiceReference<S> reference);
 
-    public boolean ungetService(ServiceReference reference);
+    public boolean ungetService(ServiceReference<?> reference);
 }
diff --git a/connect/src/main/java/org/apache/felix/connect/launch/PojoServiceRegistryFactory.java b/connect/src/main/java/org/apache/felix/connect/launch/PojoServiceRegistryFactory.java
index 1084486..2ce9523 100644
--- a/connect/src/main/java/org/apache/felix/connect/launch/PojoServiceRegistryFactory.java
+++ b/connect/src/main/java/org/apache/felix/connect/launch/PojoServiceRegistryFactory.java
@@ -20,11 +20,10 @@
 
 import java.util.Map;
 
-public interface PojoServiceRegistryFactory 
+public interface PojoServiceRegistryFactory
 {
-    public static final String BUNDLE_DESCRIPTORS = PojoServiceRegistry.class
-            .getName().toLowerCase() + ".bundles";
+    public static final String BUNDLE_DESCRIPTORS =
+            PojoServiceRegistry.class.getName().toLowerCase() + ".bundles";
 
-    public PojoServiceRegistry newPojoServiceRegistry(Map configuration)
-            throws Exception;
+    public PojoServiceRegistry newPojoServiceRegistry(Map<String, Object> configuration) throws Exception;
 }