KickJava   Java API By Example, From Geeks To Geeks.

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


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

11 package org.eclipse.core.internal.registry.osgi;
12
13 import java.io.File JavaDoc;
14 import java.io.IOException JavaDoc;
15 import java.net.URL JavaDoc;
16 import java.util.ResourceBundle JavaDoc;
17 import javax.xml.parsers.SAXParserFactory JavaDoc;
18 import org.eclipse.core.internal.registry.*;
19 import org.eclipse.core.internal.runtime.ResourceTranslator;
20 import org.eclipse.core.runtime.*;
21 import org.eclipse.core.runtime.spi.*;
22 import org.eclipse.osgi.util.NLS;
23 import org.osgi.framework.Bundle;
24 import org.osgi.framework.BundleContext;
25 import org.osgi.util.tracker.ServiceTracker;
26
27 /**
28  * The registry strategy that can be used in OSGi world. It provides the following functionality:
29  * <p><ul>
30  * <li>Translation is done with ResourceTranslator</li>
31  * <li>Registry is filled with information stored in plugin.xml / fragment.xml of OSGi bundles</li>
32  * <li>Uses bunlde-based class loading to create executable extensions</li>
33  * <li>Performs registry validation based on the time stamps of the plugin.xml / fragment.xml files</li>
34  * <li>XML parser is obtained via an OSGi service</li>
35  * </ul></p>
36  * @see RegistryFactory#setDefaultRegistryProvider(IRegistryProvider)
37  * @since org.eclipse.equinox.registry 3.2
38  */

