package org.simpleflatmapper.osgi; import org.apache.commons.io.IOUtils; import org.apache.felix.framework.Felix; import org.apache.felix.framework.util.FelixConstants; import org.apache.felix.resolver.Activator; import org.osgi.framework.Bundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleException; import org.osgi.framework.wiring.BundleRevision; import org.osgi.framework.wiring.BundleWiring; import java.io.*; import java.net.URL; import java.nio.file.*; import java.util.*; import java.util.jar.*; import java.util.stream.Collectors; import java.util.zip.ZipEntry; public class HostApplication { private HostActivator m_activator = null; private Felix m_felix = null; public HostApplication() throws IOException { // Create a configuration property map. Map<String, Object> config = new HashMap<String, Object>(); // Create host activator; m_activator = new HostActivator(); List<BundleActivator> list = new ArrayList<BundleActivator>(); list.add(m_activator); config.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, list); config.put(FelixConstants.FRAMEWORK_STORAGE, "target/felix"); config.put(FelixConstants.LOG_LEVEL_PROP, "5"); cleanUp("target/felix"); try { // Now create an instance of the framework with // our configuration properties. m_felix = new Felix(config); // Now start Felix instance. m_felix.start(); } catch (Exception ex) { System.err.println("Could not create framework: " + ex); ex.printStackTrace(); } } private void cleanUp(String location) throws IOException { System.out.println("cleanUp = " + location); Path path = FileSystems.getDefault().getPath(location); if(!Files.exists(path)) { return; } List<Path> collect = Files.walk(path).collect(Collectors.toList()); for(int i = collect.size() - 1; i >=0 ; i--) { Files.delete(collect.get(i)); } } public Bundle install(String location) throws BundleException { return m_activator.getContext().installBundle(location); } public Bundle[] getInstalledBundles() { // Use the system bundle activator to gain external // access to the set of installed bundles. return m_activator.getBundles(); } public void shutdownApplication() throws BundleException, InterruptedException { // Shut down the felix framework when stopping the // host application. m_felix.stop(); m_felix.waitForStop(0); } public void deployBundleWithClass(Class<?> aClass) throws BundleException, IOException { URL resource = Thread.currentThread().getContextClassLoader().getResource(aClass.getName().replace('.', '/') + ".class"); if (resource == null) { throw new RuntimeException("Could not find resource for " + aClass); } System.out.println("resource = " + resource); Bundle b; if ("jar".equals(resource.getProtocol())) { String file = resource.getFile(); file = file.substring(0, file.indexOf('!')); System.out.println("jar = " + file); b = install(file); } else { int indexOfTarget = resource.getFile().indexOf("target/classes"); if (indexOfTarget >= 0) { File root = new File(resource.getFile().substring(0, indexOfTarget + "target/classes".length())); System.out.println("dir = " + root); File tmp = File.createTempFile("tmp", "jar"); Manifest man; try (FileInputStream is = new FileInputStream(new File(root, "META-INF/MANIFEST.MF"))) { man = new Manifest(is); } try (FileOutputStream fos = new FileOutputStream(tmp); JarOutputStream jarOutputStream = new JarOutputStream(fos, man)) { Files.walk(Paths.get(root.getPath())).forEach((p) -> { if (Files.isRegularFile(p) && !p.endsWith("MANIFEST.MF")) { ZipEntry zipEntry = new ZipEntry(p.toString().substring(root.getPath().length() + 1)); try { jarOutputStream.putNextEntry(zipEntry); Files.copy(p, jarOutputStream); } catch (IOException e) { e.printStackTrace(); } } }); } b = install("file:" + tmp.getPath()); } else { throw new RuntimeException("Cannot build jar"); } } b.start(); ClassLoader classLoader = b.adapt(BundleWiring.class).getClassLoader(); try { Class<?> aClass1 = classLoader.loadClass(aClass.getName()); System.out.println("aClass1 = " + aClass1); } catch (ClassNotFoundException e) { e.printStackTrace(); } debugBundle(b); } public void deployWrapBundleWithClass(Class<?> aClass) throws BundleException, IOException { URL resource = Thread.currentThread().getContextClassLoader().getResource(aClass.getName().replace('.', '/') + ".class"); if (resource == null) { throw new RuntimeException("Could not find resource for " + aClass); } if ("jar".equals(resource.getProtocol())) { String file = resource.getFile(); file = file.substring(file.indexOf(':') + 1, file.indexOf('!')); File tmpFile = File.createTempFile("wrap", ".jar"); Set<String> packages = new HashSet<String>(); try (FileInputStream fis = new FileInputStream(file); JarInputStream jis = new JarInputStream(fis); ) { JarEntry zentry; while ((zentry = jis.getNextJarEntry()) != null) { String name = zentry.getName(); if (name.endsWith(".class")) { packages.add(name.substring(0, name.lastIndexOf('/'))); } } } try (FileInputStream fis = new FileInputStream(file); JarInputStream jis = new JarInputStream(fis); ) { Manifest man = jis.getManifest(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); man.write(bos); Attributes mainAttributes = man.getMainAttributes(); mainAttributes.put(new Attributes.Name("Bundle-ManifestVersion"), "2"); mainAttributes.put(new Attributes.Name("Bundle-SymbolicName"), file.substring(file.lastIndexOf("/") + 1, file.lastIndexOf('.'))); StringBuilder sb = new StringBuilder(); boolean first = true; for(String p : packages) { if (!first) { sb.append(","); } sb.append(p.replace('/', '.')); first = false; } mainAttributes.put(new Attributes.Name("Export-Package"), sb.toString()); try (FileOutputStream fos = new FileOutputStream(tmpFile); JarOutputStream jos = new JarOutputStream(fos, man) ) { JarEntry zentry; while ((zentry = jis.getNextJarEntry()) != null) { jos.putNextEntry(zentry); IOUtils.copy(jis, jos); } } } Bundle b = install("file:" + tmpFile.getPath()); b.start(); ClassLoader classLoader = b.adapt(BundleWiring.class).getClassLoader(); try { Class<?> aClass1 = classLoader.loadClass(aClass.getName()); System.out.println("aClass1 = " + aClass1); } catch (ClassNotFoundException e) { e.printStackTrace(); } debugBundle(b); } else { throw new RuntimeException("No jar " + resource); } } private void debugBundle(Bundle b) { BundleRevision br = b.adapt(BundleRevision.class); br.getCapabilities(null).forEach(System.out::println); b.adapt(BundleWiring.class).getProvidedWires(null).forEach(System.out::println); ; } public Bundle install(URL url) throws IOException, BundleException { System.out.println("install = " + url); InputStream is = url.openStream(); try { Bundle b = install(url.toString(), is); b.start(); return b; } finally { is.close(); } } public Bundle install(String location, InputStream is) throws BundleException { return m_activator.getContext().installBundle(location, is); } }