KickJava   Java API By Example, From Geeks To Geeks.

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


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

11 package org.eclipse.core.runtime.internal.adaptor;
12
13 import java.io.*;
14 import java.net.MalformedURLException JavaDoc;
15 import java.net.URL JavaDoc;
16 import java.util.*;
17 import java.util.zip.ZipEntry JavaDoc;
18 import java.util.zip.ZipFile JavaDoc;
19 import org.eclipse.core.runtime.adaptor.*;
20 import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
21 import org.eclipse.osgi.framework.internal.core.Constants;
22 import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
23 import org.eclipse.osgi.framework.log.FrameworkLogEntry;
24 import org.eclipse.osgi.internal.baseadaptor.DevClassPathHelper;
25 import org.eclipse.osgi.service.pluginconversion.PluginConversionException;
26 import org.eclipse.osgi.service.pluginconversion.PluginConverter;
27 import org.eclipse.osgi.service.resolver.VersionRange;
28 import org.eclipse.osgi.util.ManifestElement;
29 import org.eclipse.osgi.util.NLS;
30 import org.osgi.framework.*;
31
32 /**
33  * Internal class.
34  */

35 public class PluginConverterImpl implements PluginConverter {
36     public static boolean DEBUG = false;
37     /** bundle manifest type unknown */
38     static public final byte MANIFEST_TYPE_UNKNOWN = 0x00;
39     /** bundle manifest type bundle (META-INF/MANIFEST.MF) */
40     static public final byte MANIFEST_TYPE_BUNDLE = 0x01;
41     /** bundle manifest type plugin (plugin.xml) */
42     static public final byte MANIFEST_TYPE_PLUGIN = 0x02;
43     /** bundle manifest type fragment (fragment.xml) */
44     static public final byte MANIFEST_TYPE_FRAGMENT = 0x04;
45     /** bundle manifest type jared bundle */
46     static public final byte MANIFEST_TYPE_JAR = 0x08;
47     private static final String JavaDoc SEMICOLON = "; "; //$NON-NLS-1$
48
private static final String JavaDoc UTF_8 = "UTF-8"; //$NON-NLS-1$
49
private static final String JavaDoc LIST_SEPARATOR = ",\n "; //$NON-NLS-1$
50
private static final String JavaDoc LINE_SEPARATOR = "\n "; //$NON-NLS-1$
51
private static final String JavaDoc DOT = "."; //$NON-NLS-1$
52
private static int MAXLINE = 511;
53     private BundleContext context;
54     private FrameworkAdaptor adaptor;
55     private BufferedWriter out;
56     private IPluginInfo pluginInfo;
57     private File JavaDoc pluginManifestLocation;
58     private Dictionary generatedManifest;
59     private byte manifestType;
60     private Version target;
61     private Dictionary devProperties;
62     static final Version TARGET31 = new Version(3, 1, 0);
63     static final Version TARGET32 = new Version(3, 2, 0);
64     private static final String JavaDoc MANIFEST_VERSION = "Manifest-Version"; //$NON-NLS-1$
65
private static final String JavaDoc PLUGIN_PROPERTIES_FILENAME = "plugin"; //$NON-NLS-1$
66
private static PluginConverterImpl instance;
67     private static final String JavaDoc[] 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};
68     static public final String JavaDoc FRAGMENT_MANIFEST = "fragment.xml"; //$NON-NLS-1$
69
static public final String JavaDoc GENERATED_FROM = "Generated-from"; //$NON-NLS-1$
70
static public final String JavaDoc MANIFEST_TYPE_ATTRIBUTE = "type"; //$NON-NLS-1$
71
private static final String JavaDoc[] 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};
72     protected static final String JavaDoc PI_RUNTIME = "org.eclipse.core.runtime"; //$NON-NLS-1$
73
protected static final String JavaDoc PI_BOOT = "org.eclipse.core.boot"; //$NON-NLS-1$
74
protected static final String JavaDoc PI_RUNTIME_COMPATIBILITY = "org.eclipse.core.runtime.compatibility"; //$NON-NLS-1$
75
static public final String JavaDoc PLUGIN_MANIFEST = "plugin.xml"; //$NON-NLS-1$
76
private static final String JavaDoc COMPATIBILITY_ACTIVATOR = "org.eclipse.core.internal.compatibility.PluginActivator"; //$NON-NLS-1$
77
private static final String JavaDoc[] 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};
78     private static final String JavaDoc IGNORE_DOT = "@ignoredot@"; //$NON-NLS-1$
79

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

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

