1 11 12 package org.eclipse.core.runtime.internal.adaptor; 13 14 import java.io.*; 15 import java.net.URL ; 16 import java.util.*; 17 import org.eclipse.core.runtime.adaptor.LocationManager; 18 import org.eclipse.osgi.baseadaptor.*; 19 import org.eclipse.osgi.baseadaptor.hooks.StorageHook; 20 import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor; 21 import org.eclipse.osgi.framework.internal.core.Constants; 22 import org.eclipse.osgi.framework.internal.core.FrameworkProperties; 23 import org.eclipse.osgi.framework.log.FrameworkLogEntry; 24 import org.eclipse.osgi.framework.util.Headers; 25 import org.eclipse.osgi.framework.util.KeyedElement; 26 import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil; 27 import org.eclipse.osgi.service.datalocation.Location; 28 import org.eclipse.osgi.service.pluginconversion.PluginConversionException; 29 import org.eclipse.osgi.util.ManifestElement; 30 import org.eclipse.osgi.util.NLS; 31 import org.osgi.framework.BundleException; 32 import org.osgi.framework.Version; 33 34 public final class EclipseStorageHook implements StorageHook, HookConfigurator { 35 private static final String PROP_CHECK_CONFIG = "osgi.checkConfiguration"; private static final String PROP_COMPATIBILITY_LAZYSTART = "osgi.compatibility.eagerStart.LazyActivation"; private static final boolean COMPATIBILITY_LAZYSTART = Boolean.valueOf(FrameworkProperties.getProperty(PROP_COMPATIBILITY_LAZYSTART, "true")).booleanValue(); private static final int STORAGE_VERION = 2; 40 41 public static final String KEY = EclipseStorageHook.class.getName(); 42 public static final int HASHCODE = KEY.hashCode(); 43 44 private static final byte FLAG_LAZY_START = 0x01; 45 private static final byte FLAG_HAS_PACKAGE_INFO = 0x02; 46 private static final byte FLAG_HAS_LAZY_INCLUDE = 0x08; 50 51 52 private long manifestTimeStamp = 0; 53 private byte manifestType = PluginConverterImpl.MANIFEST_TYPE_UNKNOWN; 54 55 private BaseData bundledata; 56 57 58 private String pluginClass = null; 59 60 private String [] lazyStartExcludes; 61 private String [] lazyStartIncludes; 62 63 private String buddyList; 64 65 private String registeredBuddyList; 66 private byte flags = 0; 67 68 public int getStorageVersion() { 69 return STORAGE_VERION; 70 } 71 72 public StorageHook create(BaseData bundledata) throws BundleException { 73 EclipseStorageHook storageHook = new EclipseStorageHook(); 74 storageHook.bundledata = bundledata; 75 return storageHook; 76 } 77 78 public void initialize(Dictionary manifest) throws BundleException { 79 String activationPolicy = (String ) manifest.get(Constants.BUNDLE_ACTIVATIONPOLICY); 80 if (activationPolicy != null) { 81 parseActivationPolicy(this, activationPolicy); 82 } else { 83 String lazyStart = (String ) manifest.get(Constants.ECLIPSE_LAZYSTART); 84 if (lazyStart == null) 85 lazyStart = (String ) manifest.get(Constants.ECLIPSE_AUTOSTART); 86 parseLazyStart(this, lazyStart); 87 } 88 pluginClass = (String ) manifest.get(Constants.PLUGIN_CLASS); 89 buddyList = (String ) manifest.get(Constants.BUDDY_LOADER); 90 registeredBuddyList = (String ) manifest.get(Constants.REGISTERED_POLICY); 91 if (hasPackageInfo(bundledata.getEntry(Constants.OSGI_BUNDLE_MANIFEST))) 92 flags |= FLAG_HAS_PACKAGE_INFO; 93 String genFrom = (String ) manifest.get(PluginConverterImpl.GENERATED_FROM); 94 if (genFrom != null) { 95 ManifestElement generatedFrom = ManifestElement.parseHeader(PluginConverterImpl.GENERATED_FROM, genFrom)[0]; 96 if (generatedFrom != null) { 97 manifestTimeStamp = Long.parseLong(generatedFrom.getValue()); 98 manifestType = Byte.parseByte(generatedFrom.getAttribute(PluginConverterImpl.MANIFEST_TYPE_ATTRIBUTE)); 99 } 100 } 101 if (isAutoStartable()) { 102 bundledata.setStatus(bundledata.getStatus() | Constants.BUNDLE_LAZY_START); 103 if (COMPATIBILITY_LAZYSTART) 104 bundledata.setStatus(bundledata.getStatus() | Constants.BUNDLE_STARTED | Constants.BUNDLE_ACTIVATION_POLICY); 105 } 106 } 107 108 public StorageHook load(BaseData target, DataInputStream in) throws IOException { 109 EclipseStorageHook storageHook = new EclipseStorageHook(); 110 storageHook.bundledata = target; 111 storageHook.flags = in.readByte(); 112 int pkgCount = in.readInt(); 113 String [] packageList = pkgCount > 0 ? new String [pkgCount] : null; 114 for (int i = 0; i < pkgCount; i++) 115 packageList[i] = in.readUTF(); 116 storageHook.lazyStartExcludes = packageList; 117 if ((storageHook.flags & FLAG_HAS_LAZY_INCLUDE) != 0) { 118 pkgCount = in.readInt(); 119 packageList = pkgCount > 0 ? new String [pkgCount] : null; 120 for (int i = 0; i < pkgCount; i++) 121 packageList[i] = in.readUTF(); 122 storageHook.lazyStartIncludes = packageList; 123 } 124 storageHook.buddyList = AdaptorUtil.readString(in, false); 125 storageHook.registeredBuddyList = AdaptorUtil.readString(in, false); 126 storageHook.pluginClass = AdaptorUtil.readString(in, false); 127 storageHook.manifestTimeStamp = in.readLong(); 128 storageHook.manifestType = in.readByte(); 129 if (storageHook.isAutoStartable()) { 130 if ((target.getStatus() & Constants.BUNDLE_LAZY_START) == 0) 131 target.setStatus(target.getStatus() | Constants.BUNDLE_LAZY_START); 132 if (COMPATIBILITY_LAZYSTART && (target.getStatus() & Constants.BUNDLE_STARTED ) == 0) 135 target.setStatus(target.getStatus() | Constants.BUNDLE_STARTED | Constants.BUNDLE_ACTIVATION_POLICY); 136 } 137 return storageHook; 138 } 139 140 public void save(DataOutputStream out) throws IOException { 141 if (bundledata == null) 142 throw new IllegalStateException (); 143 out.writeByte(flags); 145 String [] excludes = getLazyStartExcludes(); 146 if (excludes == null) 147 out.writeInt(0); 148 else { 149 out.writeInt(excludes.length); 150 for (int i = 0; i < excludes.length; i++) 151 out.writeUTF(excludes[i]); 152 } 153 if ((flags & FLAG_HAS_LAZY_INCLUDE) != 0) { 154 String [] includes = getLazyStartIncludes(); 155 if (includes == null) 156 out.writeInt(0); 157 else { 158 out.writeInt(includes.length); 159 for (int i = 0; i < includes.length; i++) 160 out.writeUTF(includes[i]); 161 } 162 } 163 AdaptorUtil.writeStringOrNull(out, getBuddyList()); 164 AdaptorUtil.writeStringOrNull(out, getRegisteredBuddyList()); 165 AdaptorUtil.writeStringOrNull(out, getPluginClass()); 166 out.writeLong(getManifestTimeStamp()); 167 out.writeByte(getManifestType()); 168 } 169 170 public int getKeyHashCode() { 171 return HASHCODE; 172 } 173 174 public boolean compare(KeyedElement other) { 175 return other.getKey() == KEY; 176 } 177 178 public Object getKey() { 179 return KEY; 180 } 181 182 public boolean isLazyStart() { 183 return (flags & FLAG_LAZY_START) == FLAG_LAZY_START; 184 } 185 186 public String [] getLazyStartExcludes() { 187 return lazyStartExcludes; 188 } 189 190 public String [] getLazyStartIncludes() { 191 return lazyStartIncludes; 192 } 193 194 public String getBuddyList() { 195 return buddyList; 196 } 197 198 public boolean hasPackageInfo() { 199 return (flags & FLAG_HAS_PACKAGE_INFO) == FLAG_HAS_PACKAGE_INFO; 200 } 201 202 public String getPluginClass() { 203 return pluginClass; 204 } 205 206 public String getRegisteredBuddyList() { 207 return registeredBuddyList; 208 } 209 210 public long getManifestTimeStamp() { 211 return manifestTimeStamp; 212 } 213 214 public byte getManifestType() { 215 return manifestType; 216 } 217 218 223 public boolean isAutoStartable() { 224 return isLazyStart() || (lazyStartExcludes != null && lazyStartExcludes.length > 0); 225 } 226 227 private void parseLazyStart(EclipseStorageHook storageHook, String headerValue) { 228 storageHook.lazyStartExcludes = null; 229 ManifestElement[] allElements = null; 230 try { 231 allElements = ManifestElement.parseHeader(Constants.ECLIPSE_LAZYSTART, headerValue); 232 } catch (BundleException e) { 233 String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_CANNOT_GET_HEADERS, storageHook.bundledata.getLocation()); 235 bundledata.getAdaptor().getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, e, null)); 236 } 237 if (allElements == null) 239 return; 240 if ("true".equalsIgnoreCase(allElements[0].getValue())) storageHook.flags |= FLAG_LAZY_START; 243 String [] exceptions = ManifestElement.getArrayFromList(allElements[0].getAttribute(Constants.ECLIPSE_LAZYSTART_EXCEPTIONS)); 245 storageHook.lazyStartExcludes = exceptions; 246 } 247 248 private void parseActivationPolicy(EclipseStorageHook storageHook, String headerValue) { 249 storageHook.lazyStartExcludes = null; 250 ManifestElement[] allElements = null; 251 try { 252 allElements = ManifestElement.parseHeader(Constants.BUNDLE_ACTIVATIONPOLICY, headerValue); 253 } catch (BundleException e) { 254 String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_CANNOT_GET_HEADERS, storageHook.bundledata.getLocation()); 256 bundledata.getAdaptor().getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, e, null)); 257 } 258 if (allElements == null) 260 return; 261 if (!Constants.ACTIVATION_LAZY.equalsIgnoreCase(allElements[0].getValue())) return; 264 storageHook.flags |= FLAG_LAZY_START; 265 storageHook.lazyStartExcludes = ManifestElement.getArrayFromList(allElements[0].getDirective(Constants.EXCLUDE_DIRECTIVE)); 267 storageHook.lazyStartIncludes = ManifestElement.getArrayFromList(allElements[0].getDirective(Constants.INCLUDE_DIRECTIVE)); 268 if (storageHook.lazyStartIncludes != null) 269 storageHook.flags |= FLAG_HAS_LAZY_INCLUDE; 270 } 271 272 private static boolean hasPackageInfo(URL url) { 276 if (url == null) 277 return false; 278 BufferedReader br = null; 279 try { 280 br = new BufferedReader(new InputStreamReader(url.openStream())); 281 String line; 282 while ((line = br.readLine()) != null) { 283 if (line.startsWith("Specification-Title: ") || line.startsWith("Specification-Version: ") || line.startsWith("Specification-Vendor: ") || line.startsWith("Implementation-Title: ") || line.startsWith("Implementation-Version: ") || line.startsWith("Implementation-Vendor: ")) return true; 285 } 286 } catch (IOException ioe) { 287 } finally { 289 if (br != null) 290 try { 291 br.close(); 292 } catch (IOException e) { 293 } 295 } 296 return false; 297 } 298 299 public void addHooks(HookRegistry hookRegistry) { 300 hookRegistry.addStorageHook(this); 301 } 302 303 private void checkTimeStamp() throws IllegalArgumentException { 304 if (!checkManifestTimeStamp()) 305 throw new IllegalArgumentException (); 306 } 307 308 private boolean checkManifestTimeStamp() { 309 if (!"true".equalsIgnoreCase(FrameworkProperties.getProperty(EclipseStorageHook.PROP_CHECK_CONFIG))) return true; 311 if (PluginConverterImpl.getTimeStamp(bundledata.getBundleFile().getBaseFile(), getManifestType()) == getManifestTimeStamp()) { 312 if ((getManifestType() & (PluginConverterImpl.MANIFEST_TYPE_JAR | PluginConverterImpl.MANIFEST_TYPE_BUNDLE)) != 0) 313 return true; 314 String cacheLocation = FrameworkProperties.getProperty(LocationManager.PROP_MANIFEST_CACHE); 315 Location parentConfiguration = LocationManager.getConfigurationLocation().getParentLocation(); 316 if (parentConfiguration != null) { 317 try { 318 return checkManifestAndParent(cacheLocation, bundledata.getSymbolicName(), bundledata.getVersion().toString(), getManifestType()) != null; 319 } catch (BundleException e) { 320 return false; 321 } 322 } 323 File cacheFile = new File(cacheLocation, bundledata.getSymbolicName() + '_' + bundledata.getVersion() + ".MF"); if (cacheFile.isFile()) 325 return true; 326 } 327 return false; 328 } 329 330 private Headers checkManifestAndParent(String cacheLocation, String symbolicName, String version, byte inputType) throws BundleException { 331 Headers result = basicCheckManifest(cacheLocation, symbolicName, version, inputType); 332 if (result != null) 333 return result; 334 Location parentConfiguration = null; 335 if ((parentConfiguration = LocationManager.getConfigurationLocation().getParentLocation()) != null) 336 result = basicCheckManifest(new File(parentConfiguration.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME + '/' + LocationManager.MANIFESTS_DIR).toString(), symbolicName, version, inputType); 337 return result; 338 } 339 340 private Headers basicCheckManifest(String cacheLocation, String symbolicName, String version, byte inputType) throws BundleException { 341 File currentFile = new File(cacheLocation, symbolicName + '_' + version + ".MF"); if (PluginConverterImpl.upToDate(currentFile, bundledata.getBundleFile().getBaseFile(), inputType)) { 343 try { 344 return Headers.parseManifest(new FileInputStream(currentFile)); 345 } catch (FileNotFoundException e) { 346 } 348 } 349 return null; 350 } 351 352 Dictionary createCachedManifest(boolean firstTime) throws BundleException { 353 return firstTime ? getGeneratedManifest() : new CachedManifest(this); 354 } 355 356 public Dictionary getGeneratedManifest() throws BundleException { 357 Dictionary builtIn = AdaptorUtil.loadManifestFrom(bundledata); 358 if (builtIn != null) { 359 if (!isComplete(builtIn)) { 361 Dictionary generatedManifest = generateManifest(builtIn); 362 if (generatedManifest != null) 363 return generatedManifest; 364 } 365 manifestType = PluginConverterImpl.MANIFEST_TYPE_BUNDLE; 367 if (bundledata.getBundleFile().getBaseFile().isFile()) { 368 manifestTimeStamp = bundledata.getBundleFile().getBaseFile().lastModified(); 369 manifestType |= PluginConverterImpl.MANIFEST_TYPE_JAR; 370 } else 371 manifestTimeStamp = bundledata.getBundleFile().getEntry(Constants.OSGI_BUNDLE_MANIFEST).getTime(); 372 return builtIn; 373 } 374 Dictionary result = generateManifest(null); 375 if (result == null) 376 throw new BundleException(NLS.bind(EclipseAdaptorMsg.ECLIPSE_DATA_MANIFEST_NOT_FOUND, bundledata.getLocation())); 377 return result; 378 } 379 380 private Dictionary generateManifest(Dictionary builtIn) throws BundleException { 381 String cacheLocation = FrameworkProperties.getProperty(LocationManager.PROP_MANIFEST_CACHE); 382 if (bundledata.getSymbolicName() != null) { 383 Headers existingHeaders = checkManifestAndParent(cacheLocation, bundledata.getSymbolicName(), bundledata.getVersion().toString(), manifestType); 384 if (existingHeaders != null) 385 return existingHeaders; 386 } 387 388 PluginConverterImpl converter = PluginConverterImpl.getDefault(); 389 if (converter == null) 390 converter = new PluginConverterImpl(bundledata.getAdaptor(), bundledata.getAdaptor().getContext()); 391 392 Dictionary generatedManifest; 393 try { 394 generatedManifest = converter.convertManifest(bundledata.getBundleFile().getBaseFile(), true, null, true, null); 395 } catch (PluginConversionException pce) { 396 String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_ERROR_CONVERTING, bundledata.getBundleFile().getBaseFile()); 397 throw new BundleException(message, pce); 398 } 399 400 Version version = Version.parseVersion((String ) generatedManifest.get(Constants.BUNDLE_VERSION)); 402 String symbolicName = ManifestElement.parseHeader(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME, (String ) generatedManifest.get(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME))[0].getValue(); 403 ManifestElement generatedFrom = ManifestElement.parseHeader(PluginConverterImpl.GENERATED_FROM, (String ) generatedManifest.get(PluginConverterImpl.GENERATED_FROM))[0]; 404 Headers existingHeaders = checkManifestAndParent(cacheLocation, symbolicName, version.toString(), Byte.parseByte(generatedFrom.getAttribute(PluginConverterImpl.MANIFEST_TYPE_ATTRIBUTE))); 405 manifestTimeStamp = Long.parseLong(generatedFrom.getValue()); 407 manifestType = Byte.parseByte(generatedFrom.getAttribute(PluginConverterImpl.MANIFEST_TYPE_ATTRIBUTE)); 408 if (bundledata.getAdaptor().isReadOnly() || existingHeaders != null) 409 return existingHeaders; 410 411 if (builtIn != null) { 413 Enumeration keysEnum = builtIn.keys(); 414 while (keysEnum.hasMoreElements()) { 415 Object key = keysEnum.nextElement(); 416 generatedManifest.put(key, builtIn.get(key)); 417 } 418 } 419 420 File bundleManifestLocation = new File(cacheLocation, symbolicName + '_' + version.toString() + ".MF"); try { 423 converter.writeManifest(bundleManifestLocation, generatedManifest, true); 424 } catch (Exception e) { 425 } 427 return generatedManifest; 428 429 } 430 431 private boolean isComplete(Dictionary manifest) { 432 if (manifest.get(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME) != null) 434 return true; 435 return bundledata.getEntry(PluginConverterImpl.PLUGIN_MANIFEST) == null && bundledata.getEntry(PluginConverterImpl.FRAGMENT_MANIFEST) == null; 437 } 438 439 public BaseData getBaseData() { 440 return bundledata; 441 } 442 443 public void copy(StorageHook storageHook) { 444 } 446 447 public void validate() throws IllegalArgumentException { 448 checkTimeStamp(); 449 } 450 451 public FrameworkAdaptor getAdaptor() { 452 if (bundledata != null) 453 return bundledata.getAdaptor(); 454 return null; 455 } 456 457 public Dictionary getManifest(boolean firstLoad) throws BundleException { 458 return createCachedManifest(firstLoad); 459 } 460 461 public boolean forgetStatusChange(int status) { 462 return false; 463 } 464 465 public boolean forgetStartLevelChange(int startlevel) { 466 return false; 467 } 468 469 public boolean matchDNChain(String pattern) { 470 return false; 471 } 472 } 473 | Popular Tags |