View | Details | Raw Unified | Return to bug 147831 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/pde/internal/core/ExternalModelManager.java (-2 / +191 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 *  Copyright (c) 2000, 2010 IBM Corporation and others.
2
 *  Copyright (c) 2000, 2011 IBM Corporation and others.
3
 *  All rights reserved. This program and the accompanying materials
3
 *  All rights reserved. This program and the accompanying materials
4
 *  are made available under the terms of the Eclipse Public License v1.0
4
 *  are made available under the terms of the Eclipse Public License v1.0
5
 *  which accompanies this distribution, and is available at
5
 *  which accompanies this distribution, and is available at
Lines 10-27 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.pde.internal.core;
11
package org.eclipse.pde.internal.core;
12
12
13
import java.io.File;
13
import java.io.*;
14
import java.net.MalformedURLException;
14
import java.net.MalformedURLException;
15
import java.net.URL;
15
import java.net.URL;
16
import java.util.*;
16
import java.util.*;
17
import java.util.jar.JarFile;
18
import java.util.zip.ZipEntry;
19
import org.eclipse.core.runtime.IPath;
17
import org.eclipse.core.runtime.Path;
20
import org.eclipse.core.runtime.Path;
21
import org.eclipse.osgi.service.resolver.BundleDescription;
22
import org.eclipse.pde.core.plugin.IPluginLibrary;
18
import org.eclipse.pde.core.plugin.IPluginModelBase;
23
import org.eclipse.pde.core.plugin.IPluginModelBase;
19
import org.eclipse.pde.internal.core.target.P2TargetUtils;
24
import org.eclipse.pde.internal.core.target.P2TargetUtils;
20
import org.eclipse.pde.internal.core.target.provisional.NameVersionDescriptor;
25
import org.eclipse.pde.internal.core.target.provisional.NameVersionDescriptor;
26
import org.eclipse.pde.internal.core.util.CoreUtility;
21
27
22
public class ExternalModelManager extends AbstractModelManager {
28
public class ExternalModelManager extends AbstractModelManager {
23
29
24
	private IPluginModelBase[] fModels = new IPluginModelBase[0];
30
	private IPluginModelBase[] fModels = new IPluginModelBase[0];
31
	private ExternalLibraryCache fLibCache = new ExternalLibraryCache();
25
32
26
	protected IPluginModelBase[] getAllModels() {
33
	protected IPluginModelBase[] getAllModels() {
27
		return fModels;
34
		return fModels;
Lines 63-72 Link Here
63
				}
70
				}
64
			}
71
			}
65
		}
72
		}
73
		fLibCache.cleanExtractedLibraries(fModels);
66
	}
74
	}
67
75
68
	public void setModels(IPluginModelBase[] models) {
76
	public void setModels(IPluginModelBase[] models) {
69
		fModels = models;
77
		fModels = models;
78
		fLibCache.cleanExtractedLibraries(fModels);
70
	}
79
	}
71
80
72
	/**
81
	/**
Lines 137-142 Link Here
137
		return result;
146
		return result;
138
	}
147
	}
139
148
149
	/**
150
	 * Returns all libraries extracted from an external jarred plug-in.  Will return an empty
151
	 * array if the plug-in is not jarred or if no jarred libraries exist inside it.
152
	 * <p>
153
	 * Previously cached libraries will be returned.  Any libraries not found in the cache will
154
	 * extracted from the plug-in and placed in PDE's metadata location.
155
	 * </p>
156
	 * @param model model to get the libraries for
157
	 * @return all extracted libraries or an empty array
158
	 */
159
	public File[] getExtractedLibraries(IPluginModelBase model) {
160
		return fLibCache.getExtractedLibraries(model);
161
	}
162
163
	/**
164
	 * Appends one {@link URL} to another
165
	 * 
166
	 * @param base first URL
167
	 * @param additional second URL
168
	 * @return a URL with the additional URL appended to the base
169
	 */
