Setting up the environement:
- Build Jigsaw
- Build the Maven plugin for Jigsaw
- Download and extract Maven 3(.0.5) in ~/dev
- Export the variables:
export M2_HOME=~/dev/apache-maven-3.0.5/
export MAVEN_HOME=~/dev/apache-maven-3.0.5/
export JAVA_HOME=~/dev/jigsaw/build/linux-x86_64-normal-server-release/images/jdk-module-image
export PATH=$JAVA_HOME/bin:$M2_HOME/bin:$PATH
Create the launcher
- Create the directoriesmkdir -p ~/dev/felix/felix-launcher/src/main/java/lh.jigsaw.felix.launcher/lh/jigsaw/felix/launchermkdir ~/dev/felix/bundlesmkdir ~/dev/felix/nonbundlesmkdir ~/dev/felix/modules
- Create the modules libraryjmod create -L ~/dev/felix/modules
- Download Felix
wget -O ~/dev/felix/nonbundles/org.apache.felix.framework-4.2.1.jar http://mirror.tcpdiag.net/apache//felix/org.apache.felix.framework-4.2.1.jar
(although Felix framework is a bundle it is used as a non bundle) - Add the pom
gedit ~/dev/felix/felix-launcher/pom.xml &<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/maven-v4_0_0.xsd">
change the libraryDirectory to your appropriate path
<modelVersion>4.0.0</modelVersion>
<groupId>lh.jigsaw</groupId>
<artifactId>jigsaw-felix-launcher</artifactId>
<version>0.1-SNAPSHOT</version>
<name>Jigsaw Felix launcher</name>
<packaging>jmod</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
</plugin>
<plugin>
<groupId>lh.jigsaw</groupId>
<artifactId>jigsaw-maven-plugin</artifactId>
<version>0.1-SNAPSHOT</version>
<extensions>true</extensions>
<configuration>
<libraryDirectory>/home/ludovic/dev/felix/modules</libraryDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project> - Add the module-info
gedit ~/dev/felix/felix-launcher/src/main/java/lh.jigsaw.felix.launcher/module-info.java &module lh.jigsaw.felix.launcher @ 0.1
(depends on jdk.jre to expose the JRE)
{
requires jdk.jre;
class lh.jigsaw.felix.launcher.Main;
} - Add the Main class
gedit ~/dev/felix/felix-launcher/src/main/java/lh.jigsaw.felix.launcher/lh/jigsaw/felix/launcher/Main.java &package lh.jigsaw.felix.launcher;
import java.io.File;
import java.io.IOException;
import java.lang.module.ModuleId;
import java.lang.module.ModuleInfo;
import java.lang.module.ModuleView;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import org.openjdk.jigsaw.SimpleLibrary;
/**
*
* @author ludovic
*/
public class Main
{
public static void main(final String[] args)
{
try
{
// Extract information from Jigsaw
//
final String libraryPath = System.getProperty("sun.java.launcher.module.library");
final SimpleLibrary library = SimpleLibrary.open(new File(libraryPath));
final StringBuilder packages = new StringBuilder();
final List<URL> urls = new ArrayList<>(); // 'classpath' for launching Felix
for (ModuleId id: library.listModuleIds())
{
if (isJreModule(id.name()))
{
urls.add(library.classPath(id).toURI().toURL());
final ModuleInfo info = library.readModuleInfo(id);
appendExportedPackages(info, packages);
}
}
packages.deleteCharAt(packages.length()-1);
final File userDir = new File(System.getProperty("user.dir"));
// Additional "classpath" (Felix's jar is added there)
//
addNonOsgiJars(userDir, urls);
// Initialise and start OSGi
//
startOsgi(userDir, urls, packages.toString());
}
catch (IOException | ClassNotFoundException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | IllegalAccessException ex)
{
throw new RuntimeException("error initialising", ex);
}
System.out.println("started.");
}
private static boolean isJreModule(final String moduleName)
{
return moduleName.startsWith("java") || moduleName.startsWith("javax");
}
private static void appendExportedPackages(final ModuleInfo info, final StringBuilder packages)
{
final ModuleView view = info.defaultView();
for (String exportedPackage: view.exports())
{
if (!isJavaPackage(exportedPackage))
{
packages.append(exportedPackage).append(';');
}
}
}
private static boolean isJavaPackage(final String packageName)
{
// java.* are always available to bundles
return packageName.startsWith("java.");
}
private static void addNonOsgiJars(final File userDir, final List<URL> urls) throws MalformedURLException
{
final File bundlesDir = new File(userDir, "nonbundles");
for (File file : bundlesDir.listFiles())
{
urls.add(file.toURI().toURL());
}
}
// As Jigsaw currently identificate itself as Java 1.8, and as Felix already has Java 1.8 package,
// override the full system packages, including Felix's own
private static final String FELIX_SYSTEM_PACKAGES =
"org.osgi.framework; version=1.7.0," +
" org.osgi.framework.hooks.bundle; version=1.1.0," +
" org.osgi.framework.hooks.resolver; version=1.0.0," +
" org.osgi.framework.hooks.service; version=1.1.0," +
" org.osgi.framework.hooks.weaving; version=1.0.0," +
" org.osgi.framework.launch; version=1.1.0," +
" org.osgi.framework.namespace; version=1.0.0," +
" org.osgi.framework.startlevel; version=1.0.0," +
" org.osgi.framework.wiring; version=1.1.0," +
" org.osgi.resource; version=1.0.0," +
" org.osgi.service.packageadmin; version=1.2.0," +
" org.osgi.service.startlevel; version=1.1.0," +
" org.osgi.service.url; version=1.0.0," +
" org.osgi.util.tracker; version=1.5.1 ";
private static Map<String, Object> getFrameworkProperties(final String packages)
{
final Map config = new HashMap<>();
config.put("org.osgi.framework.system.packages", FELIX_SYSTEM_PACKAGES + "," + packages);
// config.put("org.osgi.framework.system.packages.extra", packages);
return config;
}
// we use reflection to not depend on OSGi core (and to not make a module of it)
private static final Class<?>[] NO_ARG_SIG = null;
private static final Object[] NO_ARG_INV = null;
private static void startOsgi(final File userDir, final List<URL> urls, final String packages) throws ClassNotFoundException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, IllegalAccessException
{
final URLClassLoader cl = getClassLoaderFor(urls);
final Class<?> bundleClass = cl.loadClass("org.osgi.framework.Bundle");
final Class<?> bundleContextClass = cl.loadClass("org.osgi.framework.BundleContext");
final Class<?> frameworkFactoryClass = cl.loadClass("org.osgi.framework.launch.FrameworkFactory");
final Map<String, Object> properties = getFrameworkProperties(packages);
final Object framework = getFrameworkFor(frameworkFactoryClass, cl, properties);
final Class<?> frameworkClass = framework.getClass();
initialiseFramework(frameworkClass, framework);
final Object bundleContext = getBundleContextFor(frameworkClass, framework);
final List<Object> installedBundles = new ArrayList<>();
installBundles(installedBundles, userDir, bundleContextClass, bundleContext);
startBundles(installedBundles, bundleClass);
startFramework(frameworkClass, framework);
}
private static URLClassLoader getClassLoaderFor(final List<URL> urls)
{
final URL[] urlsArray = urls.toArray(new URL[urls.size()]);
return new URLClassLoader(urlsArray);
}
private static Object getFrameworkFor(final Class<?> frameworkFactoryClass, final URLClassLoader cl, final Map<String, Object> properties) throws IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, IllegalAccessException
{
final ServiceLoader<?> sl = ServiceLoader.load(frameworkFactoryClass, cl);
final Object factory = sl.iterator().next();
final Method newFramework = factory.getClass().getMethod("newFramework", Map.class);
return newFramework.invoke(factory, properties);
}
private static Object getBundleContextFor(final Class<?> frameworkClass, final Object framework) throws NoSuchMethodException, IllegalAccessException, SecurityException, IllegalArgumentException, InvocationTargetException
{
final Method getBundleContext = frameworkClass.getDeclaredMethod("getBundleContext", NO_ARG_SIG);
final Object bundleContext = getBundleContext.invoke(framework, NO_ARG_INV);
return bundleContext;
}
private static void initialiseFramework(final Class<?> frameworkClass, final Object framework) throws InvocationTargetException, SecurityException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException
{
final Method init = frameworkClass.getDeclaredMethod("init", NO_ARG_SIG);
init.invoke(framework, NO_ARG_INV);
}
private static void installBundles(final List<Object> installedBundles, final File userDir, final Class<?> bundleContextClass, final Object bundleContext) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
final Method installBundle = bundleContextClass.getDeclaredMethod("installBundle", String.class);
final File bundlesDir = new File(userDir, "bundles");
for (File file : bundlesDir.listFiles())
{
final String name = file.toURI().toString();
final Object bundle = installBundle.invoke(bundleContext, name);
installedBundles.add(bundle);
}
}
private static void startBundles(final List<Object> installedBundles, final Class<?> bundleClass) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
final Method start = bundleClass.getDeclaredMethod("start", NO_ARG_SIG);
for (Object bundle: installedBundles)
{
start.invoke(bundle, NO_ARG_INV);
}
}
private static void startFramework(final Class<?> frameworkClass, final Object framework) throws IllegalAccessException, SecurityException, NoSuchMethodException, InvocationTargetException, IllegalArgumentException
{
final Method start = frameworkClass.getDeclaredMethod("start", NO_ARG_SIG);
start.invoke(framework, NO_ARG_INV);
}
} - Make
cd ~/dev/felix/felix-launcher/
mvn install
- Create the directoriesmkdir -p ~/dev/felix/simplebundle/src/main/java/lh/jigsaw/test/simplebundle
- Add the pom
gedit ~/dev/felix/simplebundle/pom.xml &<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>
<groupId>lh.jigsaw.test</groupId>
<artifactId>simplebundle</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>simplebundle OSGi Bundle</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Activator>lh.jigsaw.test.simplebundle.Activator</Bundle-Activator>
<Export-Package/>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project> - Add the bundle activator
gedit ~/dev/felix/simplebundle/src/main/java/lh/jigsaw/test/simplebundle/Activator.java &package lh.jigsaw.test.simplebundle;
import javax.swing.JOptionPane;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator
{
public void start(BundleContext context) throws Exception
{
System.out.println("Hello Jigsaw/Felix!");
JOptionPane.showMessageDialog(null, "Hello Jigsaw/Felix!");
}
public void stop(BundleContext context) throws Exception
{
}
} - Make
(as the bundle is compiled with a compiler that does not know about Jigsaw, we must use the standard Java 7)export JAVA_HOME='/usr/lib/jvm/java-7-openjdk-amd64'
cd ~/dev/felix/simplebundle/
mvn install
- Copy to the bundle directory
cp ~/dev/felix/simplebundle/target/simplebundle-1.0-SNAPSHOT.jar ~/dev/felix/bundles
cd ~/dev/felix/
java -L ~/dev/felix/modules -m lh.jigsaw.felix.launcher
No comments:
Post a Comment