KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2003, 2005 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.adaptor;
12
13 import java.io.*;
14 import java.net.MalformedURLException JavaDoc;
15 import java.net.URL JavaDoc;
16 import java.util.*;
17 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
18 import javax.xml.parsers.SAXParserFactory JavaDoc;
19 import org.eclipse.core.runtime.internal.adaptor.*;
20 import org.eclipse.core.runtime.internal.stats.StatsManager;
21 import org.eclipse.osgi.framework.adaptor.*;
22 import org.eclipse.osgi.framework.adaptor.core.*;
23 import org.eclipse.osgi.framework.console.CommandProvider;
24 import org.eclipse.osgi.framework.debug.Debug;
25 import org.eclipse.osgi.framework.debug.FrameworkDebugOptions;
26 import org.eclipse.osgi.framework.internal.core.Constants;
27 import org.eclipse.osgi.framework.log.FrameworkLog;
28 import org.eclipse.osgi.framework.log.FrameworkLogEntry;
29 import org.eclipse.osgi.service.datalocation.Location;
30 import org.eclipse.osgi.service.pluginconversion.PluginConverter;
31 import org.eclipse.osgi.service.resolver.*;
32 import org.eclipse.osgi.service.urlconversion.URLConverter;
33 import org.eclipse.osgi.util.NLS;
34 import org.osgi.framework.*;
35
36 /**
37  * The FrameworkAdaptor implementation used to launch to OSGi framework for Eclipse.
38  * <p>
39  * Clients may extend this class.
40  * </p>
41  * @since 3.1
42  */

