KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > runtime > adaptor > PluginConverterImpl


1 /*******************************************************************************
2  * Copyright (c) 2003, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.core.runtime.adaptor;
12
13 import java.io.BufferedInputStream;
14 import java.io.BufferedReader;
15 import java.io.BufferedWriter;
16 import java.io.File;
17 import java.io.FileInputStream;
18 import java.io.FileOutputStream;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.InputStreamReader;
22 import java.io.OutputStreamWriter;
23 import java.net.MalformedURLException;
24 import java.net.URL;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.Dictionary;
28 import java.util.Enumeration;
29 import java.util.HashSet;
30 import java.util.Hashtable;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Set;
35 import java.util.jar.JarEntry;
36 import java.util.jar.JarFile;
37
38 import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
39 import org.eclipse.osgi.framework.internal.core.Constants;
40 import org.eclipse.osgi.framework.internal.defaultadaptor.DevClassPathHelper;
41 import org.eclipse.osgi.framework.log.FrameworkLogEntry;
42 import org.eclipse.osgi.service.pluginconversion.PluginConversionException;
43 import org.eclipse.osgi.service.pluginconversion.PluginConverter;
44 import org.eclipse.osgi.service.resolver.Version;
45 import org.eclipse.osgi.service.resolver.VersionRange;
46 import org.eclipse.osgi.util.ManifestElement;
47 import org.osgi.framework.BundleContext;
48 import org.osgi.framework.BundleException;
49
50 /**
51  * Internal class.
52  */

