### Eclipse Workspace Patch 1.0 #P org.eclipse.pde.core Index: src/org/eclipse/pde/internal/core/ExternalModelManager.java =================================================================== RCS file: /cvsroot/eclipse/pde/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/ExternalModelManager.java,v retrieving revision 1.64 diff -u -r1.64 ExternalModelManager.java --- src/org/eclipse/pde/internal/core/ExternalModelManager.java 11 May 2010 18:10:05 -0000 1.64 +++ src/org/eclipse/pde/internal/core/ExternalModelManager.java 10 Mar 2011 19:11:37 -0000 @@ -10,17 +10,24 @@ *******************************************************************************/ package org.eclipse.pde.internal.core; -import java.io.File; +import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.util.*; +import java.util.jar.JarFile; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; +import org.eclipse.osgi.service.resolver.BundleDescription; +import org.eclipse.pde.core.plugin.IPluginLibrary; import org.eclipse.pde.core.plugin.IPluginModelBase; import org.eclipse.pde.internal.core.target.AbstractTargetHandle; import org.eclipse.pde.internal.core.target.provisional.NameVersionDescriptor; +import org.eclipse.pde.internal.core.util.CoreUtility; public class ExternalModelManager extends AbstractModelManager { + private static final String LIB_CACHE_DIR = ".libcache"; //$NON-NLS-1$ + private IPluginModelBase[] fModels = new IPluginModelBase[0]; protected IPluginModelBase[] getAllModels() { @@ -63,6 +70,7 @@ } } } + purgeLibraryCache(fModels); } public void setModels(IPluginModelBase[] models) { @@ -130,4 +138,121 @@ System.arraycopy(additional, 0, result, base.length, additional.length); return result; } + + /** + * Caches the libraries contained in the given external bundle (if not already cached). + * The JAR files are stored in the local file system (in the state location + * of PDE Core). + * + * @param model Model of an external bundle. + * + * @return The cached versions of the JAR files wrapped by this bundle, or + * an empty array if the given bundle is not packaged as a JAR or does not contain + * any wrapped libraries. + */ + public File[] getCachedLibraryFiles(IPluginModelBase model) { + File fJarFile = new File(model.getInstallLocation()); + if (!fJarFile.isFile()) + return new File[0]; + + BundleDescription desc = model.getBundleDescription(); + IPluginLibrary[] libs = model.getPluginBase().getLibraries(); + + File fCacheDir = new File(getLibraryCacheDir(), getBundleLibsCacheDirName(desc)); + + List files = new ArrayList(); + + for (int i = 0; i < libs.length; i++) { + String libName = libs[i].getName(); + if (!".".equals(libName)) { //$NON-NLS-1$ + libName = ClasspathUtilCore.expandLibraryName(libName); + File fDestFile = new File(fCacheDir, libName); + // assume that an existing file is always valid + if (!fDestFile.isFile()) { + try { + fDestFile.getParentFile().mkdirs(); + extractJar(fJarFile, libName, fDestFile); + files.add(fDestFile); + } catch (IOException ie) { + // do not add file, but log error + PDECore.logException(ie, "Could not extract JAR file from bundle " + desc.getSymbolicName()); //$NON-NLS-1$ + } + } else + files.add(fDestFile); + } + } + + return (File[]) files.toArray(new File[0]); + } + + /** + * Delete all the cached JARs of libraries which are currently not contained + * or enabled in the target platform. Will ignore any errors when trying to + * delete a directory. + * + * @param targetModels The current contents of the target platform. + */ + private void purgeLibraryCache(IPluginModelBase[] targetModels) { + File fCacheDir = getLibraryCacheDir(); + if (!fCacheDir.isDirectory()) + return; + + // build a list with all potential directory names for quick check + Set bundleKeys = new HashSet(); + + for (int i = 0; i < targetModels.length; i++) { + if (targetModels[i].isEnabled()) { + BundleDescription desc = targetModels[i].getBundleDescription(); + bundleKeys.add(getBundleLibsCacheDirName(desc)); + } + } + + File[] fDirs = fCacheDir.listFiles(); + for (int i = 0; i < fDirs.length; i++) { + if (fDirs[i].isDirectory() && !bundleKeys.contains(fDirs[i].getName())) + CoreUtility.deleteContent(fDirs[i]); + } + } + + /** + * @return The directory in the PDE Core's state location where wrapped JARs + * from external bundles are stored. + */ + private static File getLibraryCacheDir() { + IPath path = PDECore.getDefault().getStateLocation(); + return new File(path.toFile(), LIB_CACHE_DIR); + } + + /** + * Returns the name of the library cache directory for the given bundle. + * + * @param desc Bundle descriptor. + * + * @return [bundle ID]_[bundle version] + */ + private static String getBundleLibsCacheDirName(BundleDescription desc) { + return desc.getSymbolicName() + "_" + desc.getVersion(); //$NON-NLS-1$ + } + + private static void extractJar(File fJarFile, String libName, File fTargetFile) throws IOException { + JarFile f = new JarFile(fJarFile); + InputStream in = null; + try { + in = f.getInputStream(f.getEntry(libName)); + if (in == null) + throw new IOException(); + + CoreUtility.readFile(in, fTargetFile); + } finally { + try { + f.close(); + } catch (Exception e) { + } + try { + in.close(); + } catch (Exception e) { + } + } + } + } Index: src/org/eclipse/pde/internal/core/PDEClasspathContainer.java =================================================================== RCS file: /cvsroot/eclipse/pde/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDEClasspathContainer.java,v retrieving revision 1.28 diff -u -r1.28 PDEClasspathContainer.java --- src/org/eclipse/pde/internal/core/PDEClasspathContainer.java 27 May 2009 20:25:20 -0000 1.28 +++ src/org/eclipse/pde/internal/core/PDEClasspathContainer.java 10 Mar 2011 19:11:37 -0000 @@ -67,6 +67,11 @@ if (srcPath == null) srcPath = new Path(model.getInstallLocation()); addLibraryEntry(new Path(model.getInstallLocation()), srcPath, rules, getClasspathAttributes(model), entries); + File[] jars = PDECore.getDefault().getModelManager().getExternalModelManager().getCachedLibraryFiles(model); + for (int i = 0; i < jars.length; i++) { + Path path = new Path(jars[i].getAbsolutePath()); + addLibraryEntry(path, path, rules, getClasspathAttributes(model), entries); + } } else { IPluginLibrary[] libraries = model.getPluginBase().getLibraries(); for (int i = 0; i < libraries.length; i++) {