43 public class EclipseAdaptor extends AbstractFrameworkAdaptor {
44     /** System property used to clean the osgi configuration area */
45     public static final String JavaDoc PROP_CLEAN = "osgi.clean"; //$NON-NLS-1$
46
/** System property used to prevent VM exit when unexpected errors occur */
47     public static final String JavaDoc PROP_EXITONERROR = "eclipse.exitOnError"; //$NON-NLS-1$
48

49     static final String JavaDoc F_LOG = ".log"; //$NON-NLS-1$
50
/** Manifest header used to specify the plugin class */
51     // TODO rename it to Eclipse-PluginClass
52
public static final String JavaDoc PLUGIN_CLASS = "Plugin-Class"; //$NON-NLS-1$
53
/** Manifest header used to specify the auto start properties of a bundle */
54     public static final String JavaDoc ECLIPSE_AUTOSTART = "Eclipse-AutoStart"; //$NON-NLS-1$
55

56     /** An Eclipse-AutoStart attribute used to specify exception classes for auto start */
57     public static final String JavaDoc ECLIPSE_AUTOSTART_EXCEPTIONS = "exceptions"; //$NON-NLS-1$
58
/** The SAX factory name */
59     public static final String JavaDoc SAXFACTORYNAME = "javax.xml.parsers.SAXParserFactory"; //$NON-NLS-1$
60
/** The DOM factory name */
61     public static final String JavaDoc DOMFACTORYNAME = "javax.xml.parsers.DocumentBuilderFactory"; //$NON-NLS-1$
62

63     private static final String JavaDoc RUNTIME_ADAPTOR = FRAMEWORK_SYMBOLICNAME + "/eclipseadaptor"; //$NON-NLS-1$
64

65     private static final String JavaDoc OPTION_PLATFORM_ADMIN = RUNTIME_ADAPTOR + "/debug/platformadmin"; //$NON-NLS-1$
66

67     private static final String JavaDoc OPTION_PLATFORM_ADMIN_RESOLVER = RUNTIME_ADAPTOR + "/debug/platformadmin/resolver"; //$NON-NLS-1$
68

69     private static final String JavaDoc OPTION_MONITOR_PLATFORM_ADMIN = RUNTIME_ADAPTOR + "/resolver/timing"; //$NON-NLS-1$
70

71     private static final String JavaDoc OPTION_RESOLVER_READER = RUNTIME_ADAPTOR + "/resolver/reader/timing"; //$NON-NLS-1$
72

73     private static final String JavaDoc OPTION_CONVERTER = RUNTIME_ADAPTOR + "/converter/debug"; //$NON-NLS-1$
74

75     private static final String JavaDoc OPTION_LOCATION = RUNTIME_ADAPTOR + "/debug/location"; //$NON-NLS-1$
76

77     /** The current bundle data version */
78     public static final byte BUNDLEDATA_VERSION = 16;
79     /** The NULL tag used in bundle data */
80     public static final byte NULL = 0;
81     /** The OBJECT tag used in bundle data */
82     public static final byte OBJECT = 1;
83
84     private static EclipseAdaptor instance;
85
86     private byte cacheVersion;
87
88     private long timeStamp = 0;
89
90     // assume a file: installURL
91
private String JavaDoc installPath = null;
92
93     private boolean exitOnError = true;
94
95     private BundleStopper stopper;
96
97     private FileManager fileManager;
98
99     private boolean reinitialize = false;
100
101     /**
102      * Should be instantiated only by the framework (through reflection).
103      * @param args the adaptor arguments
104      */

105     public EclipseAdaptor(String JavaDoc[] args) {
106         super(args);
107         instance = this;
108         setDebugOptions();
109     }
110
111     /**
112      * Gets the default instance
113      * @return the default instance
114      */

115     public static EclipseAdaptor getDefault() {
116         return instance;
117     }
118
119     private FrameworkLog createPerformanceLog() {
120         String JavaDoc logFileProp = System.getProperty(EclipseStarter.PROP_LOGFILE);
121         if (logFileProp != null) {
122             int lastSlash = logFileProp.lastIndexOf(File.separatorChar);
123             if (lastSlash > 0) {
124                 String JavaDoc logFile = logFileProp.substring(0, lastSlash + 1) + "performance.log"; //$NON-NLS-1$
125
return new EclipseLog(new File(logFile));
126             }
127         }
128         //if all else fails, write to std err
129
return new EclipseLog(new PrintWriter(System.err));
130     }
131
132     /**
133      * @see FrameworkAdaptor#initialize(EventPublisher)
134      */

135     public void initialize(EventPublisher publisher) {
136         if (Boolean.getBoolean(EclipseAdaptor.PROP_CLEAN))
137             cleanOSGiCache();
138         boolean readOnlyConfiguration = LocationManager.getConfigurationLocation().isReadOnly();
139         fileManager = initFileManager(LocationManager.getOSGiConfigurationDir(), readOnlyConfiguration ? "none" : null, readOnlyConfiguration); //$NON-NLS-1$
140
readHeaders();
141         super.initialize(publisher);
142         // default the bootdelegation to all packages
143
if (System.getProperty(Constants.OSGI_BOOTDELEGATION) == null && !Constants.OSGI_BOOTDELEGATION_NONE.equals(System.getProperty(Constants.OSGI_JAVA_PROFILE_BOOTDELEGATION)))
144             System.getProperties().put(Constants.OSGI_BOOTDELEGATION, "*"); //$NON-NLS-1$
145
// we need to set the install path as soon as possible so we can determine
146
// the absolute location of install relative URLs
147
Location installLoc = LocationManager.getInstallLocation();
148         if (installLoc != null) {
149             URL JavaDoc installURL = installLoc.getURL();
150             // assume install URL is file: based
151
installPath = installURL.getPath();
152         }
153     }
154
155     /**
156      * @see AbstractFrameworkAdaptor#initializeMetadata()
157      */

158     public void initializeMetadata() {
159         // do nothing here; metadata is already initialized by readHeaders.
160
}
161
162     protected void initBundleStoreRootDir() {
163         File configurationLocation = LocationManager.getOSGiConfigurationDir();
164         if (configurationLocation != null) {
165             bundleStoreRootDir = new File(configurationLocation, LocationManager.BUNDLES_DIR);
166             bundleStore = bundleStoreRootDir.getAbsolutePath();
167         } else {
168             // last resort just default to "bundles"
169
bundleStore = LocationManager.BUNDLES_DIR;
170             bundleStoreRootDir = new File(bundleStore);
171         }
172
173         /* store bundleStore back into adaptor properties for others to see */
174         properties.put(BUNDLE_STORE, bundleStoreRootDir.getAbsolutePath());
175     }
176
177     protected FrameworkLog createFrameworkLog() {
178         if (frameworkLog != null)
179             return frameworkLog;
180         return EclipseStarter.createFrameworkLog();
181     }
182
183     private File[] findStateFiles() {
184         if (reinitialize)
185             return new File[2]; // return null enties to indicate reinitialize
186
File stateFile = null;
187         File lazyFile = null;
188         try {
189             stateFile = fileManager.lookup(LocationManager.STATE_FILE, false);
190             lazyFile = fileManager.lookup(LocationManager.LAZY_FILE, false);
191         } catch (IOException ex) {
192             if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
193                 Debug.println("Error reading state file " + ex.getMessage()); //$NON-NLS-1$
194
Debug.printStackTrace(ex);
195             }
196         }
197         //if it does not exist, try to read it from the parent
198
if (stateFile == null || !stateFile.isFile()) { // NOTE this check is redundant since it
199
// is done in StateManager, however it
200
// is more convenient to have it here
201
Location parentConfiguration = null;
202             Location currentConfiguration = LocationManager.getConfigurationLocation();
203             if (currentConfiguration != null && (parentConfiguration = currentConfiguration.getParentLocation()) != null) {
204                 try {
205                     File stateLocationDir = new File(parentConfiguration.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME);
206                     FileManager newFileManager = initFileManager(stateLocationDir, "none", true); //$NON-NLS-1$);
207
stateFile = newFileManager.lookup(LocationManager.STATE_FILE, false);
208                     lazyFile = newFileManager.lookup(LocationManager.LAZY_FILE, false);
209                 } catch (IOException ex) {
210                     if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
211                         Debug.println("Error reading state file " + ex.getMessage()); //$NON-NLS-1$
212
Debug.printStackTrace(ex);
213                     }
214                 }
215             } else {
216                 try {
217                     //it did not exist in either place, so create it in the original location
218
if (canWrite()) {
219                         stateFile = fileManager.lookup(LocationManager.STATE_FILE, true);
220                         lazyFile = fileManager.lookup(LocationManager.LAZY_FILE, true);
221                     }
222                 } catch (IOException ex) {
223                     if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
224                         Debug.println("Error reading state file " + ex.getMessage()); //$NON-NLS-1$
225
Debug.printStackTrace(ex);
226                     }
227                 }
228             }
229         }
230         return new File[] {stateFile, lazyFile};
231     }
232
233     protected StateManager createStateManager() {
234         File[] stateFiles = findStateFiles();
235         File stateFile = stateFiles[0];
236         File lazyFile = stateFiles[1];
237
238         stateManager = new StateManager(stateFile, lazyFile, context, timeStamp);
239         stateManager.setInstaller(new EclipseBundleInstaller(context));
240         State systemState = null;
241         if (!invalidState) {
242             systemState = stateManager.readSystemState();
243             if (systemState != null)
244                 return stateManager;
245         }
246         systemState = stateManager.createSystemState();
247         Bundle[] installedBundles = context.getBundles();
248         if (installedBundles == null)
249             return stateManager;
250         StateObjectFactory factory = stateManager.getFactory();
251         for (int i = 0; i < installedBundles.length; i++) {
252             Bundle toAdd = installedBundles[i];
253             try {
254                 Dictionary toAddManifest = toAdd.getHeaders(""); //$NON-NLS-1$
255
// if this is a cached manifest need to get the real one
256
if (toAddManifest instanceof CachedManifest)
257                     toAddManifest = ((CachedManifest) toAddManifest).getManifest();
258                 BundleDescription newDescription = factory.createBundleDescription(systemState, toAddManifest, toAdd.getLocation(), toAdd.getBundleId());
259                 systemState.addBundle(newDescription);
260             } catch (BundleException be) {
261                 // just ignore bundle datas with invalid manifests
262
}
263         }
264         // we need the state resolved
265
systemState.setTimeStamp(timeStamp);
266         systemState.resolve();
267         invalidState = false;
268         return stateManager;
269     }
270
271     public void shutdownStateManager() {
272         if (!canWrite() || stateManager.getCachedTimeStamp() == stateManager.getSystemState().getTimeStamp())
273             return;
274         try {
275             File stateTmpFile = File.createTempFile(LocationManager.STATE_FILE, ".new", LocationManager.getOSGiConfigurationDir()); //$NON-NLS-1$
276
File lazyTmpFile = File.createTempFile(LocationManager.LAZY_FILE, ".new", LocationManager.getOSGiConfigurationDir()); //$NON-NLS-1$
277
stateManager.shutdown(stateTmpFile, lazyTmpFile);
278             fileManager.lookup(LocationManager.STATE_FILE, true);
279             fileManager.lookup(LocationManager.LAZY_FILE, true);
280             fileManager.update(new String JavaDoc[] {LocationManager.STATE_FILE, LocationManager.LAZY_FILE}, new String JavaDoc[] {stateTmpFile.getName(), lazyTmpFile.getName()});
281         } catch (IOException e) {
282             frameworkLog.log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e));
283         }
284     }
285
286     private void cleanOSGiCache() {
287         File osgiConfig = LocationManager.getOSGiConfigurationDir();
288         if (!rm(osgiConfig)) {
289             // TODO log error?
290
}
291     }
292
293     private void readHeaders() {
294         InputStream bundleDataStream = findBundleDataFile();
295         if (bundleDataStream == null)
296             return;
297
298         try {
299             DataInputStream in = new DataInputStream(new BufferedInputStream(bundleDataStream));
300             try {
301                 cacheVersion = in.readByte();
302                 if (cacheVersion == BUNDLEDATA_VERSION) {
303                     timeStamp = in.readLong();
304                     initialBundleStartLevel = in.readInt();
305                     nextId = in.readLong();
306                 }
307             } finally {
308                 in.close();
309             }
310         } catch (IOException e) {
311             if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
312                 Debug.println("Error reading framework metadata: " + e.getMessage()); //$NON-NLS-1$
313
Debug.printStackTrace(e);
314             }
315         }
316     }
317
318     public AdaptorElementFactory getElementFactory() {
319         if (elementFactory == null)
320             elementFactory = new EclipseElementFactory();
321         return elementFactory;
322     }
323
324     public void frameworkStart(BundleContext aContext) throws BundleException {
325         // EnvironmentInfo has to be initialized first to compute defaults for system context (see bug 88925)
326
EclipseEnvironmentInfo.getDefault();
327         // must register the xml parser and initialize the plugin converter
328
// instance first because we may need it when creating the statemanager
329
// in super.frameworkStart(context)
330
registerEndorsedXMLParser(aContext);
331         PluginConverter converter = new PluginConverterImpl(aContext);
332         super.frameworkStart(aContext);
333         Bundle bundle = aContext.getBundle();
334         Location location;
335
336         // Less than optimal reference to EclipseStarter here. Not sure how we
337
// can make the location
338
// objects available. They are needed very early in EclipseStarter but
339
// these references tie the adaptor to that starter.
340
location = LocationManager.getUserLocation();
341         Hashtable locationProperties = new Hashtable(1);
342         if (location != null) {
343             locationProperties.put("type", LocationManager.PROP_USER_AREA); //$NON-NLS-1$
344
aContext.registerService(Location.class.getName(), location, locationProperties);
345         }
346         location = LocationManager.getInstanceLocation();
347         if (location != null) {
348             locationProperties.put("type", LocationManager.PROP_INSTANCE_AREA); //$NON-NLS-1$
349
aContext.registerService(Location.class.getName(), location, locationProperties);
350         }
351         location = LocationManager.getConfigurationLocation();
352         if (location != null) {
353             locationProperties.put("type", LocationManager.PROP_CONFIG_AREA); //$NON-NLS-1$
354
aContext.registerService(Location.class.getName(), location, locationProperties);
355         }
356         location = LocationManager.getInstallLocation();
357         if (location != null) {
358             locationProperties.put("type", LocationManager.PROP_INSTALL_AREA); //$NON-NLS-1$
359
aContext.registerService(Location.class.getName(), location, locationProperties);
360         }
361
362         register(org.eclipse.osgi.service.environment.EnvironmentInfo.class.getName(), EclipseEnvironmentInfo.getDefault(), bundle);
363         register(PlatformAdmin.class.getName(), stateManager, bundle);
364         register(PluginConverter.class.getName(), converter, bundle);
365         register(URLConverter.class.getName(), new URLConverterImpl(), bundle);
366         register(CommandProvider.class.getName(), new EclipseCommandProvider(aContext), bundle);
367         register(FrameworkLog.class.getName(), getFrameworkLog(), bundle);
368         registerPerformanceLog(bundle);
369         register(org.eclipse.osgi.service.localization.BundleLocalization.class.getName(), new BundleLocalizationImpl(), bundle);
370     }
371
372     private void registerPerformanceLog(Bundle bundle) {
373         Object JavaDoc service = createPerformanceLog();
374         String JavaDoc serviceName = FrameworkLog.class.getName();
375         Hashtable serviceProperties = new Hashtable(7);
376         Dictionary headers = bundle.getHeaders();
377
378         serviceProperties.put(Constants.SERVICE_VENDOR, headers.get(Constants.BUNDLE_VENDOR));
379         serviceProperties.put(Constants.SERVICE_RANKING, new Integer JavaDoc(Integer.MIN_VALUE));
380         serviceProperties.put(Constants.SERVICE_PID, bundle.getBundleId() + '.' + service.getClass().getName());
381         serviceProperties.put(FrameworkLog.SERVICE_PERFORMANCE, Boolean.TRUE.toString());
382
383         context.registerService(serviceName, service, serviceProperties);
384     }
385
386     private void setDebugOptions() {
387         FrameworkDebugOptions options = FrameworkDebugOptions.getDefault();
388         // may be null if debugging is not enabled
389
if (options == null)
390             return;
391         StateManager.DEBUG = options != null;
392         StateManager.DEBUG_READER = options.getBooleanOption(OPTION_RESOLVER_READER, false);
393         StateManager.MONITOR_PLATFORM_ADMIN = options.getBooleanOption(OPTION_MONITOR_PLATFORM_ADMIN, false);
394         StateManager.DEBUG_PLATFORM_ADMIN = options.getBooleanOption(OPTION_PLATFORM_ADMIN, false);
395         StateManager.DEBUG_PLATFORM_ADMIN_RESOLVER = options.getBooleanOption(OPTION_PLATFORM_ADMIN_RESOLVER, false);
396         PluginConverterImpl.DEBUG = options.getBooleanOption(OPTION_CONVERTER, false);
397         BasicLocation.DEBUG = options.getBooleanOption(OPTION_LOCATION, false);
398     }
399
400     private void registerEndorsedXMLParser(BundleContext bc) {
401         try {
402             Class.forName(SAXFACTORYNAME);
403             bc.registerService(SAXFACTORYNAME, new SaxParsingService(), new Hashtable());
404             Class.forName(DOMFACTORYNAME);
405             bc.registerService(DOMFACTORYNAME, new DomParsingService(), new Hashtable());
406         } catch (ClassNotFoundException JavaDoc e) {
407             // In case the JAXP API is not on the boot classpath
408
String JavaDoc message = EclipseAdaptorMsg.ECLIPSE_ADAPTOR_ERROR_XML_SERVICE;
409             getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, message, 0, e, null));
410         }
411     }
412
413     private class SaxParsingService implements ServiceFactory {
414         public Object JavaDoc getService(Bundle bundle, ServiceRegistration registration) {
415             return SAXParserFactory.newInstance();
416         }
417
418         public void ungetService(Bundle bundle, ServiceRegistration registration, Object JavaDoc service) {
419             // Do nothing.
420
}
421     }
422
423     private class DomParsingService implements ServiceFactory {
424         public Object JavaDoc getService(Bundle bundle, ServiceRegistration registration) {
425             return DocumentBuilderFactory.newInstance();
426         }
427
428         public void ungetService(Bundle bundle, ServiceRegistration registration, Object JavaDoc service) {
429             // Do nothing.
430
}
431     }
432
433     public boolean canWrite() {
434         return !fileManager.isReadOnly();
435     }
436
437     public void frameworkStop(BundleContext aContext) throws BundleException {
438         saveMetaData();
439         super.frameworkStop(aContext);
440         printStats();
441         PluginParser.releaseXMLParsing();
442         fileManager.close();
443     }
444
445     private void printStats() {
446         FrameworkDebugOptions debugOptions = FrameworkDebugOptions.getDefault();
447         if (debugOptions == null)
448             return;
449         String JavaDoc registryParsing = debugOptions.getOption("org.eclipse.core.runtime/registry/parsing/timing/value"); //$NON-NLS-1$
450
if (registryParsing != null)
451             EclipseAdaptorMsg.debug("Time spent in registry parsing: " + registryParsing); //$NON-NLS-1$
452
String JavaDoc packageAdminResolution = debugOptions.getOption("debug.packageadmin/timing/value"); //$NON-NLS-1$
453
if (packageAdminResolution != null)
454             System.out.println("Time spent in package admin resolve: " + packageAdminResolution); //$NON-NLS-1$
455
String JavaDoc constraintResolution = debugOptions.getOption("org.eclipse.core.runtime.adaptor/resolver/timing/value"); //$NON-NLS-1$
456
if (constraintResolution != null)
457             System.out.println("Time spent resolving the dependency system: " + constraintResolution); //$NON-NLS-1$
458
}
459
460     private InputStream findBundleDataFile() {
461         if (reinitialize)
462             return null; // return null to indicate we are reinitializing
463
StreamManager streamManager = new StreamManager(fileManager);
464         InputStream bundleDataStream = null;
465         try {
466             bundleDataStream = streamManager.getInputStream(LocationManager.BUNDLE_DATA_FILE, StreamManager.OPEN_BEST_AVAILABLE);
467         } catch (IOException ex) {
468             if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
469                 Debug.println("Error reading framework metadata: " + ex.getMessage()); //$NON-NLS-1$
470
Debug.printStackTrace(ex);
471             }
472         }
473         if (bundleDataStream == null) {
474             Location currentConfiguration = LocationManager.getConfigurationLocation();
475             Location parentConfiguration = null;
476             if (currentConfiguration != null && (parentConfiguration = currentConfiguration.getParentLocation()) != null) {
477                 try {
478                     File bundledataLocationDir = new File(parentConfiguration.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME);
479                     FileManager newFileManager = initFileManager(bundledataLocationDir, "none", true); //$NON-NLS-1$
480
bundleDataStream = streamManager.getInputStream(LocationManager.BUNDLE_DATA_FILE, StreamManager.OPEN_BEST_AVAILABLE);
481                     newFileManager.close();
482                 } catch (MalformedURLException JavaDoc e1) {
483                     // This will not happen since all the URLs are derived by us
484
// and we are GODS!
485
} catch (IOException e1) {
486                     // That's ok we will regenerate the .bundleData
487
}
488             }
489         }
490         return bundleDataStream;
491     }
492
493     /**
494      * @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getInstalledBundles()
495      */

