/******************************************************************************* * Copyright (c) 2012 Bundlemaker project team. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bundlemaker project team - initial API and implementation ******************************************************************************/ package org.bundlemaker.core.internal.common.classpath; import java.io.File; import java.net.URL; import java.util.Arrays; import java.util.Hashtable; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.bundlemaker.core.common.Activator; import org.bundlemaker.core.common.Constants; import org.bundlemaker.core.internal.modelext.ModelExtFactory; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.ClasspathContainerInitializer; import org.eclipse.jdt.core.IAccessRule; import org.eclipse.jdt.core.IClasspathContainer; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.osgi.service.datalocation.Location; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.util.tracker.ServiceTracker; /** * @author Nils Hartmann (nils@nilshartmann.net) * */ public class BundleMakerClasspathContainerInitializer extends ClasspathContainerInitializer { /** * Name of the bundles that define the Classpath Container (as plain JARs) */ private final static String[] BUNDLEMAKER_LIBRARY_BUNDLES = new String[] { "org.bundlemaker.core", // "org.bundlemaker.com.tinkerpop.blueprints.blueprints-core", // "org.bundlemaker.core.transformations", // "org.bundlemaker.core.ui", // "org.eclipse.core.resources", // "org.eclipse.core.runtime", "org.eclipse.equinox.common"// }; private static IClasspathEntry[] _classpathEntries; /** * Eclipse install location used to convert relative plug-in paths to absolute ones */ private static IPath _eclipseInstallLocation; public BundleMakerClasspathContainerInitializer() { // required no-arg constructor } /* * (non-Javadoc) * * @see org.eclipse.jdt.core.ClasspathContainerInitializer#initialize(org.eclipse.core.runtime.IPath, * org.eclipse.jdt.core.IJavaProject) */ @Override public void initialize(IPath containerPath, IJavaProject javaProject) throws CoreException { JavaCore.setClasspathContainer(Constants.BUNDLEMAKER_CONTAINER_PATH, new IJavaProject[] { javaProject }, new IClasspathContainer[] { new BundleMakerClasspathContainer() }, null); } /** * @return */ static IClasspathEntry[] getClasspathEntries() { if (_classpathEntries == null) { _classpathEntries = determineBundleMakerLibraryClasspathEntries(); } return _classpathEntries; } /** * @return */ private static IClasspathEntry[] determineBundleMakerLibraryClasspathEntries() { Map<String, Bundle> installedBundles = getInstalledBundles(); final List<IClasspathEntry> classpathEntries = new LinkedList<IClasspathEntry>(); // List<String> libBundles = new LinkedList<String>(); libBundles.addAll(Arrays.asList(BUNDLEMAKER_LIBRARY_BUNDLES)); libBundles.addAll(ModelExtFactory.getModelExtensionFactory() .getExtensionBundleNamespaces()); // for (String bundleMakerLibraryBundleName : libBundles) { Bundle bundle = installedBundles.get(bundleMakerLibraryBundleName); if (bundle == null) { // TODO System.err.println("[BundleMakerClassPathContainerInitializer] No bundle found with name '" + bundleMakerLibraryBundleName + "'"); continue; } IPath bundlePath = getBundlePath(bundle); if (bundlePath == null) { continue; } IPath sourceBundlePath = getSourceLocation(bundle, bundlePath); IClasspathEntry entry = JavaCore.newLibraryEntry(bundlePath, sourceBundlePath, null, new IAccessRule[0], null, false); classpathEntries.add(entry); } return classpathEntries.toArray(new IClasspathEntry[0]); } private static synchronized IPath eclipseInstallLocation() { if (_eclipseInstallLocation == null) { // Try Eclipe Location Service Location location = null; ServiceTracker<Location, Location> serviceTracker; try { serviceTracker = new ServiceTracker<Location, Location>( Activator.getDefault().getContext(), Activator.getDefault().getContext().createFilter(Location.ECLIPSE_HOME_FILTER), null); serviceTracker.open(); location = serviceTracker.getService(); serviceTracker.close(); } catch (InvalidSyntaxException e) { // ignore } String locationString; if (location != null && location.isSet()) { // Use url from Location service URL url = location.getURL(); locationString = url.toString(); } else { // Fallback: use System property locationString = System.getProperty("eclipse.home.location"); } if (locationString == null) { throw new IllegalStateException("Could not determine Eclipse home location."); } // Convert URL to Path if (locationString.startsWith("file:")) { locationString = locationString.substring("file:".length()); } _eclipseInstallLocation = new Path(locationString); } return _eclipseInstallLocation; } private static IPath getBundlePath(Bundle bundle) { String location = bundle.getLocation(); if (location.startsWith("initial@")) { location = location.substring("initial@".length()); } if (location.startsWith("reference:")) { location = location.substring("reference:".length()); } if (!location.startsWith("file:")) { System.err.println("Location kein file: " + location); return null; } location = location.substring("file:".length()); File file = new File(location); if (file.isDirectory()) { File binDirectory = new File(file, "bin"); if (binDirectory.isDirectory()) { file = binDirectory; } } IPath bundlePath; if (file.isAbsolute()) { bundlePath = new Path(file.getAbsolutePath()); } else { String path = file.getPath(); bundlePath = eclipseInstallLocation().append(path); } return bundlePath; } private static IPath getSourceLocation(Bundle bundle, IPath bundlePath) { // TODO For now this seems to be enough but we could make the algorithm more sophisticated IPath sourcePath = null; File bundleFile = new File(bundlePath.toOSString()); if ("bin".equals(bundleFile.getName())) { // project sourcePath = bundlePath.removeLastSegments(1).append("src"); } else { IPath parentPath = bundlePath.removeLastSegments(1); String sourceJarName = bundle.getSymbolicName() + ".source_" + bundle.getVersion() + ".jar"; sourcePath = parentPath.append(sourceJarName); } File sourceFile = new File(sourcePath.toOSString()); if (sourceFile.exists()) { return sourcePath; } // source location couldn't be determined return null; } private static Map<String, Bundle> getInstalledBundles() { BundleContext bundleContext = Activator.getDefault().getBundle().getBundleContext(); Bundle[] allBundles = bundleContext.getBundles(); Map<String, Bundle> result = new Hashtable<String, Bundle>(); for (Bundle bundle : allBundles) { result.put(bundle.getSymbolicName(), bundle); } return result; } /* * (non-Javadoc) * * @see org.eclipse.jdt.core.ClasspathContainerInitializer#getDescription(org.eclipse.core.runtime.IPath, * org.eclipse.jdt.core.IJavaProject) */ @Override public String getDescription(IPath containerPath, IJavaProject project) { return "BundleMaker Libraries"; } }