KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > framework > adaptor > core > AbstractFrameworkAdaptor


1 /*******************************************************************************
2  * Copyright (c) 2004, 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
12 package org.eclipse.osgi.framework.adaptor.core;
13
14 import java.io.*;
15 import java.lang.reflect.InvocationTargetException JavaDoc;
16 import java.lang.reflect.Method JavaDoc;
17 import java.net.URL JavaDoc;
18 import java.net.URLConnection JavaDoc;
19 import java.util.*;
20 import org.eclipse.osgi.framework.adaptor.*;
21 import org.eclipse.osgi.framework.debug.Debug;
22 import org.eclipse.osgi.framework.internal.core.*;
23 import org.eclipse.osgi.framework.internal.core.Constants;
24 import org.eclipse.osgi.framework.log.FrameworkLog;
25 import org.eclipse.osgi.framework.util.Headers;
26 import org.eclipse.osgi.service.resolver.*;
27 import org.eclipse.osgi.util.ManifestElement;
28 import org.eclipse.osgi.util.NLS;
29 import org.osgi.framework.*;
30
31 /**
32  * An abstract FrameworkAdaptor class that has default implementations that most
33  * FrameworkAdaptor implementations can use.
34  * <p>
35  * Clients may extend this class.
36  * </p>
37  * @since 3.1
38  */

39 public abstract class AbstractFrameworkAdaptor implements FrameworkAdaptor {
40     /**
41      * System property used to set the parent classloader type (boot is the default)
42      */

43     public static final String JavaDoc PROP_PARENT_CLASSLOADER = "osgi.parentClassloader"; //$NON-NLS-1$
44
/**
45      * System property used to specify the list of framework extension bundles
46      */

47     public static final String JavaDoc PROP_FRAMEWORK_EXTENSIONS = "osgi.framework.extensions"; //$NON-NLS-1$
48
/**
49      * System property used to specify the bundle singing support class name
50      */

51     public static final String JavaDoc PROP_SIGNINGSUPPORT = "osgi.bundlesigning.support"; //$NON-NLS-1$
52
/**
53      * A parent classloader type that specifies the application classloader
54      */

55     public static final String JavaDoc PARENT_CLASSLOADER_APP = "app"; //$NON-NLS-1$
56
/**
57      * A parent classloader type that specifies the extension classlaoder
58      */

59     public static final String JavaDoc PARENT_CLASSLOADER_EXT = "ext"; //$NON-NLS-1$
60
/**
61      * A parent classloader type that specifies the boot classlaoder
62      */

63     public static final String JavaDoc PARENT_CLASSLOADER_BOOT = "boot"; //$NON-NLS-1$
64
/**
65      * A parent classloader type that specifies the framework classlaoder
66      */

67     public static final String JavaDoc PARENT_CLASSLOADER_FWK = "fwk"; //$NON-NLS-1$
68
/**
69      * The bundle file name used to store bundles into the bundle storage area
70      */

71     public static final String JavaDoc BUNDLEFILE_NAME = "bundlefile"; //$NON-NLS-1$
72

73     /**
74      * flag to indicate a framework extension is being intialized
75      */

76     public static final byte EXTENSION_INITIALIZE = 0x01;
77     /**
78      * flag to indicate a framework extension is being installed
79      */

80     public static final byte EXTENSION_INSTALLED = 0x02;
81     /**
82      * flag to indicate a framework extension is being uninstalled
83      */

84     public static final byte EXTENSION_UNINSTALLED = 0x04;
85     /**
86      * flag to indicate a framework extension is being updated
87      */

88     public static final byte EXTENSION_UPDATED = 0x08;
89
90     /** Name of the Adaptor manifest file */
91     protected final String JavaDoc ADAPTOR_MANIFEST = "ADAPTOR.MF"; //$NON-NLS-1$
92

93     /**
94      * The default bundle signing support class name
95      */

96     protected final String JavaDoc DEFAULT_SIGNEDBUNDLE_SUPPORT = "org.eclipse.osgi.framework.pkcs7verify.SignedBundleSupportImpl"; //$NON-NLS-1$
97

98     /**
99      * The EventPublisher for the FrameworkAdaptor
100      */

101     protected EventPublisher eventPublisher;
102
103     /**
104      * The ServiceRegistry object for this FrameworkAdaptor.
105      */

106     protected ServiceRegistry serviceRegistry;
107
108     /**
109      * The Properties object for this FrameworkAdaptor
110      */

111     protected Properties properties;
112
113     /**
114      * The System Bundle's BundleContext.
115      */

116     protected BundleContext context;
117
118     /**
119      * The initial bundle start level.
120      */

121     protected int initialBundleStartLevel = 1;
122
123     /** This adaptor's manifest file */
124     protected Headers manifest = null;
125
126     /**
127      * Indicates the Framework is stopoing;
128      * set to true when frameworkStopping(BundleContext) is called
129      */

130     protected boolean stopping = false;
131
132     /**
133      * The BundleClassLoader parent to use when creating BundleClassLoaders.
134      * The behavior of the ParentClassLoader will load classes
135      * from the boot strap classloader.
136      */

137     protected static ClassLoader JavaDoc bundleClassLoaderParent;
138     /**
139      * next available bundle id
140      */

141     protected long nextId = 1;
142     /**
143      * The State Manager
144      */

145     protected StateManager stateManager;
146     /**
147      * directory containing installed bundles
148      */

149     protected File bundleStoreRootDir;
150
151     /**
152      * The adaptor element factory
153      */

154     protected AdaptorElementFactory elementFactory;
155
156     static {
157         // check property for specified parent
158
String JavaDoc type = System.getProperty(PROP_PARENT_CLASSLOADER, PARENT_CLASSLOADER_BOOT);
159         if (PARENT_CLASSLOADER_FWK.equalsIgnoreCase(type))
160             bundleClassLoaderParent = FrameworkAdaptor.class.getClassLoader();
161         else if (PARENT_CLASSLOADER_APP.equalsIgnoreCase(type))
162             bundleClassLoaderParent = ClassLoader.getSystemClassLoader();
163         else if (PARENT_CLASSLOADER_EXT.equalsIgnoreCase(type)) {
164             ClassLoader JavaDoc appCL = ClassLoader.getSystemClassLoader();
165             if (appCL != null)
166                 bundleClassLoaderParent = appCL.getParent();
167         }
168
169         // default to boot classloader
170
if (bundleClassLoaderParent == null)
171             bundleClassLoaderParent = new ParentClassLoader();
172     }
173
174     /**
175      * The add URL method used to support framework extensions
176      */

177     protected Method JavaDoc addURLMethod;
178
179     /**
180      * The list of configured framework extensions
181      */

182     protected String JavaDoc[] configuredExtensions;
183
184     /**
185      * Indicates if signed bundles are supported
186      */

187     protected boolean supportSignedBundles = true;
188     /**
189      * The SingedBundleSupport object. This is set if signed bundles are supported
190      */

191     protected SignedBundleSupport signedBundleSupport = null;
192
193     /**
194      * Constructor for DefaultAdaptor. This constructor parses the arguments passed
195      * and remembers them for later when initialize is called.
196      * <p>No blank spaces should be used in the arguments to the DefaultAdaptor.
197      * The options that DefaultAdaptor recognizes and handles are:
198      * <ul>
199      * <li><b>bundledir=<i>directory name</i></b>If a directory name is specified, the adaptor should initialize
200      * to store bundles in that directory. This arg should be enclosed in "" if it contains the ":"
201      * character (example "bundledir=c:\mydir").
202      * <li><b>reset</b>Resets the bundle storage by deleting the bundledir
203      * </ul>
204      * Any other arguments are ignored.
205      *
206      * @param args An array of strings containing arguments.
207      * This object cannot be used until initialize is called.
208      *
209      */

210     public AbstractFrameworkAdaptor(String JavaDoc[] args) {
211         ClassLoader JavaDoc fwloader = AbstractFrameworkAdaptor.class.getClassLoader();
212         if (fwloader != null)
213             addURLMethod = findaddURLMethod(fwloader.getClass());
214         if (args != null) {
215             for (int i = 0; i < args.length; i++) {
216                 String JavaDoc arg = args[i];
217                 if (arg.equalsIgnoreCase("reset")) { //$NON-NLS-1$
218
reset = true;
219                 } else if (arg.indexOf("=") != -1) { //$NON-NLS-1$
220
StringTokenizer tok = new StringTokenizer(args[i], "="); //$NON-NLS-1$
221
if (tok.countTokens() == 2) {
222                         String JavaDoc key = tok.nextToken();
223                         if (key.equalsIgnoreCase("bundledir")) { //$NON-NLS-1$
224
// save file name for initializeStorage to use
225
bundleStore = tok.nextToken();
226                         }
227                     }
228                 }
229             }
230         }
231     }
232
233     /**
234      * @see FrameworkAdaptor#initialize(EventPublisher)
235      */

236     public void initialize(EventPublisher eventPublisher) {
237         this.eventPublisher = eventPublisher;
238         serviceRegistry = new ServiceRegistryImpl();
239         ((ServiceRegistryImpl) serviceRegistry).initialize();
240         loadProperties();
241         readAdaptorManifest();
242         initBundleStoreRootDir();
243         // need to create the FrameworkLog very early
244
frameworkLog = createFrameworkLog();
245     }
246
247     /**
248      * @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getProperties()
249      */

250     public Properties getProperties() {
251         return properties;
252     }
253
254     /**
255      * Returns the AdaptorElementFactory for this Adaptor. This allows
256      * extending adaptors to control how BundleData and BundleClassLoader
257      * objects are created.
258      * @return the AdaptorElementFactory for this Adapotr.
259      */

260     public abstract AdaptorElementFactory getElementFactory();
261
262     /**
263      * Saves the next bundle id to persist storage
264      * @param value the next bundle id
265      * @throws IOException
266      */

267     protected abstract void persistNextBundleID(long value) throws IOException;
268
269     /**
270      * @see FrameworkAdaptor#getFrameworkLog()
271      */

272     public FrameworkLog getFrameworkLog() {
273         if (frameworkLog == null)
274             frameworkLog = createFrameworkLog();
275         return frameworkLog;
276     }
277
278     /**
279      * @see FrameworkAdaptor#getState()
280      */

281     public State getState() {
282         return stateManager.getSystemState();
283     }
284
285     /**
286      * @see FrameworkAdaptor#getPlatformAdmin()
287      */

288     public PlatformAdmin getPlatformAdmin() {
289         return stateManager;
290     }
291
292     /**
293      * @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#mapLocationToURLConnection(String)
294      */

295     public URLConnection JavaDoc mapLocationToURLConnection(String JavaDoc location) throws BundleException {
296         try {
297             return (new URL JavaDoc(location).openConnection());
298         } catch (IOException e) {
299             throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_URL_CREATE_EXCEPTION, location), e);
300         }
301     }
302
303     /**
304      * Always returns -1 to indicate that this operation is not supported by this
305      * FrameworkAdaptor. Extending classes should override this method if
306      * they support this operation.
307      * @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getTotalFreeSpace()
308      */

