killbill-memoizeit

Changes

Details

diff --git a/api/src/main/java/com/ning/billing/osgi/api/OSGIPluginProperties.java b/api/src/main/java/com/ning/billing/osgi/api/OSGIPluginProperties.java
index 2c4bb7c..e1873e0 100644
--- a/api/src/main/java/com/ning/billing/osgi/api/OSGIPluginProperties.java
+++ b/api/src/main/java/com/ning/billing/osgi/api/OSGIPluginProperties.java
@@ -16,8 +16,22 @@
 
 package com.ning.billing.osgi.api;
 
+/**
+ * Those represents the properties that plugin can use when registering services
+ * and that Killbill knows how to interpret. At a minimum, the plugin should use PLUGIN_NAME_PROP
+ */
 public interface OSGIPluginProperties {
 
+    /** Name of the plugin when it registers itself */
+    // TODO We should make sure that this mataches the 'symbolic name' of the plugin, or if not how those two play together
     public static final String PLUGIN_NAME_PROP = "killbill.pluginName";
 
+    /** Name of the instnace of the plugin; if 2 instances of the same plugin register */
+    public static final String PLUGIN_INSTANCE_PROP = "killbill.pluginInstance";
+
+    /** Used to export an additional configuration string for that service
+     *  For instance for Servlet services this is used to specify the path of the servlet.
+     */
+    public static final String PLUGIN_SERVICE_INFO = "killbill.pluginServiceInfo";
+
 }
diff --git a/api/src/main/java/com/ning/billing/osgi/api/OSGIServiceDescriptor.java b/api/src/main/java/com/ning/billing/osgi/api/OSGIServiceDescriptor.java
new file mode 100644
index 0000000..d281471
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/osgi/api/OSGIServiceDescriptor.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.osgi.api;
+
+public interface OSGIServiceDescriptor {
+
+    /**
+     * @return the symbolic name of the OSGI plugin registering that service
+     */
+    public String getPluginSymbolicName();
+
+    /**
+     *
+     * @return the unique of that service-- plugin should rely on namespace to enforce the uniqueness
+     */
+    public String getServiceName();
+
+    /**
+     *
+     * @return additional service info that can be interpreted by the OSGIServiceRegistration system
+     */
+    public String getServiceInfo();
+
+    /**
+     *
+     * @return the type of the service being registered
+     */
+    public String getServiceType();
+}
diff --git a/api/src/main/java/com/ning/billing/osgi/api/OSGIServiceRegistration.java b/api/src/main/java/com/ning/billing/osgi/api/OSGIServiceRegistration.java
index 83293e0..cfa3127 100644
--- a/api/src/main/java/com/ning/billing/osgi/api/OSGIServiceRegistration.java
+++ b/api/src/main/java/com/ning/billing/osgi/api/OSGIServiceRegistration.java
@@ -16,11 +16,9 @@
 
 package com.ning.billing.osgi.api;
 
