KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2005, 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
12 package org.eclipse.core.runtime.internal.adaptor;
13
14 import java.io.*;
15 import java.net.URL JavaDoc;
16 import java.util.*;
17 import org.eclipse.core.runtime.adaptor.LocationManager;
18 import org.eclipse.osgi.baseadaptor.*;
19 import org.eclipse.osgi.baseadaptor.hooks.StorageHook;
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.framework.util.Headers;
25 import org.eclipse.osgi.framework.util.KeyedElement;
26 import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
27 import org.eclipse.osgi.service.datalocation.Location;
28 import org.eclipse.osgi.service.pluginconversion.PluginConversionException;
29 import org.eclipse.osgi.util.ManifestElement;
30 import org.eclipse.osgi.util.NLS;
31 import org.osgi.framework.BundleException;
32 import org.osgi.framework.Version;
33
34 public final class EclipseStorageHook implements StorageHook, HookConfigurator {
35     // System property used to check timestamps of the bundles in the configuration
36
private static final String JavaDoc PROP_CHECK_CONFIG = "osgi.checkConfiguration"; //$NON-NLS-1$
37
private static final String JavaDoc PROP_COMPATIBILITY_LAZYSTART = "osgi.compatibility.eagerStart.LazyActivation"; //$NON-NLS-1$
38
private static final boolean COMPATIBILITY_LAZYSTART = Boolean.valueOf(FrameworkProperties.getProperty(PROP_COMPATIBILITY_LAZYSTART, "true")).booleanValue(); //$NON-NLS-1$
39
private static final int STORAGE_VERION = 2;
40
41     public static final String JavaDoc KEY = EclipseStorageHook.class.getName();
42     public static final int HASHCODE = KEY.hashCode();
43
44     private static final byte FLAG_LAZY_START = 0x01;
45     private static final byte FLAG_HAS_PACKAGE_INFO = 0x02;
46     // Note that the 0x04 was used in previous versions, if a new flag is needed then do not reuse this one
47
//private static final byte FLAG_ACTIVATE_ON_CLASSLOAD = 0x04;
48
// Flag to indicate that an include directive is present on the lazy activation policy
49
private static final byte FLAG_HAS_LAZY_INCLUDE = 0x08;
50
51     /** data to detect modification made in the manifest */
52     private long manifestTimeStamp = 0;
53     private byte manifestType = PluginConverterImpl.MANIFEST_TYPE_UNKNOWN;
54
55     private BaseData bundledata;
56
57     /** the Plugin-Class header */
58     private String JavaDoc pluginClass = null;
59     /** Eclipse-LazyStart header */
60     private String JavaDoc[] lazyStartExcludes;
61     private String JavaDoc[] lazyStartIncludes;
62     /** shortcut to know if a bundle has a buddy */
63     private String JavaDoc buddyList;
64     /** shortcut to know if a bundle is a registrant to a registered policy */
65     private String JavaDoc registeredBuddyList;
66     private byte flags = 0;
67
68     public int getStorageVersion() {
69         return STORAGE_VERION;
70     }
71
72     public StorageHook create(BaseData bundledata) throws BundleException {
73         EclipseStorageHook storageHook = new EclipseStorageHook();
74         storageHook.bundledata = bundledata;
75         return storageHook;
76     }
77
78     public void initialize(Dictionary manifest) throws BundleException {
79         String JavaDoc activationPolicy = (String JavaDoc) manifest.get(Constants.BUNDLE_ACTIVATIONPOLICY);
80         if (activationPolicy != null) {
81             parseActivationPolicy(this, activationPolicy);
82         } else {
83             String JavaDoc lazyStart = (String JavaDoc) manifest.get(Constants.ECLIPSE_LAZYSTART);
84             if (lazyStart == null)
85                 lazyStart = (String JavaDoc) manifest.get(Constants.ECLIPSE_AUTOSTART);
86             parseLazyStart(this, lazyStart);
87         }
88         pluginClass = (String JavaDoc) manifest.get(Constants.PLUGIN_CLASS);
89         buddyList = (String JavaDoc) manifest.get(Constants.BUDDY_LOADER);
90         registeredBuddyList = (String JavaDoc) manifest.get(Constants.REGISTERED_POLICY);
91         if (hasPackageInfo(bundledata.getEntry(Constants.OSGI_BUNDLE_MANIFEST)))
92             flags |= FLAG_HAS_PACKAGE_INFO;
93         String JavaDoc genFrom = (String JavaDoc) manifest.get(PluginConverterImpl.GENERATED_FROM);
94         if (genFrom != null) {
95             ManifestElement generatedFrom = ManifestElement.parseHeader(PluginConverterImpl.GENERATED_FROM, genFrom)[0];
96             if (generatedFrom != null) {
97                 manifestTimeStamp = Long.parseLong(generatedFrom.getValue());
98                 manifestType = Byte.parseByte(generatedFrom.getAttribute(PluginConverterImpl.MANIFEST_TYPE_ATTRIBUTE));
99             }
100         }
101         if (isAutoStartable()) {
102             bundledata.setStatus(bundledata.getStatus() | Constants.BUNDLE_LAZY_START);
103             if (COMPATIBILITY_LAZYSTART)
104                 bundledata.setStatus(bundledata.getStatus() | Constants.BUNDLE_STARTED | Constants.BUNDLE_ACTIVATION_POLICY);
105         }
106     }
107
108     public StorageHook load(BaseData target, DataInputStream in) throws IOException {
109         EclipseStorageHook storageHook = new EclipseStorageHook();
110         storageHook.bundledata = target;
111         storageHook.flags = in.readByte();
112         int pkgCount = in.readInt();
113         String JavaDoc[] packageList = pkgCount > 0 ? new String JavaDoc[pkgCount] : null;
114         for (int i = 0; i < pkgCount; i++)
115             packageList[i] = in.readUTF();
116         storageHook.lazyStartExcludes = packageList;
117         if ((storageHook.flags & FLAG_HAS_LAZY_INCLUDE) != 0) {
118             pkgCount = in.readInt();
119             packageList = pkgCount > 0 ? new String JavaDoc[pkgCount] : null;
120             for (int i = 0; i < pkgCount; i++)
121                 packageList[i] = in.readUTF();
122             storageHook.lazyStartIncludes = packageList;
123         }
124         storageHook.buddyList = AdaptorUtil.readString(in, false);
125         storageHook.registeredBuddyList = AdaptorUtil.readString(in, false);
126         storageHook.pluginClass = AdaptorUtil.readString(in, false);
127         storageHook.manifestTimeStamp = in.readLong();
128         storageHook.manifestType = in.readByte();
129         if (storageHook.isAutoStartable()) {
130             if ((target.getStatus() & Constants.BUNDLE_LAZY_START) == 0)
131                 target.setStatus(target.getStatus() | Constants.BUNDLE_LAZY_START);
132             // if the compatibility flag is set then we must make sure the persistent start bit is set and the activation policy bit;
133
// if the persistent start bit was already set then we should not set the activation policy bit because this is an "eager" started bundle.
134
if (COMPATIBILITY_LAZYSTART && (target.getStatus() & Constants.BUNDLE_STARTED ) == 0)
135                 target.setStatus(target.getStatus() | Constants.BUNDLE_STARTED | Constants.BUNDLE_ACTIVATION_POLICY);
136         }
137         return storageHook;
138     }
139
140     public void save(DataOutputStream out) throws IOException {
141         if (bundledata == null)
142             throw new IllegalStateException JavaDoc();
143         // when this is stored back we always use the has include/exclude flag
144
out.writeByte(flags);
145         String JavaDoc[] excludes = getLazyStartExcludes();
146         if (excludes == null)
147             out.writeInt(0);
148         else {
149             out.writeInt(excludes.length);
150             for (int i = 0; i < excludes.length; i++)
151                 out.writeUTF(excludes[i]);
152         }
153         if ((flags & FLAG_HAS_LAZY_INCLUDE) != 0) {
154             String JavaDoc[] includes = getLazyStartIncludes();
155             if (includes == null)
156                 out.writeInt(0);
157             else {
158                 out.writeInt(includes.length);
159                 for (int i = 0; i < includes.length; i++)
160                     out.writeUTF(includes[i]);
161             }
162         }
163         AdaptorUtil.writeStringOrNull(out, getBuddyList());
164         AdaptorUtil.writeStringOrNull(out, getRegisteredBuddyList());
165         AdaptorUtil.writeStringOrNull(out, getPluginClass());
166         out.writeLong(getManifestTimeStamp());
167         out.writeByte(getManifestType());
168     }
169
170     public int getKeyHashCode() {
171         return HASHCODE;
172     }
173
174     public boolean compare(KeyedElement other) {
175         return other.getKey() == KEY;
176     }
177
178     public Object JavaDoc getKey() {
179         return KEY;
180     }
181
182     public boolean isLazyStart() {
183         return (flags & FLAG_LAZY_START) == FLAG_LAZY_START;
184     }
185
186     public String JavaDoc[] getLazyStartExcludes() {
187         return lazyStartExcludes;
188     }
189
190     public String JavaDoc[] getLazyStartIncludes() {
191         return lazyStartIncludes;
192     }
193
194     public String JavaDoc getBuddyList() {
195         return buddyList;
196     }
197
198     public boolean hasPackageInfo() {
199         return (flags & FLAG_HAS_PACKAGE_INFO) == FLAG_HAS_PACKAGE_INFO;
200     }
201
202     public String JavaDoc getPluginClass() {
203         return pluginClass;
204     }
205
206     public String JavaDoc getRegisteredBuddyList() {
207         return registeredBuddyList;
208     }
209
210     public long getManifestTimeStamp() {
211         return manifestTimeStamp;
212     }
213
214     public byte getManifestType() {
215         return manifestType;
216     }
217
218     /**
219      * Checks whether this bundle is auto started for all resource/class loads or only for a
220      * subset of resource/classloads
221      * @return true if the bundle is auto started; false otherwise
222      */

223     public boolean isAutoStartable() {
224         return isLazyStart() || (lazyStartExcludes != null && lazyStartExcludes.length > 0);
225     }
226
227     private void parseLazyStart(EclipseStorageHook storageHook, String JavaDoc headerValue) {
228         storageHook.lazyStartExcludes = null;
229         ManifestElement[] allElements = null;
230         try {
231             allElements = ManifestElement.parseHeader(Constants.ECLIPSE_LAZYSTART, headerValue);
232         } catch (BundleException e) {
233             // just use the default settings (no auto activation)
234
String JavaDoc message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_CANNOT_GET_HEADERS, storageHook.bundledata.getLocation());
235             bundledata.getAdaptor().getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, e, null));
236         }
237         //Eclipse-AutoStart not found...
238
if (allElements == null)
239             return;
240         // the single value for this element should be true|false
241
if ("true".equalsIgnoreCase(allElements[0].getValue())) //$NON-NLS-1$
242
storageHook.flags |= FLAG_LAZY_START;
243         // look for any exceptions (the attribute) to the autoActivate setting
244
String JavaDoc[] exceptions = ManifestElement.getArrayFromList(allElements[0].getAttribute(Constants.ECLIPSE_LAZYSTART_EXCEPTIONS));
245         storageHook.lazyStartExcludes = exceptions;
246     }
247
248     private void parseActivationPolicy(EclipseStorageHook storageHook, String JavaDoc headerValue) {
249         storageHook.lazyStartExcludes = null;
250         ManifestElement[] allElements = null;
251         try {
252             allElements = ManifestElement.parseHeader(Constants.BUNDLE_ACTIVATIONPOLICY, headerValue);
253         } catch (BundleException e) {
254             // just use the default settings (no auto activation)
255
String JavaDoc message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_CANNOT_GET_HEADERS, storageHook.bundledata.getLocation());
256             bundledata.getAdaptor().getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, e, null));
257         }
258         //Bundle-ActivationPolicy not found.
259
if (allElements == null)
260             return;
261         // the single value for this type is lazy
262
if (!Constants.ACTIVATION_LAZY.equalsIgnoreCase(allElements[0].getValue())) //$NON-NLS-1$
263
return;
264         storageHook.flags |= FLAG_LAZY_START;
265         // look for any include or exclude attrs
266
storageHook.lazyStartExcludes = ManifestElement.getArrayFromList(allElements[0].getDirective(Constants.EXCLUDE_DIRECTIVE));
267         storageHook.lazyStartIncludes = ManifestElement.getArrayFromList(allElements[0].getDirective(Constants.INCLUDE_DIRECTIVE));
268         if (storageHook.lazyStartIncludes != null)
269             storageHook.flags |= FLAG_HAS_LAZY_INCLUDE;
270     }
271
272     // Used to check the bundle manifest file for any package information.
273
// This is used when '.' is on the Bundle-ClassPath to prevent reading
274
// the bundle manifest for pacakge information when loading classes.
275
private static boolean hasPackageInfo(URL JavaDoc url) {
276         if (url == null)
277             return false;
278         BufferedReader br = null;
279         try {
280             br = new BufferedReader(new InputStreamReader(url.openStream()));
281             String JavaDoc line;
282             while ((line = br.readLine()) != null) {
283                 if (line.startsWith("Specification-Title: ") || line.startsWith("Specification-Version: ") || line.startsWith("Specification-Vendor: ") || line.startsWith("Implementation-Title: ") || line.startsWith("Implementation-Version: ") || line.startsWith("Implementation-Vendor: ")) //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
284
return true;
285             }
286         } catch (IOException ioe) {
287             // do nothing
288
} finally {
289             if (br != null)
290                 try {
291                     br.close();
292                 } catch (IOException e) {
293                     // do nothing
294
}
295         }
296         return false;
297     }
298
299     public void addHooks(HookRegistry hookRegistry) {
300         hookRegistry.addStorageHook(this);
301     }
302
303     private void checkTimeStamp() throws IllegalArgumentException JavaDoc {
304         if (!checkManifestTimeStamp())
305             throw new IllegalArgumentException JavaDoc();
306     }
307
308     private boolean checkManifestTimeStamp() {
309         if (!"true".equalsIgnoreCase(FrameworkProperties.getProperty(EclipseStorageHook.PROP_CHECK_CONFIG))) //$NON-NLS-1$
310
return true;
311         if (PluginConverterImpl.getTimeStamp(bundledata.getBundleFile().getBaseFile(), getManifestType()) == getManifestTimeStamp()) {
312             if ((getManifestType() & (PluginConverterImpl.MANIFEST_TYPE_JAR | PluginConverterImpl.MANIFEST_TYPE_BUNDLE)) != 0)
313                 return true;
314             String JavaDoc cacheLocation = FrameworkProperties.getProperty(LocationManager.PROP_MANIFEST_CACHE);
315             Location parentConfiguration = LocationManager.getConfigurationLocation().getParentLocation();
316             if (parentConfiguration != null) {
317                 try {
318                     return checkManifestAndParent(cacheLocation, bundledata.getSymbolicName(), bundledata.getVersion().toString(), getManifestType()) != null;
319                 } catch (BundleException e) {
320                     return false;
321                 }
322             }
323             File cacheFile = new File(cacheLocation, bundledata.getSymbolicName() + '_' + bundledata.getVersion() + ".MF"); //$NON-NLS-1$
324
if (cacheFile.isFile())
325                 return true;
326         }
327         return false;
328     }
329
330     private Headers checkManifestAndParent(String JavaDoc cacheLocation, String JavaDoc symbolicName, String JavaDoc version, byte inputType) throws BundleException {
331         Headers result = basicCheckManifest(cacheLocation, symbolicName, version, inputType);
332         if (result != null)
333             return result;
334         Location parentConfiguration = null;
335         if ((parentConfiguration = LocationManager.getConfigurationLocation().getParentLocation()) != null)
336             result = basicCheckManifest(new File(parentConfiguration.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME + '/' + LocationManager.MANIFESTS_DIR).toString(), symbolicName, version, inputType);
337         return result;
338     }
339
340     private Headers basicCheckManifest(String JavaDoc cacheLocation, String JavaDoc symbolicName, String JavaDoc version, byte inputType) throws BundleException {
341         File currentFile = new File(cacheLocation, symbolicName + '_' + version + ".MF"); //$NON-NLS-1$
342
if (PluginConverterImpl.upToDate(currentFile, bundledata.getBundleFile().getBaseFile(), inputType)) {
343             try {
344                 return Headers.parseManifest(new FileInputStream(currentFile));
345             } catch (FileNotFoundException e) {
346                 // do nothing.
347
}
348         }
349         return null;
350     }
351
352     Dictionary createCachedManifest(boolean firstTime) throws BundleException {
353         return firstTime ? getGeneratedManifest() : new CachedManifest(this);
354     }
355
356     public Dictionary getGeneratedManifest() throws BundleException {
357         Dictionary builtIn = AdaptorUtil.loadManifestFrom(bundledata);
358         if (builtIn != null) {
359             // the bundle has a built-in manifest - we may not have to generate one
360
if (!isComplete(builtIn)) {
361                 Dictionary generatedManifest = generateManifest(builtIn);
362                 if (generatedManifest != null)
363                     return generatedManifest;
364             }
365             // the manifest is complete or we could not complete it - take it as it is
366
manifestType = PluginConverterImpl.MANIFEST_TYPE_BUNDLE;
367             if (bundledata.getBundleFile().getBaseFile().isFile()) {
368                 manifestTimeStamp = bundledata.getBundleFile().getBaseFile().lastModified();
369                 manifestType |= PluginConverterImpl.MANIFEST_TYPE_JAR;
370             } else
371                 manifestTimeStamp = bundledata.getBundleFile().getEntry(Constants.OSGI_BUNDLE_MANIFEST).getTime();
372             return builtIn;
373         }
374         Dictionary result = generateManifest(null);
375         if (result == null)
376             throw new BundleException(NLS.bind(EclipseAdaptorMsg.ECLIPSE_DATA_MANIFEST_NOT_FOUND, bundledata.getLocation()));
377         return result;
378     }
379
380     private Dictionary generateManifest(Dictionary builtIn) throws BundleException {
381         String JavaDoc cacheLocation = FrameworkProperties.getProperty(LocationManager.PROP_MANIFEST_CACHE);
382         if (bundledata.getSymbolicName() != null) {
383             Headers existingHeaders = checkManifestAndParent(cacheLocation, bundledata.getSymbolicName(), bundledata.getVersion().toString(), manifestType);
384             if (existingHeaders != null)
385                 return existingHeaders;
386         }
387
388         PluginConverterImpl converter = PluginConverterImpl.getDefault();
389         if (converter == null)
390             converter = new PluginConverterImpl(bundledata.getAdaptor(), bundledata.getAdaptor().getContext());
391
392         Dictionary generatedManifest;
393         try {
394             generatedManifest = converter.convertManifest(bundledata.getBundleFile().getBaseFile(), true, null, true, null);
395         } catch (PluginConversionException pce) {
396             String JavaDoc message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_ERROR_CONVERTING, bundledata.getBundleFile().getBaseFile());
397             throw new BundleException(message, pce);
398         }
399
400         //Now we know the symbolicId and the version of the bundle, we check to see if don't have a manifest for it already
401
Version version = Version.parseVersion((String JavaDoc) generatedManifest.get(Constants.BUNDLE_VERSION));
402         String JavaDoc symbolicName = ManifestElement.parseHeader(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME, (String JavaDoc) generatedManifest.get(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME))[0].getValue();
403         ManifestElement generatedFrom = ManifestElement.parseHeader(PluginConverterImpl.GENERATED_FROM, (String JavaDoc) generatedManifest.get(PluginConverterImpl.GENERATED_FROM))[0];
404         Headers existingHeaders = checkManifestAndParent(cacheLocation, symbolicName, version.toString(), Byte.parseByte(generatedFrom.getAttribute(PluginConverterImpl.MANIFEST_TYPE_ATTRIBUTE)));
405         //We don't have a manifest.
406
manifestTimeStamp = Long.parseLong(generatedFrom.getValue());
407         manifestType = Byte.parseByte(generatedFrom.getAttribute(PluginConverterImpl.MANIFEST_TYPE_ATTRIBUTE));
408         if (bundledata.getAdaptor().isReadOnly() || existingHeaders != null)
409             return existingHeaders;
410
411         //merge the original manifest with the generated one
412
if (builtIn != null) {
413             Enumeration keysEnum = builtIn.keys();
414             while (keysEnum.hasMoreElements()) {
415                 Object JavaDoc key = keysEnum.nextElement();
416                 generatedManifest.put(key, builtIn.get(key));
417             }
418         }
419
420         //write the generated manifest
421
File bundleManifestLocation = new File(cacheLocation, symbolicName + '_' + version.toString() + ".MF"); //$NON-NLS-1$
422
try {
423             converter.writeManifest(bundleManifestLocation, generatedManifest, true);
424         } catch (Exception JavaDoc e) {
425             //TODO Need to log
426
}
427         return generatedManifest;
428
429     }
430
431     private boolean isComplete(Dictionary manifest) {
432         // a manifest is complete if it has a Bundle-SymbolicName entry...
433
if (manifest.get(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME) != null)
434             return true;
435         // ...or it does not have a plugin/fragment manifest where to get the other entries from
436
return bundledata.getEntry(PluginConverterImpl.PLUGIN_MANIFEST) == null && bundledata.getEntry(PluginConverterImpl.FRAGMENT_MANIFEST) == null;
437     }
438
439     public BaseData getBaseData() {
440         return bundledata;
441     }
442
443     public void copy(StorageHook storageHook) {
444         // copy nothing all must be re-read from a manifest
445
}
446
447     public void validate() throws IllegalArgumentException JavaDoc {
448         checkTimeStamp();
449     }
450
451     public FrameworkAdaptor getAdaptor() {
452         if (bundledata != null)
453             return bundledata.getAdaptor();
454         return null;
455     }
456
457     public Dictionary getManifest(boolean firstLoad) throws BundleException {
458         return createCachedManifest(firstLoad);
459     }
460
461     public boolean forgetStatusChange(int status) {
462         return false;
463     }
464
465     public boolean forgetStartLevelChange(int startlevel) {
466         return false;
467     }
468
469     public boolean matchDNChain(String JavaDoc pattern) {
470         return false;
471     }
472 }
473
Popular Tags