309     public long getTotalFreeSpace() throws IOException {
310         return -1;
311     }
312
313     /**
314      * @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getServiceRegistry()
315      */

316     public org.eclipse.osgi.framework.adaptor.ServiceRegistry getServiceRegistry() {
317         return serviceRegistry;
318     }
319
320     /**
321      * @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#frameworkStart(org.osgi.framework.BundleContext)
322      */

323     public void frameworkStart(BundleContext context) throws BundleException {
324         this.stopping = false;
325         this.context = context;
326         BundleResourceHandler.setContext(context);
327         if (frameworkLog == null)
328             frameworkLog = createFrameworkLog();
329         if (stateManager == null)
330             stateManager = createStateManager();
331         State state = stateManager.getSystemState();
332         checkSystemState(state);
333         BundleDescription systemBundle = state.getBundle(0);
334         if (systemBundle == null || !systemBundle.isResolved())
335             // this would be a bug in the framework
336
throw new IllegalStateException JavaDoc();
337     }
338
339     /**
340      * @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#frameworkStop(org.osgi.framework.BundleContext)
341      */

342     public void frameworkStop(BundleContext context) throws BundleException {
343         shutdownStateManager();
344         this.context = null;
345         BundleResourceHandler.setContext(null);
346         frameworkLog.close();
347         frameworkLog = null;
348     }
349
350     /**
351      * @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#frameworkStopping(BundleContext)
352      */

353     public void frameworkStopping(BundleContext context) {
354         this.stopping = true;
355     }
356
357     /**
358      * @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getExportPackages()
359      */

360     public String JavaDoc getExportPackages() {
361         if (manifest == null)
362             return null;
363         return (String JavaDoc) manifest.get(Constants.EXPORT_PACKAGE);
364     }
365
366     /**
367      * @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getExportServices()
368      */

369     public String JavaDoc getExportServices() {
370         if (manifest == null)
371             return null;
372         return (String JavaDoc) manifest.get(Constants.EXPORT_SERVICE);
373     }
374
375     /**
376      * @see FrameworkAdaptor#getProvidePackages()
377      */

378     public String JavaDoc getProvidePackages() {
379         if (manifest == null)
380             return null;
381         return (String JavaDoc) manifest.get(Constants.PROVIDE_PACKAGE);
382     }
383
384     /**
385      * Returns the EventPublisher for this FrameworkAdaptor.
386      * @return The EventPublisher.
387      */

388     public EventPublisher getEventPublisher() {
389         return eventPublisher;
390     }
391
392     /**
393      * Indicates if the framework is currently stopping
394      * @return true if the framework is currently stopping
395      */