140
	private URL[] append(URL[] base, URL[] additional) {
170
	private URL[] append(URL[] base, URL[] additional) {
141
		if (additional.length == 0) {
171
		if (additional.length == 0) {
142
			return base;
172
			return base;
Lines 146-149 Link Here
146
		System.arraycopy(additional, 0, result, base.length, additional.length);
176
		System.arraycopy(additional, 0, result, base.length, additional.length);
147
		return result;
177
		return result;
148
	}
178
	}
179
180
}
181
182
/**
183
 * When an external model is added to the classpath its libraries as defined by the bundle-classpath
184
 * header also need to be added to the classpath for the JDT compiler.  This is handled by the 
185
 * {@link PDEClasspathContainer}.  However, because the classpath does not support nested jars, we
186
 * must extract any libraries from within a jarred bundle.  This class manages the set of libraries
187
 * that we have extracted and deletes them when the list of external models changes.
188
 * 
189
 * @see PDEClasspathContainer#addExternalPlugin(IPluginModelBase, org.eclipse.pde.internal.core.PDEClasspathContainer.Rule[], ArrayList)
190
 * @since 3.7
191
 */
192
class ExternalLibraryCache {
193
194
	/**
195
	 * Location inside the PDE metadata area where extracted libraries will be stored.
196
	 * Extracted libraries will be stored under a directory named from the plug-in it
197
	 * was extracted from.
198
	 * <p>
199
	 * [workspace]/.metadata/.plugins/org.eclipse.pde.core/.external_libraries/[plugin_name]_[plugin_version]/[library_name].jar
200
	 * </p> 
201
	 */
202
	private static final String LIB_CACHE_DIR = ".external_libraries"; //$NON-NLS-1$
203
204
	/**
205
	 * Returns all libraries extracted from an external jarred plug-in.  Will return an empty
206
	 * array if the plug-in is not jarred or if no jarred libraries exist inside it.
207
	 * <p>
208
	 * Previously cached libraries will be returned.  Any libraries not found in the cache will
209
	 * extracted from the plug-in and placed in PDE's metadata location.
210
	 * </p>
211
	 * @param model model to get the libraries for
212
	 * @return all extracted libraries or an empty array
213
	 */
214
	public File[] getExtractedLibraries(IPluginModelBase model) {
215
		File fJarFile = new File(model.getInstallLocation());
216
		if (!fJarFile.isFile())
217
			return new File[0];
218
219
		BundleDescription desc = model.getBundleDescription();
220
		IPluginLibrary[] libs = model.getPluginBase().getLibraries();
221
222
		File fCacheDir = new File(getLibraryCacheDir(), getBundleLibsCacheDirName(desc));
223
224
		List files = new ArrayList();
225
226
		for (int i = 0; i < libs.length; i++) {
227
			String libName = libs[i].getName();
228
			if (!".".equals(libName)) { //$NON-NLS-1$
229
				libName = ClasspathUtilCore.expandLibraryName(libName);
230
				File fDestFile = new File(fCacheDir, libName);
231
				// assume that an existing file is always valid
232
				if (!fDestFile.isFile()) {
233
					try {
234
						File extractedLib = extractJar(fJarFile, libName, fDestFile);
235
						if (extractedLib != null) {
236
							files.add(extractedLib);
237
						}
238
					} catch (IOException ie) {
239
						// do not add file, but log error
240
						PDECore.logException(ie, "Could not extract library from jarred bundle " + desc.getSymbolicName()); //$NON-NLS-1$
241
					}
242
				} else
243
					files.add(fDestFile);
244
			}
245
		}
246
247
		return (File[]) files.toArray(new File[0]);
248
	}
249
250
	/**
251
	 * Deletes all the cached JARs of libraries which are currently not contained 
252
	 * or enabled in the target platform. Will ignore any errors when trying to
253
	 * delete a directory.
254
	 * 
255
	 * @param targetModels The current contents of the target platform.
256
	 */
257
	public void cleanExtractedLibraries(IPluginModelBase[] targetModels) {
258
		File fCacheDir = getLibraryCacheDir();
259
		if (!fCacheDir.isDirectory())
260
			return;
261
262
		// build a list with all potential directory names for quick check
263
		Set bundleKeys = new HashSet();
264
265
		for (int i = 0; i < targetModels.length; i++) {
266
			if (targetModels[i].isEnabled()) {
267
				BundleDescription desc = targetModels[i].getBundleDescription();
268
				bundleKeys.add(getBundleLibsCacheDirName(desc));
269
			}
270
		}
271
272
		File[] fDirs = fCacheDir.listFiles();
273
		for (int i = 0; i < fDirs.length; i++) {
274
			if (fDirs[i].isDirectory() && !bundleKeys.contains(fDirs[i].getName()))
275
				CoreUtility.deleteContent(fDirs[i]);
276
		}
277
278
		// Delete the cache folder if it is empty
279
		fCacheDir.delete();
280
	}
281
282
	/**
283
	 * @return The directory in the PDE Core's state location where wrapped JARs
284
	 * from external bundles are stored.
285
	 */
286
	private File getLibraryCacheDir() {
287
		IPath path = PDECore.getDefault().getStateLocation();
288
		return new File(path.toFile(), LIB_CACHE_DIR);
289
	}
290
291
	/**
292
	 * Returns the name of the library cache directory for the given bundle.
293
	 * 
294
	 * @param desc Bundle descriptor. 
295
	 * 
296
	 * @return <code>[bundle ID]_[bundle version]</code>
297
	 */
298
	private String getBundleLibsCacheDirName(BundleDescription desc) {
299
		return desc.getSymbolicName() + "_" + desc.getVersion(); //$NON-NLS-1$
300
	}
301
302
	/**
303
	 * Extracts a library from a jarred plug-in to the specified directory.
304
	 * 
305
	 * @param fJarFile jar file to extract from
306
	 * @param libName name of the library to extract
307
	 * @param fTargetFile file location to extract the library to
308
	 * @return the file where the jar is extracted if successful, <code>null</code> otherwise.
309
	 * @throws IOException
310
	 */
311
	private File extractJar(File fJarFile, String libName, File fTargetFile) throws IOException {
312
		JarFile f = new JarFile(fJarFile);
313
		InputStream in = null;
314
		try {
315
			ZipEntry libEntry = f.getEntry(libName);
316
			if (libEntry == null) {
317
				return null;
318
			}
319
			fTargetFile.getParentFile().mkdirs();
320
			in = f.getInputStream(libEntry);
321
			if (in == null)
322
				throw new IOException();
323
324
			CoreUtility.readFile(in, fTargetFile);
325
			return fTargetFile;
326
		} finally {
327
			try {
328
				f.close();
329
			} catch (Exception e) {
330
			}
331
			try {
332
				in.close();
333
			} catch (Exception e) {
334
			}
335
		}
336
	}
337
149
}
338
}
(-)src/org/eclipse/pde/internal/core/PDEClasspathContainer.java (-1 / +8 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 *  Copyright (c) 2005, 2008 IBM Corporation and others.
2
 *  Copyright (c) 2005, 2011 IBM Corporation and others.
3
 *  All rights reserved. This program and the accompanying materials
3
 *  All rights reserved. This program and the accompanying materials
4
 *  are made available under the terms of the Eclipse Public License v1.0
4
 *  are made available under the terms of the Eclipse Public License v1.0
5
 *  which accompanies this distribution, and is available at
5
 *  which accompanies this distribution, and is available at
Lines 67-72 Link Here
67
			if (srcPath == null)
67
			if (srcPath == null)
68
				srcPath = new Path(model.getInstallLocation());
68
				srcPath = new Path(model.getInstallLocation());
69
			addLibraryEntry(new Path(model.getInstallLocation()), srcPath, rules, getClasspathAttributes(model), entries);
69
			addLibraryEntry(new Path(model.getInstallLocation()), srcPath, rules, getClasspathAttributes(model), entries);
70
71
			// If the jarred plugin contains any jarred libraries they must be extracted as the compiler can't handle nested jar files
72
			File[] extractedLibraries = PDECore.getDefault().getModelManager().getExternalModelManager().getExtractedLibraries(model);
73
			for (int i = 0; i < extractedLibraries.length; i++) {
74
				Path path = new Path(extractedLibraries[i].getAbsolutePath());
75
				addLibraryEntry(path, path, rules, getClasspathAttributes(model), entries);
76
			}
70
		} else {
77
		} else {
71
			IPluginLibrary[] libraries = model.getPluginBase().getLibraries();
78
			IPluginLibrary[] libraries = model.getPluginBase().getLibraries();
72
			for (int i = 0; i < libraries.length; i++) {
79
			for (int i = 0; i < libraries.length; i++) {

Return to bug 147831