/**************************************************************************** * Copyright 2008-2011 ThoughtWorks, Inc. * * Licensed 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. * * Initial Contributors: * Håkan Råberg * Manish Chakravarty * Pavan K S ***************************************************************************/ package com.thoughtworks.krypton.osgi; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.net.URLDecoder; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class EmbeddedEquinoxLauncher { private Class<?> eclipseStarterClass; private Class<?> bundleContextClass; private Class<?> serviceReferenceClass; private Object bundleContext; private HashMap<String, String> configuration; public EmbeddedEquinoxLauncher(URL... optionalClasspath) throws Exception { URL eclipseUrl = getClass().getClassLoader().getResource("eclipse"); if ("jar".equals(eclipseUrl.getProtocol())) { eclipseUrl = extractEclipseFromJar(eclipseUrl); } List<URL> classpath = new ArrayList<URL>(); classpath.addAll(Arrays.asList(optionalClasspath)); classpath.add(findFrameworkJar(eclipseUrl)); ClassLoader frameworkLoader = new URLClassLoader(classpath.toArray(new URL[0]), getClass().getClassLoader()); eclipseStarterClass = frameworkLoader.loadClass("org.eclipse.core.runtime.adaptor.EclipseStarter"); bundleContextClass = frameworkLoader.loadClass("org.osgi.framework.BundleContext"); serviceReferenceClass = frameworkLoader.loadClass("org.osgi.framework.ServiceReference"); configuration = configureInstallArea(eclipseUrl); } public void addProperty(String key, String value) { configuration.put(key, value); } public void startup(String... args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { eclipseStarterClass.getMethod("setInitialProperties", Map.class).invoke(null, configuration); bundleContext = eclipseStarterClass.getMethod("startup", String[].class, Runnable.class).invoke(null, args, null); } public void shutdown() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { eclipseStarterClass.getMethod("shutdown").invoke(null); } @SuppressWarnings("unchecked") public <T> T create(Class<T> service) throws Exception { Object serviceReference = bundleContextClass.getMethod("getServiceReference", String.class) .invoke(bundleContext, service.getName()); System.out.println("Resolving ServiceReference " + serviceReference); Object serviceImplementation = bundleContextClass.getMethod("getService", serviceReferenceClass).invoke(bundleContext, serviceReference); System.out.println("Returning " + serviceImplementation); System.out.println(); return (T) serviceImplementation; } private HashMap<String, String> configureInstallArea(URL eclipseUrl) { HashMap<String, String> configuration = new HashMap<String, String>(); configuration.put("osgi.install.area", eclipseUrl.toExternalForm()); return configuration; } private URL findFrameworkJar(URL eclipseUrl) throws URISyntaxException, MalformedURLException { URL osgiUrl = null; for (File file : new File(new File(eclipseUrl.toURI()), "plugins").listFiles()) { if (file.getName().startsWith("org.eclipse.osgi_")) { osgiUrl = file.toURL(); break; } } return osgiUrl; } private URL extractEclipseFromJar(URL eclipseUrl) throws IOException, UnsupportedEncodingException, FileNotFoundException, MalformedURLException { String[] jarAndPath = eclipseUrl.toExternalForm().split("!/"); System.out.println("Jar containing plugins directory: " + jarAndPath[0]); System.out.println("Jar plugins directory path: " + jarAndPath[1]); File jarFile = new File(URLDecoder.decode(jarAndPath[0].substring("jar:file:".length()), "UTF-8")); File driverRoot = new File(System.getProperty("java.io.tmpdir"), jarFile.getName()); File eclipseDir = new File(driverRoot, "eclipse"); if (driverRoot.isDirectory()) { System.out.println("Already extracted to " + driverRoot); return eclipseDir.toURL(); } driverRoot.mkdirs(); long currentTimeMillis = System.currentTimeMillis(); extractJar(jarFile, driverRoot); System.out.println("Extraction time: " + (System.currentTimeMillis() - currentTimeMillis)); return eclipseDir.toURL(); } private void extractJar(File jarFile, File driverRoot) throws IOException, FileNotFoundException { JarFile jar = new JarFile(jarFile); for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements();) { JarEntry nextElement = entries.nextElement(); if (nextElement.getName().startsWith("eclipse/")) { File file = new File(driverRoot, nextElement.getName()); if (nextElement.isDirectory()) { file.mkdirs(); } else { extractAndClose(jar.getInputStream(nextElement), new FileOutputStream(file), nextElement.getSize()); } } } } private void extractAndClose(InputStream in, FileOutputStream out, long size) throws IOException, FileNotFoundException { FileChannel outChannel = null; ReadableByteChannel inChannel = null; try { inChannel = Channels.newChannel(in); outChannel = out.getChannel(); outChannel.transferFrom(inChannel, 0, size); } finally { if (outChannel != null) { outChannel.close(); } if (inChannel != null) { inChannel.close(); } } } }