396     public boolean isStopping() {
397         return stopping;
398     }
399
400     /**
401      * @see FrameworkAdaptor#getInitialBundleStartLevel()
402      */

403     public int getInitialBundleStartLevel() {
404         return initialBundleStartLevel;
405     }
406
407     /**
408      * @see FrameworkAdaptor#setInitialBundleStartLevel(int)
409      */

410     public void setInitialBundleStartLevel(int value) {
411         initialBundleStartLevel = value;
412     }
413
414     /**
415      * @see FrameworkAdaptor#getBundleWatcher()
416      */

417     public BundleWatcher getBundleWatcher() {
418         return null;
419     }
420
421     /**
422      * The FrameworkLog for the adaptor
423      */

424     protected FrameworkLog frameworkLog;
425
426     public static final String JavaDoc BUNDLE_STORE = "osgi.bundlestore"; //$NON-NLS-1$
427

428     /**
429      * This method locates and reads the osgi.properties file.
430      * If the system property <i>org.eclipse.osgi.framework.internal.core.properties</i> is specifed, its value
431      * will be used as the name of the file instead of
432      * <tt>osgi.properties</tt>. There are 3 places to look for these properties. These
433      * 3 places are searched in the following order, stopping when the properties are found.
434      *
435      * <ol>
436      * <li>Look for a file in the file system
437      * <li>Look for a resource in the FrameworkAdaptor's package
438      * </ol>
439      */

440     protected void loadProperties() {
441         properties = new Properties();
442
443         String JavaDoc resource = System.getProperty(Constants.OSGI_PROPERTIES, Constants.DEFAULT_OSGI_PROPERTIES);
444
445         try {
446             InputStream in = null;
447             File file = new File(resource);
448             if (file.exists()) {
449                 in = new FileInputStream(file);
450             }
451
452             if (in == null) {
453                 in = getClass().getResourceAsStream(resource);
454             }
455
456             if (in != null) {
457                 try {
458                     properties.load(new BufferedInputStream(in));
459                 } finally {
460                     try {
461                         in.close();
462                     } catch (IOException ee) {
463                     }
464                 }
465             } else {
466                 if (Debug.DEBUG && Debug.DEBUG_GENERAL)
467                     Debug.println("Skipping osgi.properties: " + resource); //$NON-NLS-1$
468
}
469         } catch (IOException e) {
470             if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
471                 Debug.println("Unable to load osgi.properties: " + e.getMessage()); //$NON-NLS-1$
472
}
473         }
474
475         // need to set some OSGi Framework properties that only the adaptor would know about
476
if (addURLMethod != null)
477             properties.put(Constants.SUPPORTS_FRAMEWORK_EXTENSION, "true"); //$NON-NLS-1$
478
}
479
480     /**
481      * Return the next valid, unused bundle id.
482      *
483      * @return Next valid, unused bundle id.
484      * @throws IOException If there are no more unused bundle ids.
485      */

486     protected synchronized long getNextBundleId() throws IOException {
487         while (nextId < Long.MAX_VALUE) {
488             long id = nextId;
489             nextId++;
490
491             File bundleDir = new File(getBundleStoreRootDir(), String.valueOf(id));
492             if (bundleDir.exists()) {
493                 continue;
494             }
495             persistNextBundleID(id);
496             return (id);
497         }
498
499         throw new IOException(AdaptorMsg.ADAPTOR_STORAGE_EXCEPTION);
500     }
501
502     /**
503      * Initializes the root bundle data directory
504      *
505      */

506     protected void initDataRootDir() {
507         dataRootDir = getBundleStoreRootDir();
508     }
509
510     /**
511      * Reads and initializes the adaptor BundleManifest object. The
512      * BundleManifest is used by the getExportPackages() and getExportServices()
513      * methods of the adpator.
514      */

515     protected void readAdaptorManifest() {
516         InputStream in = null;
517         // walk up the class hierarchy until we find the ADAPTOR_MANIFEST.
518
Class JavaDoc adaptorClazz = getClass();
519         while (in == null && AbstractFrameworkAdaptor.class.isAssignableFrom(adaptorClazz)) {
520             in = adaptorClazz.getResourceAsStream(ADAPTOR_MANIFEST);
521             adaptorClazz = adaptorClazz.getSuperclass();
522         }
523
524         if (in == null) {
525             if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
526                 Debug.println("Unable to find adaptor bundle manifest " + ADAPTOR_MANIFEST); //$NON-NLS-1$
527
}
528             manifest = new Headers(new Properties());
529             return;
530         }
531         try {
532             manifest = Headers.parseManifest(in);
533         } catch (BundleException e) {
534             Debug.println("Unable to read adaptor bundle manifest " + ADAPTOR_MANIFEST); //$NON-NLS-1$
535
}
536     }
537
538     /**
539      * Creates a framework log
540      * @return a framework log
541      */

542     abstract protected FrameworkLog createFrameworkLog();
543
544     /**
545      * @see FrameworkAdaptor#createSystemBundleData()
546      */

547     public BundleData createSystemBundleData() throws BundleException {
548         return new SystemBundleData(this);
549     }
550
551     /**
552      * Does a recursive copy of one directory to another.
553      * @param inDir input directory to copy.
554      * @param outDir output directory to copy to.
555      * @throws IOException if any error occurs during the copy.
556      */

557     public static void copyDir(File inDir, File outDir) throws IOException {
558         String JavaDoc[] files = inDir.list();
559         if (files != null && files.length > 0) {
560             outDir.mkdir();
561             for (int i = 0; i < files.length; i++) {
562                 File inFile = new File(inDir, files[i]);
563                 File outFile = new File(outDir, files[i]);
564                 if (inFile.isDirectory()) {
565                     copyDir(inFile, outFile);
566                 } else {
567                     InputStream in = new FileInputStream(inFile);
568                     readFile(in, outFile);
569                 }
570             }
571         }
572     }
573
574     /**
575      * Read a file from an InputStream and write it to the file system.
576      *
577      * @param in InputStream from which to read.
578      * @param file output file to create.
579      * @exception IOException
580      */

581     public static void readFile(InputStream in, File file) throws IOException {
582         FileOutputStream fos = null;
583         try {
584             fos = new FileOutputStream(file);
585
586             byte buffer[] = new byte[1024];
587             int count;
588             while ((count = in.read(buffer, 0, buffer.length)) > 0) {
589                 fos.write(buffer, 0, count);
590             }
591
592             fos.close();
593             fos = null;
594
595             in.close();
596             in = null;
597         } catch (IOException e) {
598             // close open streams
599
if (fos != null) {
600                 try {
601                     fos.close();
602                 } catch (IOException ee) {
603                 }
604             }
605
606             if (in != null) {
607                 try {
608                     in.close();
609                 } catch (IOException ee) {
610                 }
611             }
612
613             if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
614                 Debug.println("Unable to read file"); //$NON-NLS-1$
615
Debug.printStackTrace(e);
616             }
617
618             throw e;
619         }
620     }
621
622     private static Method JavaDoc findaddURLMethod(Class JavaDoc clazz) {
623         if (clazz == null)
624             return null; // ends the recursion when getSuperClass returns null
625
try {
626             Method JavaDoc result = clazz.getDeclaredMethod("addURL", new Class JavaDoc[] {URL JavaDoc.class}); //$NON-NLS-1$
627
result.setAccessible(true);
628             return result;
629         } catch (NoSuchMethodException JavaDoc e) {
630             // do nothing look in super class below
631
} catch (SecurityException JavaDoc e) {
632             // if we do not have the permissions then we will not find the method
633
}
634         return findaddURLMethod(clazz.getSuperclass());
635     }
636
637     /**
638      * @see FrameworkAdaptor#getBundleClassLoaderParent()
639      */

