summaryrefslogtreecommitdiffstats
path: root/python-integration
diff options
context:
space:
mode:
Diffstat (limited to 'python-integration')
-rw-r--r--python-integration/pom.xml89
-rw-r--r--python-integration/src/main/java/eu/novi/python/integration/JythonObjectFactory.java97
-rw-r--r--python-integration/src/test/java/eu/novi/python/integration/Hello.java11
-rw-r--r--python-integration/src/test/java/eu/novi/python/integration/JythonObjectFactoryTest.java45
-rw-r--r--python-integration/src/test/resources/data/cache/bundle1/version0.0/bundle.jarbin0 -> 383 bytes
5 files changed, 242 insertions, 0 deletions
diff --git a/python-integration/pom.xml b/python-integration/pom.xml
new file mode 100644
index 0000000..a9adb6c
--- /dev/null
+++ b/python-integration/pom.xml
@@ -0,0 +1,89 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>eu.novi</groupId>
+ <artifactId>parent</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ <relativePath>../parent/</relativePath>
+ </parent>
+ <packaging>jar</packaging>
+ <artifactId>python-integration</artifactId>
+ <name>Python Integration Framework</name>
+ <description>Integration code for OSGi components written in Python</description>
+
+ <developers>
+ <developer>
+ <id>szwed</id>
+ <name>Blazej Pietrzak</name>
+ <email>blazej.pietrzak@man.poznan.pl</email>
+ <organization>PSNC</organization>
+ <organizationUrl>http://www.man.poznan.pl/</organizationUrl>
+ <roles>
+ <role>architect</role>
+ <role>developer</role>
+ </roles>
+ <timezone>+1</timezone>
+ </developer>
+ <developer>
+ <id>pikusa</id>
+ <name>Piotr Pikusa</name>
+ <email>pikusa@man.poznan.pl</email>
+ <organization>PSNC</organization>
+ <organizationUrl>http://www.man.poznan.pl/</organizationUrl>
+ <roles>
+ <role>architect</role>
+ <role>developer</role>
+ </roles>
+ <timezone>+1</timezone>
+ </developer>
+ </developers>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.python</groupId>
+ <artifactId>jython-standalone</artifactId>
+ <version>2.5.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>4.2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>novi-job</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.3</version>
+ <executions>
+ <execution>
+ <id>unpack-dependencies</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <includeArtifactIds>jython-standalone</includeArtifactIds>
+ <outputDirectory>${project.build.directory}/classes</outputDirectory>
+ <excludes>META-INF/**</excludes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+</profiles>
+
+</project> \ No newline at end of file
diff --git a/python-integration/src/main/java/eu/novi/python/integration/JythonObjectFactory.java b/python-integration/src/main/java/eu/novi/python/integration/JythonObjectFactory.java
new file mode 100644
index 0000000..5963964
--- /dev/null
+++ b/python-integration/src/main/java/eu/novi/python/integration/JythonObjectFactory.java
@@ -0,0 +1,97 @@
+package eu.novi.python.integration;
+
+import java.io.File;
+import java.util.regex.Matcher;
+
+import org.osgi.framework.BundleContext;
+import org.python.core.PyObject;
+import org.python.util.PythonInterpreter;
+
+/**
+ * Creates Python Class instances.
+ *
+ * @author <a href="mailto:blazej.pietrzak@man.poznan.pl">Blazej Pietrzak</a>, <a href="mailto:pikusa@man.poznan.pl">Piotr Pikusa</a>
+ */
+public class JythonObjectFactory {
+ protected static String rootDirectory = System.getProperty("user.dir");
+
+ /**
+ * Instantiates Python class. Use only in blueprint configuration files.
+ *
+ * @param interfaceType Java interface that is implemented by Python class
+ * @param moduleName name of the module the Python class is in
+ * @return object implementing interfaceType
+ * @throws ClassNotFoundException when cannot instantiate Python class
+ */
+ public static Object createObject(String interfaceType, String moduleName, BundleContext context) throws ClassNotFoundException {
+ return JythonObjectFactory.createObject(Class.forName(interfaceType), moduleName, context);
+ }
+
+ /**
+ * Instantiates Python class.
+ *
+ * @param interfaceType Java interface that is implemented by Python class
+ * @param moduleName name of the module the Python class is in
+ * @param context OSGi bundle context
+ * @return object implementing interfaceType
+ * @throws ClassNotFoundException when cannot instantiate Python class
+ */
+ @SuppressWarnings("unchecked")
+ public static <T>T createObject(Class<T> interfaceType, String moduleName, BundleContext context) throws ClassNotFoundException {
+ final PythonInterpreter interpreter = new PythonInterpreter();
+ //interpreter.getSystemState().setClassLoader(interfaceType.getClass().getClassLoader());
+ importModule(moduleName, interpreter, getJarPath(context));
+ return (T) createObject(moduleName, interpreter).__tojava__(interfaceType);
+ }
+
+ private static String getJarPath(BundleContext context) {
+ if (new File(getKarafJarPath(context)).exists())
+ return getKarafJarPath(context);
+ if (new File(getIntegrationTestingJarPath(context)).exists()) {
+ System.out.println("bundle under test: " + getIntegrationTestingJarPath(context));
+ return getIntegrationTestingJarPath(context);
+ }
+
+ System.out.println("Cannot find bundles to test (in directory " + new File(".").getAbsolutePath() + ")");
+ return null;
+ }
+
+ private static String getIntegrationTestingJarPath(BundleContext context) {
+ return Matcher.quoteReplacement("felix" + File.separator
+ + "cache" + File.separator + "runner" + File.separator
+ + "bundle" + context.getBundle().getBundleId()
+ + File.separator + "version0.0" + File.separator + "bundle.jar");
+ }
+
+ private static String getKarafJarPath(BundleContext context) {
+ return Matcher.quoteReplacement(rootDirectory
+ + File.separator + "data" + File.separator + "cache"
+ + File.separator + "bundle" + context.getBundle().getBundleId()
+ + File.separator + "version0.0" + File.separator + "bundle.jar");
+ }
+
+ private static void importModule(String moduleName, final PythonInterpreter interpreter, String jarPath) {
+ interpreter.exec("import sys");
+ interpreter.exec("sys.path.append(\"" + jarPath + "/Lib\")");
+ interpreter.exec("from " + moduleName + " import " + getClassName(moduleName));
+ }
+
+ private static String getClassName(String moduleName) {
+ final String name;
+ if (moduleName.indexOf(".") == -1)
+ name = moduleName;
+ else
+ name = moduleName.substring(moduleName.lastIndexOf(".") + 1);
+ return name;
+ }
+
+ private static PyObject createObject(String moduleName,
+ final PythonInterpreter interpreter) {
+ return getClass(moduleName, interpreter).__call__();
+ }
+
+ private static PyObject getClass(String moduleName,
+ final PythonInterpreter interpreter) {
+ return interpreter.get(getClassName(moduleName));
+ }
+}
diff --git a/python-integration/src/test/java/eu/novi/python/integration/Hello.java b/python-integration/src/test/java/eu/novi/python/integration/Hello.java
new file mode 100644
index 0000000..60c941b
--- /dev/null
+++ b/python-integration/src/test/java/eu/novi/python/integration/Hello.java
@@ -0,0 +1,11 @@
+package eu.novi.python.integration;
+
+/**
+ * Interface implemented by then Python class HelloImpl.
+ *
+ * @author <a href="mailto:blazej.pietrzak@man.poznan.pl">Blazej Pietrzak</a>
+ */
+public interface Hello {
+
+ String sayHello();
+}
diff --git a/python-integration/src/test/java/eu/novi/python/integration/JythonObjectFactoryTest.java b/python-integration/src/test/java/eu/novi/python/integration/JythonObjectFactoryTest.java
new file mode 100644
index 0000000..d3f5888
--- /dev/null
+++ b/python-integration/src/test/java/eu/novi/python/integration/JythonObjectFactoryTest.java
@@ -0,0 +1,45 @@
+package eu.novi.python.integration;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+
+/**
+ * @author <a href="mailto:blazej.pietrzak@man.poznan.pl">Blazej Pietrzak</a>
+ */
+public class JythonObjectFactoryTest {
+ static {
+ //setting fake bundle repository directory location
+ JythonObjectFactory.rootDirectory
+ = "src" + File.separator + "test" + File.separator + "resources";
+ }
+
+ protected BundleContext context;
+
+ @Before
+ public void givenBundleContext() {
+ final Bundle bundle = Mockito.mock(Bundle.class);
+ Mockito.when(bundle.getBundleId()).thenReturn(1L);
+ context = Mockito.mock(BundleContext.class);
+ Mockito.when(context.getBundle()).thenReturn(bundle);
+ }
+
+ @After
+ public void destroy() {
+ context = null;
+ }
+
+ @Test
+ public void whenCreatingPythonObject() throws ClassNotFoundException {
+ final Hello hello = JythonObjectFactory.createObject(Hello.class, "HelloImpl", context);
+ assertEquals("Hello", hello.sayHello());
+ }
+}
diff --git a/python-integration/src/test/resources/data/cache/bundle1/version0.0/bundle.jar b/python-integration/src/test/resources/data/cache/bundle1/version0.0/bundle.jar
new file mode 100644
index 0000000..10bed4a
--- /dev/null
+++ b/python-integration/src/test/resources/data/cache/bundle1/version0.0/bundle.jar
Binary files differ