killbill-memoizeit
Changes
osgi-bundles/libs/killbill/pom.xml 10(+8 -2)
Details
diff --git a/api/src/main/java/com/ning/billing/osgi/api/LiveTrackerException.java b/api/src/main/java/com/ning/billing/osgi/api/LiveTrackerException.java
new file mode 100644
index 0000000..23eee3e
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/osgi/api/LiveTrackerException.java
@@ -0,0 +1,28 @@
+/*
+ * 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 class LiveTrackerException extends Exception {
+
+ public LiveTrackerException(String msg) {
+ super(msg);
+ }
+
+ public LiveTrackerException(String msg, Throwable e) {
+ super(msg, e);
+ }
+}
diff --git a/api/src/main/java/com/ning/billing/osgi/api/OSGIUserApi.java b/api/src/main/java/com/ning/billing/osgi/api/OSGIUserApi.java
new file mode 100644
index 0000000..60067be
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/osgi/api/OSGIUserApi.java
@@ -0,0 +1,22 @@
+/*
+ * 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 OSGIUserApi {
+
+ public <S> S getService(Class<S> serviceClass) throws LiveTrackerException;
+}
diff --git a/api/src/main/java/com/ning/billing/payment/plugin/api/PaymentPluginApiException.java b/api/src/main/java/com/ning/billing/payment/plugin/api/PaymentPluginApiException.java
index 91c106c..f9a2000 100644
--- a/api/src/main/java/com/ning/billing/payment/plugin/api/PaymentPluginApiException.java
+++ b/api/src/main/java/com/ning/billing/payment/plugin/api/PaymentPluginApiException.java
@@ -24,6 +24,12 @@ public class PaymentPluginApiException extends Exception {
private final String errorType;
private final String errorMessage;
+ public PaymentPluginApiException(final String msg, final Throwable e) {
+ super(msg, e);
+ errorMessage = msg;
+ errorType = e.getMessage();
+ }
+
public PaymentPluginApiException(final String errorType, final String errorMessage) {
this.errorMessage = errorMessage;
this.errorType = errorType;
@@ -46,8 +52,12 @@ public class PaymentPluginApiException extends Exception {
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("PaymentPluginApiException");
- sb.append("{errorMessage='").append(errorMessage).append('\'');
- sb.append(", errorType='").append(errorType).append('\'');
+ if (errorMessage != null) {
+ sb.append("{errorMessage='").append(errorMessage).append('\'');
+ }
+ if (errorType != null) {
+ sb.append(", errorType='").append(errorType).append('\'');
+ }
sb.append('}');
return sb.toString();
}
diff --git a/osgi/src/main/java/com/ning/billing/osgi/api/DefaultOSGIUserApi.java b/osgi/src/main/java/com/ning/billing/osgi/api/DefaultOSGIUserApi.java
new file mode 100644
index 0000000..be9050b
--- /dev/null
+++ b/osgi/src/main/java/com/ning/billing/osgi/api/DefaultOSGIUserApi.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+import javax.inject.Inject;
+
+import com.ning.billing.osgi.LiveTracker;
+
+public class DefaultOSGIUserApi implements OSGIUserApi {
+
+ private final LiveTracker liveTracker;
+
+ @Inject
+ public DefaultOSGIUserApi(LiveTracker liveTracker) {
+ this.liveTracker = liveTracker;
+ }
+
+ @Override
+ public <S> S getService(final Class<S> serviceClass) throws LiveTrackerException {
+ return liveTracker.getRegisteredOSGIService(serviceClass);
+ }
+}
diff --git a/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIService.java b/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIService.java
index 15516d0..e1ea4b7 100644
--- a/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIService.java
+++ b/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIService.java
@@ -112,6 +112,7 @@ public class DefaultOSGIService implements OSGIService {
try {
framework.stop();
framework.waitForStop(0);
+
} catch (BundleException e) {
logger.error("Failed to Stop Killbill OSGIService " + e.getMessage());
} catch (InterruptedException e) {
diff --git a/osgi/src/main/java/com/ning/billing/osgi/glue/DefaultOSGIModule.java b/osgi/src/main/java/com/ning/billing/osgi/glue/DefaultOSGIModule.java
index c793069..ce9b51e 100644
--- a/osgi/src/main/java/com/ning/billing/osgi/glue/DefaultOSGIModule.java
+++ b/osgi/src/main/java/com/ning/billing/osgi/glue/DefaultOSGIModule.java
@@ -27,10 +27,13 @@ import com.ning.billing.osgi.DefaultOSGIKillbill;
import com.ning.billing.osgi.DefaultOSGIService;
import com.ning.billing.osgi.KillbillActivator;
import com.ning.billing.osgi.KillbillEventObservable;
+import com.ning.billing.osgi.LiveTracker;
import com.ning.billing.osgi.PureOSGIBundleFinder;
+import com.ning.billing.osgi.api.DefaultOSGIUserApi;
import com.ning.billing.osgi.api.OSGIKillbill;
import com.ning.billing.osgi.api.OSGIService;
import com.ning.billing.osgi.api.OSGIServiceRegistration;
+import com.ning.billing.osgi.api.OSGIUserApi;
import com.ning.billing.osgi.api.config.PluginConfigServiceApi;
import com.ning.billing.osgi.http.DefaultHttpService;
import com.ning.billing.osgi.http.DefaultServletRouter;
@@ -72,6 +75,8 @@ public class DefaultOSGIModule extends AbstractModule {
bind(OSGIService.class).to(DefaultOSGIService.class).asEagerSingleton();
+ bind(OSGIUserApi.class).to(DefaultOSGIUserApi.class).asEagerSingleton();
+ bind(LiveTracker.class).to(KillbillActivator.class).asEagerSingleton();
bind(KillbillActivator.class).asEagerSingleton();
bind(PureOSGIBundleFinder.class).asEagerSingleton();
bind(PluginFinder.class).asEagerSingleton();
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 715c120..2a242f2 100644
--- a/osgi/src/main/java/com/ning/billing/osgi/KillbillActivator.java
+++ b/osgi/src/main/java/com/ning/billing/osgi/KillbillActivator.java
@@ -17,8 +17,10 @@
package com.ning.billing.osgi;
import java.util.Dictionary;
+import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
+import java.util.Map;
import java.util.Observable;
import javax.inject.Inject;
@@ -32,9 +34,11 @@ import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpService;
+import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.ning.billing.osgi.api.LiveTrackerException;
import com.ning.billing.osgi.api.OSGIKillbill;
import com.ning.billing.osgi.api.OSGIPluginProperties;
import com.ning.billing.osgi.api.OSGIServiceDescriptor;
@@ -45,7 +49,7 @@ import com.ning.killbill.osgi.libs.killbill.OSGIKillbillRegistrar;
import com.google.common.collect.ImmutableList;
-public class KillbillActivator implements BundleActivator, ServiceListener {
+public class KillbillActivator implements BundleActivator, ServiceListener, LiveTracker {
// 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);
@@ -55,6 +59,7 @@ public class KillbillActivator implements BundleActivator, ServiceListener {
private final DataSource dataSource;
private final KillbillEventObservable observable;
private final OSGIKillbillRegistrar registrar;
+ private final Map<String, ServiceTracker> liveTrackers;
private final List<OSGIServiceRegistration> allRegistrationHandlers;
@@ -75,6 +80,7 @@ public class KillbillActivator implements BundleActivator, ServiceListener {
this.observable = observable;
this.registrar = new OSGIKillbillRegistrar();
this.allRegistrationHandlers = ImmutableList.<OSGIServiceRegistration>of(servletRouter, paymentProviderPluginRegistry);
+ this.liveTrackers = new HashMap<String, ServiceTracker>();
}
@@ -101,6 +107,9 @@ public class KillbillActivator implements BundleActivator, ServiceListener {
context.removeServiceListener(this);
observable.unregister();
registrar.unregisterAll();
+ for (ServiceTracker tracker : liveTrackers.values()) {
+ tracker.close();
+ }
}
@Override
@@ -110,16 +119,70 @@ public class KillbillActivator implements BundleActivator, ServiceListener {
return;
}
+
final ServiceReference serviceReference = event.getServiceReference();
- boolean processedServiceChange = false;
+
+ registerUnregisterLiveTrackers(serviceReference, event.getType());
+
for (OSGIServiceRegistration cur : allRegistrationHandlers) {
if (listenForServiceType(serviceReference, event.getType(), cur.getServiceType(), cur)) {
- processedServiceChange = true;
break;
}
}
- if (!processedServiceChange) {
- logger.warn("Did not process ServiceEvent for {} ", serviceReference.getBundle().getSymbolicName());
+ }
+
+ @Override
+ public <S> S getRegisteredOSGIService(final Class<S> serviceType) throws LiveTrackerException {
+ try {
+ ServiceTracker tracker = liveTrackers.get(serviceType.getName());
+ if (tracker == null) {
+ throw new LiveTrackerException("No live tracker for service " + serviceType.getName());
+ }
+ S result = (S) tracker.getService();
+ if (result == null) {
+ throw new LiveTrackerException("Live tracker found a null service for " + serviceType.getName());
+ }
+ return result;
+ } catch (ClassCastException e) {
+ throw new LiveTrackerException("Live tracker got ClassCastException for " + serviceType.getName(), e);
+ }
+ }
+
+
+ private void registerUnregisterLiveTrackers(final ServiceReference serviceReference, final int eventType) {
+ final Object theServiceObject = context.getService(serviceReference);
+ switch (eventType) {
+ case ServiceEvent.REGISTERED:
+ createLiveTrackerForService(theServiceObject);
+ break;
+ case ServiceEvent.UNREGISTERING:
+ removeLiveTrackerForService(theServiceObject);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ private void createLiveTrackerForService(final Object theServiceObject) {
+ final String serviceClassName = theServiceObject.getClass().getName();
+ synchronized (liveTrackers) {
+ if (liveTrackers.get(serviceClassName) == null) {
+ final ServiceTracker tracker = new ServiceTracker(context, serviceClassName, null);
+ liveTrackers.put(serviceClassName, tracker);
+ tracker.open();
+ }
+ }
+ }
+
+ private void removeLiveTrackerForService(final Object theServiceObject) {
+ final String serviceClassName = theServiceObject.getClass().getName();
+ synchronized (liveTrackers) {
+ ServiceTracker tracker = liveTrackers.get(serviceClassName);
+ if (tracker != null) {
+ tracker.close();
+ liveTrackers.remove(serviceClassName);
+ }
}
}
@@ -131,14 +194,15 @@ public class KillbillActivator implements BundleActivator, ServiceListener {
return true;
}
- final T theService = (T) context.getService(serviceReference);
+ final Object theServiceObject = context.getService(serviceReference);
// Is that for us? We look for a subclass here for greater flexibility (e.g. HttpServlet for a Servlet service)
- if (theService == null || !claz.isAssignableFrom(theService.getClass())) {
+ if (theServiceObject == null || !claz.isAssignableFrom(theServiceObject.getClass())) {
return false;
}
+ final T theService = (T) theServiceObject;
final String serviceInfo = (String) serviceReference.getProperty(OSGIPluginProperties.PLUGIN_SERVICE_INFO);
- final OSGIServiceDescriptor desc = new DefaultOSGIServiceDescriptor(serviceReference.getBundle().getSymbolicName(), serviceName, serviceInfo, claz.getName());
+ final OSGIServiceDescriptor desc = new DefaultOSGIServiceDescriptor(serviceReference.getBundle().getSymbolicName(), serviceName, serviceInfo, claz.getName());
switch (eventType) {
case ServiceEvent.REGISTERED:
registration.registerService(desc, theService);
diff --git a/osgi/src/main/java/com/ning/billing/osgi/LiveTracker.java b/osgi/src/main/java/com/ning/billing/osgi/LiveTracker.java
new file mode 100644
index 0000000..110c937
--- /dev/null
+++ b/osgi/src/main/java/com/ning/billing/osgi/LiveTracker.java
@@ -0,0 +1,24 @@
+/*
+ * 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.LiveTrackerException;
+
+public interface LiveTracker {
+
+ public <S> S getRegisteredOSGIService(final Class<S> serviceType) throws LiveTrackerException;
+}
osgi-bundles/libs/killbill/pom.xml 10(+8 -2)
diff --git a/osgi-bundles/libs/killbill/pom.xml b/osgi-bundles/libs/killbill/pom.xml
index 47ef9c0..eb5c542 100644
--- a/osgi-bundles/libs/killbill/pom.xml
+++ b/osgi-bundles/libs/killbill/pom.xml
@@ -28,24 +28,30 @@
<packaging>jar</packaging>
<dependencies>
<dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>1.3.9</version>
+ <scope>compile</scope>
</dependency>
<dependency>
<groupId>com.ning.billing</groupId>
<artifactId>killbill-api</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
+ <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
diff --git a/osgi-bundles/libs/killbill/src/main/java/com/ning/killbill/osgi/libs/killbill/KillbillActivatorBase.java b/osgi-bundles/libs/killbill/src/main/java/com/ning/killbill/osgi/libs/killbill/KillbillActivatorBase.java
index bd2056f..3b2da79 100644
--- a/osgi-bundles/libs/killbill/src/main/java/com/ning/killbill/osgi/libs/killbill/KillbillActivatorBase.java
+++ b/osgi-bundles/libs/killbill/src/main/java/com/ning/killbill/osgi/libs/killbill/KillbillActivatorBase.java
@@ -53,24 +53,39 @@ public abstract class KillbillActivatorBase implements BundleActivator {
public void stop(final BundleContext context) throws Exception {
// Close trackers
- killbillAPI.close();
- dispatcher.close();
- dataSource.close();
- logService.close();
+ if (killbillAPI != null) {
+ killbillAPI.close();
+ killbillAPI = null;
+ }
+ if (dispatcher != null) {
+ dispatcher.close();
+ dispatcher = null;
+ }
+ if (dataSource != null) {
+ dataSource.close();
+ dataSource = null;
+ }
+ if (logService != null) {
+ logService.close();
+ logService = null;
+ }
try {
// Remove Killbill event handler
final OSGIKillbillEventHandler handler = getOSGIKillbillEventHandler();
- if (handler != null) {
+ if (handler != null && dispatcher != null) {
dispatcher.unregisterEventHandler(handler);
+ dispatcher = null;
}
} catch (OSGIServiceNotAvailable ignore) {
// If the system bundle shut down prior to that bundle, we can' unregister our Observer, which is fine.
}
- // Unregistaer all servies from that bundle
- registrar.unregisterAll();
- System.out.println("Good bye world from TestActivator!");
+ // Unregister all servies from that bundle
+ if (registrar != null) {
+ registrar.unregisterAll();
+ registrar = null;
+ }
}
diff --git a/osgi-bundles/tests/beatrix/src/test/java/com/ning/billing/osgi/bundles/test/Foo.java b/osgi-bundles/tests/beatrix/src/test/java/com/ning/billing/osgi/bundles/test/Foo.java
new file mode 100644
index 0000000..300374a
--- /dev/null
+++ b/osgi-bundles/tests/beatrix/src/test/java/com/ning/billing/osgi/bundles/test/Foo.java
@@ -0,0 +1,4 @@
+package com.ning.billing.osgi.bundles.test;
+
+public class Foo {
+}
diff --git a/util/src/main/java/com/ning/billing/util/config/OSGIConfig.java b/util/src/main/java/com/ning/billing/util/config/OSGIConfig.java
index bef6e97..59afa86 100644
--- a/util/src/main/java/com/ning/billing/util/config/OSGIConfig.java
+++ b/util/src/main/java/com/ning/billing/util/config/OSGIConfig.java
@@ -48,6 +48,7 @@ public interface OSGIConfig extends KillbillConfig {
"com.ning.billing.entitlement.api.transfer," +
"com.ning.billing.entitlement.api.user," +
"com.ning.billing.invoice.api," +
+ "com.ning.billing," +
"com.ning.billing.osgi.api," +
"com.ning.billing.osgi.api.config," +
"com.ning.billing.overdue," +