640     public ClassLoader JavaDoc getBundleClassLoaderParent() {
641         return bundleClassLoaderParent;
642     }
643
644     /**
645      * Processes an extension bundle
646      * @param bundleData the extension bundle data
647      * @param type the type of extension bundle
648      * @throws BundleException on any errors or if the extension bundle type is not supported
649      */

650     protected void processExtension(BundleData bundleData, byte type) throws BundleException {
651         if ((bundleData.getType() & BundleData.TYPE_FRAMEWORK_EXTENSION) != 0) {
652             validateExtension(bundleData);
653             processFrameworkExtension(bundleData, type);
654         } else if ((bundleData.getType() & BundleData.TYPE_BOOTCLASSPATH_EXTENSION) != 0) {
655             validateExtension(bundleData);
656             processBootExtension(bundleData, type);
657         }
658     }
659
660     /**
661      * Validates the extension bundle metadata
662      * @param bundleData the extension bundle data
663      * @throws BundleException if the extension bundle metadata is invalid
664      */

665     protected void validateExtension(BundleData bundleData) throws BundleException {
666         Dictionary extensionManifest = bundleData.getManifest();
667         if (extensionManifest.get(Constants.IMPORT_PACKAGE) != null)
668             throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_EXTENSION_IMPORT_ERROR, bundleData.getLocation()));
669         if (extensionManifest.get(Constants.REQUIRE_BUNDLE) != null)
670             throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_EXTENSION_REQUIRE_ERROR, bundleData.getLocation()));
671         if (extensionManifest.get(Constants.BUNDLE_NATIVECODE) != null)
672             throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_EXTENSION_NATIVECODE_ERROR, bundleData.getLocation()));
673     }
674
675     /**
676      * Processes a framework extension bundle
677      * @param bundleData the extension bundle data
678      * @param type the type of extension bundle
679      * @throws BundleException on errors or if framework extensions are not supported
680      */

681     protected void processFrameworkExtension(BundleData bundleData, byte type) throws BundleException {
682         if (addURLMethod == null)
683             throw new BundleException("Framework extensions are not supported.", new UnsupportedOperationException JavaDoc()); //$NON-NLS-1$
684
if ((type & (EXTENSION_UNINSTALLED | EXTENSION_UPDATED)) != 0)
685             // if uninstalled or updated then do nothing framework must be restarted.
686
return;
687
688         // first make sure this BundleData is not on the pre-configured osgi.framework.extensions list
689
String JavaDoc[] extensions = getConfiguredExtensions();
690         for (int i = 0; i < extensions.length; i++)
691             if (extensions[i].equals(bundleData.getSymbolicName()))
692                 return;
693         File[] files = getExtensionFiles(bundleData);
694         if (files == null)
695             return;
696         for (int i = 0; i < files.length; i++) {
697             if (files[i] == null)
698                 continue;
699             Throwable JavaDoc exceptionLog = null;
700             try {
701                 addURLMethod.invoke(getClass().getClassLoader(), new Object JavaDoc[] {files[i].toURL()});
702             } catch (InvocationTargetException JavaDoc e) {
703                 exceptionLog = e.getTargetException();
704             } catch (Throwable JavaDoc t) {
705                 exceptionLog = t;
706             } finally {
707                 if (exceptionLog != null)
708                     eventPublisher.publishFrameworkEvent(FrameworkEvent.ERROR, ((AbstractBundleData) bundleData).getBundle(), exceptionLog);
709             }
710         }
711     }
712
713     /**
714      * Returns a list of configured extensions
715      * @return a list of configured extensions
716      */

717     protected String JavaDoc[] getConfiguredExtensions() {
718         if (configuredExtensions != null)
719             return configuredExtensions;
720         String JavaDoc prop = System.getProperty(PROP_FRAMEWORK_EXTENSIONS);
721         if (prop == null || prop.trim().length() == 0)
722             configuredExtensions = new String JavaDoc[0];
723         else
724             configuredExtensions = ManifestElement.getArrayFromList(prop);
725         return configuredExtensions;
726     }
727
728     /**
729      * Processes a boot extension bundle
730      * @param bundleData the extension bundle data
731      * @param type the type of extension bundle
732      * @throws BundleException on errors or if boot extensions are not supported
733      */

734     protected void processBootExtension(BundleData bundleData, byte type) throws BundleException {
735         throw new BundleException("Boot classpath extensions are not supported.", new UnsupportedOperationException JavaDoc()); //$NON-NLS-1$
736
}
737
738     /**
739      * Returns a list of classpath files for an extension bundle
740      * @param bundleData the bundle data for an extension bundle
741      * @return a list of classpath files for an extension bundle
742      */

743     protected File[] getExtensionFiles(BundleData bundleData) {
744         File[] files = null;
745         try {
746             String JavaDoc[] paths = bundleData.getClassPath();
747             // TODO need to be smarter about dev path here
748
if (System.getProperty("osgi.dev") != null) { //$NON-NLS-1$
749
String JavaDoc[] origPaths = paths;
750                 paths = new String JavaDoc[origPaths.length + 1];
751                 System.arraycopy(origPaths, 0, paths, 0, origPaths.length);
752                 paths[paths.length - 1] = "bin"; //$NON-NLS-1$
753
}
754             files = ((AbstractBundleData) bundleData).getClasspathFiles(paths);
755         } catch (BundleException e) {
756             eventPublisher.publishFrameworkEvent(FrameworkEvent.ERROR, ((AbstractBundleData) bundleData).getBundle(), e);
757         }
758         return files;
759     }
760
761     /**
762      * @see FrameworkAdaptor#handleRuntimeError(Throwable)
763      */

764     public void handleRuntimeError(Throwable JavaDoc error) {
765         // do nothing by default.
766
}
767
768     /**
769      * Returns the root data directory
770      * @return the root data directory
771      */

772     public File getDataRootDir() {
773         if (dataRootDir == null)
774             initDataRootDir();
775         return dataRootDir;
776     }
777
778     /**
779      * Creates a BundleFile object from a File object and a BundleData
780      * object. This implementation checks to see if the basefile is
781      * a directory or a regular file and creates the proper BundleFile
782      * type accordingly. If the file is a regular file this implementation
783      * assumes that the file is a zip file.
784      * @param basefile the base File object.
785      * @param bundledata the BundleData object that BundleFile is associated with.
786      * @return A new BundleFile object
787      * @throws IOException if an error occurred creating the BundleFile object.
788      */

