1 11 package org.eclipse.core.runtime.adaptor; 12 13 import java.io.IOException ; 14 import java.io.InputStream ; 15 import java.net.URL ; 16 import java.security.ProtectionDomain ; 17 import java.util.ArrayList ; 18 import java.util.StringTokenizer ; 19 import java.util.jar.Attributes ; 20 import java.util.jar.Manifest ; 21 import org.eclipse.core.runtime.internal.adaptor.BundleStopper; 22 import org.eclipse.core.runtime.internal.adaptor.EclipseEnvironmentInfo; 23 import org.eclipse.core.runtime.internal.stats.*; 24 import org.eclipse.osgi.framework.adaptor.*; 25 import org.eclipse.osgi.framework.adaptor.core.*; 26 import org.eclipse.osgi.framework.internal.core.AbstractBundle; 27 import org.eclipse.osgi.framework.internal.core.Msg; 28 import org.eclipse.osgi.framework.log.FrameworkLogEntry; 29 import org.eclipse.osgi.util.NLS; 30 import org.osgi.framework.*; 31 32 39 public class EclipseClassLoader extends DefaultClassLoader { 40 private static String [] NL_JAR_VARIANTS = buildNLJarVariants(EclipseEnvironmentInfo.getDefault().getNL()); 41 private static boolean DEFINE_PACKAGES; 42 private static final String VARIABLE_DELIM_STRING = "$"; private static final char VARIABLE_DELIM_CHAR = '$'; 44 private static final String EXTERNAL_LIB_PREFIX = "external:"; static { 46 try { 47 Class.forName("java.lang.Package"); DEFINE_PACKAGES = true; 49 } catch (ClassNotFoundException e) { 50 DEFINE_PACKAGES = false; 51 } 52 } 53 54 public EclipseClassLoader(ClassLoaderDelegate delegate, ProtectionDomain domain, String [] classpath, ClassLoader parent, BundleData bundleData) { 55 super(delegate, domain, classpath, parent, (EclipseBundleData) bundleData); 56 } 57 58 public Class findLocalClass(String className) throws ClassNotFoundException { 59 if (StatsManager.MONITOR_CLASSES) ClassloaderStats.startLoadingClass(getClassloaderId(), className); 61 boolean found = true; 62 63 try { 64 AbstractBundle bundle = (AbstractBundle) hostdata.getBundle(); 65 if ((bundle.getState() & (Bundle.ACTIVE | Bundle.UNINSTALLED | Bundle.STOPPING)) != 0) 68 return basicFindLocalClass(className); 69 70 if (!shouldActivateFor(className)) 72 return basicFindLocalClass(className); 73 74 if (bundle.getState() == Bundle.STARTING) { 80 if (bundle.testStateChanging(Thread.currentThread()) || bundle.testStateChanging(null)) 82 return basicFindLocalClass(className); 83 84 if (!bundle.testStateChanging(Thread.currentThread())) { 88 Thread threadChangingState = bundle.getStateChanging(); 89 if (StatsManager.TRACE_BUNDLES && threadChangingState != null) { 90 System.out.println("Concurrent startup of bundle " + bundle.getSymbolicName() + " by " + Thread.currentThread() + " and " + threadChangingState.getName() + ". Waiting up to 5000ms for " + threadChangingState + " to finish the initialization."); } 92 long start = System.currentTimeMillis(); 93 long delay = 5000; 94 long timeLeft = delay; 95 while (true) { 96 try { 97 Thread.sleep(100); if (bundle.testStateChanging(null) || timeLeft <= 0) 99 break; 100 } catch (InterruptedException e) { 101 } 103 timeLeft = start + delay - System.currentTimeMillis(); 104 } 105 if (timeLeft <= 0 || bundle.getState() != Bundle.ACTIVE) { 106 String bundleName = bundle.getSymbolicName() == null ? Long.toString(bundle.getBundleId()) : bundle.getSymbolicName(); 107 String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_CONCURRENT_STARTUP, new Object [] {Thread.currentThread().getName(), className, threadChangingState.getName(), bundleName, Long.toString(delay)}); 108 EclipseAdaptor.getDefault().getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, message, 0, new Exception (EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_GENERATED_EXCEPTION), null)); 109 } 110 return basicFindLocalClass(className); 111 } 112 } 113 114 try { 116 hostdata.getBundle().start(); 117 } catch (BundleException e) { 118 String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_ACTIVATION, bundle.getSymbolicName(), Long.toString(bundle.getBundleId())); EclipseAdaptor.getDefault().getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, message, 0, e, null)); 120 throw new ClassNotFoundException (className, e); 121 } 122 return basicFindLocalClass(className); 123 } catch (ClassNotFoundException e) { 124 found = false; 125 throw e; 126 } finally { 127 if (StatsManager.MONITOR_CLASSES) 128 ClassloaderStats.endLoadingClass(getClassloaderId(), className, found); 129 } 130 } 131 132 140 protected Class basicFindLocalClass(String name) throws ClassNotFoundException { 141 return super.findLocalClass(name); 142 } 143 144 147 private boolean shouldActivateFor(String className) throws ClassNotFoundException { 148 if (hostdata.getAdaptor().isStopping()) { 150 BundleStopper stopper = EclipseAdaptor.getDefault().getBundleStopper(); 151 if (stopper != null && stopper.isStopped(hostdata.getBundle())) { 152 String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_ALREADY_STOPPED, className, hostdata.getSymbolicName()); 153 throw new ClassNotFoundException (message); 154 } 155 } 156 boolean autoStart = ((EclipseBundleData) hostdata).isAutoStart(); 157 String [] autoStartExceptions = ((EclipseBundleData) hostdata).getAutoStartExceptions(); 158 if (autoStartExceptions == null) 160 return autoStart; 161 int dotPosition = className.lastIndexOf('.'); 163 if (dotPosition == -1) 165 return autoStart; 166 String packageName = className.substring(0, dotPosition); 167 return autoStart ^ contains(autoStartExceptions, packageName); 169 } 170 171 private boolean contains(String [] array, String element) { 172 for (int i = 0; i < array.length; i++) 173 if (array[i].equals(element)) 174 return true; 175 return false; 176 } 177 178 181 protected Class defineClass(String name, byte[] classbytes, int off, int len, ClasspathEntry classpathEntry) throws ClassFormatError { 182 if (!DEFINE_PACKAGES) 183 return super.defineClass(name, classbytes, off, len, classpathEntry); 184 185 int lastIndex = name.lastIndexOf('.'); 187 if (lastIndex != -1) { 188 String packageName = name.substring(0, lastIndex); 189 Package pkg = getPackage(packageName); 190 if (pkg == null) { 191 String specTitle = null, specVersion = null, specVendor = null, implTitle = null, implVersion = null, implVendor = null; 193 Manifest mf = ((EclipseClasspathEntry) classpathEntry).getManifest(); 194 if (mf != null) { 195 Attributes mainAttributes = mf.getMainAttributes(); 196 String dirName = packageName.replace('.', '/') + '/'; 197 Attributes packageAttributes = mf.getAttributes(dirName); 198 boolean noEntry = false; 199 if (packageAttributes == null) { 200 noEntry = true; 201 packageAttributes = mainAttributes; 202 } 203 specTitle = packageAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE); 204 if (specTitle == null && !noEntry) 205 specTitle = mainAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE); 206 specVersion = packageAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION); 207 if (specVersion == null && !noEntry) 208 specVersion = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION); 209 specVendor = packageAttributes.getValue(Attributes.Name.SPECIFICATION_VENDOR); 210 if (specVendor == null && !noEntry) 211 specVendor = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VENDOR); 212 implTitle = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE); 213 if (implTitle == null && !noEntry) 214 implTitle = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE); 215 implVersion = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION); 216 if (implVersion == null && !noEntry) 217 implVersion = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION); 218 implVendor = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR); 219 if (implVendor == null && !noEntry) 220 implVendor = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR); 221 } 222 definePackage(packageName, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, null); 225 } 226 } 227 return super.defineClass(name, classbytes, off, len, classpathEntry); 228 } 229 230 private String getClassloaderId() { 231 return hostdata.getBundle().getSymbolicName(); 232 } 233 234 public URL getResource(String name) { 235 URL result = super.getResource(name); 236 if (StatsManager.MONITOR_RESOURCES) { 237 if (result != null && name.endsWith(".properties")) { ClassloaderStats.loadedBundle(getClassloaderId(), new ResourceBundleStats(getClassloaderId(), name, result)); 239 } 240 } 241 return result; 242 } 243 244 protected void findClassPathEntry(ArrayList result, String entry, AbstractBundleData bundledata, ProtectionDomain domain) { 245 String var = hasPrefix(entry); 246 if (var != null) { 247 findInternalClassPath(var, result, entry, bundledata, domain); 249 return; 250 } 251 if (entry.startsWith(EXTERNAL_LIB_PREFIX)) { 252 entry = entry.substring(EXTERNAL_LIB_PREFIX.length()); 253 ClasspathEntry cpEntry = getExternalClassPath(substituteVars(entry), bundledata, domain); 255 if (cpEntry != null) 256 result.add(cpEntry); 257 return; 258 } 259 super.findClassPathEntry(result, entry, bundledata, domain); 261 } 262 263 private void findInternalClassPath(String var, ArrayList result, String entry, AbstractBundleData bundledata, ProtectionDomain domain) { 264 if (var.equals("ws")) { super.findClassPathEntry(result, "ws/" + EclipseEnvironmentInfo.getDefault().getWS() + entry.substring(4), bundledata, domain); return; 267 } 268 if (var.equals("os")) { super.findClassPathEntry(result, "os/" + EclipseEnvironmentInfo.getDefault().getOS() + entry.substring(4), bundledata, domain); return; 271 } 272 if (var.equals("nl")) { entry = entry.substring(4); 274 for (int i = 0; i < NL_JAR_VARIANTS.length; i++) { 275 if (addClassPathEntry(result, "nl/" + NL_JAR_VARIANTS[i] + entry, bundledata, domain)) return; 277 } 278 if (!DevClassPathHelper.inDevelopmentMode()) { 280 BundleException be = new BundleException(NLS.bind(Msg.BUNDLE_CLASSPATH_ENTRY_NOT_FOUND_EXCEPTION, entry)); bundledata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundledata.getBundle(), be); 283 } 284 } 285 } 286 287 private static String [] buildNLJarVariants(String nl) { 288 ArrayList result = new ArrayList (); 289 nl = nl.replace('_', '/'); 290 while (nl.length() > 0) { 291 result.add("nl/" + nl + "/"); int i = nl.lastIndexOf('/'); nl = (i < 0) ? "" : nl.substring(0, i); } 295 result.add(""); return (String []) result.toArray(new String [result.size()]); 297 } 298 299 private String hasPrefix(String libPath) { 301 if (libPath.startsWith("$ws$")) return "ws"; if (libPath.startsWith("$os$")) return "os"; if (libPath.startsWith("$nl$")) return "nl"; return null; 308 } 309 310 private String substituteVars(String cp) { 311 StringBuffer buf = new StringBuffer (cp.length()); 312 StringTokenizer st = new StringTokenizer (cp, VARIABLE_DELIM_STRING, true); 313 boolean varStarted = false; String var = null; while (st.hasMoreElements()) { 316 String tok = st.nextToken(); 317 if (VARIABLE_DELIM_STRING.equals(tok)) { 318 if (!varStarted) { 319 varStarted = true; var = ""; } else { 322 String prop = null; 324 if (var != null && var.length() > 0) 326 prop = System.getProperty(var); 327 if (prop != null) 328 buf.append(prop); 330 else 331 buf.append(var == null ? "" : var); varStarted = false; 334 var = null; 335 } 336 } else { 337 if (!varStarted) 338 buf.append(tok); else 340 var = tok; } 342 } 343 if (var != null) 344 buf.append(VARIABLE_DELIM_CHAR).append(var); 346 return buf.toString(); 347 } 348 349 353 protected ClasspathEntry createClassPathEntry(BundleFile bundlefile, ProtectionDomain domain) { 354 return new EclipseClasspathEntry(bundlefile, domain); 355 } 356 357 360 protected class EclipseClasspathEntry extends ClasspathEntry { 361 Manifest mf; 362 boolean initMF = false; 363 364 protected EclipseClasspathEntry(BundleFile bundlefile, ProtectionDomain domain) { 365 super(bundlefile, domain); 366 } 367 368 public Manifest getManifest() { 369 if (initMF) 370 return mf; 371 if (!hasPackageInfo()) { 372 initMF = true; 373 mf = null; 374 return mf; 375 } 376 BundleEntry mfEntry = getBundleFile().getEntry(org.eclipse.osgi.framework.internal.core.Constants.OSGI_BUNDLE_MANIFEST); 377 if (mfEntry != null) 378 try { 379 InputStream manIn = mfEntry.getInputStream(); 380 mf = new Manifest (manIn); 381 manIn.close(); 382 } catch (IOException e) { 383 } 385 initMF = true; 386 return mf; 387 } 388 389 private boolean hasPackageInfo() { 390 if (getBundleFile() == getHostData().getBaseBundleFile()) 391 return ((EclipseBundleData)getHostData()).hasPackageInfo; 392 FragmentClasspath[] fragCPs = getFragClasspaths(); 393 if (fragCPs != null) 394 for (int i = 0; i < fragCPs.length; i++) 395 if (getBundleFile() == fragCPs[i].getBundleData().getBaseBundleFile()) 396 return ((EclipseBundleData)fragCPs[i].getBundleData()).hasPackageInfo; 397 return true; 398 } 399 } 400 } 401 | Popular Tags |