1 11 12 package org.eclipse.core.runtime.internal.adaptor; 13 14 import java.io.IOException ; 15 import java.net.URL ; 16 import java.net.URLConnection ; 17 import java.security.AccessController ; 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")); private static final SecureAction secureAction = (SecureAction) AccessController.doPrivileged(SecureAction.createSecureAction()); 41 private StartLevelImpl startLevelService; 42 private ServiceReference slRef; 43 private BaseAdaptor adaptor; 44 private ThreadLocal activationStack = new ThreadLocal (); 46 private final Map errors = Collections.synchronizedMap(new WeakHashMap()); 50 51 public void preFindLocalClass(String name, ClasspathManager manager) throws ClassNotFoundException { 52 AbstractBundle bundle = (AbstractBundle) manager.getBaseData().getBundle(); 53 if ((bundle.getState() & (Bundle.ACTIVE | Bundle.UNINSTALLED | Bundle.STOPPING)) != 0) 56 return; 57 EclipseStorageHook storageHook = (EclipseStorageHook) manager.getBaseData().getStorageHook(EclipseStorageHook.KEY); 58 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 int size = stack.size(); 70 if (size > 1) { 71 for (int i = size -1; i >= 1; i--) 72 if (manager == stack.get(i)) 73 return; 75 } 76 Thread threadChangingState = bundle.getStateChanging(); 77 if (bundle.getState() == Bundle.STARTING && threadChangingState == Thread.currentThread()) 78 return; if (size == 0) 80 stack.add(name); 81 stack.add(manager); 82 } 83 84 public void postFindLocalClass(String name, Class clazz, ClasspathManager manager) throws ClassNotFoundException { 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 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 try { 110 secureAction.start(bundle, Bundle.START_TRANSIENT); 112 } catch (BundleException e) { 113 Throwable 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 ) { 118 String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_CONCURRENT_STARTUP, new Object [] {Thread.currentThread(), name, status.getStatus(), bundle, new Integer (5000)}); 119 adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, message, 0, e, null)); 120 } 121 continue; 122 } 123 } 124 String 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 name, ClasspathManager manager) { 137 } 139 140 public void postFindLocalResource(String name, URL resource, ClasspathManager manager) { 141 } 143 144 public void recordClassDefine(String name, Class clazz, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) { 145 } 147 148 private boolean shouldActivateFor(String className, BaseData bundledata, EclipseStorageHook storageHook, ClasspathManager manager) throws ClassNotFoundException { 149 if (!isLazyStartable(className, bundledata, storageHook)) 150 return false; 151 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 className, BaseData bundledata, EclipseStorageHook storageHook) { 165 if (storageHook == null) 166 return false; 167 boolean lazyStart = storageHook.isLazyStart(); 168 String [] excludes = storageHook.getLazyStartExcludes(); 169 String [] includes = storageHook.getLazyStartIncludes(); 170 if (excludes == null && includes == null) 172 return lazyStart; 173 int dotPosition = className.lastIndexOf('.'); 175 if (dotPosition == -1) 177 return lazyStart; 178 String 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 [] array, String 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 } 199 200 public FrameworkLog createFrameworkLog() { 201 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 [][] cycles = stateHelper.sortBundles(allBundles); 225 logCycles(cycles); 226 } 227 228 public void handleRuntimeError(Throwable error) { 229 231 } 232 233 public void initialize(BaseAdaptor baseAdaptor) { 234 this.adaptor = baseAdaptor; 235 } 236 237 public URLConnection mapLocationToURLConnection(String location) throws IOException { 238 return null; 240 } 241 242 public boolean matchDNChain(String pattern, String [] dnChain) { 243 return false; 245 } 246 247 private void logCycles(Object [][] cycles) { 248 if (cycles.length > 0) { 250 StringBuffer cycleText = new StringBuffer ("["); 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 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 implements StatusException { 267 private static final long serialVersionUID = -6730732895632169173L; 268 private Object cause; 269 public TerminatingClassNotFoundException(String message, Throwable cause) { 270 super(message, cause); 271 this.cause = cause; 272 } 273 274 public Object getStatus() { 275 return cause; 276 } 277 278 public int getStatusCode() { 279 return StatusException.CODE_ERROR; 280 } 281 282 } 283 } 284
| Popular Tags
|