package org.xpect.util; import java.io.File; import java.net.URISyntaxException; import java.net.URL; import java.util.Collection; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.plugin.EcorePlugin; import org.xpect.util.ResourceAccess.ResourceInfo; import com.google.common.base.Joiner; import com.google.common.base.Predicate; import com.google.common.collect.Maps; public interface IBundleInfo { public class BundleInfo implements IBundleInfo { private ResourceInfo info; private final URI location; private final String symbolicName; public BundleInfo(String symbolicName, URI locationURI) { super(); this.symbolicName = symbolicName; this.location = locationURI; } private ResourceInfo getInfo() { if (info == null) info = ResourceAccess.create(location); return info; } public List<URI> find(Context context) { return getInfo().find(context); } public URI find(Context context, String fileName) { return getInfo().find(context, fileName); } public List<URI> find(Context context, String path, Predicate<String> matcher, String... fileExtensions) { return getInfo().find(context, path, matcher, fileExtensions); } public URI getRootURI() { return getInfo().getLocation(); } public String getSymbolicName() { return symbolicName; } @Override public String toString() { return symbolicName + ": " + getInfo(); } } public enum Context { CLASSPATH, ROOT, SOURCE } public class Delegate implements Registry { private IBundleInfo.Registry delegate; public Collection<String> getAllBundleNames() { return delegate.getAllBundleNames(); } public IBundleInfo getBundle(Class<?> clazz) { return delegate.getBundle(clazz); } public IBundleInfo getBundle(String symbolicName) { return delegate.getBundle(symbolicName); } public IBundleInfo.Registry getDelegate() { return delegate; } public void setDelegate(IBundleInfo.Registry delegate) { this.delegate = delegate; } public IBundleInfo getBundle(URI uri) { return delegate.getBundle(uri); } } public interface Registry { public final Registry INSTANCE = EcorePlugin.IS_ECLIPSE_RUNNING ? new Delegate() : new StandaloneBundleRegistry(); Collection<String> getAllBundleNames(); IBundleInfo getBundle(Class<?> clazz); IBundleInfo getBundle(URI uri); IBundleInfo getBundle(String symbolicName); } public class StandaloneBundleRegistry implements IBundleInfo.Registry { public static final Logger LOG = Logger.getLogger(StandaloneBundleRegistry.class); public static void main(String[] args) { System.out.println(new StandaloneBundleRegistry()); } private final Map<URI, IBundleInfo> locationToBundle; private final Map<String, IBundleInfo> symbolicNameToBundle; public StandaloneBundleRegistry() { symbolicNameToBundle = Maps.newLinkedHashMap(); locationToBundle = Maps.newLinkedHashMap(); for (URL url : ClasspathUtil.findResources("META-INF/MANIFEST.MF")) { String name; try { name = ClasspathUtil.getSymbolicName(url.openStream()); if (name != null) { URI location = URI.createURI(url.toString()).trimSegments(2).appendSegment(""); BundleInfo info = createBundleInfo(name, location); symbolicNameToBundle.put(name, info); locationToBundle.put(location, info); } } catch (Throwable e) { LOG.error("can't open " + url, e); } } } private BundleInfo createBundleInfo(String name, URI location) { return new BundleInfo(name, location); } public Collection<String> getAllBundleNames() { return symbolicNameToBundle.keySet(); } public IBundleInfo getBundle(Class<?> clazz) { URI bundleURI = getBundleURI(clazz); IBundleInfo info = locationToBundle.get(bundleURI); if (info != null) return info; info = createBundleInfo(null, bundleURI); locationToBundle.put(bundleURI, info); return info; } public IBundleInfo getBundle(String symbolicName) { return symbolicNameToBundle.get(symbolicName); } private URI getBundleURI(Class<?> clazz) { String[] segments = clazz.getName().split("\\."); String fileName = Joiner.on('/').join(segments) + ".class"; URL resource = clazz.getClassLoader().getResource(fileName); if ("jar".equals(resource.getProtocol())) { URI location = URI.createURI(resource.toString()).trimSegments(segments.length).appendSegment(""); return location; } else { File classFile; try { classFile = new File(resource.toURI()); File packageRootFolder = classFile; for (int i = 0; i < segments.length; i++) { packageRootFolder = packageRootFolder.getParentFile(); if (packageRootFolder == null) throw new RuntimeException("Could not determine package root for " + clazz); } File current = packageRootFolder; while (current != null) { if (new File(current, ".project").isFile()) return URI.createFileURI(current.toString()).appendSegment(""); current = current.getParentFile(); } throw new RuntimeException("Could not find .project file in super-folder of " + packageRootFolder); } catch (URISyntaxException e) { throw new RuntimeException(e); } } } @Override public String toString() { return Joiner.on("\n").join(symbolicNameToBundle.values()); } public IBundleInfo getBundle(URI uri) { return createBundleInfo(null, uri); } } List<URI> find(Context context); URI find(Context context, String fileName); List<URI> find(Context context, String path, Predicate<String> matcher, String... fileExtensions); URI getRootURI(); String getSymbolicName(); }