789     public BundleFile createBundleFile(File basefile, BundleData bundledata) throws IOException {
790         if (basefile.isDirectory())
791             return new BundleFile.DirBundleFile(basefile);
792         return new BundleFile.ZipBundleFile(basefile, bundledata);
793     }
794
795     /**
796      * Creates a base bundle file for a bundle
797      * @param basefile the base file object for the bundle
798      * @param bundledata the bundle data for the bundle
799      * @return a base bundle file for a bundle
800      * @throws IOException
801      */

802     public BundleFile createBaseBundleFile(File basefile, BundleData bundledata) throws IOException {
803         BundleFile base = createBundleFile(basefile, bundledata);
804         if (System.getSecurityManager() == null || !supportSignedBundles)
805             return base;
806         SignedBundleSupport support = getSignedBundleSupport();
807         if (support == null)
808             return base;
809         SignedBundle signedBundle = support.createSignedBundle();
810         signedBundle.setBundleFile(base);
811         return signedBundle;
812     }
813
814     /**
815      * @see FrameworkAdaptor#matchDNChain(String, String[])
816      */

817     public boolean matchDNChain(String JavaDoc pattern, String JavaDoc[] dnChain) {
818         SignedBundleSupport support = getSignedBundleSupport();
819         if (support != null)
820             return support.matchDNChain(pattern, dnChain);
821         return false;
822     }
823
824     /**
825      * Returns the SignedBundleSupport object. If signed bundles are not
826      * supported then <code>null</code> is returned.
827      * @return the SignedBundleSupport object or <code>null</code> if signed bundles
828      * are not supported.
829      */

830     protected SignedBundleSupport getSignedBundleSupport() {
831         if (System.getSecurityManager() == null || !supportSignedBundles)
832             return null;
833         try {
834             if (signedBundleSupport == null) {
835                 String JavaDoc clazzName = System.getProperty(PROP_SIGNINGSUPPORT, DEFAULT_SIGNEDBUNDLE_SUPPORT);
836                 Class JavaDoc clazz = Class.forName(clazzName);
837                 signedBundleSupport = (SignedBundleSupport) clazz.newInstance();
838             }
839             return signedBundleSupport;
840         } catch (ClassNotFoundException JavaDoc e) {
841             supportSignedBundles = false;
842         } catch (IllegalAccessException JavaDoc e) {
843             supportSignedBundles = false;
844         } catch (InstantiationException JavaDoc e) {
845             supportSignedBundles = false;
846         }
847         return null;
848     }
849
850     /**
851      * @see FrameworkAdaptor#installBundle(String, URLConnection)
852      */

853     public BundleOperation installBundle(final String JavaDoc location, final URLConnection JavaDoc source) {
854         return (new BundleOperation() {
855             private AbstractBundleData data;
856
857             /**
858              * Begin the operation on the bundle (install, update, uninstall).
859              *
860              * @return BundleData object for the target bundle.
861              * @throws BundleException If a failure occured modifiying peristent storage.
862              */

863             public org.eclipse.osgi.framework.adaptor.BundleData begin() throws BundleException {
864                 long id;
865
866                 try {
867                     /*
868                      * Open InputStream first to trigger prereq installs, if any,
869                      * before allocating bundle id.
870                      */

871                     InputStream in = source.getInputStream();
872                     URL JavaDoc sourceURL = source.getURL();
873                     String JavaDoc protocol = sourceURL == null ? null : sourceURL.getProtocol();
874                     try {
875                         try {
876                             id = getNextBundleId();
877                         } catch (IOException e) {
878                             throw new BundleException(AdaptorMsg.ADAPTOR_STORAGE_EXCEPTION, e);
879                         }
880                         data = getElementFactory().createBundleData(AbstractFrameworkAdaptor.this, id);
881                         data.setLastModified(System.currentTimeMillis());
882                         data.setLocation(location);
883                         data.setStartLevel(getInitialBundleStartLevel());
884
885                         if (in instanceof ReferenceInputStream) {
886                             URL JavaDoc reference = ((ReferenceInputStream) in).getReference();
887
888                             if (!"file".equals(reference.getProtocol())) { //$NON-NLS-1$
889
throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_URL_CREATE_EXCEPTION, reference));
890                             }
891
892                             data.setReference(true);
893                             data.setFileName(reference.getPath());
894                             data.initializeNewBundle();
895                         } else {
896                             File genDir = data.createGenerationDir();
897                             if (!genDir.exists()) {
898                                 throw new IOException(NLS.bind(AdaptorMsg.ADAPTOR_DIRECTORY_CREATE_EXCEPTION, genDir.getPath()));
899                             }
900
901                             String JavaDoc fileName = BUNDLEFILE_NAME;
902                             File outFile = new File(genDir, fileName);
903                             if ("file".equals(protocol)) { //$NON-NLS-1$
904
File inFile = new File(source.getURL().getPath());
905                                 if (inFile.isDirectory()) {
906                                     copyDir(inFile, outFile);
907                                 } else {
908                                     readFile(in, outFile);
909                                 }
910                             } else {
911                                 readFile(in, outFile);
912                             }
913                             data.setReference(false);
914                             data.setFileName(fileName);
915                             data.initializeNewBundle();
916                         }
917                     } finally {
918                         try {
919                             in.close();
920                         } catch (IOException e) {
921                         }
922                     }
923                 } catch (IOException ioe) {
924                     throw new BundleException(AdaptorMsg.BUNDLE_READ_EXCEPTION, ioe);
925                 }
926
927                 return (data);
928             }
929
930             public void undo() {
931                 if (data != null) {
932                     try {
933                         data.close();
934                     } catch (IOException e) {
935                         if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
936                             Debug.println("Unable to close " + data + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
937
}
938                     }
939                 }
940
941                 if (data != null) {
942                     File bundleDir = data.getBundleStoreDir();
943
944                     if (!rm(bundleDir)) {
945                         /* mark this bundle to be deleted to ensure it is fully cleaned up
946                          * on next restart.
947                          */

948                         File delete = new File(bundleDir, ".delete"); //$NON-NLS-1$
949

950                         if (!delete.exists()) {
951                             try {
952                                 /* create .delete */
953                                 FileOutputStream out = new FileOutputStream(delete);
954                                 out.close();
955                             } catch (IOException e) {
956                                 if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
957                                     Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
958
}
959                             }
960                         }
961                     }
962                 }
963             }
964
965             public void commit(boolean postpone) throws BundleException {
966                 processExtension(data, EXTENSION_INSTALLED);
967                 try {
968                     data.save();
969                 } catch (IOException e) {
970                     throw new BundleException(AdaptorMsg.ADAPTOR_STORAGE_EXCEPTION, e);
971                 }
972                 updateState(data, BundleEvent.INSTALLED);
973             }
974
975         });
976     }
977
978     /**
979      * This function performs the equivalent of "rm -r" on a file or directory.
980      *
981      * @param file file or directory to delete
982      * @return false is the specified files still exists, true otherwise.
983      */