39
40 public class RegistryStrategyOSGI extends RegistryStrategy {
41
42     /**
43      * Registry access key
44      */

45     private Object JavaDoc token;
46
47     /**
48      * Debug extension registry
49      */

50     protected boolean DEBUG;
51
52     /**
53      * Debug extension registry events
54      */

55     protected boolean DEBUG_REGISTRY_EVENTS;
56
57     /**
58      * Tracker for the XML parser service
59      */

60     private ServiceTracker xmlTracker = null;
61
62     /**
63      * Value of the query "should we track contributions timestamps" is cached
64      * in this variable
65      */

66     private boolean trackTimestamp;
67
68     /**
69      * @param theStorageDir - array of file system directories to store cache files; might be null
70      * @param cacheReadOnly - array of read only attributes. True: cache at this location is read
71      * only; false: cache is read/write
72      * @param key - control key for the registry (should be the same key as used in
73      * the RegistryManager#createExtensionRegistry() of this registry
74      */

75     public RegistryStrategyOSGI(File JavaDoc[] theStorageDir, boolean[] cacheReadOnly, Object JavaDoc key) {
76         super(theStorageDir, cacheReadOnly);
77         token = key;
78
79         // Only do timestamp calculations if osgi.checkConfiguration is set to "true" (typically,
80
// this implies -dev mode)
81
BundleContext context = Activator.getContext();
82         if (context != null)
83             trackTimestamp = "true".equalsIgnoreCase(context.getProperty(IRegistryConstants.PROP_CHECK_CONFIG)); //$NON-NLS-1$
84
else
85             trackTimestamp = false;
86     }
87
88     /* (non-Javadoc)
89      * @see org.eclipse.core.runtime.spi.RegistryStrategy#translate(java.lang.String, java.util.ResourceBundle)
90      */

91     public final String JavaDoc translate(String JavaDoc key, ResourceBundle JavaDoc resources) {
92         return ResourceTranslator.getResourceString(null, key, resources);
93     }
94
95     ////////////////////////////////////////////////////////////////////////////////////////
96
// Use OSGi bundles for namespace resolution (contributors: plugins and fragments)
97

98     /**
99      * The default load factor for the bundle cache.
100      */

101     private static float DEFAULT_BUNDLECACHE_LOADFACTOR = 0.75f;
102
103     /**
104      * The expected bundle cache size (calculated as a number of bundles divided
105      * by the DEFAULT_BUNDLECACHE_LOADFACTOR). The bundle cache will be resized
106      * automatically is this number is exceeded.
107      */

108     private static int DEFAULT_BUNDLECACHE_SIZE = 200;
109
110     /**
111      * For performance, we cache mapping of IDs to Bundles.
112      *
113      * We don't expect mapping to change during the runtime. (Or, in the OSGI terms,
114      * we don't expect bundle IDs to be reused during the Eclipse run.)
115      * The Bundle object is stored as a weak reference to facilitate GC
116      * in case the bundle was uninstalled during the Eclipse run.
117      */

118     private ReferenceMap bundleMap = new ReferenceMap(ReferenceMap.SOFT, DEFAULT_BUNDLECACHE_SIZE, DEFAULT_BUNDLECACHE_LOADFACTOR);
119
120     // String Id to OSGi Bundle conversion
121
private Bundle JavaDoc getBundle(String JavaDoc id) {
122         if (id == null)
123             return null;
124         long OSGiId;
125         try {
126             OSGiId = Long.parseLong(id);
127         } catch (NumberFormatException JavaDoc e) {
128             return null;
129         }
130         // We assume here that OSGI Id will fit into "int". As the number of
131
// registry elements themselves are expected to fit into "int", this
132
// is a valid assumption for the time being.
133
Bundle JavaDoc bundle = (Bundle JavaDoc) bundleMap.get((int) OSGiId);
134         if (bundle != null)
135             return bundle;
136         bundle = Activator.getContext().getBundle(OSGiId);
137         bundleMap.put((int) OSGiId, bundle);
138         return bundle;
139     }
140
141     /////////////////////////////////////////////////////////////////////////////////////
142
// Executable extensions: bundle-based class loading
143

144     /* (non-Javadoc)
145      * @see org.eclipse.core.runtime.spi.RegistryStrategy#createExecutableExtension(org.eclipse.core.runtime.spi.RegistryContributor, java.lang.String, java.lang.String)
146      */

147     public Object JavaDoc createExecutableExtension(RegistryContributor contributor, String JavaDoc className, String JavaDoc overridenContributorName) throws CoreException {
148         Bundle JavaDoc contributingBundle;
149         if (overridenContributorName != null && !overridenContributorName.equals("")) //$NON-NLS-1$
150
contributingBundle = OSGIUtils.getDefault().getBundle(overridenContributorName);
151         else
152             contributingBundle = getBundle(contributor.getId());
153
154         if (contributingBundle == null)
155             throwException(NLS.bind(RegistryMessages.plugin_loadClassError, "UNKNOWN BUNDLE", className), new InvalidRegistryObjectException()); //$NON-NLS-1$
156

157         // load the requested class from this bundle
158
Class JavaDoc classInstance = null;
159         try {
160             classInstance = contributingBundle.loadClass(className);
161         } catch (Exception JavaDoc e1) {
162             throwException(NLS.bind(RegistryMessages.plugin_loadClassError, contributingBundle.getSymbolicName(), className), e1);
163         } catch (LinkageError JavaDoc e) {
164             throwException(NLS.bind(RegistryMessages.plugin_loadClassError, contributingBundle.getSymbolicName(), className), e);
165         }
166
167         // create a new instance
168
Object JavaDoc result = null;
169         try {
170             result = classInstance.newInstance();
171         } catch (Exception JavaDoc e) {
172             throwException(NLS.bind(RegistryMessages.plugin_instantiateClassError, contributingBundle.getSymbolicName(), className), e);
173         } catch (LinkageError JavaDoc e1) {
174             throwException(NLS.bind(RegistryMessages.plugin_instantiateClassError, contributingBundle.getSymbolicName(), className), e1);
175         }
176         return result;
177     }
178
179     private void throwException(String JavaDoc message, Throwable JavaDoc exception) throws CoreException {
180         throw new CoreException(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, IRegistryConstants.PLUGIN_ERROR, message, exception));
181     }
182
183     /////////////////////////////////////////////////////////////////////////////////////
184
// Start / stop extra processing: adding bundle listener; fill registry if not filled from cache
185

186     /**
187      * Listening to the bundle events.
188      */

189     private EclipseBundleListener pluginBundleListener = null;
190
191     /* (non-Javadoc)
192      * @see org.eclipse.core.runtime.spi.RegistryStrategy#onStart(org.eclipse.core.runtime.IExtensionRegistry)
193      */

