1 11 package org.eclipse.osgi.internal.resolver; 12 13 import java.io.*; 14 import java.lang.ref.WeakReference ; 15 import java.lang.reflect.Constructor ; 16 import java.security.AccessController ; 17 import java.util.*; 18 import org.eclipse.osgi.framework.util.SecureAction; 19 import org.eclipse.osgi.service.resolver.*; 20 import org.osgi.framework.InvalidSyntaxException; 21 import org.osgi.framework.Version; 22 23 class StateReader { 24 public static final String STATE_FILE = ".state"; public static final String LAZY_FILE = ".lazy"; private static final int BUFFER_SIZE_LAZY = 4096; 27 private static final int BUFFER_SIZE_FULLYREAD = 16384; 28 private static final SecureAction secureAction = (SecureAction) AccessController.doPrivileged(SecureAction.createSecureAction()); 29 30 protected Map objectTable = new HashMap(); 35 36 private File stateFile; 37 private File lazyFile; 38 39 private boolean lazyLoad = true; 40 private int numBundles; 41 private boolean accessedFlag = false; 42 43 public static final byte STATE_CACHE_VERSION = 26; 44 public static final byte NULL = 0; 45 public static final byte OBJECT = 1; 46 public static final byte INDEX = 2; 47 48 public StateReader() { 50 lazyLoad = false; 51 } 52 53 public StateReader(File stateDirectory) { 54 if (!stateDirectory.exists()) 55 stateDirectory.mkdirs(); 56 this.stateFile = new File(stateDirectory, STATE_FILE); 57 this.lazyFile = new File(stateDirectory, LAZY_FILE); 58 this.lazyLoad = false; 59 } 60 61 public StateReader(File stateFile, File lazyFile, boolean lazyLoad) { 62 this.stateFile = stateFile; 63 this.lazyFile = lazyFile; 64 this.lazyLoad = lazyLoad; 65 } 66 67 private void addToObjectTable(Object object, int index) { 68 objectTable.put(new Integer (index), object); 69 } 70 71 private Object getFromObjectTable(int index) { 72 return objectTable.get(new Integer (index)); 73 } 74 75 private boolean readState(StateImpl state, long expectedTimestamp) throws IOException { 76 DataInputStream in = new DataInputStream(new BufferedInputStream(secureAction.getFileInputStream(stateFile), BUFFER_SIZE_FULLYREAD)); 77 DataInputStream lazyIn = null; 78 try { 79 if (in.readByte() != STATE_CACHE_VERSION) 80 return false; 81 byte tag = readTag(in); 82 if (tag != OBJECT) 83 return false; 84 int index = in.readInt(); 85 long timestampRead = in.readLong(); 86 if (expectedTimestamp >= 0 && timestampRead != expectedTimestamp) 87 return false; 88 addToObjectTable(state, index); 89 String [] platformPropKeys = (String []) readPlatformProp(in); 91 state.addPlatformPropertyKeys(platformPropKeys); 92 int numSets = in.readInt(); 93 Dictionary[] platformProps = new Dictionary[numSets]; 94 for (int i = 0; i < numSets; i++) { 95 Hashtable props = new Hashtable(platformPropKeys.length); 96 int numProps = in.readInt(); 97 for (int j = 0; j < numProps; j++) { 98 Object value = readPlatformProp(in); 99 if (value != null && j < platformPropKeys.length) 100 props.put(platformPropKeys[j], value); 101 } 102 platformProps[i] = props; 103 } 104 state.setPlatformProperties(platformProps, false); 105 numBundles = in.readInt(); 106 if (numBundles == 0) 107 return true; 108 for (int i = 0; i < numBundles; i++) { 109 BundleDescriptionImpl bundle = readBundleDescription(in); 110 state.basicAddBundle(bundle); 111 if (bundle.isResolved()) 112 state.addResolvedBundle(bundle); 113 } 114 state.setTimeStamp(timestampRead); 115 state.setResolved(in.readBoolean()); 116 if (lazyLoad) 117 return true; 118 lazyIn = new DataInputStream(new BufferedInputStream(secureAction.getFileInputStream(lazyFile), BUFFER_SIZE_FULLYREAD)); 120 for (int i = 0; i < numBundles; i++) 121 readBundleDescriptionLazyData(lazyIn, 0); 122 } finally { 123 in.close(); 124 if (lazyIn != null) 125 try { 126 lazyIn.close(); 127 } catch (IOException e) { 128 } 130 } 131 return true; 132 } 133 134 private boolean readStateDeprecated(StateImpl state, DataInputStream in, long expectedTimestamp) throws IOException { 135 if (in.readByte() != STATE_CACHE_VERSION) 136 return false; 137 byte tag = readTag(in); 138 if (tag != OBJECT) 139 return false; 140 int index = in.readInt(); 141 long timestampRead = in.readLong(); 142 if (expectedTimestamp >= 0 && timestampRead != expectedTimestamp) 143 return false; 144 addToObjectTable(state, index); 145 String [] platformPropKeys = (String []) readPlatformProp(in); 147 state.addPlatformPropertyKeys(platformPropKeys); 148 int numSets = in.readInt(); 149 Dictionary[] platformProps = new Dictionary[numSets]; 150 for (int i = 0; i < numSets; i++) { 151 Hashtable props = new Hashtable(platformPropKeys.length); 152 int numProps = in.readInt(); 153 for (int j = 0; j < numProps; j++) { 154 Object value = readPlatformProp(in); 155 if (value != null && j < platformPropKeys.length) 156 props.put(platformPropKeys[j], value); 157 } 158 platformProps[i] = props; 159 } 160 state.setPlatformProperties(platformProps); 161 numBundles = in.readInt(); 162 if (numBundles == 0) 163 return true; 164 for (int i = 0; i < numBundles; i++) { 165 BundleDescriptionImpl bundle = readBundleDescription(in); 166 state.basicAddBundle(bundle); 167 if (bundle.isResolved()) 168 state.addResolvedBundle(bundle); 169 } 170 state.setTimeStamp(timestampRead); 171 state.setResolved(in.readBoolean()); 172 in.readInt(); if (lazyLoad) 174 return true; 175 for (int i = 0; i < numBundles; i++) 176 readBundleDescriptionLazyData(in, 0); 177 return true; 178 } 179 180 private Object readPlatformProp(DataInputStream in) throws IOException { 181 byte type = in.readByte(); 182 if (type == NULL) 183 return null; 184 int num = in.readInt(); 185 if (num == 1) 186 return readString(in, false); 187 String [] result = new String [num]; 188 for (int i = 0; i < result.length; i++) 189 result[i] = readString(in, false); 190 return result; 191 } 192 193 private BundleDescriptionImpl readBundleDescription(DataInputStream in) throws IOException { 194 byte tag = readTag(in); 195 if (tag == NULL) 196 return null; 197 if (tag == INDEX) 198 return (BundleDescriptionImpl) getFromObjectTable(in.readInt()); 199 BundleDescriptionImpl result = new BundleDescriptionImpl(); 201 addToObjectTable(result, in.readInt()); 202 203 result.setBundleId(in.readLong()); 204 readBaseDescription(result, in); 205 result.setLazyDataOffset(in.readInt()); 206 result.setLazyDataSize(in.readInt()); 207 result.setStateBit(BundleDescriptionImpl.RESOLVED, in.readBoolean()); 208 result.setStateBit(BundleDescriptionImpl.SINGLETON, in.readBoolean()); 209 result.setStateBit(BundleDescriptionImpl.HAS_DYNAMICIMPORT, in.readBoolean()); 210 result.setStateBit(BundleDescriptionImpl.ATTACH_FRAGMENTS, in.readBoolean()); 211 result.setStateBit(BundleDescriptionImpl.DYNAMIC_FRAGMENTS, in.readBoolean()); 212 result.setHost(readHostSpec(in)); 213 214 int numDeps = in.readInt(); 216 if (numDeps > 0) { 217 BundleDescription[] deps = new BundleDescription[numDeps]; 218 for (int i = 0; i < numDeps; i++) 219 deps[i] = readBundleDescription(in); 220 result.addDependencies(deps, false); } 222 HostSpecificationImpl hostSpec = (HostSpecificationImpl) result.getHost(); 225 if (hostSpec != null) { 226 BundleDescription[] hosts = hostSpec.getHosts(); 227 if (hosts != null) { 228 for (int i = 0; i < hosts.length; i++) 229 ((BundleDescriptionImpl) hosts[i]).addDependency(result, false); 230 } 231 } 232 result.setFullyLoaded(false); 234 return result; 235 } 236 237 private BundleDescriptionImpl readBundleDescriptionLazyData(DataInputStream in, int skip) throws IOException { 238 if (skip > 0) 239 in.skipBytes(skip); 240 int index = in.readInt(); 241 BundleDescriptionImpl result = (BundleDescriptionImpl) getFromObjectTable(index); 242 if (result.isFullyLoaded()) { 243 in.skipBytes(result.getLazyDataSize() - 4); return result; 245 } 246 247 result.setLocation(readString(in, false)); 248 result.setPlatformFilter(readString(in, false)); 249 250 int exportCount = in.readInt(); 251 if (exportCount > 0) { 252 ExportPackageDescription[] exports = new ExportPackageDescription[exportCount]; 253 for (int i = 0; i < exports.length; i++) 254 exports[i] = readExportPackageDesc(in); 255 result.setExportPackages(exports); 256 } 257 258 int importCount = in.readInt(); 259 if (importCount > 0) { 260 ImportPackageSpecification[] imports = new ImportPackageSpecification[importCount]; 261 for (int i = 0; i < imports.length; i++) 262 imports[i] = readImportPackageSpec(in); 263 result.setImportPackages(imports); 264 } 265 266 int requiredBundleCount = in.readInt(); 267 if (requiredBundleCount > 0) { 268 BundleSpecification[] requiredBundles = new BundleSpecification[requiredBundleCount]; 269 for (int i = 0; i < requiredBundles.length; i++) 270 requiredBundles[i] = readBundleSpec(in); 271 result.setRequiredBundles(requiredBundles); 272 } 273 274 int selectedCount = in.readInt(); 275 if (selectedCount > 0) { 276 ExportPackageDescription[] selected = new ExportPackageDescription[selectedCount]; 277 for (int i = 0; i < selected.length; i++) 278 selected[i] = readExportPackageDesc(in); 279 result.setSelectedExports(selected); 280 } 281 282 int resolvedCount = in.readInt(); 283 if (resolvedCount > 0) { 284 ExportPackageDescription[] resolved = new ExportPackageDescription[resolvedCount]; 285 for (int i = 0; i < resolved.length; i++) 286 resolved[i] = readExportPackageDesc(in); 287 result.setResolvedImports(resolved); 288 } 289 290 int resolvedRequiredCount = in.readInt(); 291 if (resolvedRequiredCount > 0) { 292 BundleDescription[] resolved = new BundleDescription[resolvedRequiredCount]; 293 for (int i = 0; i < resolved.length; i++) 294 resolved[i] = readBundleDescription(in); 295 result.setResolvedRequires(resolved); 296 } 297 298 int eeCount = in.readInt(); 299 if (eeCount > 0) { 300 String [] ee = new String [eeCount]; 301 for (int i = 0; i < ee.length; i++) 302 ee[i] = readString(in, false); 303 result.setExecutionEnvironments(ee); 304 } 305 306 int dynamicPkgCnt = in.readInt(); 307 if (dynamicPkgCnt > 0) { 308 HashMap dynamicStamps = new HashMap(dynamicPkgCnt); 309 for (int i = 0; i < dynamicPkgCnt; i++) { 310 String pkg = readString(in, false); 311 Long stamp = new Long (in.readLong()); 312 dynamicStamps.put(pkg, stamp); 313 } 314 result.setDynamicStamps(dynamicStamps); 315 } 316 317 int genericCapCnt = in.readInt(); 318 if (genericCapCnt > 0) { 319 GenericDescription[] capabilities = new GenericDescription[genericCapCnt]; 320 for (int i = 0; i < capabilities.length; i++) 321 capabilities[i] = readGenericDescription(in); 322 result.setGenericCapabilities(capabilities); 323 } 324 325 int genericReqCnt = in.readInt(); 326 if (genericReqCnt > 0) { 327 GenericSpecification[] reqs = new GenericSpecification[genericReqCnt]; 328 for (int i = 0; i < reqs.length; i++) 329 reqs[i] = readGenericSpecification(in); 330 result.setGenericRequires(reqs); 331 } 332 333 result.setFullyLoaded(true); return result; 337 } 338 339 private BundleSpecificationImpl readBundleSpec(DataInputStream in) throws IOException { 340 BundleSpecificationImpl result = new BundleSpecificationImpl(); 341 readVersionConstraint(result, in); 342 result.setSupplier(readBundleDescription(in)); 343 result.setExported(in.readBoolean()); 344 result.setOptional(in.readBoolean()); 345 return result; 346 } 347 348 private ExportPackageDescriptionImpl readExportPackageDesc(DataInputStream in) throws IOException { 349 byte tag = readTag(in); 350 if (tag == NULL) 351 return null; 352 if (tag == INDEX) 353 return (ExportPackageDescriptionImpl) getFromObjectTable(in.readInt()); 354 ExportPackageDescriptionImpl exportPackageDesc = new ExportPackageDescriptionImpl(); 355 int tableIndex = in.readInt(); 356 addToObjectTable(exportPackageDesc, tableIndex); 357 exportPackageDesc.setTableIndex(tableIndex); 358 readBaseDescription(exportPackageDesc, in); 359 exportPackageDesc.setRoot(in.readBoolean()); 360 exportPackageDesc.setAttributes(readMap(in)); 361 exportPackageDesc.setDirectives(readMap(in)); 362 return exportPackageDesc; 363 } 364 365 private Map readMap(DataInputStream in) throws IOException { 366 int count = in.readInt(); 367 if (count == 0) 368 return null; 369 HashMap result = new HashMap(count); 370 for (int i = 0; i < count; i++) { 371 String key = readString(in, false); 372 Object value = null; 373 byte type = in.readByte(); 374 if (type == 0) 375 value = readString(in, false); 376 else if (type == 1) 377 value = readList(in); 378 else if (type == 2) 379 value = in.readBoolean() ? Boolean.TRUE : Boolean.FALSE; 380 else if (type == 3) 381 value = new Integer (in.readInt()); 382 else if (type == 4) 383 value = new Long (in.readLong()); 384 else if (type == 5) 385 value = new Double (in.readDouble()); 386 else if (type == 6) 387 value = readVersion(in); 388 else if (type == 7) { 389 value = readString(in, false); 390 try { 391 Class uriClazz = Class.forName("java.net.URI"); Constructor constructor = uriClazz.getConstructor(new Class [] {String .class}); 393 value = constructor.newInstance(new Object [] {value}); 394 } catch (ClassNotFoundException e) { 395 } catch (Exception e) { if (e instanceof RuntimeException ) 398 throw (RuntimeException ) e; 399 throw new RuntimeException (e.getMessage()); 400 } 401 } 402 result.put(key, value); 403 } 404 return result; 405 } 406 407 private String [] readList(DataInputStream in) throws IOException { 408 int count = in.readInt(); 409 if (count == 0) 410 return null; 411 String [] result = new String [count]; 412 for (int i = 0; i < count; i++) 413 result[i] = readString(in, false); 414 return result; 415 } 416 417 private void readBaseDescription(BaseDescriptionImpl root, DataInputStream in) throws IOException { 418 root.setName(readString(in, false)); 419 root.setVersion(readVersion(in)); 420 } 421 422 private ImportPackageSpecificationImpl readImportPackageSpec(DataInputStream in) throws IOException { 423 ImportPackageSpecificationImpl result = new ImportPackageSpecificationImpl(); 424 readVersionConstraint(result, in); 425 result.setSupplier(readExportPackageDesc(in)); 426 result.setBundleSymbolicName(readString(in, false)); 427 result.setBundleVersionRange(readVersionRange(in)); 428 result.setAttributes(readMap(in)); 429 result.setDirectives(readMap(in)); 430 return result; 431 } 432 433 private HostSpecificationImpl readHostSpec(DataInputStream in) throws IOException { 434 byte tag = readTag(in); 435 if (tag == NULL) 436 return null; 437 HostSpecificationImpl result = new HostSpecificationImpl(); 438 readVersionConstraint(result, in); 439 int hostCount = in.readInt(); 440 if (hostCount > 0) { 441 BundleDescription[] hosts = new BundleDescription[hostCount]; 442 for (int i = 0; i < hosts.length; i++) 443 hosts[i] = readBundleDescription(in); 444 result.setHosts(hosts); 445 } 446 return result; 447 } 448 449 private GenericDescription readGenericDescription(DataInputStream in) throws IOException { 450 byte tag = readTag(in); 451 if (tag == NULL) 452 return null; 453 if (tag == INDEX) 454 return (GenericDescription) getFromObjectTable(in.readInt()); 455 int tableIndex = in.readInt(); 456 GenericDescriptionImpl result = new GenericDescriptionImpl(); 457 addToObjectTable(result, tableIndex); 458 readBaseDescription(result, in); 459 result.setType(readString(in, false)); 460 Map mapAttrs = readMap(in); 461 Dictionary attrs = new Hashtable(); 462 if (mapAttrs != null) { 463 for (Iterator keys = mapAttrs.keySet().iterator(); keys.hasNext();) { 464 Object key = keys.next(); 465 attrs.put(key, mapAttrs.get(key)); 466 } 467 } 468 result.setAttributes(attrs); 469 return result; 470 } 471 472 private GenericSpecification readGenericSpecification(DataInputStream in) throws IOException { 473 GenericSpecificationImpl result = new GenericSpecificationImpl(); 474 readVersionConstraint(result, in); 475 result.setType(readString(in, false)); 476 int num = in.readInt(); 477 GenericDescription[] suppliers = num == 0 ? null : new GenericDescription[num]; 478 for (int i = 0; i < num; i++) 479 suppliers[i] = readGenericDescription(in); 480 result.setSupplers(suppliers); 481 result.setResolution(in.readInt()); 482 try { 483 result.setMatchingFilter(readString(in, false)); 484 } catch (InvalidSyntaxException e) { 485 } 487 return result; 488 } 489 490 private void readVersionConstraint(VersionConstraintImpl version, DataInputStream in) throws IOException { 492 version.setName(readString(in, false)); 493 version.setVersionRange(readVersionRange(in)); 494 } 495 496 private Version readVersion(DataInputStream in) throws IOException { 497 byte tag = readTag(in); 498 if (tag == NULL) 499 return Version.emptyVersion; 500 int majorComponent = in.readInt(); 501 int minorComponent = in.readInt(); 502 int serviceComponent = in.readInt(); 503 String qualifierComponent = readString(in, false); 504 Version result = new Version(majorComponent, minorComponent, serviceComponent, qualifierComponent); 505 return result; 506 } 507 508 private VersionRange readVersionRange(DataInputStream in) throws IOException { 509 byte tag = readTag(in); 510 if (tag == NULL) 511 return null; 512 return new VersionRange(readVersion(in), in.readBoolean(), readVersion(in), in.readBoolean()); 513 } 514 515 519 public final boolean loadStateDeprecated(StateImpl state, DataInputStream input, long expectedTimestamp) throws IOException { 520 try { 521 return readStateDeprecated(state, input, expectedTimestamp); 522 } finally { 523 input.close(); 524 } 525 } 526 527 531 public final boolean loadState(StateImpl state, long expectedTimestamp) throws IOException { 532 return readState(state, expectedTimestamp); 533 } 534 535 private WeakHashMap stringCache = new WeakHashMap(); 536 537 private String readString(DataInputStream in, boolean intern) throws IOException { 538 byte type = in.readByte(); 539 if (type == NULL) 540 return null; 541 String result; 542 if (intern) 543 result = in.readUTF().intern(); 544 else 545 result = in.readUTF(); 546 WeakReference ref = (WeakReference ) stringCache.get(result); 547 if (ref != null) { 548 String refString = (String ) ref.get(); 549 if (refString != null) 550 result = refString; 551 } else 552 stringCache.put(result, new WeakReference (result)); 553 return result; 554 } 555 556 private byte readTag(DataInputStream in) throws IOException { 557 return in.readByte(); 558 } 559 560 private DataInputStream openLazyFile() throws IOException { 561 if (lazyFile == null) 562 throw new IOException(); return new DataInputStream(new BufferedInputStream(secureAction.getFileInputStream(lazyFile), BUFFER_SIZE_LAZY)); 564 } 565 566 boolean isLazyLoaded() { 567 return lazyLoad; 568 } 569 570 boolean getAccessedFlag() { 571 return accessedFlag; 572 } 573 574 void setAccessedFlag(boolean accessedFlag) { 575 this.accessedFlag = accessedFlag; 576 } 577 578 synchronized void fullyLoad() { 579 setAccessedFlag(true); 580 DataInputStream in = null; 581 try { 582 in = openLazyFile(); 583 for (int i = 0; i < numBundles; i++) 584 readBundleDescriptionLazyData(in, 0); 585 } catch (IOException ioe) { 586 throw new RuntimeException (); } finally { 588 if (in != null) 589 try { 590 in.close(); 591 } catch (IOException e) { 592 } 594 } 595 } 596 597 synchronized void fullyLoad(BundleDescriptionImpl target) throws IOException { 598 setAccessedFlag(true); 599 DataInputStream in = null; 600 try { 601 in = openLazyFile(); 602 ArrayList toLoad = new ArrayList(); 604 addDependencies(target, toLoad); 605 int skipBytes[] = getSkipBytes(toLoad); 606 for (int i = 0; i < skipBytes.length; i++) 608 readBundleDescriptionLazyData(in, skipBytes[i]); 609 } finally { 610 if (in != null) 611 in.close(); 612 } 613 } 614 615 private void addDependencies(BundleDescriptionImpl target, List toLoad) { 616 if (toLoad.contains(target) || target.isFullyLoaded()) 617 return; 618 Iterator load = toLoad.iterator(); 619 int i = 0; 620 while (load.hasNext()) { 621 BundleDescriptionImpl bundle = (BundleDescriptionImpl) load.next(); 623 if (target.getLazyDataOffset() < bundle.getLazyDataOffset()) 624 break; 625 i++; 626 } 627 if (i >= toLoad.size()) 628 toLoad.add(target); 629 else 630 toLoad.add(i, target); 631 List deps = target.getBundleDependencies(); 632 for (Iterator iter = deps.iterator(); iter.hasNext();) 633 addDependencies((BundleDescriptionImpl) iter.next(), toLoad); 634 } 635 636 private int[] getSkipBytes(ArrayList toLoad) { 637 int[] skipBytes = new int[toLoad.size()]; 638 for (int i = 0; i < skipBytes.length; i++) { 639 BundleDescriptionImpl current = (BundleDescriptionImpl) toLoad.get(i); 640 if (i == 0) { 641 skipBytes[i] = current.getLazyDataOffset(); 642 continue; 643 } 644 BundleDescriptionImpl previous = (BundleDescriptionImpl) toLoad.get(i - 1); 645 skipBytes[i] = current.getLazyDataOffset() - previous.getLazyDataOffset() - previous.getLazyDataSize(); 646 } 647 return skipBytes; 648 } 649 } 650 | Popular Tags |