-import java.util.List;
 import java.util.Set;
 
 /**
- *
  * The purpose is to register within Killbill OSGI services
  * that were exported by specific Killbill plugins
  *
@@ -28,34 +26,25 @@ import java.util.Set;
  */
 public interface OSGIServiceRegistration<T> {
 
-    /**
-     *
-     * @param pluginName the name of plugin
-     * @param service    the instance that should be registered
-     */
-    void registerService(String pluginName, T service);
+    void registerService(OSGIServiceDescriptor desc, T service);
 
     /**
-     *
-     * @param pluginName the name of plugin
+     * @param serviceName the name of the service as it was registered
      */
-    void unregisterService(String pluginName);
+    void unregisterService(String serviceName);
 
     /**
-     *
-     * @param pluginName the name of plugin
+     * @param serviceName the name of the service as it was registered
      * @return the instance that was registered under that name
      */
-    T getServiceForPluginName(String pluginName);
+    T getServiceForName(String serviceName);
 
     /**
-     *
-     * @return the set of all the plugins registered
+     * @return the set of all the service registered
      */
-    Set<String> getAllServiceForPluginName();
+    Set<String> getAllServices();
 
     /**
-     *
      * @return the type of service that is registered under that OSGIServiceRegistration
      */
     Class<T> getServiceType();
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestBasicOSGIWithTestBundle.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestBasicOSGIWithTestBundle.java
index 9515c1d..1630a41 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestBasicOSGIWithTestBundle.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestBasicOSGIWithTestBundle.java
@@ -107,7 +107,7 @@ public class TestBasicOSGIWithTestBundle extends TestOSGIBase {
     }
 
     private PaymentPluginApi getTestPluginPaymentApi() {
-        PaymentPluginApi result = paymentPluginApiOSGIServiceRegistration.getServiceForPluginName("test");
+        PaymentPluginApi result = paymentPluginApiOSGIServiceRegistration.getServiceForName("test");
         Assert.assertNotNull(result);
         return result;
     }
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestPaymentOSGIWithTestPaymentBundle.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestPaymentOSGIWithTestPaymentBundle.java
index f80e292..bbe1df6 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestPaymentOSGIWithTestPaymentBundle.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestPaymentOSGIWithTestPaymentBundle.java
@@ -179,7 +179,7 @@ public class TestPaymentOSGIWithTestPaymentBundle extends TestOSGIBase {
 
 
     private PaymentPluginApiWithTestControl getTestPluginPaymentApi() {
-        PaymentPluginApiWithTestControl result = (PaymentPluginApiWithTestControl) paymentPluginApiOSGIServiceRegistration.getServiceForPluginName(BeatrixIntegrationModule.OSGI_PLUGIN_NAME);
+        PaymentPluginApiWithTestControl result = (PaymentPluginApiWithTestControl) paymentPluginApiOSGIServiceRegistration.getServiceForName(BeatrixIntegrationModule.OSGI_PLUGIN_NAME);
         Assert.assertNotNull(result);
         return result;
     }
diff --git a/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIServiceDescriptor.java b/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIServiceDescriptor.java
new file mode 100644
index 0000000..dcbcd4d
--- /dev/null
+++ b/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIServiceDescriptor.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.osgi;
+
+import com.ning.billing.osgi.api.OSGIServiceDescriptor;
+
+public class DefaultOSGIServiceDescriptor implements OSGIServiceDescriptor {
+
+    private final String pluginSymbolicName;
+    private final String serviceName;
+    private final String serviceInfo;
+    private final String serviceType;
+
+    public DefaultOSGIServiceDescriptor(final String pluginSymbolicName, final String serviceName, final String serviceInfo, final String serviceType) {
+        this.pluginSymbolicName = pluginSymbolicName;
+        this.serviceName = serviceName;
+        this.serviceInfo = serviceInfo;
+        this.serviceType = serviceType;
+    }
+
+    @Override
+    public String getPluginSymbolicName() {
+        return pluginSymbolicName;
+    }
+
+    @Override
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    @Override
+    public String getServiceInfo() {
+        return serviceInfo;
+    }
+
+    @Override
+    public String getServiceType() {
+        return serviceType;
+    }
+}
diff --git a/osgi/src/main/java/com/ning/billing/osgi/http/DefaultHttpService.java b/osgi/src/main/java/com/ning/billing/osgi/http/DefaultHttpService.java
index a5d606c..30220f7 100644
--- a/osgi/src/main/java/com/ning/billing/osgi/http/DefaultHttpService.java
+++ b/osgi/src/main/java/com/ning/billing/osgi/http/DefaultHttpService.java
@@ -46,7 +46,7 @@ public class DefaultHttpService implements HttpService {
             throw new IllegalArgumentException("Invalid servlet (null)");
         }
 
-        servletRouter.registerService(alias, servlet);
+        servletRouter.registerServiceFromPath(alias, servlet);
     }
 
     @Override
@@ -61,7 +61,7 @@ public class DefaultHttpService implements HttpService {
 
     @Override
     public void unregister(final String alias) {
-        servletRouter.unregisterService(alias);
+        servletRouter.unregisterServiceFromPath(alias);
     }
 
     @Override
diff --git a/osgi/src/main/java/com/ning/billing/osgi/http/DefaultServletRouter.java b/osgi/src/main/java/com/ning/billing/osgi/http/DefaultServletRouter.java
index e822259..30551cf 100644
--- a/osgi/src/main/java/com/ning/billing/osgi/http/DefaultServletRouter.java
+++ b/osgi/src/main/java/com/ning/billing/osgi/http/DefaultServletRouter.java
@@ -16,9 +16,9 @@
 
 package com.ning.billing.osgi.http;
 
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 
 import javax.inject.Singleton;
 import javax.servlet.Servlet;
@@ -26,6 +26,7 @@ import javax.servlet.Servlet;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.ning.billing.osgi.api.OSGIServiceDescriptor;
 import com.ning.billing.osgi.api.OSGIServiceRegistration;
 
 @Singleton
@@ -35,35 +36,60 @@ public class DefaultServletRouter implements OSGIServiceRegistration<Servlet> {
 
     // Internal Servlet routing table: map of plugin prefixes to servlet instances.
     // A plugin prefix can be /foo, /foo/bar, /foo/bar/baz, ... and is mounted on /plugins/<pluginPrefix>
-    private final Map<String, Servlet> pluginServlets = new ConcurrentHashMap<String, Servlet>();
+    private final Map<String, Servlet> pluginPathServlets = new HashMap<String, Servlet>();
+    private final Map<String, OSGIServiceDescriptor> pluginRegistrations = new HashMap<String, OSGIServiceDescriptor>();
 
     @Override
-    public void registerService(final String originalPathPrefix, final Servlet httpServlet) {
+    public void registerService(final OSGIServiceDescriptor desc, final Servlet httpServlet) {
         // Enforce each route to start with /
-        final String pathPrefix;
-        if (originalPathPrefix.charAt(0) != '/') {
-            pathPrefix = "/" + originalPathPrefix;
-        } else {
-            pathPrefix = originalPathPrefix;
-        }
+        final String pathPrefix = sanitizePathPrefix(desc.getServiceInfo());
         logger.info("Registering OSGI servlet at " + pathPrefix);
-        pluginServlets.put(pathPrefix, httpServlet);
+        synchronized (this) {
+            pluginPathServlets.put(pathPrefix, httpServlet);
+            pluginRegistrations.put(desc.getServiceName(), desc);
+        }
     }
 
-    @Override
-    public void unregisterService(final String pathPrefix) {
-        logger.info("Unregistering OSGI servlet at " + pathPrefix);
-        pluginServlets.remove(pathPrefix);
+    public void registerServiceFromPath(final String path, final Servlet httpServlet) {
+        pluginPathServlets.put(sanitizePathPrefix(path), httpServlet);
+    }
+
+
+        @Override
+    public void unregisterService(final String serviceName) {
+        synchronized (this) {
+            final OSGIServiceDescriptor desc = pluginRegistrations.get(serviceName);
+            if (desc != null) {
+                final String registeredPath = sanitizePathPrefix(desc.getServiceInfo());
+                pluginPathServlets.remove(registeredPath);
+                pluginRegistrations.remove(desc);
+                logger.info("Unregistering OSGI servlet " + desc.getServiceName() + " at path " + registeredPath);
+            }
+        }
+    }
+
+    public void unregisterServiceFromPath(final String path) {
+        pluginPathServlets.remove(sanitizePathPrefix(path));
     }
 
+
     @Override
-    public Servlet getServiceForPluginName(final String pathPrefix) {
-        return getServletForPathPrefix(pathPrefix);
+    public Servlet getServiceForName(final String serviceName) {
+        final OSGIServiceDescriptor desc = pluginRegistrations.get(serviceName);
+        if (desc == null) {
+            return null;
+        }
+        final String registeredPath = sanitizePathPrefix(desc.getServiceInfo());
+        return pluginPathServlets.get(registeredPath);
+    }
+
+    public Servlet getServiceForPath(final String path) {
+        return getServletForPathPrefix(path);
     }
 
     @Override
-    public Set<String> getAllServiceForPluginName() {
-        return pluginServlets.keySet();
+    public Set<String> getAllServices() {
+        return pluginPathServlets.keySet();
     }
 
     @Override
@@ -74,7 +100,7 @@ public class DefaultServletRouter implements OSGIServiceRegistration<Servlet> {
     // TODO PIERRE Naive implementation - we should rather switch to e.g. heap tree
     public String getPluginPrefixForPath(final String pathPrefix) {
         String bestMatch = null;
-        for (final String potentialMatch : pluginServlets.keySet()) {
+        for (final String potentialMatch : pluginPathServlets.keySet()) {
             if (pathPrefix.startsWith(potentialMatch) && (bestMatch == null || bestMatch.length() < potentialMatch.length())) {
                 bestMatch = potentialMatch;
             }
@@ -84,6 +110,17 @@ public class DefaultServletRouter implements OSGIServiceRegistration<Servlet> {
 
     private Servlet getServletForPathPrefix(final String pathPrefix) {
         final String bestMatch = getPluginPrefixForPath(pathPrefix);
-        return bestMatch == null ? null : pluginServlets.get(bestMatch);
+        return bestMatch == null ? null : pluginPathServlets.get(bestMatch);
+    }
+
+
+    private static final String sanitizePathPrefix(final String inputPath) {
+        final String pathPrefix;
+        if (inputPath.charAt(0) != '/') {
+            pathPrefix = "/" + inputPath;
+        } else {
+            pathPrefix = inputPath;
+        }
+        return pathPrefix;
     }
 }
diff --git a/osgi/src/main/java/com/ning/billing/osgi/http/OSGIServlet.java b/osgi/src/main/java/com/ning/billing/osgi/http/OSGIServlet.java
index a9af086..92c9b80 100644
--- a/osgi/src/main/java/com/ning/billing/osgi/http/OSGIServlet.java
+++ b/osgi/src/main/java/com/ning/billing/osgi/http/OSGIServlet.java
@@ -119,9 +119,9 @@ public class OSGIServlet extends HttpServlet {
         }
     }
 
-    private Servlet getPluginServlet(final String pluginName) {
-        if (pluginName != null) {
-            return servletRouter.getServiceForPluginName(pluginName);
+    private Servlet getPluginServlet(final String requestPath) {
+        if (requestPath != null) {
+            return servletRouter.getServiceForPath(requestPath);
         } else {
             return null;
         }
diff --git a/osgi/src/main/java/com/ning/billing/osgi/KillbillActivator.java b/osgi/src/main/java/com/ning/billing/osgi/KillbillActivator.java
index 8d493a8..715c120 100644
--- a/osgi/src/main/java/com/ning/billing/osgi/KillbillActivator.java
+++ b/osgi/src/main/java/com/ning/billing/osgi/KillbillActivator.java
@@ -31,11 +31,13 @@ import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceEvent;
 import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.http.HttpService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.ning.billing.osgi.api.OSGIKillbill;
 import com.ning.billing.osgi.api.OSGIPluginProperties;
+import com.ning.billing.osgi.api.OSGIServiceDescriptor;
 import com.ning.billing.osgi.api.OSGIServiceRegistration;
 import com.ning.billing.osgi.glue.DefaultOSGIModule;
 import com.ning.billing.payment.plugin.api.PaymentPluginApi;
@@ -45,6 +47,9 @@ import com.google.common.collect.ImmutableList;
 
 public class KillbillActivator implements BundleActivator, ServiceListener {
 
+    // TODO : Is that ok for system bundle to use Killbill Logger or do we need to LoggerService like we do for any other bundle
+    private final static Logger logger = LoggerFactory.getLogger(KillbillActivator.class);
+
     private final OSGIKillbill osgiKillbill;
     private final HttpService defaultHttpService;
     private final DataSource dataSource;
@@ -52,7 +57,6 @@ public class KillbillActivator implements BundleActivator, ServiceListener {
     private final OSGIKillbillRegistrar registrar;
 
 
-    private volatile ServiceRegistration osgiKillbillRegistration;
     private final List<OSGIServiceRegistration> allRegistrationHandlers;
 
 
@@ -63,7 +67,6 @@ public class KillbillActivator implements BundleActivator, ServiceListener {
                              final OSGIKillbill osgiKillbill,
                              final HttpService defaultHttpService,
                              final KillbillEventObservable observable,
-
                              final OSGIServiceRegistration<Servlet> servletRouter,
                              final OSGIServiceRegistration<PaymentPluginApi> paymentProviderPluginRegistry) {
         this.osgiKillbill = osgiKillbill;
@@ -77,8 +80,8 @@ public class KillbillActivator implements BundleActivator, ServiceListener {
 
     @Override
     public void start(final BundleContext context) throws Exception {
-        this.context = context;
 
+        this.context = context;
         final Dictionary props = new Hashtable();
         props.put(OSGIPluginProperties.PLUGIN_NAME_PROP, "killbill");
 
@@ -106,19 +109,25 @@ public class KillbillActivator implements BundleActivator, ServiceListener {
             // We are not initialized or uninterested
             return;
         }
+
+        final ServiceReference serviceReference = event.getServiceReference();
+        boolean processedServiceChange = false;
         for (OSGIServiceRegistration cur : allRegistrationHandlers) {
-            if (listenForServiceType(event, cur.getServiceType(), cur)) {
+            if (listenForServiceType(serviceReference, event.getType(), cur.getServiceType(), cur)) {
+                processedServiceChange = true;
                 break;
             }
         }
+        if (!processedServiceChange) {
+            logger.warn("Did not process ServiceEvent for {} ", serviceReference.getBundle().getSymbolicName());
+        }
     }
 
-    private <T> boolean listenForServiceType(final ServiceEvent event, final Class<T> claz, final OSGIServiceRegistration<T> registration) {
+    private <T> boolean listenForServiceType(final ServiceReference serviceReference, final int eventType, final Class<T> claz, final OSGIServiceRegistration<T> registration) {
         // Make sure we can retrieve the plugin name
-        final ServiceReference serviceReference = event.getServiceReference();
-        final String pluginName = (String) serviceReference.getProperty(OSGIPluginProperties.PLUGIN_NAME_PROP);
-        if (pluginName == null) {
-            // TODO STEPH logger ?
+        final String serviceName = (String) serviceReference.getProperty(OSGIPluginProperties.PLUGIN_NAME_PROP);
+        if (serviceName == null) {
+            logger.warn("Ignoring registered OSGI service {} with no {} property", claz.getName(), OSGIPluginProperties.PLUGIN_NAME_PROP);
             return true;
         }
 
@@ -128,17 +137,18 @@ public class KillbillActivator implements BundleActivator, ServiceListener {
             return false;
         }
 
-        switch (event.getType()) {
+        final String serviceInfo = (String) serviceReference.getProperty(OSGIPluginProperties.PLUGIN_SERVICE_INFO);
+        final OSGIServiceDescriptor desc =  new DefaultOSGIServiceDescriptor(serviceReference.getBundle().getSymbolicName(), serviceName, serviceInfo, claz.getName());
+        switch (eventType) {
             case ServiceEvent.REGISTERED:
-                registration.registerService(pluginName, theService);
+                registration.registerService(desc, theService);
                 break;
             case ServiceEvent.UNREGISTERING:
-                registration.unregisterService(pluginName);
+                registration.unregisterService(desc.getServiceName());
                 break;
             default:
                 break;
         }
-
         return true;
     }
 }
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
index ab294d9..dd48514 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
@@ -74,7 +74,7 @@ public class PaymentMethodProcessor extends ProcessorBase {
     }
 
     public Set<String> getAvailablePlugins() {
-        return pluginRegistry.getAllServiceForPluginName();
+        return pluginRegistry.getAllServices();
     }
 
     public UUID addPaymentMethod(final String pluginName, final Account account,
@@ -88,7 +88,7 @@ public class PaymentMethodProcessor extends ProcessorBase {
                 PaymentMethod pm = null;
                 PaymentPluginApi pluginApi = null;
                 try {
-                    pluginApi = pluginRegistry.getServiceForPluginName(pluginName);
+                    pluginApi = pluginRegistry.getServiceForName(pluginName);
                     pm = new DefaultPaymentMethod(account.getId(), pluginName, paymentMethodProps);
                     pluginApi.addPaymentMethod(pm.getId(), paymentMethodProps, setDefault, context.toCallContext());
                     final PaymentMethodModelDao pmModel = new PaymentMethodModelDao(pm.getId(), pm.getCreatedDate(), pm.getUpdatedDate(),
@@ -157,7 +157,7 @@ public class PaymentMethodProcessor extends ProcessorBase {
             addPaymentMethod(ExternalPaymentProviderPlugin.PLUGIN_NAME, account, false, props, context);
         }
 
-        return (ExternalPaymentProviderPlugin) pluginRegistry.getServiceForPluginName(ExternalPaymentProviderPlugin.PLUGIN_NAME);
+        return (ExternalPaymentProviderPlugin) pluginRegistry.getServiceForName(ExternalPaymentProviderPlugin.PLUGIN_NAME);
     }
 
     private List<PaymentMethod> getPaymentMethodInternal(final List<PaymentMethodModelDao> paymentMethodModels, final UUID accountId,
@@ -244,7 +244,7 @@ public class PaymentMethodProcessor extends ProcessorBase {
         if (paymentMethod == null) {
             throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_PAYMENT_METHOD, paymentMethodId);
         }
-        return pluginRegistry.getServiceForPluginName(paymentMethod.getPluginName());
+        return pluginRegistry.getServiceForName(paymentMethod.getPluginName());
     }
 
     /**
@@ -262,7 +262,7 @@ public class PaymentMethodProcessor extends ProcessorBase {
 
 
         // Don't hold the account lock while fetching the payment methods from the gateway as those could change anyway
-        final PaymentPluginApi pluginApi = pluginRegistry.getServiceForPluginName(pluginName);
+        final PaymentPluginApi pluginApi = pluginRegistry.getServiceForName(pluginName);
         final List<PaymentMethodInfoPlugin> pluginPms;
         try {
             pluginPms = pluginApi.getPaymentMethods(account.getId(), true, context.toCallContext());
diff --git a/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java b/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
index cd345fc..e3366aa 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
@@ -110,7 +110,7 @@ public abstract class ProcessorBase {
             log.error("PaymentMethod dpes not exist", paymentMethodId);
             throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_PAYMENT_METHOD, paymentMethodId);
         }
-        return pluginRegistry.getServiceForPluginName(methodDao.getPluginName());
+        return pluginRegistry.getServiceForName(methodDao.getPluginName());
     }
 
     protected PaymentPluginApi getPaymentProviderPlugin(final String accountKey, final InternalTenantContext context)
@@ -121,7 +121,7 @@ public abstract class ProcessorBase {
             final Account account = accountInternalApi.getAccountByKey(accountKey, context);
             return getPaymentProviderPlugin(account, context);
         }
-        return pluginRegistry.getServiceForPluginName(paymentProviderName);
+        return pluginRegistry.getServiceForName(paymentProviderName);
     }
 
     protected PaymentPluginApi getPaymentProviderPlugin(final Account account, final InternalTenantContext context) throws PaymentApiException {
diff --git a/payment/src/main/java/com/ning/billing/payment/glue/DefaultPaymentProviderPluginRegistryProvider.java b/payment/src/main/java/com/ning/billing/payment/glue/DefaultPaymentProviderPluginRegistryProvider.java
index 4bc2349..ed47264 100644
--- a/payment/src/main/java/com/ning/billing/payment/glue/DefaultPaymentProviderPluginRegistryProvider.java
+++ b/payment/src/main/java/com/ning/billing/payment/glue/DefaultPaymentProviderPluginRegistryProvider.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.payment.glue;
 
+import com.ning.billing.osgi.api.OSGIServiceDescriptor;
 import com.ning.billing.osgi.api.OSGIServiceRegistration;
 import com.ning.billing.payment.plugin.api.PaymentPluginApi;
 import com.ning.billing.util.config.PaymentConfig;
@@ -41,7 +42,25 @@ public class DefaultPaymentProviderPluginRegistryProvider implements Provider<OS
         final DefaultPaymentProviderPluginRegistry pluginRegistry = new DefaultPaymentProviderPluginRegistry(paymentConfig);
 
         // Make the external payment provider plugin available by default
-        pluginRegistry.registerService(ExternalPaymentProviderPlugin.PLUGIN_NAME, externalPaymentProviderPlugin);
+        final OSGIServiceDescriptor desc = new OSGIServiceDescriptor() {
+            @Override
+            public String getPluginSymbolicName() {
+                return null;
+            }
+            @Override
+            public String getServiceName() {
+                return ExternalPaymentProviderPlugin.PLUGIN_NAME;
+            }
+            @Override
+            public String getServiceInfo() {
+                return null;
+            }
+            @Override
+            public String getServiceType() {
+                return null;
+            }
+        };
+        pluginRegistry.registerService(desc, externalPaymentProviderPlugin);
 
         return pluginRegistry;
     }
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/DefaultPaymentProviderPluginRegistry.java b/payment/src/main/java/com/ning/billing/payment/provider/DefaultPaymentProviderPluginRegistry.java
index 0bfc1b1..6825980 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/DefaultPaymentProviderPluginRegistry.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/DefaultPaymentProviderPluginRegistry.java
@@ -20,6 +20,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
+import com.ning.billing.osgi.api.OSGIServiceDescriptor;
 import com.ning.billing.osgi.api.OSGIServiceRegistration;
 import com.ning.billing.payment.plugin.api.PaymentPluginApi;
 import com.ning.billing.util.config.PaymentConfig;
@@ -39,17 +40,17 @@ public class DefaultPaymentProviderPluginRegistry implements OSGIServiceRegistra
 
 
     @Override
-    public void registerService(final String pluginName, final PaymentPluginApi service) {
-        pluginsByName.put(pluginName.toLowerCase(), service);
+    public void registerService(final OSGIServiceDescriptor desc, final PaymentPluginApi service) {
+        pluginsByName.put(desc.getServiceName().toLowerCase(), service);
     }
 
     @Override
-    public void unregisterService(final String pluginName) {
-        pluginsByName.remove(pluginName.toLowerCase());
+    public void unregisterService(final String serviceName) {
+        pluginsByName.remove(serviceName.toLowerCase());
     }
 
     @Override
-    public PaymentPluginApi getServiceForPluginName(final String name) {
+    public PaymentPluginApi getServiceForName(final String name) {
         final PaymentPluginApi plugin = pluginsByName.get((Strings.emptyToNull(name) == null ? defaultPlugin : name).toLowerCase());
 
         if (plugin == null) {
@@ -60,7 +61,7 @@ public class DefaultPaymentProviderPluginRegistry implements OSGIServiceRegistra
     }
 
     @Override
-    public Set<String> getAllServiceForPluginName() {
+    public Set<String> getAllServices() {
         return pluginsByName.keySet();
     }
 
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPluginProvider.java b/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPluginProvider.java
index 8bd3830..2a9cf4c 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPluginProvider.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPluginProvider.java
@@ -19,6 +19,7 @@ package com.ning.billing.payment.provider;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
+import com.ning.billing.osgi.api.OSGIServiceDescriptor;
 import com.ning.billing.osgi.api.OSGIServiceRegistration;
 import com.ning.billing.payment.plugin.api.PaymentPluginApi;
 import com.ning.billing.util.clock.Clock;
@@ -43,9 +44,27 @@ public class NoOpPaymentProviderPluginProvider implements Provider<DefaultNoOpPa
 
     @Override
     public DefaultNoOpPaymentProviderPlugin get() {
-        final DefaultNoOpPaymentProviderPlugin plugin = new DefaultNoOpPaymentProviderPlugin(clock);
 
-        registry.registerService(instanceName, plugin);
+        final DefaultNoOpPaymentProviderPlugin plugin = new DefaultNoOpPaymentProviderPlugin(clock);
+        final OSGIServiceDescriptor desc = new OSGIServiceDescriptor() {
+            @Override
+            public String getPluginSymbolicName() {
+                return null;
+            }
+            @Override
+            public String getServiceName() {
+                return instanceName;
+            }
+            @Override
+            public String getServiceInfo() {
+                return null;
+            }
+            @Override
+            public String getServiceType() {
+                return null;
+            }
+        };
+        registry.registerService(desc, plugin);
         return plugin;
     }
 }
diff --git a/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPluginProvider.java b/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPluginProvider.java
index 3fb098d..0c4f4ac 100644
--- a/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPluginProvider.java
+++ b/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPluginProvider.java
@@ -19,6 +19,7 @@ package com.ning.billing.payment.provider;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
+import com.ning.billing.osgi.api.OSGIServiceDescriptor;
 import com.ning.billing.osgi.api.OSGIServiceRegistration;
 import com.ning.billing.payment.plugin.api.PaymentPluginApi;
 import com.ning.billing.util.clock.Clock;
@@ -44,7 +45,25 @@ public class MockPaymentProviderPluginProvider implements Provider<MockPaymentPr
     public MockPaymentProviderPlugin get() {
         final MockPaymentProviderPlugin plugin = new MockPaymentProviderPlugin(clock);
 
-        registry.registerService(instanceName, plugin);
+        final OSGIServiceDescriptor desc =  new OSGIServiceDescriptor() {
+            @Override
+            public String getPluginSymbolicName() {
+                return null;
+            }
+            @Override
+            public String getServiceName() {
+                return instanceName;
+            }
+            @Override
+            public String getServiceInfo() {
+                return null;
+            }
+            @Override
+            public String getServiceType() {
+                return null;
+            }
+        };
+        registry.registerService(desc, plugin);
         return plugin;
     }
 }
diff --git a/payment/src/test/java/com/ning/billing/payment/TestRetryService.java b/payment/src/test/java/com/ning/billing/payment/TestRetryService.java
index f7cbd7a..281f0e9 100644
--- a/payment/src/test/java/com/ning/billing/payment/TestRetryService.java
+++ b/payment/src/test/java/com/ning/billing/payment/TestRetryService.java
@@ -59,7 +59,7 @@ public class TestRetryService extends PaymentTestSuiteNoDB {
         retryService.initialize(DefaultPaymentService.SERVICE_NAME);
         retryService.start();
 
-        mockPaymentProviderPlugin = (MockPaymentProviderPlugin) registry.getServiceForPluginName(null);
+        mockPaymentProviderPlugin = (MockPaymentProviderPlugin) registry.getServiceForName(null);
         mockPaymentProviderPlugin.clear();
     }
 
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestPlugin.java b/server/src/test/java/com/ning/billing/jaxrs/TestPlugin.java
index 87befef..7d4ec76 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestPlugin.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestPlugin.java
@@ -29,6 +29,7 @@ import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.ning.billing.osgi.http.DefaultServletRouter;
 import com.ning.http.client.Response;
 
 public class TestPlugin extends TestJaxrsBase {
@@ -159,7 +160,7 @@ public class TestPlugin extends TestJaxrsBase {
     }
 
     private void setupOSGIPlugin() {
-        servletRouter.registerService(TEST_PLUGIN_NAME, new HttpServlet() {
+        ((DefaultServletRouter) servletRouter).registerServiceFromPath(TEST_PLUGIN_NAME, new HttpServlet() {
             @Override
             protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
                 if (("/" + TEST_PLUGIN_VALID_GET_PATH).equals(req.getPathInfo())) {