496     public BundleData[] getInstalledBundles() {
497         InputStream bundleDataStream = findBundleDataFile();
498         if (bundleDataStream == null)
499             return null;
500
501         try {
502             DataInputStream in = new DataInputStream(new BufferedInputStream(bundleDataStream));
503             try {
504                 byte version = in.readByte();
505                 if (version != BUNDLEDATA_VERSION)
506                     return null;
507                 // skip timeStamp - was read by readHeaders
508
in.readLong();
509                 in.readInt();
510                 in.readLong();
511
512                 int bundleCount = in.readInt();
513                 ArrayList result = new ArrayList(bundleCount);
514                 long id = -1;
515                 boolean bundleDiscarded = false;
516                 for (int i = 0; i < bundleCount; i++) {
517                     try {
518                         id = in.readLong();
519                         if (id != 0) {
520                             EclipseBundleData data = (EclipseBundleData) getElementFactory().createBundleData(this, id);
521                             loadMetaDataFor(data, in, version);
522                             data.initializeExistingBundle();
523                             if (Debug.DEBUG && Debug.DEBUG_GENERAL)
524                                 Debug.println("BundleData created: " + data); //$NON-NLS-1$
525
processExtension(data, EXTENSION_INITIALIZE);
526                             result.add(data);
527                         }
528                     } catch (NumberFormatException JavaDoc e) {
529                         // should never happen
530
bundleDiscarded = true;
531                     } catch (BundleException e) {
532                         // should never happen
533
bundleDiscarded = true;
534                     } catch (IOException e) {
535                         bundleDiscarded = true;
536                         if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
537                             Debug.println("Error reading framework metadata: " + e.getMessage()); //$NON-NLS-1$
538
Debug.printStackTrace(e);
539                         }
540                     }
541                 }
542                 if (bundleDiscarded)
543                     System.getProperties().put(EclipseStarter.PROP_REFRESH_BUNDLES, "true"); //$NON-NLS-1$
544
return (BundleData[]) result.toArray(new BundleData[result.size()]);
545             } finally {
546                 in.close();
547             }
548         } catch (IOException e) {
549             if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
550                 Debug.println("Error reading framework metadata: " + e.getMessage()); //$NON-NLS-1$
551
Debug.printStackTrace(e);
552             }
553         }
554         return null;
555     }
556
557     /**
558      * Loads the meta data for the specified bundle data
559      * @param data the bundle data to load meta data for
560      * @param in the stream to read the meta data from
561      * @param version the version of data being read
562      * @throws IOException when an io error occurs reading the metadata
563      */

