killbill-aplcache
Changes
osgi-bundles/jruby/pom.xml 7(+4 -3)
osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyHttpServlet.java 40(+40 -0)
osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyNotificationPlugin.java 5(+2 -3)
osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java 5(+2 -3)
pom.xml 7(+7 -0)
Details
diff --git a/api/src/main/java/com/ning/billing/osgi/api/http/ServletRouter.java b/api/src/main/java/com/ning/billing/osgi/api/http/ServletRouter.java
index ef4d3bb..7a77de6 100644
--- a/api/src/main/java/com/ning/billing/osgi/api/http/ServletRouter.java
+++ b/api/src/main/java/com/ning/billing/osgi/api/http/ServletRouter.java
@@ -22,5 +22,7 @@ public interface ServletRouter {
void registerServlet(String pluginName, HttpServlet httpServlet);
+ void unregisterServlet(String pluginName);
+
HttpServlet getServletForPlugin(String pluginName);
}
diff --git a/api/src/main/java/com/ning/billing/osgi/api/OSGIKillbill.java b/api/src/main/java/com/ning/billing/osgi/api/OSGIKillbill.java
index 4212b9b..b9a7adc 100644
--- a/api/src/main/java/com/ning/billing/osgi/api/OSGIKillbill.java
+++ b/api/src/main/java/com/ning/billing/osgi/api/OSGIKillbill.java
@@ -16,7 +16,6 @@
package com.ning.billing.osgi.api;
-import javax.servlet.http.HttpServlet;
import javax.sql.DataSource;
import com.ning.billing.account.api.AccountUserApi;
@@ -92,12 +91,4 @@ public interface OSGIKillbill {
* @return the dataSource for the OSGI bundles
*/
public DataSource getDataSource();
-
- /**
- * Register a servlet
- *
- * @param pluginName plugin name
- * @param pluginServlet servlet from the bundle
- */
- public void registerServlet(String pluginName, HttpServlet pluginServlet);
}
diff --git a/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIKillbill.java b/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIKillbill.java
index dbcb4bc..08e2d04 100644
--- a/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIKillbill.java
+++ b/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIKillbill.java
@@ -18,7 +18,6 @@ package com.ning.billing.osgi;
import javax.inject.Inject;
import javax.inject.Named;
-import javax.servlet.http.HttpServlet;
import javax.sql.DataSource;
import com.ning.billing.account.api.AccountUserApi;
@@ -232,9 +231,4 @@ public class DefaultOSGIKillbill implements OSGIKillbill {
public DataSource getDataSource() {
return dataSource;
}
-
- @Override
- public void registerServlet(final String pluginName, final HttpServlet pluginServlet) {
- servletRouter.registerServlet(pluginName, pluginServlet);
- }
}
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 dea87a9..a4795d5 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,8 +16,8 @@
package com.ning.billing.osgi.http;
-import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Singleton;
import javax.servlet.http.HttpServlet;
@@ -27,7 +27,7 @@ import com.ning.billing.osgi.api.http.ServletRouter;
@Singleton
public class DefaultServletRouter implements ServletRouter {
- private final Map<String, HttpServlet> pluginServlets = new HashMap<String, HttpServlet>();
+ private final Map<String, HttpServlet> pluginServlets = new ConcurrentHashMap<String, HttpServlet>();
@Override
public void registerServlet(final String pluginName, final HttpServlet httpServlet) {
@@ -35,6 +35,11 @@ public class DefaultServletRouter implements ServletRouter {
}
@Override
+ public void unregisterServlet(final String pluginName) {
+ pluginServlets.remove(pluginName);
+ }
+
+ @Override
public HttpServlet getServletForPlugin(final String pluginName) {
return pluginServlets.get(pluginName);
}
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 5b83eeb..8025980 100644
--- a/osgi/src/main/java/com/ning/billing/osgi/KillbillActivator.java
+++ b/osgi/src/main/java/com/ning/billing/osgi/KillbillActivator.java
@@ -16,47 +16,96 @@
package com.ning.billing.osgi;
-import java.util.List;
-
import javax.inject.Inject;
+import javax.servlet.http.HttpServlet;
import org.osgi.framework.BundleActivator;
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 com.ning.billing.osgi.api.OSGIKillbill;
-import com.ning.billing.payment.plugin.api.PaymentPluginApi;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.ImmutableList;
+import com.ning.billing.osgi.api.http.ServletRouter;
-public class KillbillActivator implements BundleActivator {
+public class KillbillActivator implements BundleActivator, ServiceListener {
private final OSGIKillbill osgiKillbill;
+ private final ServletRouter servletRouter;
private volatile ServiceRegistration osgiKillbillRegistration;
+
+ private BundleContext context = null;
+
@Inject
- public KillbillActivator(final OSGIKillbill osgiKillbill) {
+ public KillbillActivator(final OSGIKillbill osgiKillbill,
+ final ServletRouter servletRouter) {
this.osgiKillbill = osgiKillbill;
+ this.servletRouter = servletRouter;
}
@Override
public void start(final BundleContext context) throws Exception {
+ this.context = context;
+
+ context.addServiceListener(this);
registerServices(context);
}
+ @Override
+ public void stop(final BundleContext context) throws Exception {
+ this.context = null;
+
+ context.removeServiceListener(this);
+ unregisterServices();
+ }
+
+ @Override
+ public void serviceChanged(final ServiceEvent event) {
+ listenForServlets(event);
+ }
+
+ private void listenForServlets(final ServiceEvent event) {
+ if (event.getType() != ServiceEvent.REGISTERED && event.getType() != ServiceEvent.UNREGISTERING) {
+ // Servlets can only be added or removed, not modified
+ return;
+ }
+ final ServiceReference serviceReference = event.getServiceReference();
+
+ // Make sure we can retrieve the plugin name
+ final String pluginName = (String) serviceReference.getProperty("killbill.pluginName");
+ if (pluginName == null) {
+ return;
+ }
+
+ // Make sure this event is for a servlet
+ HttpServlet httpServlet = null;
+ final String[] objectClass = (String[]) event.getServiceReference().getProperty("objectClass");
+ if (context != null && objectClass != null && objectClass.length > 0 && HttpServlet.class.getName().equals(objectClass[0])) {
+ final Object service = context.getService(serviceReference);
+ httpServlet = (HttpServlet) service;
+ }
+
+ if (httpServlet == null) {
+ return;
+ }
+
+ if (event.getType() == ServiceEvent.REGISTERED) {
+ servletRouter.registerServlet(pluginName, httpServlet);
+ } else if (event.getType() == ServiceEvent.UNREGISTERING) {
+ servletRouter.unregisterServlet(pluginName);
+ }
+ }
+
private void registerServices(final BundleContext context) {
osgiKillbillRegistration = context.registerService(OSGIKillbill.class.getName(), osgiKillbill, null);
}
- @Override
- public void stop(final BundleContext context) throws Exception {
+ private void unregisterServices() {
if (osgiKillbillRegistration != null) {
osgiKillbillRegistration.unregister();
osgiKillbillRegistration = null;
}
}
-
}
osgi-bundles/jruby/pom.xml 7(+4 -3)
diff --git a/osgi-bundles/jruby/pom.xml b/osgi-bundles/jruby/pom.xml
index 18b9486..7166849 100644
--- a/osgi-bundles/jruby/pom.xml
+++ b/osgi-bundles/jruby/pom.xml
@@ -73,9 +73,10 @@
<configuration>
<instructions>
<Bundle-Activator>com.ning.billing.osgi.bundles.jruby.Activator</Bundle-Activator>
- <Import-Package>
- *;resolution:=optional,org.osgi.service.log;resolution:=optional,org.jruby;resolution:=optional;version="[1.7,2)",javax.management,javax.crypto,javax.net.ssl,javax.security.auth.x500;resolution:=optional
- </Import-Package>
+ <Export-Package></Export-Package>
+ <Private-Package>com.ning.billing.osgi.bundles.jruby.*</Private-Package>
+ <!-- Optional resolution because exported by the Felix system bundle -->
+ <Import-Package>*;resolution:=optional,javax.management;javax.management.*;javax.crypto;javax.crypto.*;javax.net;javax.net.*;javax.security;javax.security.*;resolution:=optional</Import-Package>
</instructions>
</configuration>
<executions>
diff --git a/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/Activator.java b/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/Activator.java
index 1d3ac3f..ab65cb6 100644
--- a/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/Activator.java
+++ b/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/Activator.java
@@ -54,9 +54,9 @@ public class Activator implements BundleActivator {
// Setup JRuby
final ScriptingContainer scriptingContainer = setupScriptingContainer(rubyConfig);
if (PluginType.NOTIFICATION.equals(rubyConfig.getPluginType())) {
- plugin = new JRubyNotificationPlugin(rubyConfig, scriptingContainer, osgiKillbill, logger);
+ plugin = new JRubyNotificationPlugin(rubyConfig, scriptingContainer, context, logger);
} else if (PluginType.PAYMENT.equals(rubyConfig.getPluginType())) {
- plugin = new JRubyPaymentPlugin(rubyConfig, scriptingContainer, osgiKillbill, logger);
+ plugin = new JRubyPaymentPlugin(rubyConfig, scriptingContainer, context, logger);
}
// Validate and instantiate the plugin
diff --git a/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyHttpServlet.java b/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyHttpServlet.java
new file mode 100644
index 0000000..7e576cc
--- /dev/null
+++ b/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyHttpServlet.java
@@ -0,0 +1,40 @@
+/*
+ * 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.bundles.jruby;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.jruby.runtime.builtin.IRubyObject;
+
+public class JRubyHttpServlet extends HttpServlet {
+
+ private final HttpServlet delegate;
+
+ public JRubyHttpServlet(final IRubyObject rubyObject) {
+ delegate = (HttpServlet) rubyObject.toJava(HttpServlet.class);
+ }
+
+ @Override
+ protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
+ delegate.service(req, resp);
+ }
+}
diff --git a/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyNotificationPlugin.java b/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyNotificationPlugin.java
index 9ac561a..3887a80 100644
--- a/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyNotificationPlugin.java
+++ b/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyNotificationPlugin.java
@@ -26,7 +26,6 @@ import org.osgi.service.log.LogService;
import com.ning.billing.beatrix.bus.api.ExtBusEvent;
import com.ning.billing.beatrix.bus.api.ExternalBus;
-import com.ning.billing.osgi.api.OSGIKillbill;
import com.ning.billing.osgi.api.config.PluginRubyConfig;
import com.google.common.eventbus.Subscribe;
@@ -34,8 +33,8 @@ import com.google.common.eventbus.Subscribe;
public class JRubyNotificationPlugin extends JRubyPlugin {
public JRubyNotificationPlugin(final PluginRubyConfig config, final ScriptingContainer container,
- final OSGIKillbill osgiKillbill, @Nullable final LogService logger) {
- super(config, container, osgiKillbill, logger);
+ final BundleContext bundleContext, @Nullable final LogService logger) {
+ super(config, container, bundleContext, logger);
}
@Override
diff --git a/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java b/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java
index 1071a79..623d746 100644
--- a/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java
+++ b/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java
@@ -30,7 +30,6 @@ import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.log.LogService;
-import com.ning.billing.osgi.api.OSGIKillbill;
import com.ning.billing.osgi.api.config.PluginRubyConfig;
import com.ning.billing.payment.api.PaymentMethodPlugin;
import com.ning.billing.payment.plugin.api.PaymentInfoPlugin;
@@ -45,8 +44,8 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi
private volatile ServiceRegistration<PaymentPluginApi> paymentInfoPluginRegistration;
public JRubyPaymentPlugin(final PluginRubyConfig config, final ScriptingContainer container,
- final OSGIKillbill osgiKillbill, @Nullable final LogService logger) {
- super(config, container, osgiKillbill, logger);
+ final BundleContext bundleContext, @Nullable final LogService logger) {
+ super(config, container, bundleContext, logger);
}
@Override
diff --git a/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPlugin.java b/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPlugin.java
index 9228928..84f75a9 100644
--- a/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPlugin.java
+++ b/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPlugin.java
@@ -17,6 +17,7 @@
package com.ning.billing.osgi.bundles.jruby;
import java.util.Arrays;
+import java.util.Hashtable;
import java.util.Map;
import javax.annotation.Nullable;
@@ -28,9 +29,9 @@ import org.jruby.embed.EvalFailedException;
import org.jruby.embed.ScriptingContainer;
import org.jruby.runtime.builtin.IRubyObject;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
import org.osgi.service.log.LogService;
-import com.ning.billing.osgi.api.OSGIKillbill;
import com.ning.billing.osgi.api.config.PluginRubyConfig;
// Bridge between the OSGI bundle and the ruby plugin
@@ -46,7 +47,7 @@ public abstract class JRubyPlugin {
private static final String ACTIVE = "@active";
protected final LogService logger;
- protected final OSGIKillbill osgiKillbill;
+ protected final BundleContext bundleContext;
protected final String pluginGemName;
protected final String rubyRequire;
protected final String pluginMainClass;
@@ -55,12 +56,13 @@ public abstract class JRubyPlugin {
protected RubyObject pluginInstance;
+ private ServiceRegistration httpServletServiceRegistration = null;
private String cachedRequireLine = null;
public JRubyPlugin(final PluginRubyConfig config, final ScriptingContainer container,
- final OSGIKillbill osgiKillbill, @Nullable final LogService logger) {
+ final BundleContext bundleContext, @Nullable final LogService logger) {
this.logger = logger;
- this.osgiKillbill = osgiKillbill;
+ this.bundleContext = bundleContext;
this.pluginGemName = config.getPluginName();
this.rubyRequire = config.getRubyRequire();
this.pluginMainClass = config.getRubyMainClass();
@@ -92,26 +94,41 @@ public abstract class JRubyPlugin {
// Start the plugin
pluginInstance = (RubyObject) container.runScriptlet(pluginMainClass + ".new(" + JAVA_APIS + ")");
-
- // Register the rack handler
- final IRubyObject rackHandler = pluginInstance.callMethod("rack_handler");
- if (!rackHandler.isNil()) {
- osgiKillbill.registerServlet(pluginGemName, (HttpServlet) rackHandler.toJava(HttpServlet.class));
- }
}
public void startPlugin(final BundleContext context) {
checkPluginIsStopped();
pluginInstance.callMethod("start_plugin");
checkPluginIsRunning();
+ registerHttpServlet();
}
public void stopPlugin(final BundleContext context) {
checkPluginIsRunning();
+ unregisterHttpServlet();
pluginInstance.callMethod("stop_plugin");
checkPluginIsStopped();
}
+ private void registerHttpServlet() {
+ // Register the rack handler
+ final IRubyObject rackHandler = pluginInstance.callMethod("rack_handler");
+ if (!rackHandler.isNil()) {
+ log(LogService.LOG_INFO, String.format("Using %s as rack handler", rackHandler.getMetaClass()));
+
+ final JRubyHttpServlet jRubyHttpServlet = new JRubyHttpServlet(rackHandler);
+ final Hashtable<String, String> properties = new Hashtable<>();
+ properties.put("killbill.pluginName", pluginGemName);
+ httpServletServiceRegistration = bundleContext.registerService(HttpServlet.class.getName(), jRubyHttpServlet, properties);
+ }
+ }
+
+ private void unregisterHttpServlet() {
+ if (httpServletServiceRegistration != null) {
+ httpServletServiceRegistration.unregister();
+ }
+ }
+
protected void checkPluginIsRunning() {
if (pluginInstance == null || !pluginInstance.getInstanceVariable(ACTIVE).isTrue()) {
throw new IllegalStateException(String.format("Plugin %s didn't start properly", pluginMainClass));
pom.xml 7(+7 -0)
diff --git a/pom.xml b/pom.xml
index d9b4619..dc27391 100644
--- a/pom.xml
+++ b/pom.xml
@@ -92,6 +92,7 @@
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>com.ning.billing</groupId>
@@ -316,6 +317,12 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>1.3.9</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>