KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > runtime > internal > adaptor > EclipseLazyStarter


1 /*******************************************************************************
2  * Copyright (c) 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
12 package org.eclipse.core.runtime.internal.adaptor;
13
14 import java.io.IOException JavaDoc;
15 import java.net.URL JavaDoc;
16 import java.net.URLConnection JavaDoc;
17 import java.security.AccessController JavaDoc;
18 import java.util.*;
19 import org.eclipse.osgi.baseadaptor.*;
20 import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
21 import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook;
22 import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingStatsHook;
23 import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry;
24 import org.eclipse.osgi.baseadaptor.loader.ClasspathManager;
25 import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
26 import org.eclipse.osgi.framework.adaptor.StatusException;
27 import org.eclipse.osgi.framework.debug.Debug;
28 import org.eclipse.osgi.framework.internal.core.*;
29 import org.eclipse.osgi.framework.log.FrameworkLog;
30 import org.eclipse.osgi.framework.log.FrameworkLogEntry;
31 import org.eclipse.osgi.framework.util.SecureAction;
32 import org.eclipse.osgi.service.resolver.BundleDescription;
33 import org.eclipse.osgi.service.resolver.StateHelper;
34 import org.eclipse.osgi.util.NLS;
35 import org.osgi.framework.*;
36 import org.osgi.service.startlevel.StartLevel;
37
38 public class EclipseLazyStarter implements ClassLoadingStatsHook, AdaptorHook, HookConfigurator {
39     private static final boolean throwErrorOnFailedStart = "true".equals(FrameworkProperties.getProperty("osgi.compatibility.errorOnFailedStart", "true")); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
40
private static final SecureAction secureAction = (SecureAction) AccessController.doPrivileged(SecureAction.createSecureAction());
41     private StartLevelImpl startLevelService;
42     private ServiceReference slRef;
43     private BaseAdaptor adaptor;
44     // holds the current activation trigger class and the ClasspathManagers that need to be activated
45
private ThreadLocal JavaDoc activationStack = new ThreadLocal JavaDoc();
46     // used to store exceptions that occurred while activating a bundle
47
// keyed by ClasspathManager->Exception
48
// WeakHashMap is used to prevent pinning the ClasspathManager objects.
49
private final Map errors = Collections.synchronizedMap(new WeakHashMap());
50
51     public void preFindLocalClass(String JavaDoc name, ClasspathManager manager) throws ClassNotFoundException JavaDoc {
52         AbstractBundle bundle = (AbstractBundle) manager.getBaseData().getBundle();
53         // If the bundle is active, uninstalled or stopping then the bundle has already
54
// been initialized (though it may have been destroyed) so just return the class.
55
if ((bundle.getState() & (Bundle.ACTIVE | Bundle.UNINSTALLED | Bundle.STOPPING)) != 0)
56             return;
57         EclipseStorageHook storageHook = (EclipseStorageHook) manager.getBaseData().getStorageHook(EclipseStorageHook.KEY);
58         // The bundle is not active and does not require activation, just return the class
59
if (!shouldActivateFor(name, manager.getBaseData(), storageHook, manager))
60             return;
61         ArrayList stack = (ArrayList) activationStack.get();
62         if (stack == null) {
63             stack = new ArrayList(6);
64             activationStack.set(stack);
65         }
66         // the first element in the stack is the name of the trigger class,
67
// each element after the trigger class is a classpath manager
68
// that must be activated after the trigger class has been defined (see postFindLocalClass)
69
int size = stack.size();
70         if (size > 1) {
71             for (int i = size -1; i >= 1; i--)
72                 if (manager == stack.get(i))
73                     // the manager is already on the stack in which case we are already in the process of loading the trigger class
74
return;
75         }
76         Thread JavaDoc threadChangingState = bundle.getStateChanging();
77         if (bundle.getState() == Bundle.STARTING && threadChangingState == Thread.currentThread())
78             return; // this thread is starting the bundle already
79
if (size == 0)
80             stack.add(name);
81         stack.add(manager);
82     }
83
84     public void postFindLocalClass(String JavaDoc name, Class JavaDoc clazz, ClasspathManager manager) throws ClassNotFoundException JavaDoc {
85         ArrayList stack = (ArrayList) activationStack.get();
86         if (stack == null)
87             return;
88         int size = stack.size();
89         if (size <= 1 || stack.get(0) != name)
90             return;
91         // if we have a stack we must clear it even if (clazz == null)
92
ClasspathManager[] managers = null;
93         managers = new ClasspathManager[size - 1];
94         for (int i = 1; i < size; i++)
95             managers[i - 1] = (ClasspathManager) stack.get(i);
96         stack.clear();
97         if (clazz == null)
98             return;
99         for (int i = managers.length - 1; i >= 0; i--) {
100             if (errors.get(managers[i]) != null) {
101                 if (throwErrorOnFailedStart)
102                     throw (TerminatingClassNotFoundException) errors.get(managers[i]);
103                 continue;
104             }
105             AbstractBundle bundle = (AbstractBundle) managers[i].getBaseData().getBundle();
106             // The bundle must be started.
107
// Note that another thread may already be starting this bundle;
108
// In this case we will timeout after 5 seconds and record the BundleException
109
try {
110                 // do not persist the start of this bundle
111
secureAction.start(bundle, Bundle.START_TRANSIENT);
112             } catch (BundleException e) {
113                 Throwable JavaDoc cause = e.getCause();
114                 if (cause != null && cause instanceof StatusException) {
115                     StatusException status = (StatusException) cause;
116                     if ((status.getStatusCode() & StatusException.CODE_ERROR) == 0) {
117                         if (status.getStatus() instanceof Thread JavaDoc) {
118                             String JavaDoc message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_CONCURRENT_STARTUP, new Object JavaDoc[] {Thread.currentThread(), name, status.getStatus(), bundle, new Integer JavaDoc(5000)});
119                             adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, message, 0, e, null));
120                         }
121                         continue;
122                     }
123                 }
124                 String JavaDoc message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_ACTIVATION, bundle.getSymbolicName(), Long.toString(bundle.getBundleId()));
125                 TerminatingClassNotFoundException error = new TerminatingClassNotFoundException(message, e);
126                 errors.put(managers[i], error);
127                 if (throwErrorOnFailedStart) {
128                     adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, e, null));
129                     throw error;
130                 }
131                 adaptor.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundle, new BundleException(message, e));
132             }
133         }
134     }
135
136     public void preFindLocalResource(String JavaDoc name, ClasspathManager manager) {
137         // do nothing
138
}
139
140     public void postFindLocalResource(String JavaDoc name, URL JavaDoc resource, ClasspathManager manager) {
141         // do nothing
142
}
143
144     public void recordClassDefine(String JavaDoc name, Class JavaDoc clazz, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
145         // do nothing
146
}
147
148     private boolean shouldActivateFor(String JavaDoc className, BaseData bundledata, EclipseStorageHook storageHook, ClasspathManager manager) throws ClassNotFoundException JavaDoc {
149         if (!isLazyStartable(className, bundledata, storageHook))
150             return false;
151         // Don't activate non-starting bundles
152
if (bundledata.getBundle().getState() == Bundle.RESOLVED) {
153             if (throwErrorOnFailedStart) {
154                 TerminatingClassNotFoundException error = (TerminatingClassNotFoundException) errors.get(manager);
155                 if (error != null)
156                     throw error;
157             }
158             StartLevelImpl sl = startLevelService;
159             return sl != null && ((sl.getStartLevel() == bundledata.getStartLevel() && sl.isSettingStartLevel()));
160         }
161         return true;
162     }
163
164     private boolean isLazyStartable(String JavaDoc className, BaseData bundledata, EclipseStorageHook storageHook) {
165         if (storageHook == null)
166             return false;
167         boolean lazyStart = storageHook.isLazyStart();
168         String JavaDoc[] excludes = storageHook.getLazyStartExcludes();
169         String JavaDoc[] includes = storageHook.getLazyStartIncludes();
170         // no exceptions, it is easy to figure it out
171
if (excludes == null && includes == null)
172             return lazyStart;
173         // otherwise, we need to check if the package is in the exceptions list
174
int dotPosition = className.lastIndexOf('.');
175         // the class has no package name... no exceptions apply
176
if (dotPosition == -1)
177             return lazyStart;
178         String JavaDoc packageName = className.substring(0, dotPosition);
179         if (lazyStart)
180             return ((includes == null || contains(includes, packageName)) && (excludes == null || !contains(excludes, packageName)));
181         return (excludes != null && contains(excludes, packageName));
182     }
183
184     private boolean contains(String JavaDoc[] array, String JavaDoc element) {
185         for (int i = 0; i < array.length; i++)
186             if (array[i].equals(element))
187                 return true;
188         return false;
189     }
190
191     public void addHooks(HookRegistry hookRegistry) {
192         hookRegistry.addClassLoadingStatsHook(this);
193         hookRegistry.addAdaptorHook(this);
194     }
195
196     public void addProperties(Properties properties) {
197         // do nothing
198
}
199
200     public FrameworkLog createFrameworkLog() {
201         // do nothing
202
return null;
203     }
204
205     public void frameworkStart(BundleContext context) throws BundleException {
206         slRef = context.getServiceReference(StartLevel.class.getName());
207         if (slRef != null)
208             startLevelService = (StartLevelImpl) context.getService(slRef);
209     }
210
211     public void frameworkStop(BundleContext context) throws BundleException {
212         if (slRef != null) {
213             context.ungetService(slRef);
214             startLevelService = null;
215         }
216     }
217
218     public void frameworkStopping(BundleContext context) {
219         if (!Debug.DEBUG || !Debug.DEBUG_ENABLED)
220             return;
221
222         BundleDescription[] allBundles = adaptor.getState().getResolvedBundles();
223         StateHelper stateHelper = adaptor.getPlatformAdmin().getStateHelper();
224         Object JavaDoc[][] cycles = stateHelper.sortBundles(allBundles);
225         logCycles(cycles);
226     }
227
228     public void handleRuntimeError(Throwable JavaDoc error) {
229         // do nothing
230

231     }
232
233     public void initialize(BaseAdaptor baseAdaptor) {
234         this.adaptor = baseAdaptor;
235     }
236
237     public URLConnection JavaDoc mapLocationToURLConnection(String JavaDoc location) throws IOException JavaDoc {
238         // do nothing
239
return null;
240     }
241
242     public boolean matchDNChain(String JavaDoc pattern, String JavaDoc[] dnChain) {
243         // do nothing
244
return false;
245     }
246
247     private void logCycles(Object JavaDoc[][] cycles) {
248         // log cycles
249
if (cycles.length > 0) {
250             StringBuffer JavaDoc cycleText = new StringBuffer JavaDoc("["); //$NON-NLS-1$
251
for (int i = 0; i < cycles.length; i++) {
252                 cycleText.append('[');
253                 for (int j = 0; j < cycles[i].length; j++) {
254                     cycleText.append(((BundleDescription) cycles[i][j]).getSymbolicName());
255                     cycleText.append(',');
256                 }
257                 cycleText.insert(cycleText.length() - 1, ']');
258             }
259             cycleText.setCharAt(cycleText.length() - 1, ']');
260             String JavaDoc message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_BUNDLESTOPPER_CYCLES_FOUND, cycleText);
261             FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, message, 0, null, null);
262             adaptor.getFrameworkLog().log(entry);
263         }
264     }
265
266     private static class TerminatingClassNotFoundException extends ClassNotFoundException JavaDoc implements StatusException {
267         private static final long serialVersionUID = -6730732895632169173L;
268         private Object JavaDoc cause;
269         public TerminatingClassNotFoundException(String JavaDoc message, Throwable JavaDoc cause) {
270             super(message, cause);
271             this.cause = cause;
272         }
273
274         public Object JavaDoc getStatus() {
275             return cause;
276         }
277
278         public int getStatusCode() {
279             return StatusException.CODE_ERROR;
280         }
281         
282     }
283 }
284
Popular Tags