564     protected void loadMetaDataFor(EclipseBundleData data, DataInputStream in, byte version) throws IOException {
565         byte flag = in.readByte();
566         if (flag == NULL)
567             return;
568         data.setLocation(readString(in, false));
569         data.setFileName(readString(in, false));
570         data.setSymbolicName(readString(in, false));
571         data.setVersion(Version.parseVersion(readString(in, false)));
572         data.setActivator(readString(in, false));
573         data.setAutoStart(in.readBoolean());
574         int exceptionsCount = in.readInt();
575         String JavaDoc[] autoStartExceptions = exceptionsCount > 0 ? new String JavaDoc[exceptionsCount] : null;
576         for (int i = 0; i < exceptionsCount; i++)
577             autoStartExceptions[i] = in.readUTF();
578         data.setAutoStartExceptions(autoStartExceptions);
579         data.hasPackageInfo = in.readBoolean();
580         data.buddyList = readString(in, false);
581         data.registeredBuddyList = readString(in, false);
582         data.setPluginClass(readString(in, false));
583         data.setClassPathString(readString(in, false));
584         data.setNativePaths(readString(in, false));
585         data.setExecutionEnvironment(readString(in, false));
586         data.setDynamicImports(readString(in, false));
587         data.setGeneration(in.readInt());
588         data.setStartLevel(in.readInt());
589         data.setStatus(in.readInt());
590         data.setReference(in.readBoolean());
591         data.setManifestTimeStamp(in.readLong());
592         data.setManifestType(in.readByte());
593         data.setLastModified(in.readLong());
594         data.setType(in.readInt());
595         // TODO should we rearrange the isRefernce data before the fileName data?
596
// this step is done at the end because the FileName data is read before the isReference data
597
if (data.isReference()) {
598             // fileName for bundles installed with reference URLs is stored relative to the install location
599
File storedPath = new File(data.getFileName());
600             if (!storedPath.isAbsolute())
601                 // make sure it has the absolute location instead
602
data.setFileName(new FilePath(installPath + data.getFileName()).toString());
603         }
604     }
605
606     /**
607      * Saves the metadata for the specified bundle data. This method only marks the bundle data
608      * as dirty if the bundle is not auto started. The bundle data is not persisted until the
609      * framework is shutdown.
610      * @param data
611      * @throws IOException
612      */

