1 11 package org.eclipse.core.internal.registry; 12 13 import java.io.*; 14 import java.util.HashMap ; 15 import org.eclipse.core.runtime.IStatus; 16 import org.eclipse.core.runtime.Status; 17 import org.eclipse.core.runtime.spi.RegistryContributor; 18 import org.eclipse.osgi.util.NLS; 19 20 public class TableReader { 21 static final int NULL = 0; 23 static final int OBJECT = 1; 24 25 static final int CACHE_VERSION = 5; 27 32 static final String MAIN = ".mainData"; BufferedRandomInputStream mainDataFile = null; 35 DataInputStream mainInput = null; 36 37 static final String EXTRA = ".extraData"; BufferedRandomInputStream extraDataFile = null; 40 DataInputStream extraInput = null; 41 42 static final String TABLE = ".table"; File tableFile; 45 46 static final String CONTRIBUTIONS = ".contributions"; File contributionsFile; 49 50 static final String CONTRIBUTORS = ".contributors"; File contributorsFile; 53 54 static final String NAMESPACES = ".namespaces"; File namespacesFile; 57 58 static final String ORPHANS = ".orphans"; File orphansFile; 61 62 private static final byte fileError = 0; 64 private static final boolean DEBUG = false; 66 private boolean holdObjects = false; 67 68 private ExtensionRegistry registry; 69 70 void setMainDataFile(File main) throws IOException { 71 mainDataFile = new BufferedRandomInputStream(main); 72 mainInput = new DataInputStream(mainDataFile); 73 } 74 75 void setExtraDataFile(File extra) throws IOException { 76 extraDataFile = new BufferedRandomInputStream(extra); 77 extraInput = new DataInputStream(extraDataFile); 78 } 79 80 void setTableFile(File table) { 81 tableFile = table; 82 } 83 84 void setContributionsFile(File namespace) { 85 contributionsFile = namespace; 86 } 87 88 void setContributorsFile(File file) { 89 contributorsFile = file; 90 } 91 92 void setNamespacesFile(File file) { 93 namespacesFile = file; 94 } 95 96 void setOrphansFile(File orphan) { 97 orphansFile = orphan; 98 } 99 100 public TableReader(ExtensionRegistry registry) { 101 this.registry = registry; 102 } 103 104 public Object [] loadTables(long expectedTimestamp) { 106 HashtableOfInt offsets; 107 HashtableOfStringAndInt extensionPoints; 108 109 DataInputStream tableInput = null; 110 try { 111 tableInput = new DataInputStream(new BufferedInputStream(new FileInputStream(tableFile))); 112 if (!checkCacheValidity(tableInput, expectedTimestamp)) 113 return null; 114 115 Integer nextId = new Integer (tableInput.readInt()); 116 offsets = new HashtableOfInt(); 117 offsets.load(tableInput); 118 extensionPoints = new HashtableOfStringAndInt(); 119 extensionPoints.load(tableInput); 120 return new Object [] {offsets, extensionPoints, nextId}; 121 } catch (IOException e) { 122 if (tableInput != null) 123 try { 124 tableInput.close(); 125 } catch (IOException e1) { 126 } 128 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_registryCacheReadProblems, e)); 129 return null; 130 } 131 132 } 133 134 private boolean checkCacheValidity(DataInputStream in, long expectedTimestamp) { 136 int version; 137 try { 138 version = in.readInt(); 139 if (version != CACHE_VERSION) 140 return false; 141 142 long installStamp = in.readLong(); 143 long registryStamp = in.readLong(); 144 long mainDataFileSize = in.readLong(); 145 long extraDataFileSize = in.readLong(); 146 long contributionsFileSize = in.readLong(); 147 long contributorsFileSize = in.readLong(); 148 long namespacesFileSize = in.readLong(); 149 long orphansFileSize = in.readLong(); 150 String osStamp = in.readUTF(); 151 String windowsStamp = in.readUTF(); 152 String localeStamp = in.readUTF(); 153 154 boolean validTime = (expectedTimestamp == 0 || expectedTimestamp == registryStamp); 155 boolean validInstall = (installStamp == registry.computeState()); 156 boolean validOS = (osStamp.equals(RegistryProperties.getProperty(IRegistryConstants.PROP_OS, RegistryProperties.empty))); 157 boolean validWS = (windowsStamp.equals(RegistryProperties.getProperty(IRegistryConstants.PROP_WS, RegistryProperties.empty))); 158 boolean validNL = (localeStamp.equals(RegistryProperties.getProperty(IRegistryConstants.PROP_NL, RegistryProperties.empty))); 159 160 if (!validTime || !validInstall || !validOS || !validWS || !validNL) 161 return false; 162 163 boolean validMain = (mainDataFileSize == mainDataFile.length()); 164 boolean validExtra = (extraDataFileSize == extraDataFile.length()); 165 boolean validContrib = (contributionsFileSize == contributionsFile.length()); 166 boolean validContributors = (contributorsFileSize == contributorsFile.length()); 167 boolean validNamespace = (namespacesFileSize == namespacesFile.length()); 168 boolean validOrphan = (orphansFileSize == orphansFile.length()); 169 170 return (validMain && validExtra && validContrib && validContributors && validNamespace && validOrphan); 171 } catch (IOException e) { 172 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_registryCacheInconsistent, e)); 173 return false; 174 } 175 } 176 177 public Object loadConfigurationElement(int offset) { 178 try { 179 synchronized (mainDataFile) { 180 goToInputFile(offset); 181 return basicLoadConfigurationElement(mainInput, null); 182 } 183 } catch (IOException e) { 184 String message = NLS.bind(RegistryMessages.meta_regCacheIOExceptionReading, mainDataFile); 185 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, message, e)); 186 if (DEBUG) 187 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, "Error reading a configuration element (" + offset + ") from the registry cache", e)); return null; 189 } 190 } 191 192 private ConfigurationElement basicLoadConfigurationElement(DataInputStream is, String actualContributorId) throws IOException { 193 int self = is.readInt(); 194 String contributorId = readStringOrNull(is); 195 String name = readStringOrNull(is); 196 int parentId = is.readInt(); 197 byte parentType = is.readByte(); 198 int misc = is.readInt(); String [] propertiesAndValue = readPropertiesAndValue(is); 200 int[] children = readArray(is); 201 if (actualContributorId == null) 202 actualContributorId = contributorId; 203 return getObjectFactory().createConfigurationElement(self, actualContributorId, name, propertiesAndValue, children, misc, parentId, parentType, true); 204 } 205 206 public Object loadThirdLevelConfigurationElements(int offset, RegistryObjectManager objectManager) { 207 try { 208 synchronized (extraDataFile) { 209 goToExtraFile(offset); 210 return loadConfigurationElementAndChildren(null, extraInput, 3, Integer.MAX_VALUE, objectManager, null); 211 } 212 } catch (IOException e) { 213 String message = NLS.bind(RegistryMessages.meta_regCacheIOExceptionReading, extraDataFile); 214 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, message, e)); 215 if (DEBUG) 216 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, "Error reading a third level configuration element (" + offset + ") from the registry cache", e)); return null; 218 } 219 } 220 221 private ConfigurationElement loadConfigurationElementAndChildren(DataInputStream is, DataInputStream extraIs, int depth, int maxDepth, RegistryObjectManager objectManager, String namespaceOwnerId) throws IOException { 223 DataInputStream currentStream = is; 224 if (depth > 2) 225 currentStream = extraIs; 226 227 ConfigurationElement ce = basicLoadConfigurationElement(currentStream, namespaceOwnerId); 228 if (namespaceOwnerId == null) 229 namespaceOwnerId = ce.getContributorId(); 230 int[] children = ce.getRawChildren(); 231 if (depth + 1 > maxDepth) 232 return ce; 233 234 for (int i = 0; i < children.length; i++) { 235 ConfigurationElement tmp = loadConfigurationElementAndChildren(currentStream, extraIs, depth + 1, maxDepth, objectManager, namespaceOwnerId); 236 objectManager.add(tmp, holdObjects); 237 } 238 return ce; 239 } 240 241 private String [] readPropertiesAndValue(DataInputStream inputStream) throws IOException { 242 int numberOfProperties = inputStream.readInt(); 243 if (numberOfProperties == 0) 244 return RegistryObjectManager.EMPTY_STRING_ARRAY; 245 String [] properties = new String [numberOfProperties]; 246 for (int i = 0; i < numberOfProperties; i++) { 247 properties[i] = readStringOrNull(inputStream); 248 } 249 return properties; 250 } 251 252 public Object loadExtension(int offset) { 253 try { 254 synchronized (mainDataFile) { 255 goToInputFile(offset); 256 return basicLoadExtension(mainInput); 257 } 258 } catch (IOException e) { 259 String message = NLS.bind(RegistryMessages.meta_regCacheIOExceptionReading, mainDataFile); 260 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, message, e)); 261 if (DEBUG) 262 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, "Error reading an extension (" + offset + ") from the registry cache", e)); } 264 return null; 265 } 266 267 private Extension basicLoadExtension(DataInputStream inputStream) throws IOException { 268 int self = inputStream.readInt(); 269 String simpleId = readStringOrNull(mainInput); 270 String namespace = readStringOrNull(mainInput); 271 int[] children = readArray(mainInput); 272 int extraData = mainInput.readInt(); 273 return getObjectFactory().createExtension(self, simpleId, namespace, children, extraData, true); 274 } 275 276 public ExtensionPoint loadExtensionPointTree(int offset, RegistryObjectManager objects) { 277 try { 278 synchronized (mainDataFile) { 279 ExtensionPoint xpt = (ExtensionPoint) loadExtensionPoint(offset); 280 int[] children = xpt.getRawChildren(); 281 int nbrOfExtension = children.length; 282 for (int i = 0; i < nbrOfExtension; i++) { 283 Extension loaded = basicLoadExtension(mainInput); 284 objects.add(loaded, holdObjects); 285 } 286 287 for (int i = 0; i < nbrOfExtension; i++) { 288 int nbrOfCe = mainInput.readInt(); 289 for (int j = 0; j < nbrOfCe; j++) { 290 objects.add(loadConfigurationElementAndChildren(mainInput, null, 1, 2, objects, null), holdObjects); 293 } 294 } 295 return xpt; 296 } 297 } catch (IOException e) { 298 String message = NLS.bind(RegistryMessages.meta_regCacheIOExceptionReading, mainDataFile); 299 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, message, e)); 300 if (DEBUG) 301 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, "Error reading an extension point tree (" + offset + ") from the registry cache", e)); return null; 303 } 304 } 305 306 private Object loadExtensionPoint(int offset) { 307 try { 308 goToInputFile(offset); 309 return basicLoadExtensionPoint(); 310 } catch (IOException e) { 311 String message = NLS.bind(RegistryMessages.meta_regCacheIOExceptionReading, mainDataFile); 312 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, message, e)); 313 if (DEBUG) 314 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, "Error reading an extension point (" + offset + ") from the registry cache", e)); return null; 316 } 317 } 318 319 private ExtensionPoint basicLoadExtensionPoint() throws IOException { 320 int self = mainInput.readInt(); 321 int[] children = readArray(mainInput); 322 int extraData = mainInput.readInt(); 323 return getObjectFactory().createExtensionPoint(self, children, extraData, true); 324 } 325 326 private int[] readArray(DataInputStream in) throws IOException { 327 int arraySize = in.readInt(); 328 if (arraySize == 0) 329 return RegistryObjectManager.EMPTY_INT_ARRAY; 330 int[] result = new int[arraySize]; 331 for (int i = 0; i < arraySize; i++) { 332 result[i] = in.readInt(); 333 } 334 return result; 335 } 336 337 private void goToInputFile(int offset) throws IOException { 338 mainDataFile.seek(offset); 339 } 340 341 private void goToExtraFile(int offset) throws IOException { 342 extraDataFile.seek(offset); 343 } 344 345 private String readStringOrNull(DataInputStream in) throws IOException { 346 byte type = in.readByte(); 347 if (type == NULL) 348 return null; 349 return in.readUTF(); 350 } 351 352 public String [] loadExtensionExtraData(int dataPosition) { 353 try { 354 synchronized (extraDataFile) { 355 goToExtraFile(dataPosition); 356 return basicLoadExtensionExtraData(); 357 } 358 } catch (IOException e) { 359 String message = NLS.bind(RegistryMessages.meta_regCacheIOExceptionReading, extraDataFile); 360 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, message, e)); 361 if (DEBUG) 362 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, "Error reading extension label (" + dataPosition + ") from the registry cache", e)); return null; 364 } 365 } 366 367 private String [] basicLoadExtensionExtraData() throws IOException { 368 return new String [] {readStringOrNull(extraInput), readStringOrNull(extraInput), readStringOrNull(extraInput)}; 369 } 370 371 public String [] loadExtensionPointExtraData(int offset) { 372 try { 373 synchronized (extraDataFile) { 374 goToExtraFile(offset); 375 return basicLoadExtensionPointExtraData(); 376 } 377 } catch (IOException e) { 378 String message = NLS.bind(RegistryMessages.meta_regCacheIOExceptionReading, extraDataFile); 379 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, message, e)); 380 if (DEBUG) 381 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, "Error reading extension point data (" + offset + ") from the registry cache", e)); return null; 383 } 384 } 385 386 private String [] basicLoadExtensionPointExtraData() throws IOException { 387 String [] result = new String [5]; 388 result[0] = readStringOrNull(extraInput); result[1] = readStringOrNull(extraInput); result[2] = readStringOrNull(extraInput); result[3] = readStringOrNull(extraInput); result[4] = readStringOrNull(extraInput); return result; 394 } 395 396 public KeyedHashSet loadContributions() { 397 DataInputStream namespaceInput = null; 398 try { 399 synchronized (contributionsFile) { 400 namespaceInput = new DataInputStream(new BufferedInputStream(new FileInputStream(contributionsFile))); 401 int size = namespaceInput.readInt(); 402 KeyedHashSet result = new KeyedHashSet(size); 403 for (int i = 0; i < size; i++) { 404 String contributorId = readStringOrNull(namespaceInput); 405 Contribution n = getObjectFactory().createContribution(contributorId, true); 406 n.setRawChildren(readArray(namespaceInput)); 407 result.add(n); 408 } 409 return result; 410 } 411 } catch (IOException e) { 412 String message = NLS.bind(RegistryMessages.meta_regCacheIOExceptionReading, contributionsFile); 413 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, message, e)); 414 return null; 415 } finally { 416 if (namespaceInput != null) 417 try { 418 namespaceInput.close(); 419 } catch (IOException e1) { 420 } 422 } 423 } 424 425 final static float contributorsLoadFactor = 1.2f; 427 public HashMap loadContributors() { 428 HashMap result = null; 429 DataInputStream contributorsInput = null; 430 try { 431 synchronized (contributorsFile) { 432 contributorsInput = new DataInputStream(new BufferedInputStream(new FileInputStream(contributorsFile))); 433 int size = contributorsInput.readInt(); 434 result = new HashMap ((int) (size * contributorsLoadFactor)); 435 for (int i = 0; i < size; i++) { 436 String id = readStringOrNull(contributorsInput); 437 String name = readStringOrNull(contributorsInput); 438 String hostId = readStringOrNull(contributorsInput); 439 String hostName = readStringOrNull(contributorsInput); 440 result.put(id, new RegistryContributor(id, name, hostId, hostName)); 441 } 442 } 443 return result; 444 } catch (IOException e) { 445 String message = NLS.bind(RegistryMessages.meta_regCacheIOExceptionReading, contributorsFile); 446 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, message, e)); 447 return null; 448 } finally { 449 if (contributorsInput != null) 450 try { 451 contributorsInput.close(); 452 } catch (IOException e1) { 453 } 455 } 456 } 457 458 public KeyedHashSet loadNamespaces() { 459 DataInputStream namespaceInput = null; 460 try { 461 synchronized (namespacesFile) { 462 namespaceInput = new DataInputStream(new BufferedInputStream(new FileInputStream(namespacesFile))); 463 int size = namespaceInput.readInt(); 464 KeyedHashSet result = new KeyedHashSet(size); 465 for (int i = 0; i < size; i++) { 466 String key = readStringOrNull(namespaceInput); 467 RegistryIndexElement indexElement = new RegistryIndexElement(key); 468 indexElement.updateExtensionPoints(readArray(namespaceInput), true); 469 indexElement.updateExtensions(readArray(namespaceInput), true); 470 result.add(indexElement); 471 } 472 return result; 473 } 474 } catch (IOException e) { 475 String message = NLS.bind(RegistryMessages.meta_regCacheIOExceptionReading, namespacesFile); 476 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, message, e)); 477 return null; 478 } finally { 479 if (namespaceInput != null) 480 try { 481 namespaceInput.close(); 482 } catch (IOException e1) { 483 } 485 } 486 } 487 488 private void loadAllOrphans(RegistryObjectManager objectManager) throws IOException { 489 int orphans = objectManager.getOrphanExtensions().size(); 491 for (int k = 0; k < orphans; k++) { 492 int numberOfOrphanExtensions = mainInput.readInt(); 493 for (int i = 0; i < numberOfOrphanExtensions; i++) { 494 loadFullExtension(objectManager); 495 } 496 for (int i = 0; i < numberOfOrphanExtensions; i++) { 497 int nbrOfCe = mainInput.readInt(); 498 for (int j = 0; j < nbrOfCe; j++) { 499 objectManager.add(loadConfigurationElementAndChildren(mainInput, extraInput, 1, Integer.MAX_VALUE, objectManager, null), true); 500 } 501 } 502 } 503 } 504 505 public boolean readAllCache(RegistryObjectManager objectManager) { 507 try { 508 int size = objectManager.getExtensionPoints().size(); 509 for (int i = 0; i < size; i++) { 510 objectManager.add(readAllExtensionPointTree(objectManager), holdObjects); 511 } 512 loadAllOrphans(objectManager); 513 } catch (IOException e) { 514 String message = NLS.bind(RegistryMessages.meta_regCacheIOExceptionReading, mainDataFile); 515 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, message, e)); 516 return false; 517 } 518 return true; 519 } 520 521 private ExtensionPoint readAllExtensionPointTree(RegistryObjectManager objectManager) throws IOException { 522 ExtensionPoint xpt = loadFullExtensionPoint(); 523 int[] children = xpt.getRawChildren(); 524 int nbrOfExtension = children.length; 525 for (int i = 0; i < nbrOfExtension; i++) { 526 loadFullExtension(objectManager); 527 } 528 529 for (int i = 0; i < nbrOfExtension; i++) { 530 int nbrOfCe = mainInput.readInt(); 531 for (int j = 0; j < nbrOfCe; j++) { 532 objectManager.add(loadConfigurationElementAndChildren(mainInput, extraInput, 1, Integer.MAX_VALUE, objectManager, null), true); 533 } 534 } 535 return xpt; 536 } 537 538 private ExtensionPoint loadFullExtensionPoint() throws IOException { ExtensionPoint xpt = basicLoadExtensionPoint(); 540 String [] tmp = basicLoadExtensionPointExtraData(); 541 xpt.setLabel(tmp[0]); 542 xpt.setSchema(tmp[1]); 543 xpt.setUniqueIdentifier(tmp[2]); 544 xpt.setNamespace(tmp[3]); 545 xpt.setContributorId(tmp[4]); 546 return xpt; 547 } 548 549 private Extension loadFullExtension(RegistryObjectManager objectManager) throws IOException { 550 String [] tmp; 551 Extension loaded = basicLoadExtension(mainInput); 552 tmp = basicLoadExtensionExtraData(); 553 loaded.setLabel(tmp[0]); 554 loaded.setExtensionPointIdentifier(tmp[1]); 555 loaded.setContributorId(tmp[2]); 556 objectManager.add(loaded, holdObjects); 557 return loaded; 558 } 559 560 public HashMap loadOrphans() { 561 DataInputStream orphanInput = null; 562 try { 563 synchronized (orphansFile) { 564 orphanInput = new DataInputStream(new BufferedInputStream(new FileInputStream(orphansFile))); 565 int size = orphanInput.readInt(); 566 HashMap result = new HashMap (size); 567 for (int i = 0; i < size; i++) { 568 String key = orphanInput.readUTF(); 569 int[] value = readArray(orphanInput); 570 result.put(key, value); 571 } 572 return result; 573 } 574 } catch (IOException e) { 575 return null; 576 } finally { 577 if (orphanInput != null) 578 try { 579 orphanInput.close(); 580 } catch (IOException e1) { 581 } 583 } 584 } 585 586 public void setHoldObjects(boolean holdObjects) { 588 this.holdObjects = holdObjects; 589 } 590 591 private void log(Status status) { 592 registry.log(status); 593 } 594 595 private RegistryObjectFactory getObjectFactory() { 596 return registry.getElementFactory(); 597 } 598 599 public static String getTestFileName() { 601 return TABLE; 602 } 603 604 public void close() { 605 try { 606 if (mainInput != null) 607 mainInput.close(); 608 if (extraInput != null) 609 extraInput.close(); 610 } catch (IOException e) { 611 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_registryCacheReadProblems, e)); 612 } 613 } 614 615 } 616 | Popular Tags |