984     protected boolean rm(File file) {
985         if (file.exists()) {
986             if (file.isDirectory()) {
987                 String JavaDoc list[] = file.list();
988                 if (list != null) {
989                     int len = list.length;
990                     for (int i = 0; i < len; i++) {
991                         // we are doing a lot of garbage collecting here
992
rm(new File(file, list[i]));
993                     }
994                 }
995             }
996             if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
997                 if (file.isDirectory()) {
998                     Debug.println("rmdir " + file.getPath()); //$NON-NLS-1$
999
} else {
1000                    Debug.println("rm " + file.getPath()); //$NON-NLS-1$
1001
}
1002            }
1003
1004            boolean success = file.delete();
1005
1006            if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
1007                if (!success) {
1008                    Debug.println(" rm failed!!"); //$NON-NLS-1$
1009
}
1010            }
1011
1012            return (success);
1013        }
1014        return (true);
1015    }
1016
1017    /**
1018     * Shutdown the StateManager for the adaptor. This should persist the state
1019     * for reading when createStateManager is called.
1020     */

1021    protected void shutdownStateManager() {
1022        try {
1023            if (canWrite() && (getBundleStoreRootDir().exists() || getBundleStoreRootDir().mkdirs()))
1024                stateManager.shutdown(new File(getBundleStoreRootDir(), ".state"), new File(getBundleStoreRootDir(), ".lazy")); //$NON-NLS-1$//$NON-NLS-2$
1025
} catch (IOException e) {
1026            frameworkLog.log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e));
1027        } finally {
1028            stateManager = null;
1029        }
1030    }
1031
1032    /**
1033     * Returns the bundle store root directory
1034     * @return the bundle store root directory
1035     */

1036    public File getBundleStoreRootDir() {
1037        return bundleStoreRootDir;
1038    }
1039
1040    /**
1041     * String containing bundle store root dir
1042     */

1043    protected String JavaDoc bundleStore = null;
1044    /**
1045     * Dictionary containing permission data
1046     */

1047    protected PermissionStorage permissionStore;
1048    /**
1049     * inidicates that the bundle storage should be reset
1050     */

1051    protected boolean reset = false;
1052    /**
1053     * directory containing data directories for installed bundles
1054     */

1055    protected File dataRootDir;
1056    /**
1057     * The name of the bundle data directory
1058     */

1059    public static final String JavaDoc DATA_DIR_NAME = "data";//$NON-NLS-1$
1060
/**
1061     * Indicates that the state has become invalid as a result of
1062     * installing/updating/uninstalling a bundle before the state mananger is
1063     * created
1064     */

1065    protected boolean invalidState = false;
1066
1067    /**
1068     * @see FrameworkAdaptor#updateBundle(BundleData, URLConnection)
1069     */

1070    public BundleOperation updateBundle(final org.eclipse.osgi.framework.adaptor.BundleData bundledata, final URLConnection JavaDoc source) {
1071        return (new BundleOperation() {
1072            private AbstractBundleData data;
1073            private AbstractBundleData newData;
1074
1075            /**
1076             * Perform the change to persistent storage.
1077             *
1078             * @return Bundle object for the target bundle.
1079             */

1080            public org.eclipse.osgi.framework.adaptor.BundleData begin() throws BundleException {
1081                this.data = (AbstractBundleData) bundledata;
1082                try {
1083                    InputStream in = source.getInputStream();
1084                    URL JavaDoc sourceURL = source.getURL();
1085                    String JavaDoc protocol = sourceURL == null ? null : sourceURL.getProtocol();
1086                    try {
1087                        if (in instanceof ReferenceInputStream) {
1088                            ReferenceInputStream refIn = (ReferenceInputStream) in;
1089                            URL JavaDoc reference = (refIn).getReference();
1090                            if (!"file".equals(reference.getProtocol())) { //$NON-NLS-1$
1091
throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_URL_CREATE_EXCEPTION, reference));
1092                            }
1093                            // check to make sure we are not just trying to update to the same
1094
// directory reference. This would be a no-op.
1095
String JavaDoc path = reference.getPath();
1096                            if (path.equals(data.getFileName())) {
1097                                throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_SAME_REF_UPDATE, reference));
1098                            }
1099                            try {
1100                                newData = data.nextGeneration(reference.getPath());
1101                            } catch (IOException e) {
1102                                throw new BundleException(AdaptorMsg.ADAPTOR_STORAGE_EXCEPTION, e);
1103                            }
1104                            File bundleGenerationDir = newData.createGenerationDir();
1105                            if (!bundleGenerationDir.exists()) {
1106                                throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_DIRECTORY_CREATE_EXCEPTION, bundleGenerationDir.getPath()));
1107                            }
1108                            newData.createBaseBundleFile();
1109                        } else {
1110                            try {
1111                                newData = data.nextGeneration(null);
1112                            } catch (IOException e) {
1113                                throw new BundleException(AdaptorMsg.ADAPTOR_STORAGE_EXCEPTION, e);
1114                            }
1115                            File bundleGenerationDir = newData.createGenerationDir();
1116                            if (!bundleGenerationDir.exists()) {
1117                                throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_DIRECTORY_CREATE_EXCEPTION, bundleGenerationDir.getPath()));
1118                            }
1119                            File outFile = newData.getBaseFile();
1120                            if ("file".equals(protocol)) { //$NON-NLS-1$
1121
File inFile = new File(source.getURL().getPath());
1122                                if (inFile.isDirectory()) {
1123                                    copyDir(inFile, outFile);
1124                                } else {
1125                                    readFile(in, outFile);
1126                                }
1127                            } else {
1128                                readFile(in, outFile);
1129                            }
1130                            newData.createBaseBundleFile();
1131                        }
1132                    } finally {
1133                        try {
1134                            in.close();
1135                        } catch (IOException ee) {
1136                        }
1137                    }
1138                    newData.loadFromManifest();
1139                } catch (IOException e) {
1140                    throw new BundleException(AdaptorMsg.BUNDLE_READ_EXCEPTION, e);
1141                }
1142
1143                return (newData);
1144            }
1145
1146            /**
1147             * Commit the change to persistent storage.
1148             *
1149             * @param postpone If true, the bundle's persistent
1150             * storage cannot be immediately reclaimed.
1151             * @throws BundleException If a failure occured modifiying peristent storage.
1152             */