613     public void saveMetaDataFor(EclipseBundleData data) throws IOException {
614         if (!data.isAutoStartable()) {
615             timeStamp--; // Change the value of the timeStamp, as a marker
616
// that something changed.
617
}
618     }
619
620     /**
621      * Saves the initial bundle start level. This method only marks the bundle data as
622      * dirty. The bundle dat is not persisted until the framework is shutdown.
623      */

624     public void persistInitialBundleStartLevel(int value) {
625         // Change the value of the timeStamp, as a marker that something
626
// changed.
627
timeStamp--;
628     }
629
630     public void persistNextBundleID(long value) {
631         // Do nothing the timeStamp will have changed because the state will be
632
// updated.
633
}
634
635     /**
636      * Saves the metadata for the specified bundle data.
637      * @param data the bundle data
638      * @param out the stream to save the metadata to
639      * @throws IOException when an io error occurs saving the metadata
640      */

641     protected void saveMetaDataFor(BundleData data, DataOutputStream out) throws IOException {
642         if (data.getBundleID() == 0 || !(data instanceof AbstractBundleData)) {
643             out.writeByte(NULL);
644             return;
645         }
646         EclipseBundleData bundleData = (EclipseBundleData) data;
647         out.writeByte(OBJECT);
648         writeStringOrNull(out, bundleData.getLocation());
649         String JavaDoc storedFileName = bundleData.isReference() ? new FilePath(installPath).makeRelative(new FilePath(bundleData.getFileName())) : bundleData.getFileName();
650         writeStringOrNull(out, storedFileName);
651         writeStringOrNull(out, bundleData.getSymbolicName());
652         writeStringOrNull(out, bundleData.getVersion().toString());
653         writeStringOrNull(out, bundleData.getActivator());
654         out.writeBoolean(bundleData.isAutoStart());
655         String JavaDoc[] autoStartExceptions = bundleData.getAutoStartExceptions();
656         if (autoStartExceptions == null)
657             out.writeInt(0);
658         else {
659             out.writeInt(autoStartExceptions.length);
660             for (int i = 0; i < autoStartExceptions.length; i++)
661                 out.writeUTF(autoStartExceptions[i]);
662         }
663         out.writeBoolean(bundleData.hasPackageInfo);
664         writeStringOrNull(out, bundleData.buddyList);
665         writeStringOrNull(out, bundleData.registeredBuddyList);
666         writeStringOrNull(out, bundleData.getPluginClass());
667         writeStringOrNull(out, bundleData.getClassPathString());
668         writeStringOrNull(out, bundleData.getNativePathsString());
669         writeStringOrNull(out, bundleData.getExecutionEnvironment());
670         writeStringOrNull(out, bundleData.getDynamicImports());
671         out.writeInt(bundleData.getGeneration());
672         out.writeInt(bundleData.getStartLevel());
673         out.writeInt(bundleData.getPersistentStatus());
674         out.writeBoolean(bundleData.isReference());
675         out.writeLong(bundleData.getManifestTimeStamp());
676         out.writeByte(bundleData.getManifestType());
677         out.writeLong(bundleData.getLastModified());
678         out.writeInt(bundleData.getType());
679     }
680
681     private String JavaDoc readString(DataInputStream in, boolean intern) throws IOException {
682         byte type = in.readByte();
683         if (type == NULL)
684             return null;
685         return intern ? in.readUTF().intern() : in.readUTF();
686     }
687
688     private void writeStringOrNull(DataOutputStream out, String JavaDoc string) throws IOException {
689         if (string == null)
690             out.writeByte(NULL);
691         else {
692             out.writeByte(OBJECT);
693             out.writeUTF(string);
694         }
695     }
696
697     /**
698      * Persists the bundle data for all bundles installed in the framework.
699      */