585     private IPluginInfo parsePluginInfo(URL JavaDoc pluginLocation) throws PluginConversionException {
586         InputStream input = null;
587         try {
588             input = new BufferedInputStream(pluginLocation.openStream());
589             return new PluginParser(adaptor, context, target).parsePlugin(input);
590         } catch (Exception JavaDoc e) {
591             String JavaDoc message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_ERROR_PARSING_PLUGIN_MANIFEST, pluginManifestLocation);
592             throw new PluginConversionException(message, e);
593         } finally {
594             if (input != null)
595                 try {
596                     input.close();
597                 } catch (IOException e) {
598                     //ignore exception
599
}
600         }
601     }
602
603     public static boolean upToDate(File JavaDoc generationLocation, File JavaDoc pluginLocation, byte manifestType) {
604         if (!generationLocation.isFile())
605             return false;
606         String JavaDoc secondLine = null;
607         BufferedReader reader = null;
608         try {
609             reader = new BufferedReader(new InputStreamReader(new FileInputStream(generationLocation)));
610             reader.readLine();
611             secondLine = reader.readLine();
612         } catch (IOException e) {
613             // not a big deal - we could not read an existing manifest
614
return false;
615         } finally {
616             if (reader != null)
617                 try {
618                     reader.close();
619                 } catch (IOException e) {
620                     // ignore
621
}
622         }
623         String JavaDoc tag = GENERATED_FROM + ": "; //$NON-NLS-1$
624
if (secondLine == null || !secondLine.startsWith(tag))
625             return false;
626
627         secondLine = secondLine.substring(tag.length());
628         ManifestElement generatedFrom;
629         try {
630             generatedFrom = ManifestElement.parseHeader(PluginConverterImpl.GENERATED_FROM, secondLine)[0];
631         } catch (BundleException be) {
632             return false;
633         }
634         String JavaDoc timestampStr = generatedFrom.getValue();
635         try {
636             return Long.parseLong(timestampStr.trim()) == getTimeStamp(pluginLocation, manifestType);
637         } catch (NumberFormatException JavaDoc nfe) {
638             // not a big deal - just a bogus existing manifest that will be ignored
639
}
640         return false;
641     }
642
643     public static long getTimeStamp(File JavaDoc pluginLocation, byte manifestType) {
644         if ((manifestType & MANIFEST_TYPE_JAR) != 0)
645             return pluginLocation.lastModified();
646         else if ((manifestType & MANIFEST_TYPE_PLUGIN) != 0)
647             return new File JavaDoc(pluginLocation, PLUGIN_MANIFEST).lastModified();
648         else if ((manifestType & MANIFEST_TYPE_FRAGMENT) != 0)
649             return new File JavaDoc(pluginLocation, FRAGMENT_MANIFEST).lastModified();
650         else if ((manifestType & MANIFEST_TYPE_BUNDLE) != 0)
651             return new File JavaDoc(pluginLocation, Constants.OSGI_BUNDLE_MANIFEST).lastModified();
652         return -1;
653     }
654
655     private void writeEntry(String JavaDoc key, String JavaDoc value) throws IOException {
656         if (value != null && value.length() > 0) {
657             out.write(splitOnComma(key + ": " + value)); //$NON-NLS-1$
658
out.write('\n');
659         }
660     }
661
662     private String JavaDoc splitOnComma(String JavaDoc value) {
663         if (value.length() < MAXLINE || value.indexOf(LINE_SEPARATOR) >= 0)
664             return value; // assume the line is already split
665
String JavaDoc[] values = ManifestElement.getArrayFromList(value);
666         if (values == null || values.length == 0)
667             return value;
668         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(value.length() + ((values.length - 1) * LIST_SEPARATOR.length()));
669         for (int i = 0; i < values.length - 1; i++)
670             sb.append(values[i]).append(LIST_SEPARATOR);
671         sb.append(values[values.length -1]);
672         return sb.toString();
673     }
674
675     private String JavaDoc getStringFromArray(String JavaDoc[] values, String JavaDoc separator) {
676         if (values == null)
677             return ""; //$NON-NLS-1$
678
StringBuffer JavaDoc result = new StringBuffer JavaDoc();
679         for (int i = 0; i < values.length; i++) {
680             if (i > 0)
681                 result.append(separator);
682             result.append(values[i]);
683         }
684         return result.toString();
685     }
686
687     private String JavaDoc getStringFromCollection(Collection collection, String JavaDoc separator) {
688         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
689         boolean first = true;
690         for (Iterator i = collection.iterator(); i.hasNext();) {
691             if (first)
692                 first = false;
693             else
694                 result.append(separator);
695             result.append(i.next());
696         }
697         return result.toString();
698     }
699
700     public synchronized Dictionary convertManifest(File JavaDoc pluginBaseLocation, boolean compatibility, String JavaDoc target, boolean analyseJars, Dictionary devProperties) throws PluginConversionException {
701         long start = System.currentTimeMillis();
702         if (DEBUG)
703             System.out.println("Convert " + pluginBaseLocation); //$NON-NLS-1$
704
init();
705         this.target = target == null ? TARGET32 : new Version(target);
706         this.devProperties = devProperties;
707         fillPluginInfo(pluginBaseLocation);
708         fillManifest(compatibility, analyseJars);
709         if (DEBUG)
710             System.out.println("Time to convert manifest for: " + pluginBaseLocation + ": " + (System.currentTimeMillis() - start) + "ms."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
711
return generatedManifest;
712     }
713
714     public synchronized File JavaDoc convertManifest(File JavaDoc pluginBaseLocation, File JavaDoc bundleManifestLocation, boolean compatibilityManifest, String JavaDoc target, boolean analyseJars, Dictionary devProperties) throws PluginConversionException {
715         convertManifest(pluginBaseLocation, compatibilityManifest, target, analyseJars, devProperties);
716         if (bundleManifestLocation == null) {
717             String JavaDoc cacheLocation = FrameworkProperties.getProperty(LocationManager.PROP_MANIFEST_CACHE);
718             bundleManifestLocation = new File JavaDoc(cacheLocation, pluginInfo.getUniqueId() + '_' + pluginInfo.getVersion() + ".MF"); //$NON-NLS-1$
719
}
720         if (upToDate(bundleManifestLocation, pluginManifestLocation, manifestType))
721             return bundleManifestLocation;
722         writeManifest(bundleManifestLocation, generatedManifest, compatibilityManifest);
723         return bundleManifestLocation;
724     }
725
726     private String JavaDoc getVersionRange(String JavaDoc reqVersion, String JavaDoc matchRule) {
727         if (reqVersion == null)
728             return null;
729
730         Version minVersion = Version.parseVersion(reqVersion);
731         String JavaDoc versionRange;
732         if (matchRule != null) {
733             if (matchRule.equalsIgnoreCase(IModel.PLUGIN_REQUIRES_MATCH_PERFECT)) {
734                 versionRange = new VersionRange(minVersion, true, minVersion, true).toString();
735             } else if (matchRule.equalsIgnoreCase(IModel.PLUGIN_REQUIRES_MATCH_EQUIVALENT)) {
736                 versionRange = new VersionRange(minVersion, true, new Version(minVersion.getMajor(), minVersion.getMinor() + 1, 0, ""), false).toString(); //$NON-NLS-1$
737
} else if (matchRule.equalsIgnoreCase(IModel.PLUGIN_REQUIRES_MATCH_COMPATIBLE)) {
738                 versionRange = new VersionRange(minVersion, true, new Version(minVersion.getMajor() + 1, 0, 0, ""), false).toString(); //$NON-NLS-1$
739
} else if (matchRule.equalsIgnoreCase(IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL)) {
740                 // just return the reqVersion here without any version range
741
versionRange = reqVersion;
742             } else {
743                 versionRange = new VersionRange(minVersion, true, new Version(minVersion.getMajor() + 1, 0, 0, ""), false).toString(); //$NON-NLS-1$
744
}
745         } else {
746             versionRange = new VersionRange(minVersion, true, new Version(minVersion.getMajor() + 1, 0, 0, ""), false).toString(); //$NON-NLS-1$
747
}
748
749         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
750         result.append(';').append(Constants.BUNDLE_VERSION_ATTRIBUTE).append('=');
751         result.append('\"').append(versionRange).append('\"');
752         return result.toString();
753     }
754 }
755
Popular Tags