1153
1154            public void commit(boolean postpone) throws BundleException {
1155                processExtension(data, EXTENSION_UNINSTALLED); // remove the old extension
1156
processExtension(newData, EXTENSION_UPDATED); // update to the new one
1157
try {
1158                    newData.setLastModified(System.currentTimeMillis());
1159                    newData.save();
1160                } catch (IOException e) {
1161                    throw new BundleException(AdaptorMsg.ADAPTOR_STORAGE_EXCEPTION, e);
1162                }
1163                updateState(newData, BundleEvent.UPDATED);
1164                File originalGenerationDir = data.createGenerationDir();
1165
1166                if (postpone || !rm(originalGenerationDir)) {
1167                    /* mark this bundle to be deleted to ensure it is fully cleaned up
1168                     * on next restart.
1169                     */

1170                    File delete = new File(originalGenerationDir, ".delete"); //$NON-NLS-1$
1171

1172                    if (!delete.exists()) {
1173                        try {
1174                            /* create .delete */
1175                            FileOutputStream out = new FileOutputStream(delete);
1176                            out.close();
1177                        } catch (IOException e) {
1178                            if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
1179                                Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
1180
}
1181
1182                            eventPublisher.publishFrameworkEvent(FrameworkEvent.ERROR, data.getBundle(), e);
1183                        }
1184                    }
1185                }
1186            }
1187
1188            /**
1189             * Undo the change to persistent storage.
1190             *
1191             * @throws BundleException If a failure occured modifiying peristent storage.
1192             */

1193            public void undo() throws BundleException {
1194                /*if (bundleFile != null)
1195                 {
1196                 bundleFile.close();
1197                 } */

1198
1199                if (newData != null) {
1200                    File nextGenerationDir = newData.createGenerationDir();
1201
1202                    if (!rm(nextGenerationDir)) /* delete downloaded bundle */{
1203                        /* mark this bundle to be deleted to ensure it is fully cleaned up
1204                         * on next restart.
1205                         */

1206                        File delete = new File(nextGenerationDir, ".delete"); //$NON-NLS-1$
1207

1208                        if (!delete.exists()) {
1209                            try {
1210                                /* create .delete */
1211                                FileOutputStream out = new FileOutputStream(delete);
1212                                out.close();
1213                            } catch (IOException e) {
1214                                if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
1215                                    Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
1216
}
1217                            }
1218                        }
1219                    }
1220                }
1221            }
1222        });
1223    }
1224
1225    /**
1226     * Iterates over the bundles in a state and removes any bundles in state that
1227     * do not exist in the framework
1228     * @param state the state to check
1229     */

1230    protected void checkSystemState(State state) {
1231        BundleDescription[] bundles = state.getBundles();
1232        if (bundles == null)
1233            return;
1234        boolean removedBundle = false;
1235        for (int i = 0; i < bundles.length; i++) {
1236            if (context.getBundle(bundles[i].getBundleId()) == null) {
1237                state.removeBundle(bundles[i]);
1238                removedBundle = true;
1239            }
1240        }
1241        if (removedBundle)
1242            state.resolve(false); // do a full resolve
1243
}
1244
1245    /**
1246     * Creates the StateManager for the adaptor
1247     * @return the StateManager.
1248     */

1249    protected StateManager createStateManager() {
1250        stateManager = new StateManager(new File(getBundleStoreRootDir(), ".state"), new File(getBundleStoreRootDir(), ".lazy"), context); //$NON-NLS-1$ //$NON-NLS-2$
1251
State systemState = null;
1252        if (!invalidState) {
1253            systemState = stateManager.readSystemState();
1254            if (systemState != null)
1255                return stateManager;
1256        }
1257        systemState = stateManager.createSystemState();
1258        Bundle[] installedBundles = context.getBundles();
1259        if (installedBundles == null)
1260            return stateManager;
1261        StateObjectFactory factory = stateManager.getFactory();
1262        for (int i = 0; i < installedBundles.length; i++) {
1263            Bundle toAdd = installedBundles[i];
1264            try {
1265                Dictionary manifest = toAdd.getHeaders(""); //$NON-NLS-1$
1266
BundleDescription newDescription = factory.createBundleDescription(systemState, manifest, toAdd.getLocation(), toAdd.getBundleId());
1267                systemState.addBundle(newDescription);
1268            } catch (BundleException be) {
1269                // just ignore bundle datas with invalid manifests
1270
}
1271        }
1272        // we need the state resolved
1273
systemState.resolve();
1274        invalidState = false;
1275        return stateManager;
1276    }
1277
1278    /**
1279     * @see FrameworkAdaptor#uninstallBundle(BundleData)
1280     */

1281    public BundleOperation uninstallBundle(final org.eclipse.osgi.framework.adaptor.BundleData bundledata) {
1282        return (new BundleOperation() {
1283            private AbstractBundleData data;
1284
1285            /**
1286             * Perform the change to persistent storage.
1287             *
1288             * @return Bundle object for the target bundle.
1289             * @throws BundleException If a failure occured modifiying peristent storage.
1290             */

1291            public org.eclipse.osgi.framework.adaptor.BundleData begin() throws BundleException {
1292                this.data = (AbstractBundleData) bundledata;
1293                return (bundledata);
1294            }
1295
1296            /**
1297             * Commit the change to persistent storage.
1298             *
1299             * @param postpone If true, the bundle's persistent
1300             * storage cannot be immediately reclaimed.
1301             * @throws BundleException If a failure occured modifiying peristent storage.
1302             */

1303            public void commit(boolean postpone) throws BundleException {
1304                File bundleDir = data.getBundleStoreDir();
1305
1306                if (postpone || !rm(bundleDir)) {
1307                    /* mark this bundle to be deleted to ensure it is fully cleaned up
1308                     * on next restart.
1309                     */

1310
1311                    File delete = new File(bundleDir, ".delete"); //$NON-NLS-1$
1312

1313                    if (!delete.exists()) {
1314                        try {
1315                            /* create .delete */
1316                            FileOutputStream out = new FileOutputStream(delete);
1317                            out.close();
1318                        } catch (IOException e) {
1319                            if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
1320                                Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
1321
}
1322                        }
1323                    }
1324                }
1325
1326                processExtension(data, EXTENSION_UNINSTALLED);
1327                data.setLastModified(System.currentTimeMillis());
1328                updateState(data, BundleEvent.UNINSTALLED);
1329            }
1330
1331            /**
1332             * Undo the change to persistent storage.
1333             *
1334             * @throws BundleException If a failure occured modifiying peristent storage.
1335             */

1336            public void undo() throws BundleException {
1337            }
1338        });
1339    }
1340
1341    /**
1342     * Init the directory to store the bundles in. Bundledir can be set in 3 different ways.
1343     * Priority is:
1344     * 1 - OSGI Launcher command line -adaptor argument
1345     * 2 - System property osgi.bundlestore - could be specified with -D when launching
1346     * 3 - osgi.properties - osgi.bundlestore property
1347     *
1348     * Bundledir will be stored back to adaptor properties which
1349     * the framework will copy into the System properties.
1350     */