700     public void saveMetaData() {
701         // the cache and the state match
702
if (!canWrite() | timeStamp == stateManager.getSystemState().getTimeStamp())
703             return;
704         StreamManager streamManager = new StreamManager(fileManager);
705         try {
706             StreamManagerOutputStream fmos = streamManager.getOutputStream(LocationManager.BUNDLE_DATA_FILE);
707             DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fmos));
708             boolean error = true;
709             try {
710                 out.writeByte(BUNDLEDATA_VERSION);
711                 out.writeLong(stateManager.getSystemState().getTimeStamp());
712                 out.writeInt(initialBundleStartLevel);
713                 out.writeLong(nextId);
714                 Bundle[] bundles = context.getBundles();
715                 out.writeInt(bundles.length);
716                 for (int i = 0; i < bundles.length; i++) {
717                     long id = bundles[i].getBundleId();
718                     out.writeLong(id);
719                     if (id != 0) {
720                         BundleData data = ((org.eclipse.osgi.framework.internal.core.AbstractBundle) bundles[i]).getBundleData();
721                         saveMetaDataFor(data, out);
722                     }
723                 }
724                 out.close();
725                 error = false;
726             } finally {
727                 // if something happens, don't close a corrupt file
728
if (error) {
729                     fmos.abort();
730                     try {
731                         out.close();
732                     } catch (IOException e) {/*ignore*/
733                     }
734                 }
735             }
736         } catch (IOException e) {
737             frameworkLog.log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e));
738             return;
739         }
740     }
741
742     public BundleWatcher getBundleWatcher() {
743         return StatsManager.getDefault();
744     }
745
746     /**
747      * Returns the system bundle context
748      * @return the system bundle context
749      */

