[ARIES-1405] Only use blueprint service proxies

git-svn-id: https://svn.apache.org/repos/asf/aries/trunk/jpa@1703414 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/jpa-blueprint/pom.xml b/jpa-blueprint/pom.xml
index d55a0a8..7ba9dbb 100644
--- a/jpa-blueprint/pom.xml
+++ b/jpa-blueprint/pom.xml
@@ -31,11 +31,7 @@
     <packaging>bundle</packaging>
 
     <dependencies>
-        <dependency>
-            <groupId>org.apache.aries.jpa</groupId>
-            <artifactId>org.apache.aries.jpa.api</artifactId>
-            <version>${project.version}</version>
-        </dependency>
+
         <dependency>
             <groupId>org.apache.geronimo.specs</groupId>
             <artifactId>geronimo-jpa_2.0_spec</artifactId>
diff --git a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/AnnotationScanner.java b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/AnnotationScanner.java
index a874097..18d4a9c 100644
--- a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/AnnotationScanner.java
+++ b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/AnnotationScanner.java
@@ -1,48 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.aries.jpa.blueprint.impl;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.PersistenceContext;
-import javax.persistence.PersistenceUnit;
-
-import org.apache.aries.jpa.supplier.EmSupplier;
-
 public class AnnotationScanner {
-    private final List<Class<?>> managedJpaClasses;
-    
-    public AnnotationScanner() {
-        managedJpaClasses = Arrays.asList(EntityManagerFactory.class, EntityManager.class, EmSupplier.class);
-    }
-    
-    public List<AccessibleObject> getJpaAnnotatedMembers(Class<?> c) {
+
+    public List<AccessibleObject> getJpaAnnotatedMembers(Class<?> c, Class<? extends Annotation> annotation) {
         final List<AccessibleObject> jpaAnnotated = new ArrayList<AccessibleObject>();
 
         Class<?> cl = c;
         if (c != Object.class) {
             while (cl != Object.class) {
                 for (Field field : cl.getDeclaredFields()) {
-                    if (field.getAnnotation(PersistenceContext.class) != null
-                        || field.getAnnotation(PersistenceUnit.class) != null) {
+                    if (field.isAnnotationPresent(annotation)) {
+                        field.setAccessible(true);
                         jpaAnnotated.add(field);
                     }
                 }
 
                 for (Method method : cl.getDeclaredMethods()) {
-                    if (method.getAnnotation(PersistenceContext.class) != null
-                        || method.getAnnotation(PersistenceUnit.class) != null) {
-
-                        Class<?>[] pType = method.getParameterTypes();
-                        if (method.getName().startsWith("set") && pType.length == 1
-                            && managedJpaClasses.contains(pType[0])) {
-                            jpaAnnotated.add(method);
-                        }
+                    if ((method.isAnnotationPresent(annotation)) && method.getName().startsWith("set") && method.getParameterTypes().length == 1) {
+                        jpaAnnotated.add(method);
                     }
                 }
 
@@ -52,4 +52,27 @@
 
         return jpaAnnotated;
     }
+
+    public String getName(AccessibleObject member) {
+        if (member instanceof Field) {
+            return ((Field)member).getName();
+        } else if (member instanceof Method) {
+            Method method = (Method)member;
+            String name = method.getName();
+            if (!name.startsWith("set")) {
+                return null;
+            }
+            return name. substring(3, 4).toLowerCase() + name.substring(4);
+        }
+        throw new IllegalArgumentException();
+    }
+    
+    public Class<?> getType(AccessibleObject member) {
+        if (member instanceof Field) {
+            return ((Field)member).getType();
+        } else if (member instanceof Method) {
+            return ((Method)member).getParameterTypes()[0];
+        }
+        throw new IllegalArgumentException();
+    }
 }
diff --git a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaComponentProcessor.java b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaComponentProcessor.java
index 30e091a..b8fbb4b 100644
--- a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaComponentProcessor.java
+++ b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaComponentProcessor.java
@@ -1,16 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.aries.jpa.blueprint.impl;
 
 import static org.osgi.service.jpa.EntityManagerFactoryBuilder.JPA_UNIT_NAME;
 
 import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.persistence.PersistenceUnit;
 
@@ -22,10 +38,8 @@
 import org.apache.aries.blueprint.mutable.MutableBeanMetadata;
 import org.apache.aries.blueprint.mutable.MutableRefMetadata;
 import org.apache.aries.blueprint.mutable.MutableReferenceMetadata;
-import org.apache.aries.jpa.blueprint.supplier.impl.ServiceProxy;
-import org.apache.aries.jpa.supplier.EmSupplier;
 import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
+import org.osgi.service.blueprint.container.BlueprintContainer;
 import org.osgi.service.blueprint.reflect.ComponentMetadata;
 import org.osgi.service.blueprint.reflect.ReferenceMetadata;
 import org.osgi.service.coordinator.Coordinator;
@@ -33,6 +47,7 @@
 import org.slf4j.LoggerFactory;
 
 public class JpaComponentProcessor implements ComponentDefinitionRegistryProcessor {
+    private static final String JPA_COORDINATOR = "jpa_Coordinator";
     private static final Logger LOGGER = LoggerFactory.getLogger(JpaComponentProcessor.class);
     private AnnotationScanner annotationScanner;
     private ParserContext pc;
@@ -47,111 +62,83 @@
 
     @Override
     public void process(ComponentDefinitionRegistry cdr) {
-        PassThroughMetadata bundleMeta = (PassThroughMetadata)cdr.getComponentDefinition("blueprintBundle");
-        Bundle bundle = (Bundle)bundleMeta.getObject();
-        
+        BlueprintContainer container = getComponent(cdr, "blueprintContainer");
+        Bundle bundle = getComponent(cdr, "blueprintBundle");
+        cdr.registerComponentDefinition(createServiceRef(JPA_COORDINATOR, Coordinator.class));
+
         Set<String> components = new HashSet<>(cdr.getComponentDefinitionNames());
         for (String component : components) {
             ComponentMetadata compDef = cdr.getComponentDefinition(component);
             if (compDef instanceof MutableBeanMetadata && !((MutableBeanMetadata)compDef).isProcessor()) {
-                handleComponent((MutableBeanMetadata)compDef, bundle, cdr);
+                handleComponent((MutableBeanMetadata)compDef, bundle, cdr, container);
             }
         }
-        System.out.println(cdr.getComponentDefinitionNames());
     }
 
-    private void handleComponent(MutableBeanMetadata compDef, Bundle bundle, ComponentDefinitionRegistry cdr) {
+    private void handleComponent(MutableBeanMetadata compDef, Bundle bundle, ComponentDefinitionRegistry cdr, BlueprintContainer container) {
+        final String compName = compDef.getId();
         if (compDef.getClassName() == null) {
             LOGGER.warn("No classname for " + compDef.getId());
             return;
         }
-        String compName = compDef.getId();
         Class<?> compClass;
         try {
             compClass = bundle.loadClass(compDef.getClassName());
-        } catch (ClassNotFoundException e) {
+        } catch (final ClassNotFoundException e) {
             throw new IllegalArgumentException("Bean class not found " + compDef.getClassName());
         }
-        BundleContext context = bundle.getBundleContext();
         compDef.setFieldInjection(true);
-        List<AccessibleObject> jpaAnnotatedMembers = annotationScanner.getJpaAnnotatedMembers(compClass);
-        for (AccessibleObject member : jpaAnnotatedMembers) {
-            member.setAccessible(true);
-            String propName = getName(member);
-
+        List<AccessibleObject> pcMembers = annotationScanner.getJpaAnnotatedMembers(compClass, PersistenceContext.class);
+        for (AccessibleObject member : pcMembers) {
             PersistenceContext pcAnn = member.getAnnotation(PersistenceContext.class);
-            if (pcAnn != null) {
-                LOGGER.info("Adding jpa interceptor for bean {}, prop {} with class {}", compName, propName, compClass);
-                Class<?> iface = getType(member);
-                if (iface != null) {
-                    MutableRefMetadata emRef = getServiceRef(cdr, pcAnn.unitName(), iface);
-                    compDef.addProperty(propName, emRef);
-
-                    Interceptor interceptor = createInterceptor(context, pcAnn);
-                    cdr.registerInterceptorWithComponent(compDef, interceptor);
-
-                }
-            }
-
-            PersistenceUnit puAnn = member.getAnnotation(PersistenceUnit.class);
-            if (puAnn != null) {
-                LOGGER.info("Adding emf proxy for bean {}, prop {} with class {}", compName, propName, compClass);
-                MutableRefMetadata emfRef = getServiceRef(cdr, puAnn.unitName(), EntityManagerFactory.class);
-                compDef.addProperty(propName, emfRef);
-            }
             
+            String propName = annotationScanner.getName(member);
+            Class<?> iface = annotationScanner.getType(member);
+            LOGGER.debug("Injecting {} into prop {} of bean {} with class {}", iface.getSimpleName(), propName, compName, compClass);
+            MutableRefMetadata ref = getServiceRef(cdr, pcAnn.unitName(), iface);
+            compDef.addProperty(propName, ref);
+            
+            MutableRefMetadata emRef = getServiceRef(cdr, pcAnn.unitName(), EntityManager.class);
+            Interceptor interceptor = new JpaInterceptor(container, JPA_COORDINATOR, emRef.getComponentId());
+            cdr.registerInterceptorWithComponent(compDef, interceptor);
+        }
+        
+        List<AccessibleObject> puMembers = annotationScanner.getJpaAnnotatedMembers(compClass, PersistenceUnit.class);
+        for (AccessibleObject member : puMembers) {
+            PersistenceUnit puAnn = member.getAnnotation(PersistenceUnit.class);
+            String propName = annotationScanner.getName(member);
+            Class<?> iface = annotationScanner.getType(member);
+            LOGGER.debug("Injecting {} into prop {} of bean {} with class {}", iface.getSimpleName(), propName, compName, compClass);
+            MutableRefMetadata ref = getServiceRef(cdr, puAnn.unitName(), iface);
+            compDef.addProperty(propName, ref);
         }
     }
 
     private MutableRefMetadata getServiceRef(ComponentDefinitionRegistry cdr, String unitName, Class<?> iface) {
         ComponentMetadata serviceRef = cdr.getComponentDefinition(getId(unitName, iface));
         if (serviceRef == null)  {
-            serviceRef = createServiceRef(unitName, iface);
+            serviceRef = createJPAServiceRef(unitName, iface);
             cdr.registerComponentDefinition(serviceRef);
-        } else {
-            LOGGER.info("Using already registered ref " + serviceRef.getId());
         }
         MutableRefMetadata ref = pc.createMetadata(MutableRefMetadata.class);
         ref.setComponentId(serviceRef.getId());
         return ref;
     }
-
-
-
-    private Interceptor createInterceptor(BundleContext context, PersistenceContext pcAnn) {
-        String filter = getFilter(EmSupplier.class, pcAnn.unitName());
-        EmSupplier supplierProxy = ServiceProxy.create(context, EmSupplier.class, filter);
-        Coordinator coordinator = ServiceProxy.create(context, Coordinator.class);
-        Interceptor interceptor = new JpaInterceptor(supplierProxy, coordinator);
-        return interceptor;
-    }
-
-    private String getName(AccessibleObject member) {
-        if (member instanceof Field) {
-            return ((Field)member).getName();
-        } else if (member instanceof Method) {
-            Method method = (Method)member;
-            String name = method.getName();
-            if (!name.startsWith("set")) {
-                return null;
-            }
-            return name. substring(3, 4).toLowerCase() + name.substring(4);
-        }
-        return null;
-    }
     
-    private Class<?> getType(AccessibleObject member) {
-        if (member instanceof Field) {
-            return ((Field)member).getType();
-        } else if (member instanceof Method) {
-            Method method = (Method)member;
-            return method.getParameterTypes()[0];
-        }
-        return null;
+    @SuppressWarnings("unchecked")
+    ComponentMetadata createServiceRef(String id, Class<?> iface) {
+        final MutableReferenceMetadata refMeta = pc.createMetadata(MutableReferenceMetadata.class);
+        refMeta.setActivation(getDefaultActivation(pc));
+        refMeta.setAvailability(ReferenceMetadata.AVAILABILITY_MANDATORY);
+        refMeta.setRuntimeInterface(iface);
+        refMeta.setTimeout(Integer.parseInt(pc.getDefaultTimeout()));
+        refMeta.setDependsOn((List<String>)Collections.EMPTY_LIST);
+        refMeta.setId(id);
+        return refMeta;
     }
 
     @SuppressWarnings("unchecked")
-    ComponentMetadata createServiceRef(String unitName, Class<?> iface) {
+    ComponentMetadata createJPAServiceRef(String unitName, Class<?> iface) {
         final MutableReferenceMetadata refMeta = pc.createMetadata(MutableReferenceMetadata.class);
         refMeta.setActivation(getDefaultActivation(pc));
         refMeta.setAvailability(ReferenceMetadata.AVAILABILITY_MANDATORY);
@@ -164,7 +151,7 @@
     }
     
     public String getId(String unitName, Class<?> iface) {
-        return unitName + "_" + iface.getSimpleName();
+        return unitName + "-" + iface.getSimpleName();
     }
     
     private int getDefaultActivation(ParserContext ctx) {
@@ -172,7 +159,9 @@
             ? ReferenceMetadata.ACTIVATION_EAGER : ReferenceMetadata.ACTIVATION_LAZY;
     }
     
-    private String getFilter(Class<?> clazz, String unitName) {
-        return String.format("(&(objectClass=%s)(%s=%s))", clazz.getName(), JPA_UNIT_NAME, unitName);
+    @SuppressWarnings("unchecked")
+    private <T>T getComponent(ComponentDefinitionRegistry cdr, String id) {
+        return (T)((PassThroughMetadata) cdr.getComponentDefinition(id)).getObject();
     }
+
 }
diff --git a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaInterceptor.java b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaInterceptor.java
index 36b94f2..c5c0f62 100644
--- a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaInterceptor.java
+++ b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaInterceptor.java
@@ -24,7 +24,7 @@
 import javax.persistence.spi.PersistenceUnitTransactionType;
 
 import org.apache.aries.blueprint.Interceptor;
-import org.apache.aries.jpa.supplier.EmSupplier;
+import org.osgi.service.blueprint.container.BlueprintContainer;
 import org.osgi.service.blueprint.reflect.ComponentMetadata;
 import org.osgi.service.coordinator.Coordination;
 import org.osgi.service.coordinator.Coordinator;
@@ -33,13 +33,17 @@
 
 public class JpaInterceptor implements Interceptor {
     private static Logger LOG = LoggerFactory.getLogger(JpaInterceptor.class);
-    EmSupplier emSupplier;
+    EntityManager em;
     private Boolean cachedIsResourceLocal;
     private Coordinator coordinator;
+    private BlueprintContainer container;
+    private String coordinatorId;
+    private String emId;
 
-    public JpaInterceptor(EmSupplier emSupplier, Coordinator coordinator) {
-        this.emSupplier = emSupplier;
-        this.coordinator = coordinator;
+    public JpaInterceptor(BlueprintContainer container, String coordinatorId, String emId) {
+        this.container = container;
+        this.coordinatorId = coordinatorId;
+        this.emId = emId;
     }
 
     public int getRank() {
@@ -47,10 +51,12 @@
     }
 
     public Object preCall(ComponentMetadata cm, Method m, Object... parameters) throws Throwable {
+        if (coordinator == null) {
+            initServices();
+        }
         try {
             LOG.debug("PreCall for bean {}, method {}", cm.getId(), m.getName());
             Coordination coordination = coordinator.begin("jpa", 0);
-            final EntityManager em = emSupplier.get();
             boolean weControlTx = isResourceLocal(em) && !em.getTransaction().isActive();
             if (weControlTx) {
                 coordination.addParticipant(new ResourceLocalTransactionParticipant(em));
@@ -62,6 +68,11 @@
         }
     }
 
+    private void initServices() {
+        coordinator = (Coordinator)container.getComponentInstance(coordinatorId);
+        em = (EntityManager)container.getComponentInstance(emId);
+    }
+
     public void postCallWithException(ComponentMetadata cm, Method m, Throwable ex, Object preCallToken) {
         LOG.debug("PostCallWithException for bean {}, method {}", cm.getId(), m.getName(), ex);
         if (preCallToken != null) {
diff --git a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/supplier/impl/EmProxy.java b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/supplier/impl/EmProxy.java
deleted file mode 100644
index 87d5207..0000000
--- a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/supplier/impl/EmProxy.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 WARRANTIESOR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.aries.jpa.blueprint.supplier.impl;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-
-import javax.persistence.EntityManager;
-
-import org.apache.aries.jpa.supplier.EmSupplier;
-
-public class EmProxy implements InvocationHandler {
-    EmSupplier emSupplier;
-
-    public EmProxy(EmSupplier emSupplier) {
-        this.emSupplier = emSupplier;
-    }
-
-    @Override
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-        EntityManager em = emSupplier.get();
-        if (em == null) {
-            throw new IllegalStateException("EntityManager not available. Make sure you run in an @Transactional method");
-        }
-        return method.invoke(em, args);
-    }
-
-    public static EntityManager create(final EmSupplier emSupplier) {
-        ClassLoader loader = EntityManager.class.getClassLoader();
-        Class<?>[] ifAr = {
-            EntityManager.class
-        };
-        return (EntityManager)Proxy.newProxyInstance(loader, ifAr, new EmProxy(emSupplier));
-    }
-
-}
diff --git a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/supplier/impl/ServiceProxy.java b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/supplier/impl/ServiceProxy.java
deleted file mode 100644
index d49e427..0000000
--- a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/supplier/impl/ServiceProxy.java
+++ /dev/null
@@ -1,97 +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 WARRANTIESOR CONDITIONS OF ANY

- * KIND, either express or implied.  See the License for the

- * specific language governing permissions and limitations

- * under the License.

- */

-package org.apache.aries.jpa.blueprint.supplier.impl;

-

-import java.io.Closeable;

-import java.lang.reflect.InvocationHandler;

-import java.lang.reflect.InvocationTargetException;

-import java.lang.reflect.Method;

-import java.lang.reflect.Proxy;

-

-import org.osgi.framework.BundleContext;

-import org.osgi.framework.Filter;

-import org.osgi.framework.FrameworkUtil;

-import org.osgi.framework.InvalidSyntaxException;

-import org.osgi.service.blueprint.container.ServiceUnavailableException;

-import org.osgi.util.tracker.ServiceTracker;

-

-public class ServiceProxy implements InvocationHandler {

-    private static final int SERVICE_TIMEOUT = 120000;

-

-    @SuppressWarnings("rawtypes")

-    private ServiceTracker tracker;

-

-    private String filterS;

-

-    public ServiceProxy(BundleContext context, String filterS) {

-        this.filterS = filterS;

-        tracker = new ServiceTracker<>(context, createFilter(filterS), null);

-        tracker.open();

-    }

-

-    private Filter createFilter(String filterS) {

-        try {

-            return filterS == null ? null : FrameworkUtil.createFilter(filterS);

-        } catch (InvalidSyntaxException e) {

-            throw new IllegalStateException(e);

-        }

-    }

-

-    private Object getService() {

-        try {

-            Object serviceO = tracker.waitForService(SERVICE_TIMEOUT);

-            if (serviceO == null) {

-                throw new ServiceUnavailableException("No matching service found after timeout of " + SERVICE_TIMEOUT + " ms", filterS);

-            }

-            return serviceO;

-        } catch (InterruptedException e) {

-            throw new IllegalStateException(e);

-        }

-    }

-

-    @Override

-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

-        if ("close".equals(method.getName())) {

-            tracker.close();

-            return null;

-        }

-        try {

-            return method.invoke(getService(), args);

-        } catch (IllegalArgumentException e) {

-            throw new IllegalStateException(e);

-        } catch (InvocationTargetException e) {

-            throw new IllegalStateException(e);

-        }

-    }

-    

-    public static <T> T create(BundleContext context, Class<T> iface) {

-        return  (T) create(context, iface, getFilter(iface));

-    }

-    

-    private static String getFilter(Class<?> clazz) {

-        return String.format("(objectClass=%s)", clazz.getName());

-    }

-

-    @SuppressWarnings("unchecked")

-    public static <T> T create(BundleContext context, Class<T> iface, String filter) {

-    	ClassLoader cl = iface.getClassLoader();

-        Class<?>[] ifAr = new Class[] { Closeable.class, iface };

-        return  (T) Proxy.newProxyInstance(cl, ifAr, new ServiceProxy(context, filter));

-    }

-}