diff options
author | pikusa <pikusa@man.poznan.pl> | 2013-04-03 13:18:17 (GMT) |
---|---|---|
committer | pikusa <pikusa@man.poznan.pl> | 2013-04-03 13:18:17 (GMT) |
commit | 2f2a3a129c91de540e66c3bfbe30b0df1942cd4b (patch) | |
tree | 2d313cdf0068af368d4de6067d676be16f6a6464 /python-integration | |
parent | ff8aa232b071a9b54dff833714a870fd0aec0b30 (diff) | |
download | novi-public-2f2a3a129c91de540e66c3bfbe30b0df1942cd4b.zip novi-public-2f2a3a129c91de540e66c3bfbe30b0df1942cd4b.tar.gz novi-public-2f2a3a129c91de540e66c3bfbe30b0df1942cd4b.tar.bz2 |
project commit and dir tree change
Diffstat (limited to 'python-integration')
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 Binary files differnew file mode 100644 index 0000000..10bed4a --- /dev/null +++ b/python-integration/src/test/resources/data/cache/bundle1/version0.0/bundle.jar |