KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > registry > EclipseBundleListener


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.internal.registry;
12
13 import java.io.IOException JavaDoc;
14 import java.io.InputStream JavaDoc;
15 import java.net.URL JavaDoc;
16 import java.util.*;
17 import javax.xml.parsers.ParserConfigurationException JavaDoc;
18 import javax.xml.parsers.SAXParserFactory JavaDoc;
19 import org.eclipse.core.internal.runtime.*;
20 import org.eclipse.core.runtime.*;
21 import org.eclipse.osgi.util.ManifestElement;
22 import org.eclipse.osgi.util.NLS;
23 import org.osgi.framework.*;
24 import org.osgi.util.tracker.ServiceTracker;
25 import org.xml.sax.InputSource JavaDoc;
26 import org.xml.sax.SAXException JavaDoc;
27
28 /**
29  * A listener for bundle events. When a bundles come and go we look to see
30  * if there are any extensions or extension points and update the registry accordingly.
31  * Using a Synchronous listener here is important. If the
32  * bundle activator code tries to access the registry to get its extension
33  * points, we need to ensure that they are in the registry before the
34  * bundle start is called. By listening sync we are able to ensure that
35  * happens.
36  */

37 public class EclipseBundleListener implements SynchronousBundleListener {
38     private static final String JavaDoc PLUGIN_MANIFEST = "plugin.xml"; //$NON-NLS-1$
39
private static final String JavaDoc FRAGMENT_MANIFEST = "fragment.xml"; //$NON-NLS-1$
40

41     private ExtensionRegistry registry;
42     private ServiceTracker xmlTracker;
43
44     public EclipseBundleListener(ExtensionRegistry registry) {
45         this.registry = registry;
46         xmlTracker = new ServiceTracker(InternalPlatform.getDefault().getBundleContext(), SAXParserFactory JavaDoc.class.getName(), null);
47         xmlTracker.open();
48     }
49
50     public void bundleChanged(BundleEvent event) {
51         /* Only should listen for RESOLVED and UNRESOLVED events.
52          *
53          * When a bundle is updated the Framework will publish an UNRESOLVED and
54          * then a RESOLVED event which should cause the bundle to be removed
55          * and then added back into the registry.
56          *
57          * When a bundle is uninstalled the Framework should publish an UNRESOLVED
58          * event and then an UNINSTALLED event so the bundle will have been removed
59          * by the UNRESOLVED event before the UNINSTALLED event is published.
60          *
61          * When a bundle is refreshed from PackageAdmin an UNRESOLVED event will be
62          * published which will remove the bundle from the registry. If the bundle
63          * can be RESOLVED after a refresh then a RESOLVED event will be published
64          * which will add the bundle back. This is required because the classloader
65          * will have been refreshed for the bundle so all extensions and extension
66          * points for the bundle must be refreshed.
67          */

68         Bundle bundle = event.getBundle();
69         switch (event.getType()) {
70             case BundleEvent.RESOLVED :
71                 addBundle(bundle);
72                 break;
73             case BundleEvent.UNRESOLVED :
74                 removeBundle(bundle);
75                 break;
76         }
77     }
78
79     public void processBundles(Bundle[] bundles) {
80         for (int i = 0; i < bundles.length; i++) {
81             if (isBundleResolved(bundles[i]))
82                 addBundle(bundles[i]);
83             else
84                 removeBundle(bundles[i]);
85         }
86     }
87
88     private boolean isBundleResolved(Bundle bundle) {
89         return (bundle.getState() & (Bundle.RESOLVED | Bundle.ACTIVE | Bundle.STARTING | Bundle.STOPPING)) != 0;
90     }
91
92     private void removeBundle(Bundle bundle) {
93         registry.remove(bundle.getBundleId());
94     }
95
96     private void addBundle(Bundle bundle) {
97         // if the given bundle already exists in the registry then return.
98
// note that this does not work for update cases.
99
if (registry.hasNamespace(bundle.getBundleId()))
100             return;
101         Contribution bundleModel = getBundleModel(bundle);
102         if (bundleModel == null)
103             return;
104         // bug 70941
105
// need to ensure we can find resource bundles from fragments
106
if (Platform.PI_RUNTIME.equals(bundleModel.getNamespace()))
107             Messages.reloadMessages();
108         // Do not synchronize on registry here because the registry handles
109
// the synchronization for us in registry.add
110
registry.add(bundleModel);
111     }
112
113     private boolean isSingleton(Bundle bundle) {
114         Dictionary allHeaders = bundle.getHeaders(""); //$NON-NLS-1$
115
String JavaDoc symbolicNameHeader = (String JavaDoc) allHeaders.get(Constants.BUNDLE_SYMBOLICNAME); //$NON-NLS-1$
116
try {
117             if (symbolicNameHeader != null) {
118                 ManifestElement[] symbolicNameElements = ManifestElement.parseHeader(Constants.BUNDLE_SYMBOLICNAME, symbolicNameHeader);
119                 if (symbolicNameElements.length > 0) {
120                     String JavaDoc singleton = symbolicNameElements[0].getDirective(Constants.SINGLETON_DIRECTIVE);
121                     if (singleton == null)
122                         singleton = symbolicNameElements[0].getAttribute(Constants.SINGLETON_DIRECTIVE);
123
124                     if (!"true".equalsIgnoreCase(singleton)) { //$NON-NLS-1$
125
int status = IStatus.INFO;
126                         String JavaDoc manifestVersion = (String JavaDoc) allHeaders.get(org.osgi.framework.Constants.BUNDLE_MANIFESTVERSION);
127                         if (manifestVersion == null) {//the header was not defined for previous versions of the bundle
128
//3.0 bundles without a singleton attributes are still being accepted
129
if (InternalPlatform.getDefault().getBundle(symbolicNameElements[0].getValue()) == bundle) {
130                                 return true;
131                             }
132                             status = IStatus.ERROR;
133                         }
134                         if (InternalPlatform.DEBUG_REGISTRY || status == IStatus.ERROR) {
135                             String JavaDoc message = NLS.bind(Messages.parse_nonSingleton, bundle.getLocation());
136                             InternalPlatform.getDefault().log(new Status(status, Platform.PI_RUNTIME, 0, message, null));
137                         }
138                         return false;
139                     }
140                 }
141             }
142         } catch (BundleException e1) {
143             //This can't happen because the fwk would have rejected the bundle
144
}
145         return true;
146     }
147
148     /**
149      * Tries to create a bundle model from a plugin/fragment manifest in the bundle.
150      */

151     private Contribution getBundleModel(Bundle bundle) {
152         // bail out if system bundle
153
if (bundle.getBundleId() == 0)
154             return null;
155         // bail out if the bundle does not have a symbolic name
156
if (bundle.getSymbolicName() == null)
157             return null;
158
159         //If the bundle is not a singleton, then it is not added
160
if (!isSingleton(bundle))
161             return null;
162
163         boolean isFragment = InternalPlatform.getDefault().isFragment(bundle);
164
165         //If the bundle is a fragment being added to a non singleton host, then it is not added
166
if (isFragment) {
167             Bundle[] hosts = InternalPlatform.getDefault().getHosts(bundle);
168             if (hosts != null && isSingleton(hosts[0]) == false)
169                 return null;
170         }
171
172         InputStream JavaDoc is = null;
173         String JavaDoc manifestType = null;
174         String JavaDoc manifestName = isFragment ? FRAGMENT_MANIFEST : PLUGIN_MANIFEST;
175         try {
176             URL JavaDoc url = bundle.getEntry(manifestName);
177             if (url != null) {
178                 is = url.openStream();
179                 manifestType = isFragment ? ExtensionsParser.FRAGMENT : ExtensionsParser.PLUGIN;
180             }
181         } catch (IOException JavaDoc ex) {
182             is = null;
183         }
184         if (is == null)
185             return null;
186         try {
187             String JavaDoc message = NLS.bind(Messages.parse_problems, bundle.getLocation());
188             MultiStatus problems = new MultiStatus(Platform.PI_RUNTIME, ExtensionsParser.PARSE_PROBLEM, message, null); //$NON-NLS-1$
189
ResourceBundle b = null;
190             try {
191                 b = ResourceTranslator.getResourceBundle(bundle);
192             } catch (MissingResourceException e) {
193                 //Ignore the exception
194
}
195             ExtensionsParser parser = new ExtensionsParser(problems);
196             Contribution bundleModel = new Contribution(bundle);
197             parser.parseManifest(xmlTracker, new InputSource JavaDoc(is), manifestType, manifestName, registry.getObjectManager(), bundleModel, b);
198             if (problems.getSeverity() != IStatus.OK)
199                 InternalPlatform.getDefault().log(problems);
200             return bundleModel;
201         } catch (ParserConfigurationException JavaDoc e) {
202             logParsingError(bundle, e);
203             return null;
204         } catch (SAXException JavaDoc e) {
205             logParsingError(bundle, e);
206             return null;
207         } catch (IOException JavaDoc e) {
208             logParsingError(bundle, e);
209             return null;
210         } finally {
211             try {
212                 is.close();
213             } catch (IOException JavaDoc ioe) {
214                 // nothing to do
215
}
216         }
217     }
218
219     private void logParsingError(Bundle bundle, Exception JavaDoc e) {
220         String JavaDoc message = NLS.bind(Messages.parse_failedParsingManifest, bundle.getLocation());
221         InternalPlatform.getDefault().log(new Status(IStatus.ERROR, Platform.PI_RUNTIME, 0, message, e));
222     }
223 }
224
Popular Tags