750     protected BundleContext getContext() {
751         return context;
752     }
753
754     public void frameworkStopping(BundleContext aContext) {
755         super.frameworkStopping(aContext);
756         stopper = new BundleStopper(context);
757         stopper.stopBundles();
758     }
759
760     private boolean isFatalException(Throwable JavaDoc error) {
761         if (error instanceof VirtualMachineError JavaDoc) {
762             return true;
763         }
764         if (error instanceof ThreadDeath JavaDoc) {
765             return true;
766         }
767         return false;
768     }
769
770     public void handleRuntimeError(Throwable JavaDoc error) {
771         try {
772             // check the prop each time this happens (should NEVER happen!)
773
exitOnError = Boolean.valueOf(System.getProperty(PROP_EXITONERROR, "true")).booleanValue(); //$NON-NLS-1$
774
String JavaDoc message = EclipseAdaptorMsg.ECLIPSE_ADAPTOR_RUNTIME_ERROR;
775             if (exitOnError && isFatalException(error))
776                 message += ' ' + EclipseAdaptorMsg.ECLIPSE_ADAPTOR_EXITING;
777             FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, message, 0, error, null);
778             getFrameworkLog().log(logEntry);
779         } catch (Throwable JavaDoc t) {
780             // we may be in a currupted state and must be able to handle any
781
// errors (ie OutOfMemoryError)
782
// that may occur when handling the first error; this is REALLY the
783
// last resort.
784
try {
785                 error.printStackTrace();
786                 t.printStackTrace();
787             } catch (Throwable JavaDoc t1) {
788                 // if we fail that then we are beyond help.
789
}
790         } finally {
791             // do the exit outside the try block just incase another runtime
792
// error was thrown while logging
793
if (exitOnError && isFatalException(error))
794                 System.exit(13);
795         }
796     }
797
798     protected void setLog(FrameworkLog log) {
799         frameworkLog = log;
800     }
801
802     BundleStopper getBundleStopper() {
803         return stopper;
804     }
805
806     private FileManager initFileManager(File baseDir, String JavaDoc lockMode, boolean readOnly) {
807         FileManager fManager = new FileManager(baseDir, lockMode, readOnly);
808         try {
809             fManager.open(!readOnly);
810         } catch (IOException ex) {
811             if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
812                 Debug.println("Error reading framework metadata: " + ex.getMessage()); //$NON-NLS-1$
813
Debug.printStackTrace(ex);
814             }
815             String JavaDoc message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FILEMANAGER_OPEN_ERROR, ex.getMessage());
816             FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, message, 0, ex, null);
817             getFrameworkLog().log(logEntry);
818         }
819         return fManager;
820     }
821 }
822
Popular Tags