KickJava   Java API By Example, From Geeks To Geeks.

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


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

11 package org.eclipse.core.internal.registry.osgi;
12
13 import java.io.*;
14 import java.net.URL JavaDoc;
15 import java.util.*;
16 import org.eclipse.core.internal.registry.ExtensionRegistry;
17 import org.eclipse.core.internal.registry.RegistryMessages;
18 import org.eclipse.core.internal.runtime.ResourceTranslator;
19 import org.eclipse.core.internal.runtime.RuntimeLog;
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
25 /**
26  * A listener for bundle events. When a bundles come and go we look to see
27  * if there are any extensions or extension points and update the registry accordingly.
28  * Using a Synchronous listener here is important. If the
29  * bundle activator code tries to access the registry to get its extension
30  * points, we need to ensure that they are in the registry before the
31  * bundle start is called. By listening sync we are able to ensure that
32  * happens.
33  */

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

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

66         Bundle bundle = event.getBundle();
67         switch (event.getType()) {
68             case BundleEvent.RESOLVED :
69                 addBundle(bundle);
70                 break;
71             case BundleEvent.UNRESOLVED :
72                 removeBundle(bundle);
73                 break;
74         }
75     }
76
77     public void processBundles(Bundle[] bundles) {
78         for (int i = 0; i < bundles.length; i++) {
79             if (isBundleResolved(bundles[i]))
80                 addBundle(bundles[i]);
81             else
82                 removeBundle(bundles[i]);
83         }
84     }
85
86     private boolean isBundleResolved(Bundle bundle) {
87         return (bundle.getState() & (Bundle.RESOLVED | Bundle.ACTIVE | Bundle.STARTING | Bundle.STOPPING)) != 0;
88     }
89
90     private void removeBundle(Bundle bundle) {
91         long timestamp = 0;
92         if (strategy.checkContributionsTimestamp()) {
93             URL JavaDoc pluginManifest = getExtensionURL(bundle, false);
94             if (pluginManifest != null)
95                 timestamp = strategy.getExtendedTimestamp(bundle, pluginManifest);
96         }
97         registry.remove(Long.toString(bundle.getBundleId()), timestamp);
98     }
99
100     static public URL JavaDoc getExtensionURL(Bundle bundle, boolean report) {
101         // bail out if system bundle
102
if (bundle.getBundleId() == 0)
103             return null;
104         // bail out if the bundle does not have a symbolic name
105
if (bundle.getSymbolicName() == null)
106             return null;
107
108         boolean isFragment = OSGIUtils.getDefault().isFragment(bundle);
109         String JavaDoc manifestName = isFragment ? FRAGMENT_MANIFEST : PLUGIN_MANIFEST;
110         URL JavaDoc extensionURL = bundle.getEntry(manifestName);
111         if (extensionURL == null)
112             return null;
113
114         // If the bundle is not a singleton, then it is not added
115
if (!isSingleton(bundle)) {
116             if (report) {
117                 String JavaDoc message = NLS.bind(RegistryMessages.parse_nonSingleton, bundle.getLocation());
118                 RuntimeLog.log(new Status(IStatus.INFO, RegistryMessages.OWNER_NAME, 0, message, null));
119             }
120             return null;
121         }
122         if (!isFragment)
123             return extensionURL;
124
125         // If the bundle is a fragment being added to a non singleton host, then it is not added
126
Bundle[] hosts = OSGIUtils.getDefault().getHosts(bundle);
127         if (hosts == null)
128             return null; // should never happen?
129

130         if (isSingleton(hosts[0]))
131             return extensionURL;
132
133         if (report) {
134             String JavaDoc message = NLS.bind(RegistryMessages.parse_nonSingleton, hosts[0].getLocation());
135             RuntimeLog.log(new Status(IStatus.INFO, RegistryMessages.OWNER_NAME, 0, message, null));
136         }
137         return null;
138     }
139
140     private void addBundle(Bundle bundle) {
141         String JavaDoc contributorId = Long.toString(bundle.getBundleId());
142         // if the given bundle already exists in the registry then return.
143
// note that this does not work for update cases.
144
if (registry.hasContribution(contributorId))
145             return;
146         URL JavaDoc pluginManifest = getExtensionURL(bundle, registry.debug());
147         if (pluginManifest == null)
148             return;
149         InputStream is;
150         try {
151             is = new BufferedInputStream(pluginManifest.openStream());
152         } catch (IOException ex) {
153             is = null;
154         }
155         if (is == null)
156             return;
157
158         ResourceBundle translationBundle = null;
159         try {
160             translationBundle = ResourceTranslator.getResourceBundle(bundle);
161         } catch (MissingResourceException e) {
162             //Ignore the exception
163
}
164         long timestamp = 0;
165         if (strategy.checkContributionsTimestamp())
166             timestamp = strategy.getExtendedTimestamp(bundle, pluginManifest);
167         IContributor contributor = ContributorFactoryOSGi.createContributor(bundle);
168         registry.addContribution(is, contributor, true, pluginManifest.getPath(), translationBundle, token, timestamp);
169
170         // bug 70941
171
// need to ensure we can find resource bundles from fragments
172
// The code below no longer seems necessary as all runtime plugins are installed
173
// before the corresponding Message classes are instantiated.
174
// if (RuntimeUtils.PI_RUNTIME.equals(bundleModel.getNamespace()))
175
// Messages.reloadMessages();
176
}
177
178     private static boolean isSingleton(Bundle bundle) {
179         Dictionary allHeaders = bundle.getHeaders(""); //$NON-NLS-1$
180
String JavaDoc symbolicNameHeader = (String JavaDoc) allHeaders.get(Constants.BUNDLE_SYMBOLICNAME);
181         try {
182             if (symbolicNameHeader != null) {
183                 ManifestElement[] symbolicNameElements = ManifestElement.parseHeader(Constants.BUNDLE_SYMBOLICNAME, symbolicNameHeader);
184                 if (symbolicNameElements.length > 0) {
185                     String JavaDoc singleton = symbolicNameElements[0].getDirective(Constants.SINGLETON_DIRECTIVE);
186                     if (singleton == null)
187                         singleton = symbolicNameElements[0].getAttribute(Constants.SINGLETON_DIRECTIVE);
188
189                     if (!"true".equalsIgnoreCase(singleton)) { //$NON-NLS-1$
190
String JavaDoc manifestVersion = (String JavaDoc) allHeaders.get(org.osgi.framework.Constants.BUNDLE_MANIFESTVERSION);
191                         if (manifestVersion == null) {//the header was not defined for previous versions of the bundle
192
//3.0 bundles without a singleton attributes are still being accepted
193
if (OSGIUtils.getDefault().getBundle(symbolicNameElements[0].getValue()) == bundle)
194                                 return true;
195                         }
196                         return false;
197                     }
198                 }
199             }
200         } catch (BundleException e1) {
201             //This can't happen because the fwk would have rejected the bundle
202
}
203         return true;
204     }
205 }
206
Popular Tags