1351    protected void initBundleStoreRootDir() {
1352        /* if bundleStore was not set by the constructor from the -adaptor cmd line arg */
1353        if (bundleStore == null) {
1354            /* check the system properties */
1355            bundleStore = System.getProperty(BUNDLE_STORE);
1356
1357            if (bundleStore == null) {
1358                /* check the osgi.properties file, but default to "bundles" */
1359                bundleStore = properties.getProperty(BUNDLE_STORE, "bundles"); //$NON-NLS-1$
1360
}
1361        }
1362
1363        bundleStoreRootDir = new File(bundleStore);
1364        /* store bundleStore back into adaptor properties for others to see */
1365        properties.put(BUNDLE_STORE, bundleStoreRootDir.getAbsolutePath());
1366
1367    }
1368
1369    /**
1370     * Register a service object.
1371     * @param name the service class name
1372     * @param service the service object
1373     * @param bundle the registering bundle
1374     * @return the service registration object
1375     */

1376    protected ServiceRegistration register(String JavaDoc name, Object JavaDoc service, Bundle bundle) {
1377        Hashtable properties = new Hashtable(7);
1378
1379        Dictionary headers = bundle.getHeaders();
1380
1381        properties.put(Constants.SERVICE_VENDOR, headers.get(Constants.BUNDLE_VENDOR));
1382
1383        properties.put(Constants.SERVICE_RANKING, new Integer JavaDoc(Integer.MAX_VALUE));
1384
1385        properties.put(Constants.SERVICE_PID, bundle.getBundleId() + "." + service.getClass().getName()); //$NON-NLS-1$
1386

1387        return context.registerService(name, service, properties);
1388    }
1389
1390    /**
1391     * Initialize the persistent storage.
1392     *
1393     * <p>This method initializes the bundle persistent storage
1394     * area.
1395     * If a dir was specified in the -adaptor command line option, then it
1396     * is used. If not,
1397     * if the property
1398     * <i>osgi.bundlestore</i> is specified, its value
1399     * will be used as the name of the bundle directory
1400     * instead of <tt>./bundles</tt>.
1401     * If reset was specified on the -adaptor command line option,
1402     * then the storage will be cleared.
1403     *
1404     * @throws IOException If an error occurs initializing the storage.
1405     */

1406    public void initializeStorage() throws IOException {
1407        File bundleStore;
1408        // only touch the file system if reset is specified
1409
// we create the area on demand later if needed
1410
if (reset && (bundleStore = getBundleStoreRootDir()).exists()) {
1411            if (!canWrite() || !rm(bundleStore)) {
1412                    if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
1413                        Debug.println("Could not remove directory: " + bundleStore.getPath()); //$NON-NLS-1$
1414
}
1415
1416                throw new IOException(NLS.bind(AdaptorMsg.ADAPTOR_DIRECTORY_REMOVE_EXCEPTION, bundleStore));
1417                }
1418            }
1419
1420        initializeMetadata();
1421    }
1422
1423    /**
1424     * Initialize the metadata for the adaptor
1425     * @throws IOException
1426     */

1427    abstract protected void initializeMetadata() throws IOException;
1428
1429    /**
1430     * @see FrameworkAdaptor#getPermissionStorage()
1431     */

1432    public org.eclipse.osgi.framework.adaptor.PermissionStorage getPermissionStorage() throws IOException {
1433        if (permissionStore == null) {
1434            synchronized (this) {
1435                if (permissionStore == null) {
1436                    permissionStore = new DefaultPermissionStorage(this);
1437                }
1438            }
1439        }
1440
1441        return permissionStore;
1442    }
1443
1444    /**
1445     * @see FrameworkAdaptor#compactStorage()
1446     */

1447    public void compactStorage() {
1448        if (canWrite())
1449            compact(getBundleStoreRootDir());
1450    }
1451
1452    /**
1453     * This method cleans up storage in the specified directory and
1454     * any subdirectories.
1455     *
1456     * @param directory The directory to clean.
1457     * @see #compactStorage
1458     */

1459    private void compact(File directory) {
1460        if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
1461            Debug.println("compact(" + directory.getPath() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
1462
}
1463
1464        String JavaDoc list[] = directory.list();
1465        if (list == null)
1466            return;
1467
1468        int len = list.length;
1469
1470        for (int i = 0; i < len; i++) {
1471            if (DATA_DIR_NAME.equals(list[i])) {
1472                continue; /* do not examine the bundles data dir. */
1473            }
1474
1475            File target = new File(directory, list[i]);
1476
1477            /* if the file is a directory */
1478            if (!target.isDirectory())
1479                continue;
1480            File delete = new File(target, ".delete"); //$NON-NLS-1$
1481

1482            /* and the directory is marked for delete */
1483            if (delete.exists()) {
1484                /* if rm fails to delete the directory *
1485                 * and .delete was removed
1486                 */

1487                if (!rm(target) && !delete.exists()) {
1488                    try {
1489                        /* recreate .delete */
1490                        FileOutputStream out = new FileOutputStream(delete);
1491                        out.close();
1492                    } catch (IOException e) {
1493                        if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
1494                            Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
1495
}
1496                    }
1497                }
1498            } else {
1499                compact(target); /* descend into directory */
1500            }
1501        }
1502    }
1503
1504    /**
1505     * Returns the metadata file for the adaptor
1506     * @return the metadata file for the adaptor
1507     */

1508    protected File getMetaDataFile() {
1509        return new File(getBundleStoreRootDir(), ".framework"); //$NON-NLS-1$
1510
}
1511
1512    /**
1513     * Empty parent classloader. This is used by default as the BundleClassLoader
1514     * parent.
1515     */

1516    protected static class ParentClassLoader extends ClassLoader JavaDoc {
1517        protected ParentClassLoader() {
1518            super(null);
1519        }
1520    }
1521
1522    /**
1523     * Updates the state mananager with an updated/installed/uninstalled bundle
1524     * @param bundleData the modified bundle
1525     * @param type the type of modification
1526     * @throws BundleException
1527     */

1528    protected void updateState(BundleData bundleData, int type) throws BundleException {
1529        if (stateManager == null) {
1530            invalidState = true;
1531            return;
1532        }
1533        State systemState = stateManager.getSystemState();
1534        switch (type) {
1535            case BundleEvent.UPDATED :
1536                systemState.removeBundle(bundleData.getBundleID());
1537            // fall through to INSTALLED
1538
case BundleEvent.INSTALLED :
1539                BundleDescription newDescription = stateManager.getFactory().createBundleDescription(systemState, bundleData.getManifest(), bundleData.getLocation(), bundleData.getBundleID());
1540                systemState.addBundle(newDescription);
1541                break;
1542            case BundleEvent.UNINSTALLED :
1543                systemState.removeBundle(bundleData.getBundleID());
1544                break;
1545        }
1546    }
1547
1548    /**
1549     * Whether the adaptor can make changes to the file system. Default is <code>true</code>.
1550     */

1551    public boolean canWrite() {
1552        return true;
1553    }
1554}
1555
Popular Tags