package aQute.launcher.minifw; import java.io.File; import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; import java.security.cert.X509Certificate; import java.util.Collection; import java.util.Collections; import java.util.Dictionary; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeSet; import java.util.Vector; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.Manifest; import java.util.zip.ZipEntry; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.BundleListener; import org.osgi.framework.BundleReference; import org.osgi.framework.Filter; import org.osgi.framework.FrameworkListener; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.framework.Version; public class Context extends URLClassLoader implements Bundle, BundleContext, BundleReference { long id; MiniFramework fw; String location; int state = Bundle.INSTALLED; JarFile jar; Manifest manifest; private TreeSet<String> paths; private File jarFile; class Dict extends Dictionary<String,String> { @Override public Enumeration<String> elements() { @SuppressWarnings({ "unchecked", "rawtypes" }) Enumeration<String> enumeration = (Enumeration) Collections .enumeration(manifest.getMainAttributes().values()); return enumeration; } @Override public String get(Object key) { String o = manifest.getMainAttributes().getValue((String) key); return o; } @Override public boolean isEmpty() { return manifest.getMainAttributes().isEmpty(); } @Override public Enumeration<String> keys() { Vector<String> v = new Vector<String>(); for (Iterator<Object> i = manifest.getMainAttributes().keySet().iterator(); i.hasNext();) { Attributes.Name name = (Attributes.Name) i.next(); v.add(name.toString()); } return v.elements(); } @Override public String put(String key, String value) { throw new UnsupportedOperationException(); } @Override public String remove(Object key) { throw new UnsupportedOperationException(); } @Override public int size() { return manifest.getMainAttributes().size(); } } public Context(MiniFramework fw, ClassLoader parent, int id, String location) throws Exception { super(new URL[] { new File(location).toURI().toURL() }, parent); this.fw = fw; this.id = id; this.location = location; jar = new JarFile(jarFile = new File(location)); // Enumeration<JarEntry> entries = jar.entries(); // while ( entries.hasMoreElements()) // System.err.println(entries.nextElement().getName()); manifest = jar.getManifest(); jar.close(); } @Override public BundleContext getBundleContext() { return this; } @Override public long getBundleId() { return id; } @Override public URL getEntry(String path) { if (path.startsWith("/")) path = path.substring(1); return getResource(path); } @Override public Enumeration<String> getEntryPaths(String path) { throw new UnsupportedOperationException(); } @Override public Dictionary<String,String> getHeaders() { return new Dict(); } @Override public Dictionary<String,String> getHeaders(String locale) { return new Dict(); } @Override public long getLastModified() { return jarFile.lastModified(); } @Override public String getLocation() { return location; } @Override public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse) { try { if (path.startsWith("/")) path = path.substring(1); if (!path.endsWith("/")) path += "/"; Vector<URL> paths = new Vector<URL>(); for (Iterator<String> i = getPaths().iterator(); i.hasNext();) { String entry = i.next(); if (entry.startsWith(path)) { if (recurse || entry.indexOf('/', path.length()) < 0) { if (filePattern == null || matches(entry, filePattern)) { URL url = getResource(entry); if (url == null) { System.err.println("Cannot load resource that should be there: " + entry); } else paths.add(url); } } } } return paths.elements(); } catch (Exception e) { throw new RuntimeException(e); } } public static boolean matches(String path, String filePattern) { do { int part = filePattern.indexOf('*'); if (part < 0) { return path.indexOf(filePattern) >= 0; } String match = filePattern.substring(0, part); int m = path.indexOf(match); if (m < 0) return false; path = path.substring(m + match.length()); filePattern = filePattern.substring(part + 1); } while (true); } private Collection<String> getPaths() throws Exception { if (paths != null) return paths; paths = new TreeSet<String>(); try (JarFile jar = new JarFile(new File(location))) { for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements();) { ZipEntry entry = e.nextElement(); paths.add(entry.getName()); } } return paths; } @Override public ServiceReference[] getRegisteredServices() { return null; } @Override public ServiceReference[] getServicesInUse() { return null; } @Override public Map<X509Certificate,List<X509Certificate>> getSignerCertificates(int signersType) { throw new UnsupportedOperationException(); } @Override public int getState() { return state; } @Override public String getSymbolicName() { return getHeaders().get(aQute.bnd.osgi.Constants.BUNDLE_SYMBOLICNAME).trim(); } @Override public Version getVersion() { String v = getHeaders().get(aQute.bnd.osgi.Constants.BUNDLE_VERSION).trim(); if (v == null) return new Version("0"); return new Version(v); } @Override public boolean hasPermission(Object permission) { return true; } @Override public void start() throws BundleException { state = Bundle.ACTIVE; } @Override public void start(int options) throws BundleException { state = Bundle.ACTIVE; } @Override public void stop() throws BundleException { state = Bundle.RESOLVED; } @Override public void stop(int options) throws BundleException { state = Bundle.RESOLVED; } @Override public void uninstall() throws BundleException { state = Bundle.UNINSTALLED; } @Override public void update() throws BundleException { throw new UnsupportedOperationException(); } @Override public void update(InputStream in) throws BundleException { throw new UnsupportedOperationException(); } @Override public void addBundleListener(BundleListener listener) { throw new UnsupportedOperationException(); } @Override public void addFrameworkListener(FrameworkListener listener) { throw new UnsupportedOperationException(); } @Override public void addServiceListener(ServiceListener listener) { throw new UnsupportedOperationException(); } @Override public void addServiceListener(ServiceListener listener, String filter) { throw new UnsupportedOperationException(); } @Override public Filter createFilter(String filter) throws InvalidSyntaxException { throw new UnsupportedOperationException(); } @Override public ServiceReference[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException { throw new UnsupportedOperationException(); } @Override public Bundle getBundle() { return this; } @Override public Bundle getBundle(long id) { return fw.getBundle(id); } @Override public Bundle[] getBundles() { return fw.getBundles(); } @Override public File getDataFile(String filename) { return null; } @Override public String getProperty(String key) { return fw.getProperty(key); } @Override public ServiceReference getServiceReference(String clazz) { return null; } @Override public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException { return null; } @Override public Bundle installBundle(String location) throws BundleException { return fw.installBundle(location); } @Override public Bundle installBundle(String location, InputStream input) throws BundleException { return fw.installBundle(location, input); } @Override public void removeBundleListener(BundleListener listener) { throw new UnsupportedOperationException(); } @Override public void removeFrameworkListener(FrameworkListener listener) { throw new UnsupportedOperationException(); } @Override public void removeServiceListener(ServiceListener listener) { throw new UnsupportedOperationException(); } @Override public String toString() { return id + " " + location; } public int compareTo(Bundle var0) { return 0; } @Override public ServiceRegistration registerService(String[] clazzes, Object service, Dictionary properties) { return null; } @Override public ServiceRegistration registerService(String clazz, Object service, Dictionary properties) { return null; } public ServiceRegistration registerService(Class< ? > clazz, Object service, Dictionary<String, ? > properties) { return null; } public <S> ServiceReference getServiceReference(Class<S> clazz) { return null; } public <S> Collection<ServiceReference> getServiceReferences(Class<S> clazz, String filter) throws InvalidSyntaxException { return null; } @Override public Object getService(ServiceReference reference) { return null; } @Override public boolean ungetService(ServiceReference reference) { return false; } public Bundle getBundle(String location) { return null; } public <A> A adapt(Class<A> type) { return null; } }