194     public void onStart(IExtensionRegistry registry) {
195         super.onStart(registry);
196         if (!(registry instanceof ExtensionRegistry))
197             return;
198         ExtensionRegistry theRegistry = (ExtensionRegistry) registry;
199
200         // register a listener to catch new bundle installations/resolutions.
201
pluginBundleListener = new EclipseBundleListener(theRegistry, token, this);
202         Activator.getContext().addBundleListener(pluginBundleListener);
203
204         // populate the registry with all the currently installed bundles.
205
// There is a small window here while processBundles is being
206
// called where the pluginBundleListener may receive a BundleEvent
207
// to add/remove a bundle from the registry. This is ok since
208
// the registry is a synchronized object and will not add the
209
// same bundle twice.
210
if (!theRegistry.filledFromCache())
211             pluginBundleListener.processBundles(Activator.getContext().getBundles());
212     }
213
214     /* (non-Javadoc)
215      * @see org.eclipse.core.runtime.spi.RegistryStrategy#onStop(org.eclipse.core.runtime.IExtensionRegistry)
216      */

217     public void onStop(IExtensionRegistry registry) {
218         if (pluginBundleListener != null)
219             Activator.getContext().removeBundleListener(pluginBundleListener);
220         if (xmlTracker != null) {
221             xmlTracker.close();
222             xmlTracker = null;
223         }
224         super.onStop(registry);
225     }
226
227     //////////////////////////////////////////////////////////////////////////////////////
228
// Cache strategy
229

230     /* (non-Javadoc)
231      * @see org.eclipse.core.runtime.spi.RegistryStrategy#cacheUse()
232      */

233     public boolean cacheUse() {
234         return !"true".equals(RegistryProperties.getProperty(IRegistryConstants.PROP_NO_REGISTRY_CACHE)); //$NON-NLS-1$
235
}
236
237     /* (non-Javadoc)
238      * @see org.eclipse.core.runtime.spi.RegistryStrategy#cacheLazyLoading()
239      */

240     public boolean cacheLazyLoading() {
241         return !("true".equalsIgnoreCase(RegistryProperties.getProperty(IRegistryConstants.PROP_NO_LAZY_CACHE_LOADING))); //$NON-NLS-1$
242
}
243
244     /* (non-Javadoc)
245      * @see org.eclipse.core.runtime.spi.RegistryStrategy#getContributionsTimestamp()
246      */

247     public long getContributionsTimestamp() {
248         if (!checkContributionsTimestamp())
249             return 0;
250         RegistryTimestamp expectedTimestamp = new RegistryTimestamp();
251         BundleContext context = Activator.getContext();
252         Bundle JavaDoc[] allBundles = context.getBundles();
253         for (int i = 0; i < allBundles.length; i++) {
254             URL JavaDoc pluginManifest = EclipseBundleListener.getExtensionURL(allBundles[i], false);
255             if (pluginManifest == null)
256                 continue;
257             long timestamp = getExtendedTimestamp(allBundles[i], pluginManifest);
258             expectedTimestamp.add(timestamp);
259         }
260         return expectedTimestamp.getContentsTimestamp();
261     }
262
263     public boolean checkContributionsTimestamp() {
264         return trackTimestamp;
265     }
266
267     public long getExtendedTimestamp(Bundle JavaDoc bundle, URL JavaDoc pluginManifest) {
268         if (pluginManifest == null)
269             return 0;
270         try {
271              return pluginManifest.openConnection().getLastModified() + bundle.getBundleId();
272         } catch (IOException JavaDoc e) {
273             if (debug()) {
274                 System.out.println("Unable to obtain timestamp for the bundle " + bundle.getSymbolicName()); //$NON-NLS-1$
275
e.printStackTrace();
276             }
277             return 0;
278         }
279     }
280
281     /* (non-Javadoc)
282      * @see org.eclipse.core.runtime.spi.RegistryStrategy#getXMLParser()
283      */

284     public SAXParserFactory JavaDoc getXMLParser() {
285         if (xmlTracker == null) {
286             xmlTracker = new ServiceTracker(Activator.getContext(), SAXParserFactory JavaDoc.class.getName(), null);
287             xmlTracker.open();
288         }
289         return (SAXParserFactory JavaDoc) xmlTracker.getService();
290     }
291 }
292
Popular Tags