killbill-memoizeit

Integration with Jruby payment plugin. Added and debugged

3/24/2013 6:48:18 PM

Details

beatrix/pom.xml 9(+9 -0)

diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index bd0cd00..58a2506 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -101,6 +101,14 @@
             <artifactId>jdbi</artifactId>
         </dependency>
         <!-- TEST SCOPE -->
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-compress</artifactId>
+            <version>1.5</version>
+            <scope>test</scope>
+        </dependency>
+
         <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>javax.servlet-api</artifactId>
@@ -195,6 +203,7 @@
                             <tasks>
                                 <copy file="${basedir}/../osgi-bundles/tests/beatrix/target/killbill-osgi-bundles-test-beatrix-${project.version}-jar-with-dependencies.jar" tofile="${basedir}/src/test/resources/killbill-osgi-bundles-test-beatrix-${project.version}-jar-with-dependencies.jar" />
                                 <copy file="${basedir}/../osgi-bundles/tests/payment/target/killbill-osgi-bundles-test-payment-${project.version}-jar-with-dependencies.jar" tofile="${basedir}/src/test/resources/killbill-osgi-bundles-test-payment-${project.version}-jar-with-dependencies.jar" />
+                                <copy file="${basedir}/../osgi-bundles/bundles/jruby/target/killbill-osgi-bundles-jruby-${project.version}-jar-with-dependencies.jar" tofile="${basedir}/src/test/resources/killbill-osgi-bundles-jruby-${project.version}-jar-with-dependencies.jar" />
                             </tasks>
                         </configuration>
                         <goals>
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 1630a41..f89fe31 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
@@ -81,7 +81,7 @@ public class TestBasicOSGIWithTestBundle extends TestOSGIBase {
         // This is extracted from surefire system configuration-- needs to be added explicitly in IntelliJ for correct running
         final String killbillVersion = System.getProperty("killbill.version");
         SetupBundleWithAssertion setupTest = new SetupBundleWithAssertion(BUNDLE_TEST_RESOURCE, osgiConfig, killbillVersion);
-        setupTest.setupBundle();
+        setupTest.setupJavaBundle();
 
     }
 
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestJrubyPaymentPlugin.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestJrubyPaymentPlugin.java
new file mode 100644
index 0000000..081a2ec
--- /dev/null
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestJrubyPaymentPlugin.java
@@ -0,0 +1,191 @@
+/*
+ * 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.beatrix.integration.osgi;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.ning.billing.beatrix.osgi.SetupBundleWithAssertion;
+import com.ning.billing.osgi.api.OSGIServiceRegistration;
+import com.ning.billing.payment.api.PaymentMethodPlugin;
+import com.ning.billing.payment.plugin.api.PaymentInfoPlugin;
+import com.ning.billing.payment.plugin.api.PaymentInfoPlugin.PaymentPluginStatus;
+import com.ning.billing.payment.plugin.api.PaymentMethodInfoPlugin;
+import com.ning.billing.payment.plugin.api.PaymentPluginApi;
+import com.ning.billing.payment.plugin.api.RefundInfoPlugin;
+import com.ning.billing.payment.plugin.api.RefundInfoPlugin.RefundPluginStatus;
+
+public class TestJrubyPaymentPlugin extends TestOSGIBase {
+
+    private final String BUNDLE_TEST_RESOURCE_PREFIX = "killbill-payment-test";
+    private final String BUNDLE_TEST_RESOURCE = BUNDLE_TEST_RESOURCE_PREFIX + ".tar.gz";
+
+    @Inject
+    private OSGIServiceRegistration<PaymentPluginApi> paymentPluginApiOSGIServiceRegistration;
+
+    @BeforeClass(groups = "slow", enabled = true)
+    public void beforeClass() throws Exception {
+
+
+        // OSGIDataSourceConfig
+        super.beforeClass();
+
+        // This is extracted from surefire system configuration-- needs to be added explicitly in IntelliJ for correct running
+        final String killbillVersion = System.getProperty("killbill.version");
+
+        SetupBundleWithAssertion setupTest = new SetupBundleWithAssertion(BUNDLE_TEST_RESOURCE, osgiConfig, killbillVersion);
+        //setupTest.setupJrubyBundle();
+
+    }
+
+    @Test(groups = "slow", enabled = true)
+    public void testProcessPayment() throws Exception {
+
+        PaymentPluginApi api = getTestPluginPaymentApi();
+
+        final DateTime beforeCall = new DateTime().toDateTime(DateTimeZone.UTC).minusSeconds(1);
+        PaymentInfoPlugin res = api.processPayment(UUID.randomUUID(), UUID.randomUUID(), BigDecimal.TEN, callContext);
+        final DateTime afterCall = new DateTime().toDateTime(DateTimeZone.UTC).plusSeconds(1);
+
+
+        Assert.assertTrue(res.getAmount().compareTo(BigDecimal.TEN) == 0);
+        Assert.assertTrue(res.getCreatedDate().compareTo(beforeCall) >= 0);
+        Assert.assertTrue(res.getCreatedDate().compareTo(afterCall) <= 0);
+
+        Assert.assertTrue(res.getEffectiveDate().compareTo(beforeCall) >= 0);
+        Assert.assertTrue(res.getEffectiveDate().compareTo(afterCall) <= 0);
+
+        Assert.assertEquals(res.getGatewayError(), "gateway_error");
+        Assert.assertEquals(res.getGatewayErrorCode(), "gateway_error_code");
+
+        Assert.assertEquals(res.getStatus(), PaymentPluginStatus.PROCESSED);
+    }
+
+    @Test(groups = "slow", enabled = true)
+    public void testGetPaymentInfo() throws Exception {
+
+        PaymentPluginApi api = getTestPluginPaymentApi();
+
+        final DateTime beforeCall = new DateTime().toDateTime(DateTimeZone.UTC).minusSeconds(1);
+        PaymentInfoPlugin res = api.getPaymentInfo(UUID.randomUUID(), callContext);
+        final DateTime afterCall = new DateTime().toDateTime(DateTimeZone.UTC).plusSeconds(1);
+
+
+        Assert.assertTrue(res.getAmount().compareTo(BigDecimal.ZERO) == 0);
+        Assert.assertTrue(res.getCreatedDate().compareTo(beforeCall) >= 0);
+        Assert.assertTrue(res.getCreatedDate().compareTo(afterCall) <= 0);
+
+        Assert.assertTrue(res.getEffectiveDate().compareTo(beforeCall) >= 0);
+        Assert.assertTrue(res.getEffectiveDate().compareTo(afterCall) <= 0);
+
+        Assert.assertEquals(res.getGatewayError(), "gateway_error");
+        Assert.assertEquals(res.getGatewayErrorCode(), "gateway_error_code");
+
+        Assert.assertEquals(res.getStatus(), PaymentPluginStatus.PROCESSED);
+    }
+
+
+    @Test(groups = "slow", enabled = true)
+    public void testProcessRefund() throws Exception {
+
+        PaymentPluginApi api = getTestPluginPaymentApi();
+
+        final DateTime beforeCall = new DateTime().toDateTime(DateTimeZone.UTC).minusSeconds(1);
+        RefundInfoPlugin res = api.processRefund(UUID.randomUUID(), BigDecimal.TEN, callContext);
+        final DateTime afterCall = new DateTime().toDateTime(DateTimeZone.UTC).plusSeconds(1);
+
+
+        Assert.assertTrue(res.getAmount().compareTo(BigDecimal.TEN) == 0);
+        Assert.assertTrue(res.getCreatedDate().compareTo(beforeCall) >= 0);
+        Assert.assertTrue(res.getCreatedDate().compareTo(afterCall) <= 0);
+
+        Assert.assertTrue(res.getEffectiveDate().compareTo(beforeCall) >= 0);
+        Assert.assertTrue(res.getEffectiveDate().compareTo(afterCall) <= 0);
+
+        Assert.assertEquals(res.getGatewayError(), "gateway_error");
+        Assert.assertEquals(res.getGatewayErrorCode(), "gateway_error_code");
+
+        Assert.assertEquals(res.getStatus(), RefundPluginStatus.PROCESSED);
+    }
+
+    @Test(groups = "slow", enabled = true)
+    public void testAddPaymentMethod() throws Exception {
+
+        PaymentPluginApi api = getTestPluginPaymentApi();
+
+        final DateTime beforeCall = new DateTime().toDateTime(DateTimeZone.UTC).minusSeconds(1);
+        final PaymentMethodPlugin info = createPaymentMethodPlugin();
+        api.addPaymentMethod(UUID.randomUUID(), UUID.randomUUID(), info, true, callContext);
+        final DateTime afterCall = new DateTime().toDateTime(DateTimeZone.UTC).plusSeconds(1);
+    }
+
+
+    @Test(groups = "slow", enabled = true)
+    public void testDeletePaymentMethod() throws Exception {
+
+        PaymentPluginApi api = getTestPluginPaymentApi();
+        api.deletePaymentMethod(UUID.randomUUID(), callContext);
+    }
+
+    @Test(groups = "slow", enabled = true)
+    public void testGetPaymentMethodDetail() throws Exception {
+
+        PaymentPluginApi api = getTestPluginPaymentApi();
+        final PaymentMethodPlugin res = api.getPaymentMethodDetail(UUID.randomUUID(), UUID.randomUUID(), callContext);
+
+        Assert.assertEquals(res.getExternalPaymentMethodId(), "foo");
+        Assert.assertTrue(res.isDefaultPaymentMethod());
+        Assert.assertEquals(res.getProperties().size(), 0);
+    }
+
+    @Test(groups = "slow", enabled = true)
+    public void testSetDefaultPaymentMethod() throws Exception {
+
+        PaymentPluginApi api = getTestPluginPaymentApi();
+        final PaymentMethodPlugin info = createPaymentMethodPlugin();
+        api.setDefaultPaymentMethod(UUID.randomUUID(), callContext);
+    }
+
+    @Test(groups = "slow", enabled = true)
+    public void testGetPaymentMethods() throws Exception {
+
+        PaymentPluginApi api = getTestPluginPaymentApi();
+        final List<PaymentMethodInfoPlugin> res = api.getPaymentMethods(UUID.randomUUID(), true, callContext);
+
+        Assert.assertEquals(res.size(), 1);
+
+        final PaymentMethodInfoPlugin res0 = res.get(0);
+        Assert.assertTrue(res0.isDefault());
+        Assert.assertEquals(res0.getExternalPaymentMethodId(), "external_payment_method_id");
+    }
+
+
+    private PaymentPluginApi getTestPluginPaymentApi() {
+        PaymentPluginApi result = paymentPluginApiOSGIServiceRegistration.getServiceForName(BUNDLE_TEST_RESOURCE_PREFIX);
+        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 bbe1df6..5a8d2a2 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
@@ -64,7 +64,7 @@ public class TestPaymentOSGIWithTestPaymentBundle extends TestOSGIBase {
         // This is extracted from surefire system configuration-- needs to be added explicitly in IntelliJ for correct running
         final String killbillVersion = System.getProperty("killbill.version");
         SetupBundleWithAssertion setupTest = new SetupBundleWithAssertion(BUNDLE_TEST_RESOURCE, osgiConfig, killbillVersion);
-        setupTest.setupBundle();
+        setupTest.setupJavaBundle();
 
     }
 
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
index d1c30e4..2afcfd3 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
@@ -17,6 +17,7 @@
 package com.ning.billing.beatrix.integration;
 
 import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 import java.util.UUID;
@@ -318,7 +319,15 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
         final Account account = accountUserApi.createAccount(accountData, callContext);
         assertNotNull(account);
 
-        final PaymentMethodPlugin info = new PaymentMethodPlugin() {
+        final PaymentMethodPlugin info = createPaymentMethodPlugin();
+
+        paymentApi.addPaymentMethod(paymentPluginName, account, true, info, callContext);
+        return accountUserApi.getAccountById(account.getId(), callContext);
+    }
+
+
+    protected PaymentMethodPlugin createPaymentMethodPlugin() {
+        return new PaymentMethodPlugin() {
             @Override
             public boolean isDefaultPaymentMethod() {
                 return false;
@@ -331,7 +340,10 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
 
             @Override
             public List<PaymentMethodKVInfo> getProperties() {
-                return null;
+                PaymentMethodKVInfo prop = new PaymentMethodKVInfo("whatever", "cool", Boolean.TRUE);
+                List<PaymentMethodKVInfo> res = new ArrayList<PaymentMethodKVInfo>();
+                res.add(prop);
+                return res;
             }
 
             @Override
@@ -339,9 +351,6 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
                 return UUID.randomUUID().toString();
             }
         };
-
-        paymentApi.addPaymentMethod(paymentPluginName, account, true, info, callContext);
-        return accountUserApi.getAccountById(account.getId(), callContext);
     }
 
     protected AccountData getAccountData(final int billingDay) {
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/osgi/SetupBundleWithAssertion.java b/beatrix/src/test/java/com/ning/billing/beatrix/osgi/SetupBundleWithAssertion.java
index 1b65c63..86d94be 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/osgi/SetupBundleWithAssertion.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/osgi/SetupBundleWithAssertion.java
@@ -20,43 +20,85 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.PrintStream;
 import java.net.URL;
-import java.nio.channels.FileChannel;
+import java.util.zip.GZIPInputStream;
 
+import org.apache.commons.compress.archivers.ArchiveException;
+import org.apache.commons.compress.archivers.ArchiveStreamFactory;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
 import org.testng.Assert;
 
+import com.ning.billing.osgi.api.config.PluginConfig.PluginLanguage;
 import com.ning.billing.osgi.api.config.PluginConfig.PluginType;
 import com.ning.billing.osgi.api.config.PluginJavaConfig;
 import com.ning.billing.util.config.OSGIConfig;
 
+import com.google.common.io.ByteStreams;
 import com.google.common.io.Resources;
 
 public class SetupBundleWithAssertion {
 
+    private final String JRUBY_BUNDLE_RESOURCE = "killbill-osgi-bundles-jruby";
+
     private final String bundleName;
     private final OSGIConfig config;
     private final String killbillVersion;
 
+    private final File rootInstallDir;
+
     public SetupBundleWithAssertion(final String bundleName, final OSGIConfig config, final String killbillVersion) {
         this.bundleName = bundleName;
         this.config = config;
         this.killbillVersion = killbillVersion;
+        this.rootInstallDir = new File(config.getRootInstallationDir());
     }
 
-    public void setupBundle() {
+
+    public void setupJrubyBundle() {
+
+        try {
+
+            installJrubyJar();
+
+            final URL resourceUrl = Resources.getResource(bundleName);
+            final File unzippedRubyPlugin = unGzip(new File(resourceUrl.getFile()), rootInstallDir);
+
+
+            final StringBuilder tmp = new StringBuilder(rootInstallDir.getAbsolutePath());
+            tmp.append("/plugins/")
+               .append(PluginLanguage.RUBY.toString().toLowerCase());
+
+            final File destination = new File(tmp.toString());
+            if (!destination.exists()) {
+                destination.mkdir();
+            }
+
+            unTar(unzippedRubyPlugin, destination);
+
+        } catch (IOException e) {
+            Assert.fail(e.getMessage());
+        } catch (ArchiveException e) {
+            Assert.fail(e.getMessage());
+        }
+    }
+
+    public void setupJavaBundle() {
 
         try {
             // Retrieve PluginConfig info from classpath
             // test bundle should have been exported under Beatrix resource by the maven maven-dependency-plugin
-            final PluginJavaConfig pluginConfig = extractBundleTestResource();
+            final PluginJavaConfig pluginConfig = extractJavaBundleTestResource();
             Assert.assertNotNull(pluginConfig);
 
             // Create OSGI install bundle directory
             setupDirectoryStructure(pluginConfig);
 
             // Copy the jar
-            copyFile(new File(pluginConfig.getBundleJarPath()), new File(pluginConfig.getPluginVersionRoot().getAbsolutePath(), pluginConfig.getPluginVersionnedName() + ".jar"));
+            ByteStreams.copy(new FileInputStream(new File(pluginConfig.getBundleJarPath())), new FileOutputStream(new File(pluginConfig.getPluginVersionRoot().getAbsolutePath(), pluginConfig.getPluginVersionnedName() + ".jar")));
 
             // Create the osgiConfig file
             createConfigFile(pluginConfig);
@@ -67,9 +109,8 @@ public class SetupBundleWithAssertion {
     }
 
     public void cleanBundleInstallDir() {
-        final File rootDir  = new File(config.getRootInstallationDir());
-        if (rootDir.exists()) {
-            deleteDirectory(rootDir, false);
+        if (rootInstallDir.exists()) {
+            deleteDirectory(rootInstallDir, false);
         }
     }
 
@@ -108,7 +149,6 @@ public class SetupBundleWithAssertion {
                     f.delete();
                 }
             }
-
             if (deleteParent) {
                 path.delete();
             }
@@ -116,9 +156,23 @@ public class SetupBundleWithAssertion {
     }
 
 
+    private void installJrubyJar() throws IOException {
+
+        final String resourceName = JRUBY_BUNDLE_RESOURCE + "-" + killbillVersion + "-jar-with-dependencies.jar";
+        final URL resourceUrl = Resources.getResource(resourceName);
+        final File rubyJarInput = new File(resourceUrl.getFile());
+
+        final File platform = new File(rootInstallDir, "platform");
+        if (!platform.exists()) {
+            platform.mkdir();
+        }
+
+        final File rubyJarDestination = new File(platform, "jruby.jar");
+        ByteStreams.copy(new FileInputStream(rubyJarInput), new FileOutputStream(rubyJarDestination));
+    }
 
-    private PluginJavaConfig extractBundleTestResource() {
 
+    private PluginJavaConfig extractJavaBundleTestResource() {
 
         final String resourceName = bundleName + "-" + killbillVersion + "-jar-with-dependencies.jar";
         final URL resourceUrl = Resources.getResource(resourceName);
@@ -126,14 +180,14 @@ public class SetupBundleWithAssertion {
             final String[] parts = resourceUrl.getPath().split("/");
             final String lastPart = parts[parts.length - 1];
             if (lastPart.startsWith(bundleName)) {
-                return createPluginConfig(resourceUrl.getPath(), lastPart);
+                return createPluginJavaConfig(resourceUrl.getPath());
             }
         }
         return null;
 
     }
 
-    private PluginJavaConfig createPluginConfig(final String bundleTestResourcePath, final String fileName) {
+    private PluginJavaConfig createPluginJavaConfig(final String bundleTestResourcePath) {
 
         return new PluginJavaConfig() {
             @Override
@@ -163,7 +217,7 @@ public class SetupBundleWithAssertion {
 
             @Override
             public File getPluginVersionRoot() {
-                final StringBuilder tmp = new StringBuilder(config.getRootInstallationDir());
+                final StringBuilder tmp = new StringBuilder(rootInstallDir.getAbsolutePath());
                 tmp.append("/plugins/")
                    .append(PluginLanguage.JAVA.toString().toLowerCase())
                    .append("/")
@@ -181,24 +235,62 @@ public class SetupBundleWithAssertion {
         };
     }
 
-    public static void copyFile(File sourceFile, File destFile) throws IOException {
-        if (!destFile.exists()) {
-            destFile.createNewFile();
+
+    private static void unTar(final File inputFile, final File outputDir) throws IOException, ArchiveException {
+
+        InputStream is = null;
+        TarArchiveInputStream archiveInputStream = null;
+        TarArchiveEntry entry = null;
+
+        try {
+            is = new FileInputStream(inputFile);
+            archiveInputStream = (TarArchiveInputStream) new ArchiveStreamFactory().createArchiveInputStream("tar", is);
+            while ((entry = (TarArchiveEntry) archiveInputStream.getNextEntry()) != null) {
+                final File outputFile = new File(outputDir, entry.getName());
+                if (entry.isDirectory()) {
+                    if (!outputFile.exists()) {
+                        if (!outputFile.mkdirs()) {
+                            throw new IllegalStateException(String.format("Couldn't create directory %s.", outputFile.getAbsolutePath()));
+                        }
+                    }
+                } else {
+                    final OutputStream outputFileStream = new FileOutputStream(outputFile);
+                    ByteStreams.copy(archiveInputStream, outputFileStream);
+                    outputFileStream.close();
+                }
+            }
+        } finally {
+            if (archiveInputStream != null) {
+                archiveInputStream.close();
+            }
+            if (is != null) {
+                is.close();
+            }
         }
+    }
 
-        FileChannel source = null;
-        FileChannel destination = null;
+    private static File unGzip(final File inputFile, final File outputDir) throws IOException {
+
+        GZIPInputStream in = null;
+        FileOutputStream out = null;
 
         try {
-            source = new FileInputStream(sourceFile).getChannel();
-            destination = new FileOutputStream(destFile).getChannel();
-            destination.transferFrom(source, 0, source.size());
+            final File outputFile = new File(outputDir, inputFile.getName().substring(0, inputFile.getName().length() - 3));
+
+            in = new GZIPInputStream(new FileInputStream(inputFile));
+            out = new FileOutputStream(outputFile);
+
+            for (int c = in.read(); c != -1; c = in.read()) {
+                out.write(c);
+            }
+            return outputFile;
+
         } finally {
-            if (source != null) {
-                source.close();
+            if (in != null) {
+                in.close();
             }
-            if (destination != null) {
-                destination.close();
+            if (out != null) {
+                out.close();
             }
         }
     }
diff --git a/beatrix/src/test/resources/killbill-payment-test.tar.gz b/beatrix/src/test/resources/killbill-payment-test.tar.gz
new file mode 100644
index 0000000..2ab733d
Binary files /dev/null and b/beatrix/src/test/resources/killbill-payment-test.tar.gz differ
diff --git a/beatrix/src/test/resources/resource.properties b/beatrix/src/test/resources/resource.properties
index 5002a5d..8ec7211 100644
--- a/beatrix/src/test/resources/resource.properties
+++ b/beatrix/src/test/resources/resource.properties
@@ -8,5 +8,7 @@ killbill.billing.util.persistent.bus.sleep=100
 killbill.billing.util.persistent.bus.nbThreads=1
 user.timezone=UTC
 killbill.payment.retry.days=8,8,8,8,8,8,8,8
+killbill.osgi.bundle.install.dir=/var/tmp/beatrix-bundles
+
 
 
diff --git a/osgi-bundles/bundles/jruby/pom.xml b/osgi-bundles/bundles/jruby/pom.xml
index 8ab2c71..925213d 100644
--- a/osgi-bundles/bundles/jruby/pom.xml
+++ b/osgi-bundles/bundles/jruby/pom.xml
@@ -83,7 +83,7 @@
                         <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,com.ning.billing.osgi.api,javax.management;javax.management.*;javax.crypto;javax.crypto.*;javax.net;javax.net.*;javax.net.ssl;javax.net.ssl.*;javax.security;javax.security.*;javax.security.cert;javax.security.cert.*;javax.security.auth;javax.security.auth.*;javax.security.auth.x500;javax.security.auth.x500.*;resolution:=optional</Import-Package>
+                        <Import-Package>*;resolution:=optional,org.joda.time;org.joda.time.format;resolution:=optional,com.ning.billing.osgi.api,javax.management;javax.management.*;javax.crypto;javax.crypto.*;javax.net;javax.net.*;javax.net.ssl;javax.net.ssl.*;javax.security;javax.security.*;javax.security.cert;javax.security.cert.*;javax.security.auth;javax.security.auth.*;javax.security.auth.x500;javax.security.auth.x500.*;resolution:=optional</Import-Package>
                     </instructions>
                 </configuration>
                 <executions>
diff --git a/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java b/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java
index 007847b..d63f273 100644
--- a/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java
+++ b/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java
@@ -30,6 +30,7 @@ import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.log.LogService;
 
+import com.ning.billing.osgi.api.OSGIPluginProperties;
 import com.ning.billing.osgi.api.config.PluginRubyConfig;
 import com.ning.billing.payment.api.PaymentMethodPlugin;
 import com.ning.billing.payment.plugin.api.PaymentInfoPlugin;
@@ -56,6 +57,7 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi 
 
         final Dictionary<String, Object> props = new Hashtable<String, Object>();
         props.put("name", pluginMainClass);
+        props.put(OSGIPluginProperties.PLUGIN_NAME_PROP, pluginGemName);
         paymentInfoPluginRegistration = (ServiceRegistration<PaymentPluginApi>) context.registerService(PaymentPluginApi.class.getName(), this, props);
     }
 
@@ -76,12 +78,8 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi 
 
         return callWithRuntimeAndChecking(new PluginCallback() {
             @Override
-            public PaymentInfoPlugin doCall(final Ruby runtime) {
-                final IRubyObject res = pluginInstance.callMethod("charge",
-                                                                  JavaEmbedUtils.javaToRuby(runtime, kbPaymentId.toString()),
-                                                                  JavaEmbedUtils.javaToRuby(runtime, kbPaymentMethodId.toString()),
-                                                                  JavaEmbedUtils.javaToRuby(runtime, amount.longValue() * 100));
-                return null;
+            public PaymentInfoPlugin doCall(final Ruby runtime) throws PaymentPluginApiException {
+                return ((PaymentPluginApi) pluginInstance).processPayment(kbPaymentId, kbPaymentMethodId, amount, context);
             }
         });
     }
@@ -89,11 +87,10 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi 
     @Override
     public PaymentInfoPlugin getPaymentInfo(final UUID kbPaymentId, final TenantContext context) throws PaymentPluginApiException {
 
-        return callWithRuntimeAndChecking(new PluginCallback() {
+        return callWithRuntimeAndChecking(new PluginCallback()  {
             @Override
-            public PaymentInfoPlugin doCall(final Ruby runtime) {
-                final IRubyObject res = pluginInstance.callMethod("get_payment_info", JavaEmbedUtils.javaToRuby(getRuntime(), kbPaymentId.toString()));
-                return null;
+            public PaymentInfoPlugin doCall(final Ruby runtime) throws PaymentPluginApiException {
+                return ((PaymentPluginApi) pluginInstance).getPaymentInfo(kbPaymentId, context);
             }
         });
     }
@@ -101,14 +98,10 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi 
     @Override
     public RefundInfoPlugin processRefund(final UUID kbPaymentId, final BigDecimal refundAmount, final CallContext context) throws PaymentPluginApiException {
 
-        return callWithRuntimeAndChecking(new PluginCallback() {
+        return callWithRuntimeAndChecking(new PluginCallback()  {
             @Override
-            public RefundInfoPlugin doCall(final Ruby runtime) {
-                final IRubyObject res = pluginInstance.callMethod("refund",
-                                                                  JavaEmbedUtils.javaToRuby(runtime, kbPaymentId.toString()),
-                                                                  JavaEmbedUtils.javaToRuby(runtime, refundAmount.longValue() * 100));
-
-                return null;
+            public RefundInfoPlugin doCall(final Ruby runtime) throws PaymentPluginApiException {
+                return ((PaymentPluginApi) pluginInstance).processRefund(kbPaymentId, refundAmount, context);
             }
         });
 
@@ -119,12 +112,8 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi 
 
         callWithRuntimeAndChecking(new PluginCallback() {
             @Override
-            public Void doCall(final Ruby runtime) {
-                final IRubyObject res = pluginInstance.callMethod("add_payment_method",
-                                                                  JavaEmbedUtils.javaToRuby(runtime, kbAccountId.toString()),
-                                                                  JavaEmbedUtils.javaToRuby(runtime, kbPaymentMethodId.toString()),
-                                                                  JavaEmbedUtils.javaToRuby(runtime, paymentMethodProps));
-
+            public Void doCall(final Ruby runtime) throws PaymentPluginApiException  {
+                ((PaymentPluginApi) pluginInstance).addPaymentMethod(kbAccountId, kbPaymentMethodId, paymentMethodProps, Boolean.valueOf(setDefault), context);
                 return null;
             }
         });
@@ -135,10 +124,8 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi 
 
         callWithRuntimeAndChecking(new PluginCallback() {
             @Override
-            public Void doCall(final Ruby runtime) {
-                final IRubyObject res = pluginInstance.callMethod("delete_payment_method",
-                                                                  JavaEmbedUtils.javaToRuby(runtime, kbPaymentMethodId.toString()));
-
+            public Void doCall(final Ruby runtime) throws PaymentPluginApiException  {
+                ((PaymentPluginApi) pluginInstance).deletePaymentMethod(kbPaymentMethodId, context);
                 return null;
             }
         });
@@ -147,14 +134,10 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi 
     @Override
     public PaymentMethodPlugin getPaymentMethodDetail(final UUID kbAccountId, final UUID kbPaymentMethodId, final TenantContext context) throws PaymentPluginApiException {
 
-        return callWithRuntimeAndChecking(new PluginCallback() {
+        return callWithRuntimeAndChecking(new PluginCallback()  {
             @Override
-            public PaymentMethodPlugin doCall(final Ruby runtime) {
-                final IRubyObject res =  pluginInstance.callMethod("get_payment_method_detail",
-                                                                   JavaEmbedUtils.javaToRuby(runtime, kbAccountId.toString()),
-                                                                   JavaEmbedUtils.javaToRuby(runtime, kbPaymentMethodId.toString()));
-
-                return null;
+            public PaymentMethodPlugin doCall(final Ruby runtime) throws PaymentPluginApiException {
+                return ((PaymentPluginApi) pluginInstance).getPaymentMethodDetail(kbAccountId, kbPaymentMethodId, context);
             }
         });
     }
@@ -162,12 +145,10 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi 
     @Override
     public void setDefaultPaymentMethod(final UUID kbPaymentMethodId, final CallContext context) throws PaymentPluginApiException {
 
-        callWithRuntimeAndChecking(new PluginCallback() {
+        callWithRuntimeAndChecking(new PluginCallback()  {
             @Override
-            public Void doCall(final Ruby runtime) {
-                final IRubyObject res = pluginInstance.callMethod("set_default_payment_method",
-                                                                  JavaEmbedUtils.javaToRuby(runtime, kbPaymentMethodId.toString()));
-
+            public Void doCall(final Ruby runtime) throws PaymentPluginApiException {
+                ((PaymentPluginApi) pluginInstance).setDefaultPaymentMethod(kbPaymentMethodId, context);
                 return null;
             }
         });
@@ -175,14 +156,10 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi 
 
     @Override
     public List<PaymentMethodInfoPlugin> getPaymentMethods(final UUID kbAccountId, final boolean refreshFromGateway, final CallContext context) throws PaymentPluginApiException {
-
         return callWithRuntimeAndChecking(new PluginCallback() {
             @Override
-            public List<PaymentMethodInfoPlugin> doCall(final Ruby runtime) {
-                final IRubyObject res = pluginInstance.callMethod("get_payment_methods",
-                                                                  JavaEmbedUtils.javaToRuby(runtime, kbAccountId.toString()));
-
-                return null;
+            public List<PaymentMethodInfoPlugin> doCall(final Ruby runtime) throws PaymentPluginApiException {
+                return ((PaymentPluginApi) pluginInstance).getPaymentMethods(kbAccountId, Boolean.valueOf(refreshFromGateway), context);
             }
         });
     }
@@ -192,9 +169,8 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi 
 
         callWithRuntimeAndChecking(new PluginCallback() {
             @Override
-            public Void doCall(final Ruby runtime) {
-                final IRubyObject res = pluginInstance.callMethod("reset_payment_methods",
-                                                                  JavaEmbedUtils.javaToRuby(runtime, paymentMethods));
+            public Void doCall(final Ruby runtime) throws PaymentPluginApiException  {
+                ((PaymentPluginApi) pluginInstance).resetPaymentMethods(paymentMethods);
                 return null;
             }
         });
@@ -202,14 +178,14 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi 
 
     private abstract class PluginCallback {
 
-        public abstract <T> T doCall(final Ruby runtime);
+        public abstract <T> T doCall(final Ruby runtime) throws PaymentPluginApiException;
 
         public boolean checkValidPaymentPlugin() {
             return true;
         }
     }
 
-    private <T> T callWithRuntimeAndChecking(PluginCallback cb) {
+    private <T> T callWithRuntimeAndChecking(PluginCallback cb) throws PaymentPluginApiException {
         try {
             checkPluginIsRunning();
 
diff --git a/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPlugin.java b/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPlugin.java
index 13eda28..e6b8f5d 100644
--- a/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPlugin.java
+++ b/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPlugin.java
@@ -93,7 +93,7 @@ public abstract class JRubyPlugin {
         // Don't put any code here!
 
         // Start the plugin
-        pluginInstance = (RubyObject) container.runScriptlet("Killbill::Plugin::JPlugin.new(" + KILLBILL_PLUGIN_CLASS_NAME + "," + KILLBILL_SERVICES + ")");
+        pluginInstance = (RubyObject) container.runScriptlet("Killbill::Plugin::JPayment.new(" + KILLBILL_PLUGIN_CLASS_NAME + "," + KILLBILL_SERVICES + ")");
     }
 
     public void startPlugin(final BundleContext context) {