53 public class PluginConverterImpl implements PluginConverter {
54     public static boolean DEBUG = false;
55     private static final String SEMICOLON = "; "; //$NON-NLS-1$
56
private static final String UTF_8 = "UTF-8"; //$NON-NLS-1$
57
private static final String LIST_SEPARATOR = ",\n "; //$NON-NLS-1$
58
private static final String DOT = "."; //$NON-NLS-1$
59
private BundleContext context;
60     private BufferedWriter out;
61     private IPluginInfo pluginInfo;
62     private File pluginManifestLocation;
63     private Dictionary generatedManifest;
64     private byte manifestType;
65     private String target;
66     private static final String MANIFEST_VERSION = "Manifest-Version"; //$NON-NLS-1$
67
private static final String PLUGIN_PROPERTIES_FILENAME = "plugin"; //$NON-NLS-1$
68
private static PluginConverterImpl instance;
69     private static final String[] ARCH_LIST = {org.eclipse.osgi.service.environment.Constants.ARCH_PA_RISC, org.eclipse.osgi.service.environment.Constants.ARCH_PPC, org.eclipse.osgi.service.environment.Constants.ARCH_SPARC, org.eclipse.osgi.service.environment.Constants.ARCH_X86, org.eclipse.osgi.service.environment.Constants.ARCH_AMD64, org.eclipse.osgi.service.environment.Constants.ARCH_IA64};
70     protected static final String FRAGMENT_MANIFEST = "fragment.xml"; //$NON-NLS-1$
71
protected static final String GENERATED_FROM = "Generated-from"; //$NON-NLS-1$
72
protected static final String MANIFEST_TYPE_ATTRIBUTE = "type"; //$NON-NLS-1$
73
private static final String[] OS_LIST = {org.eclipse.osgi.service.environment.Constants.OS_AIX, org.eclipse.osgi.service.environment.Constants.OS_HPUX, org.eclipse.osgi.service.environment.Constants.OS_LINUX, org.eclipse.osgi.service.environment.Constants.OS_MACOSX, org.eclipse.osgi.service.environment.Constants.OS_QNX, org.eclipse.osgi.service.environment.Constants.OS_SOLARIS, org.eclipse.osgi.service.environment.Constants.OS_WIN32};
74     protected static final String PI_RUNTIME = "org.eclipse.core.runtime"; //$NON-NLS-1$
75
protected static final String PI_BOOT = "org.eclipse.core.boot"; //$NON-NLS-1$
76
protected static final String PI_RUNTIME_COMPATIBILITY = "org.eclipse.core.runtime.compatibility"; //$NON-NLS-1$
77
protected static final String PLUGIN_MANIFEST = "plugin.xml"; //$NON-NLS-1$
78
private static final String COMPATIBILITY_ACTIVATOR = "org.eclipse.core.internal.compatibility.PluginActivator"; //$NON-NLS-1$
79
private static final String[] WS_LIST = {org.eclipse.osgi.service.environment.Constants.WS_CARBON, org.eclipse.osgi.service.environment.Constants.WS_GTK, org.eclipse.osgi.service.environment.Constants.WS_MOTIF, org.eclipse.osgi.service.environment.Constants.WS_PHOTON, org.eclipse.osgi.service.environment.Constants.WS_WIN32};
80
81     public static PluginConverterImpl getDefault() {
82         return instance;
83     }
84
85     public PluginConverterImpl() {
86         this(null);
87     }
88
89     PluginConverterImpl(BundleContext context) {
90         this.context = context;
91         instance = this;
92     }
93
94     private void init() {
95         // need to make sure these fields are cleared out for each conversion.
96
out = null;
97         pluginInfo = null;
98         pluginManifestLocation = null;
99         generatedManifest = new Hashtable(10);
100         manifestType = EclipseBundleData.MANIFEST_TYPE_UNKNOWN;
101         target = null;
102     }
103
104     private void fillPluginInfo(File pluginBaseLocation) throws PluginConversionException {
105         pluginManifestLocation = pluginBaseLocation;
106         if (pluginManifestLocation == null)
107             throw new IllegalArgumentException();
108         URL pluginFile = findPluginManifest(pluginBaseLocation);
109         if (pluginFile == null)
110             throw new PluginConversionException(EclipseAdaptorMsg.formatter.getString("ECLIPSE_CONVERTER_FILENOTFOUND", pluginBaseLocation.getAbsolutePath())); //$NON-NLS-1$
111
pluginInfo = parsePluginInfo(pluginFile);
112         String validation = pluginInfo.validateForm();
113         if (validation != null)
114             throw new PluginConversionException(validation);
115     }
116
117     private Set filterExport(Collection exportToFilter, Collection filter) {
118         if (filter == null || filter.contains("*")) //$NON-NLS-1$
119
return (Set) exportToFilter;
120         Set filteredExport = new HashSet(exportToFilter.size());
121         for (Iterator iter = exportToFilter.iterator(); iter.hasNext();) {
122             String anExport = (String) iter.next();
123             for (Iterator iter2 = filter.iterator(); iter2.hasNext();) {
124                 String aFilter = (String) iter2.next();
125                 int dotStar = aFilter.indexOf(".*"); //$NON-NLS-1$
126
if (dotStar != -1)
127                     aFilter = aFilter.substring(0, dotStar);
128                 if (anExport.equals(aFilter)) {
129                     filteredExport.add(anExport);
130                     break;
131                 }
132             }
133         }
134         return filteredExport;
135     }
136
137     private ArrayList findOSJars(File pluginRoot, String path, boolean filter) {
138         path = path.substring(4);
139         ArrayList found = new ArrayList(0);
140         for (int i = 0; i < OS_LIST.length; i++) {
141             //look for os/osname/path
142
String searchedPath = "os/" + OS_LIST[i] + "/" + path; //$NON-NLS-1$ //$NON-NLS-2$
143
if (new File(pluginRoot, searchedPath).exists())
144                 found.add(searchedPath + (filter ? ";(os=" + WS_LIST[i] + ")" : "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
145
//look for os/osname/archname/path
146
for (int j = 0; j < ARCH_LIST.length; j++) {
147                 searchedPath = "os/" + OS_LIST[i] + "/" + ARCH_LIST[j] + "/" + path; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
148
if (new File(pluginRoot, searchedPath).exists()) {
149                     found.add(searchedPath + (filter ? ";(& (os=" + WS_LIST[i] + ") (arch=" + ARCH_LIST[j] + ")" : "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
150
}
151             }
152         }
153         return found;
154     }
155
156     private URL findPluginManifest(File baseLocation) {
157         //Here, we can not use the bundlefile because it may explode the jar and returns a location from which we will not be able to derive the jars location
158
URL xmlFileLocation;
159         InputStream stream = null;
160         URL baseURL = null;
161         try {
162             if (baseLocation.getName().endsWith(".jar")) { //$NON-NLS-1$
163
baseURL = new URL("jar:file:" + baseLocation.toString() + "!/"); //$NON-NLS-1$ //$NON-NLS-2$
164
manifestType |= EclipseBundleData.MANIFEST_TYPE_JAR;
165             } else {
166                 baseURL = baseLocation.toURL();
167             }
168         } catch (MalformedURLException e1) {
169             //this can't happen since we are building the urls ourselves from a file
170
}
171         try {
172             xmlFileLocation = new URL(baseURL, PLUGIN_MANIFEST);
173             stream = xmlFileLocation.openStream();
174             manifestType |= EclipseBundleData.MANIFEST_TYPE_PLUGIN;
175             return xmlFileLocation;
176         } catch (MalformedURLException e) {
177             FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, e.getMessage(), 0, e, null);
178             EclipseAdaptor.getDefault().getFrameworkLog().log(entry);
179             return null;
180         } catch (IOException ioe) {
181             //ignore
182
} finally {
183             try {
184                 if (stream != null)
185                     stream.close();
186             } catch (IOException e) {
187                 //ignore
188
}
189         }
190         try {
191             xmlFileLocation = new URL(baseURL, FRAGMENT_MANIFEST);
192             xmlFileLocation.openStream();
193             manifestType |= EclipseBundleData.MANIFEST_TYPE_FRAGMENT;
194             return xmlFileLocation;
195         } catch (MalformedURLException e) {
196             FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, e.getMessage(), 0, e, null);
197             EclipseAdaptor.getDefault().getFrameworkLog().log(entry);
198             return null;
199         } catch (IOException ioe) {
200             // Ignore
201
} finally {
202             try {
203                 if (stream != null)
204                     stream.close();
205             } catch (IOException e) {
206                 //ignore
207
}
208         }
209         return null;
210     }
211
212     private ArrayList findWSJars(File pluginRoot, String path, boolean filter) {
213         path = path.substring(4);
214         ArrayList found = new ArrayList(0);
215         for (int i = 0; i < WS_LIST.length; i++) {
216             String searchedPath = "ws/" + WS_LIST[i] + path; //$NON-NLS-1$
217
if (new File(pluginRoot, searchedPath).exists()) {
218                 found.add(searchedPath + (filter ? ";(ws=" + WS_LIST[i] + ")" : "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
219
}
220         }
221         return found;
222     }
223
224     protected void fillManifest(boolean compatibilityManifest, boolean analyseJars) {
225         generateManifestVersion();
226         generateHeaders();
227         generateClasspath();
228         generateActivator();
229         generatePluginClass();
230         if (analyseJars)
231             generateProvidePackage();
232         generateRequireBundle();
233         generateLocalizationEntry();
234         generateEclipseHeaders();
235         if (compatibilityManifest) {
236             generateTimestamp();
237         }
238     }
239
240     public void writeManifest(File generationLocation, Dictionary manifestToWrite, boolean compatibilityManifest) throws PluginConversionException {
241         try {
242             File parentFile = new File(generationLocation.getParent());
243             parentFile.mkdirs();
244             generationLocation.createNewFile();
245             if (!generationLocation.isFile()) {
246                 String message = EclipseAdaptorMsg.formatter.getString("ECLIPSE_CONVERTER_ERROR_CREATING_BUNDLE_MANIFEST", this.pluginInfo.getUniqueId(), generationLocation); //$NON-NLS-1$
247
throw new PluginConversionException(message);
248             }
249             // replaces any eventual existing file
250
manifestToWrite = new Hashtable((Map) manifestToWrite);
251             // MANIFEST.MF files must be written using UTF-8
252
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(generationLocation), UTF_8));
253             writeEntry(MANIFEST_VERSION, (String) manifestToWrite.remove(MANIFEST_VERSION));
254             writeEntry(GENERATED_FROM, (String) manifestToWrite.remove(GENERATED_FROM)); //Need to do this first uptoDate check expect the generated-from tag to be in the first line
255
writeEntry(Constants.BUNDLE_NAME, (String) manifestToWrite.remove(Constants.BUNDLE_NAME));
256             writeEntry(Constants.BUNDLE_SYMBOLICNAME, (String) manifestToWrite.remove(Constants.BUNDLE_SYMBOLICNAME));
257             writeEntry(Constants.BUNDLE_VERSION, (String) manifestToWrite.remove(Constants.BUNDLE_VERSION));
258             writeEntry(Constants.BUNDLE_CLASSPATH, (String) manifestToWrite.remove(Constants.BUNDLE_CLASSPATH));
259             writeEntry(Constants.BUNDLE_ACTIVATOR, (String) manifestToWrite.remove(Constants.BUNDLE_ACTIVATOR));
260             writeEntry(Constants.BUNDLE_VENDOR, (String) manifestToWrite.remove(Constants.BUNDLE_VENDOR));
261             writeEntry(Constants.FRAGMENT_HOST, (String) manifestToWrite.remove(Constants.FRAGMENT_HOST));
262             writeEntry(Constants.BUNDLE_LOCALIZATION, (String) manifestToWrite.remove(Constants.BUNDLE_LOCALIZATION));
263             writeEntry(Constants.PROVIDE_PACKAGE, (String) manifestToWrite.remove(Constants.PROVIDE_PACKAGE));
264             writeEntry(Constants.REQUIRE_BUNDLE, (String) manifestToWrite.remove(Constants.REQUIRE_BUNDLE));
265             Enumeration keys = manifestToWrite.keys();
266             while (keys.hasMoreElements()) {
267                 String key = (String) keys.nextElement();
268                 writeEntry(key, (String) manifestToWrite.get(key));
269             }
270             out.flush();
271         } catch (IOException e) {
272             String message = EclipseAdaptorMsg.formatter.getString("ECLIPSE_CONVERTER_ERROR_CREATING_BUNDLE_MANIFEST", this.pluginInfo.getUniqueId(), generationLocation); //$NON-NLS-1$
273
throw new PluginConversionException(message, e);
274         } finally {
275             if (out != null)
276                 try {
277                     out.close();
278                 } catch (IOException e) {
279                     // only report problems writing to/flushing the file
280
}
281         }
282     }
283
284     private void generateLocalizationEntry() {
285         generatedManifest.put(Constants.BUNDLE_LOCALIZATION, PLUGIN_PROPERTIES_FILENAME);
286     }
287
288     private void generateManifestVersion() {
289         generatedManifest.put(MANIFEST_VERSION, "1.0"); //$NON-NLS-1$ //$NON-NLS-2$
290
}
291
292     private boolean requireRuntimeCompatibility() {
293         ArrayList requireList = pluginInfo.getRequires();
294         for (Iterator iter = requireList.iterator(); iter.hasNext();) {
295             if (((PluginParser.Prerequisite) iter.next()).getName().equalsIgnoreCase(PI_RUNTIME_COMPATIBILITY))
296                 return true;
297         }
298         return false;
299     }
300
301     private void generateActivator() {
302         if (!pluginInfo.isFragment())
303             if (!requireRuntimeCompatibility()) {
304                 String pluginClass = pluginInfo.getPluginClass();
305                 if (pluginClass != null && !pluginClass.trim().equals("")) //$NON-NLS-1$
306
generatedManifest.put(Constants.BUNDLE_ACTIVATOR, pluginClass);
307             } else {
308                 generatedManifest.put(Constants.BUNDLE_ACTIVATOR, COMPATIBILITY_ACTIVATOR);
309             }
310     }
311
312     private void generateClasspath() {
313         String[] classpath = pluginInfo.getLibrariesName();
314         if (classpath.length != 0)
315             generatedManifest.put(Constants.BUNDLE_CLASSPATH, getStringFromArray(classpath, LIST_SEPARATOR));
316     }
317
318     private void generateHeaders() {
319         generatedManifest.put(Constants.BUNDLE_NAME, pluginInfo.getPluginName());
320         generatedManifest.put(Constants.BUNDLE_VERSION, pluginInfo.getVersion());
321         generatedManifest.put(Constants.BUNDLE_SYMBOLICNAME, getSymbolicNameEntry());
322         String provider = pluginInfo.getProviderName();
323         if (provider != null)
324             generatedManifest.put(Constants.BUNDLE_VENDOR, provider);
325         if (pluginInfo.isFragment()) {
326             StringBuffer hostBundle = new StringBuffer();
327             hostBundle.append(pluginInfo.getMasterId());
328             String versionRange = getVersionRange(pluginInfo.getMasterVersion(), pluginInfo.getMasterMatch()); // TODO need to get match rule here!
329
if (versionRange != null)
330                 hostBundle.append(versionRange);
331             generatedManifest.put(Constants.FRAGMENT_HOST, hostBundle.toString());
332         }
333     }
334
335     /*
336      * Generates an entry in the form:
337      * <symbolic-name>[; singleton=true]
338      */

339     private String getSymbolicNameEntry() {
340         // false is the default, so don't bother adding anything
341
if (!pluginInfo.isSingleton())
342             return pluginInfo.getUniqueId();
343         StringBuffer result = new StringBuffer(pluginInfo.getUniqueId());
344         result.append(SEMICOLON); //$NON-NLS-1$
345
result.append(Constants.SINGLETON_ATTRIBUTE);
346         result.append("=true"); //$NON-NLS-1$
347
return result.toString();
348     }
349
350     private void generatePluginClass() {
351         if (requireRuntimeCompatibility()) {
352             String pluginClass = pluginInfo.getPluginClass();
353             if (pluginClass != null)
354                 generatedManifest.put(EclipseAdaptor.PLUGIN_CLASS, pluginClass);
355         }
356     }
357
358     private void generateProvidePackage() {
359         Set exports = getExports();
360         if (exports != null && exports.size() != 0) {
361             generatedManifest.put(Constants.PROVIDE_PACKAGE, getStringFromCollection(exports, LIST_SEPARATOR));
362         }
363     }
364
365     private void generateRequireBundle() {
366         ArrayList requiredBundles = pluginInfo.getRequires();
367         if (requiredBundles.size() == 0)
368             return;
369         StringBuffer bundleRequire = new StringBuffer();
370         for (Iterator iter = requiredBundles.iterator(); iter.hasNext();) {
371             PluginParser.Prerequisite element = (PluginParser.Prerequisite) iter.next();
372             StringBuffer modImport = new StringBuffer(element.getName());
373             String versionRange = getVersionRange(element.getVersion(), element.getMatch());
374             if (versionRange != null)
375                 modImport.append(versionRange);
376             if (element.isExported()) {
377                 modImport.append(';').append(Constants.REPROVIDE_ATTRIBUTE).append("=true");//$NON-NLS-1$
378
}
379             if (element.isOptional()) {
380                 modImport.append(';').append(Constants.OPTIONAL_ATTRIBUTE).append("=true");//$NON-NLS-1$
381
}
382             bundleRequire.append(modImport.toString());
383             if (iter.hasNext())
384                 bundleRequire.append(LIST_SEPARATOR);
385         }
386         generatedManifest.put(Constants.REQUIRE_BUNDLE, bundleRequire.toString());
387     }
388
389     private void generateTimestamp() {
390         // so it is easy to tell which ones are generated
391
generatedManifest.put(GENERATED_FROM, Long.toString(getTimeStamp(pluginManifestLocation, manifestType)) + ";" + MANIFEST_TYPE_ATTRIBUTE + "=" + manifestType); //$NON-NLS-1$ //$NON-NLS-2$
392
}
393
394     private void generateEclipseHeaders() {
395         if (!pluginInfo.isFragment())
396             generatedManifest.put(EclipseAdaptor.ECLIPSE_AUTOSTART, "true"); //$NON-NLS-1$
397
}
398
399     private Set getExports() {
400         Map libs = pluginInfo.getLibraries();
401         if (libs == null)
402             return null;
403
404         //If we are in dev mode, then add the binary folders on the list libs with the export clause set to be the cumulation of the export clause of the real libs
405
if (DevClassPathHelper.inDevelopmentMode()) {
406             String[] devClassPath = DevClassPathHelper.getDevClassPath(pluginInfo.getUniqueId());
407
408             // collect export clauses
409
List allExportClauses = new ArrayList(libs.size());
410             Set libEntries = libs.entrySet();
411             for (Iterator iter = libEntries.iterator(); iter.hasNext();) {
412                 Map.Entry element = (Map.Entry) iter.next();
413                 allExportClauses.addAll((List) element.getValue());
414             }
415             if (devClassPath != null) {
416                 for (int i = 0; i < devClassPath.length; i++)
417                     libs.put(devClassPath[i], allExportClauses);
418             }
419         }
420
421         Set result = new HashSet(7);
422         Set libEntries = libs.entrySet();
423         for (Iterator iter = libEntries.iterator(); iter.hasNext();) {
424             Map.Entry element = (Map.Entry) iter.next();
425             List filter = (List) element.getValue();
426             if (filter.size() == 0) //If the library is not exported, then ignore it
427
continue;
428             File libraryLocation = new File(pluginManifestLocation, (String) element.getKey());
429             Set exports = null;
430             if (libraryLocation.exists()) {
431                 if (libraryLocation.isFile())
432                     exports = filterExport(getExportsFromJAR(libraryLocation), filter); //TODO Need to handle $xx$ variables
433
else if (libraryLocation.isDirectory())
434                     exports = filterExport(getExportsFromDir(libraryLocation), filter);
435             } else {
436                 ArrayList expandedLibs = getLibrariesExpandingVariables((String) element.getKey(), false);
437                 exports = new HashSet();
438                 for (Iterator iterator = expandedLibs.iterator(); iterator.hasNext();) {
439                     String libName = (String) iterator.next();
440                     File libFile = new File(pluginManifestLocation, libName);
441                     if (libFile.isFile()) {
442                         exports.addAll(filterExport(getExportsFromJAR(libFile), filter));
443                     }
444                 }
445             }
446             if (exports != null)
447                 result.addAll(exports);
448         }
449         return result;
450     }
451
452     private Set getExportsFromDir(File location) {
453         return getExportsFromDir(location, ""); //$NON-NLS-1$
454
}
455
456     private Set getExportsFromDir(File location, String packageName) {
457         String prefix = (packageName.length() > 0) ? (packageName + '.') : ""; //$NON-NLS-1$
458
String[] files = location.list();
459         Set exportedPaths = new HashSet();
460         boolean containsFile = false;
461         for (int i = 0; i < files.length; i++) {
462             if (!isValidPackageName(files[i]))
463                 continue;
464             File pkgFile = new File(location, files[i]);
465             if (pkgFile.isDirectory())
466                 exportedPaths.addAll(getExportsFromDir(pkgFile, prefix + files[i]));
467             else
468                 containsFile = true;
469         }
470         if (containsFile)
471             // Allow the default package to be provided. If the default package
472
// contains a File then use "." as the package name to provide for default.
473
if (packageName.length() > 0)
474                 exportedPaths.add(packageName);
475             else
476                 exportedPaths.add(DOT);
477         return exportedPaths;
478     }
479
480     private Set getExportsFromJAR(File jarFile) {
481         Set names = new HashSet();
482         JarFile file = null;
483         try {
484             file = new JarFile(jarFile);
485         } catch (IOException e) {
486             String message = EclipseAdaptorMsg.formatter.getString("ECLIPSE_CONVERTER_PLUGIN_LIBRARY_IGNORED", jarFile, pluginInfo.getUniqueId()); //$NON-NLS-1$
487
EclipseAdaptor.getDefault().getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, message, 0, e, null));
488             return names;
489         }
490         //Run through the entries
491
for (Enumeration enum = file.entries(); enum.hasMoreElements();) {
492             JarEntry entry = (JarEntry) enum.nextElement();
493             String name = entry.getName();
494             if (!isValidPackageName(name))
495                 continue;
496             int lastSlash = name.lastIndexOf("/"); //$NON-NLS-1$
497
//Ignore folders that do not contain files
498
if (lastSlash != -1) {
499                 if (lastSlash != name.length() - 1 && name.lastIndexOf(' ') == -1)
500                     names.add(name.substring(0, lastSlash).replace('/', '.'));
501             } else {
502                 // Allow the default package to be provided. If the default package
503
// contains a File then use "." as the package name to provide for default.
504
names.add(DOT);
505             }
506         }
507         return names;
508     }
509
510     private ArrayList getLibrariesExpandingVariables(String libraryPath, boolean filter) {
511         String var = hasPrefix(libraryPath);
512         if (var == null) {
513             ArrayList returnValue = new ArrayList(1);
514             returnValue.add(libraryPath);
515             return returnValue;
516         }
517         if (var.equals("ws")) { //$NON-NLS-1$
518
return findWSJars(pluginManifestLocation, libraryPath, filter);
519         }
520         if (var.equals("os")) { //$NON-NLS-1$
521
return findOSJars(pluginManifestLocation, libraryPath, filter);
522         }
523         return new ArrayList(0);
524     }
525
526     //return a String representing the string found between the $s
527
private String hasPrefix(String libPath) {
528         if (libPath.startsWith("$ws$")) //$NON-NLS-1$
529
return "ws"; //$NON-NLS-1$
530
if (libPath.startsWith("$os$")) //$NON-NLS-1$
531
return "os"; //$NON-NLS-1$
532
if (libPath.startsWith("$nl$")) //$NON-NLS-1$
533
return "nl"; //$NON-NLS-1$
534
return null;
535     }
536
537     private boolean isValidPackageName(String name) {
538         if (name.indexOf(' ') > 0 || name.equalsIgnoreCase("META-INF") || name.startsWith("META-INF/")) //$NON-NLS-1$ //$NON-NLS-2$
539
return false;
540         return true;
541     }
542
543     /**
544      * Parses the plugin manifest to find out: - the plug-in unique identifier -
545      * the plug-in version - runtime/libraries entries - the plug-in class -
546      * the master plugin (for a fragment)
547      */

548     private IPluginInfo parsePluginInfo(URL pluginLocation) throws PluginConversionException {
549         InputStream input = null;
550         try {
551             input = new BufferedInputStream(pluginLocation.openStream());
552             return new PluginParser(context, target).parsePlugin(input);
553         } catch (Exception e) {
554             String message = EclipseAdaptorMsg.formatter.getString("ECLIPSE_CONVERTER_ERROR_PARSING_PLUGIN_MANIFEST", pluginManifestLocation); //$NON-NLS-1$
555
throw new PluginConversionException(message, e);
556         } finally {
557             if (input != null)
558                 try {
559                     input.close();
560                 } catch (IOException e) {
561                     //ignore exception
562
}
563         }
564     }
565
566     public static boolean upToDate(File generationLocation, File pluginLocation, byte manifestType) {
567         if (!generationLocation.isFile())
568             return false;
569         String secondLine = null;
570         BufferedReader reader = null;
571         try {
572             reader = new BufferedReader(new InputStreamReader(new FileInputStream(generationLocation)));
573             reader.readLine();
574             secondLine = reader.readLine();
575         } catch (IOException e) {
576             // not a big deal - we could not read an existing manifest
577
return false;
578         } finally {
579             if (reader != null)
580                 try {
581                     reader.close();
582                 } catch (IOException e) {
583                     // ignore
584
}
585         }
586         String tag = GENERATED_FROM + ": "; //$NON-NLS-1$
587
if (secondLine == null || !secondLine.startsWith(tag))
588             return false;
589
590         secondLine = secondLine.substring(tag.length());
591         ManifestElement generatedFrom;
592         try {
593             generatedFrom = ManifestElement.parseHeader(PluginConverterImpl.GENERATED_FROM, secondLine)[0];
594         } catch (BundleException be) {
595             return false;
596         }
597         String timestampStr = generatedFrom.getValue();
598         try {
599             return Long.parseLong(timestampStr.trim()) == getTimeStamp(pluginLocation, manifestType);
600         } catch (NumberFormatException nfe) {
601             // not a big deal - just a bogus existing manifest that will be ignored
602
}
603         return false;
604     }
605
606     public static long getTimeStamp(File pluginLocation, byte manifestType) {
607         if ((manifestType & EclipseBundleData.MANIFEST_TYPE_JAR) != 0)
608             return pluginLocation.lastModified();
609         else if ((manifestType & EclipseBundleData.MANIFEST_TYPE_PLUGIN) != 0)
610             return new File(pluginLocation, PLUGIN_MANIFEST).lastModified();
611         else if ((manifestType & EclipseBundleData.MANIFEST_TYPE_FRAGMENT) != 0)
612             return new File(pluginLocation, FRAGMENT_MANIFEST).lastModified();
613         else if ((manifestType & EclipseBundleData.MANIFEST_TYPE_BUNDLE) != 0)
614             return new File(pluginLocation, Constants.OSGI_BUNDLE_MANIFEST).lastModified();
615         return -1;
616     }
617
618     private void writeEntry(String key, String value) throws IOException {
619         if (value != null && value.length() > 0) {
620             out.write(key + ": " + value); //$NON-NLS-1$
621
out.newLine();
622         }
623     }
624
625     private String getStringFromArray(String[] values, String separator) {
626         if (values == null)
627             return ""; //$NON-NLS-1$
628
StringBuffer result = new StringBuffer();
629         for (int i = 0; i < values.length; i++) {
630             if (i > 0)
631                 result.append(separator);
632             result.append(values[i]);
633         }
634         return result.toString();
635     }
636
637     private String getStringFromCollection(Collection collection, String separator) {
638         StringBuffer result = new StringBuffer();
639         boolean first = true;
640         for (Iterator i = collection.iterator(); i.hasNext();) {
641             if (first)
642                 first = false;
643             else
644                 result.append(separator);
645             result.append(i.next());
646         }
647         return result.toString();
648     }
649
650     public synchronized Dictionary convertManifest(File pluginBaseLocation, boolean compatibility, String target, boolean analyseJars) throws PluginConversionException {
651         if (DEBUG)
652             System.out.println("Convert " + pluginBaseLocation); //$NON-NLS-1$
653
init();
654         this.target = target;
655         fillPluginInfo(pluginBaseLocation);
656         fillManifest(compatibility, analyseJars);
657         return generatedManifest;
658     }
659
660     public synchronized File convertManifest(File pluginBaseLocation, File bundleManifestLocation, boolean compatibilityManifest, String target, boolean analyseJars) throws PluginConversionException {
661         if (DEBUG)
662             System.out.println("Convert " + pluginBaseLocation); //$NON-NLS-1$
663
init();
664         this.target = target;
665         fillPluginInfo(pluginBaseLocation);
666         if (bundleManifestLocation == null) {
667             String cacheLocation = (String) System.getProperties().get(LocationManager.PROP_MANIFEST_CACHE);
668             bundleManifestLocation = new File(cacheLocation, pluginInfo.getUniqueId() + '_' + pluginInfo.getVersion() + ".MF"); //$NON-NLS-1$
669
}
670         fillManifest(compatibilityManifest, analyseJars);
671         if (upToDate(bundleManifestLocation, pluginManifestLocation, manifestType))
672             return bundleManifestLocation;
673         writeManifest(bundleManifestLocation, generatedManifest, compatibilityManifest);
674         return bundleManifestLocation;
675     }
676
677     private String getVersionRange(String reqVersion, String matchRule) {
678         if (reqVersion == null)
679             return null;
680
681         Version minVersion = new Version(reqVersion);
682         String versionRange;
683         if (matchRule != null) {
684             if (matchRule.equalsIgnoreCase(IModel.PLUGIN_REQUIRES_MATCH_PERFECT)) {
685                 versionRange = new VersionRange(minVersion, minVersion).toString();
686             } else if (matchRule.equalsIgnoreCase(IModel.PLUGIN_REQUIRES_MATCH_EQUIVALENT)) {
687                 versionRange = new VersionRange(minVersion, new Version(minVersion.getMajorComponent(), minVersion.getMinorComponent() + 1, 0, "", false)).toString(); //$NON-NLS-1$
688
} else if (matchRule.equalsIgnoreCase(IModel.PLUGIN_REQUIRES_MATCH_COMPATIBLE)) {
689                 versionRange = new VersionRange(minVersion, new Version(minVersion.getMajorComponent() + 1, 0, 0, "", false)).toString(); //$NON-NLS-1$
690
} else if (matchRule.equalsIgnoreCase(IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL)) {
691                 // just return the reqVersion here without any version range
692
versionRange = reqVersion;
693             } else {
694                 versionRange = new VersionRange(minVersion, new Version(minVersion.getMajorComponent() + 1, 0, 0, "", false)).toString(); //$NON-NLS-1$
695
}
696         } else {
697             versionRange = new VersionRange(minVersion, new Version(minVersion.getMajorComponent() + 1, 0, 0, "", false)).toString(); //$NON-NLS-1$
698
}
699
700         StringBuffer result = new StringBuffer();
701         result.append(';').append(Constants.BUNDLE_VERSION_ATTRIBUTE).append('=');
702         result.append('\"').append(versionRange).append('\"');
703         return result.toString();
704     }
705 }
Popular Tags