1 11 package org.eclipse.core.internal.registry; 12 13 import java.io.*; 14 import java.util.*; 15 import org.eclipse.core.runtime.*; 16 import org.eclipse.core.runtime.spi.RegistryContributor; 17 18 public class TableWriter { 19 private static final byte fileError = 0; 20 21 File mainDataFile; 22 File extraDataFile; 23 File tableFile; 24 File contributionsFile; 25 File contributorsFile; 26 File namespacesFile; 27 File orphansFile; 28 29 void setMainDataFile(File main) { 30 mainDataFile = main; 31 } 32 33 void setExtraDataFile(File extra) { 34 extraDataFile = extra; 35 } 36 37 void setTableFile(File table) { 38 tableFile = table; 39 } 40 41 void setContributionsFile(File fileName) { 42 contributionsFile = fileName; 43 } 44 45 void setContributorsFile(File fileName) { 46 contributorsFile = fileName; 47 } 48 49 void setNamespacesFile(File fileName) { 50 namespacesFile = fileName; 51 } 52 53 void setOrphansFile(File orphan) { 54 orphansFile = orphan; 55 } 56 57 DataOutputStream mainOutput; 58 DataOutputStream extraOutput; 59 FileOutputStream mainFileOutput = null; 60 FileOutputStream extraFileOutput = null; 61 62 private HashtableOfInt offsets; 63 64 private ExtensionRegistry registry; 65 private RegistryObjectManager objectManager; 66 67 public TableWriter(ExtensionRegistry registry) { 68 this.registry = registry; 69 } 70 71 private int getExtraDataPosition() { 72 return extraOutput.size(); 73 } 74 75 public boolean saveCache(RegistryObjectManager objectManager, long timestamp) { 76 this.objectManager = objectManager; 77 try { 78 if (!openFiles()) 79 return false; 80 try { 81 saveExtensionRegistry(timestamp); 82 } catch (IOException io) { 83 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_registryCacheWriteProblems, io)); 84 return false; 85 } 86 } finally { 87 closeFiles(); 88 } 89 return true; 90 } 91 92 private boolean openFiles() { 93 try { 94 mainFileOutput = new FileOutputStream(mainDataFile); 95 mainOutput = new DataOutputStream(new BufferedOutputStream(mainFileOutput)); 96 extraFileOutput = new FileOutputStream(extraDataFile); 97 extraOutput = new DataOutputStream(new BufferedOutputStream(extraFileOutput)); 98 } catch (FileNotFoundException e) { 99 if (mainFileOutput != null) 100 try { 101 mainFileOutput.close(); 102 } catch (IOException e1) { 103 } 105 106 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_unableToCreateCache, e)); 107 return false; 108 } 109 return true; 110 } 111 112 private void closeFiles() { 113 try { 114 if (mainOutput != null) { 115 mainOutput.flush(); 116 if (mainFileOutput.getFD().valid()) { 117 mainFileOutput.getFD().sync(); 118 } 119 mainOutput.close(); 120 } 121 } catch (IOException e) { 122 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_registryCacheWriteProblems, e)); 123 e.printStackTrace(); 124 } 125 try { 126 if (extraOutput != null) { 127 extraOutput.flush(); 128 if (extraFileOutput.getFD().valid()) { 129 extraFileOutput.getFD().sync(); 130 } 131 extraOutput.close(); 132 } 133 } catch (IOException e) { 134 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_registryCacheWriteProblems, e)); 135 e.printStackTrace(); 136 } 137 } 138 139 private void saveExtensionRegistry(long timestamp) throws IOException { 140 ExtensionPointHandle[] points = objectManager.getExtensionPointsHandles(); 141 offsets = new HashtableOfInt(objectManager.getNextId()); 142 for (int i = 0; i < points.length; i++) { 143 saveExtensionPoint(points[i]); 144 } 145 saveOrphans(); 146 saveContributions(objectManager.getContributions()); 147 saveContributors(objectManager.getContributors()); 148 saveNamespaces(objectManager.getNamespacesIndex()); 149 closeFiles(); saveTables(timestamp); } 152 153 private void saveContributions(KeyedHashSet[] contributions) throws IOException { 154 FileOutputStream fosNamespace = new FileOutputStream(contributionsFile); 155 DataOutputStream outputNamespace = new DataOutputStream(new BufferedOutputStream(fosNamespace)); 156 KeyedElement[] newElements = contributions[0].elements(); 157 KeyedElement[] formerElements = contributions[1].elements(); 158 159 int cacheSize = 0; 161 for (int i = 0; i < newElements.length; i++) { 162 if (((Contribution) newElements[i]).shouldPersist()) 163 cacheSize++; 164 } 165 for (int i = 0; i < formerElements.length; i++) { 166 if (((Contribution) formerElements[i]).shouldPersist()) 167 cacheSize++; 168 } 169 outputNamespace.writeInt(cacheSize); 170 171 for (int i = 0; i < newElements.length; i++) { 172 Contribution element = (Contribution) newElements[i]; 173 if (element.shouldPersist()) { 174 writeStringOrNull(element.getContributorId(), outputNamespace); 175 saveArray(filterContributionChildren(element), outputNamespace); 176 } 177 } 178 for (int i = 0; i < formerElements.length; i++) { 179 Contribution element = (Contribution) formerElements[i]; 180 if (element.shouldPersist()) { 181 writeStringOrNull(element.getContributorId(), outputNamespace); 182 saveArray(filterContributionChildren(element), outputNamespace); 183 } 184 } 185 outputNamespace.flush(); 186 fosNamespace.getFD().sync(); 187 outputNamespace.close(); 188 } 189 190 private int[] filterContributionChildren(Contribution element) { 193 int[] extensionPoints = filter(element.getExtensionPoints()); 194 int[] extensions = filter(element.getExtensions()); 195 int[] filteredRawChildren = new int[2 + extensionPoints.length + extensions.length]; 196 System.arraycopy(extensionPoints, 0, filteredRawChildren, 2, extensionPoints.length); 197 System.arraycopy(extensions, 0, filteredRawChildren, 2 + extensionPoints.length, extensions.length); 198 filteredRawChildren[Contribution.EXTENSION_POINT] = extensionPoints.length; 199 filteredRawChildren[Contribution.EXTENSION] = extensions.length; 200 return filteredRawChildren; 201 } 202 203 private void saveNamespaces(KeyedHashSet namespacesIndex) throws IOException { 204 FileOutputStream fosNamespace = new FileOutputStream(namespacesFile); 205 DataOutputStream outputNamespace = new DataOutputStream(new BufferedOutputStream(fosNamespace)); 206 KeyedElement[] elements = namespacesIndex.elements(); 207 208 KeyedElement[] cachedElements = new KeyedElement[elements.length]; 209 int cacheSize = 0; 210 for (int i = 0; i < elements.length; i++) { 211 RegistryIndexElement element = (RegistryIndexElement) elements[i]; 212 int[] extensionPoints = filter(element.getExtensionPoints()); 213 int[] extensions = filter(element.getExtensions()); 214 if (extensionPoints.length == 0 && extensions.length == 0) 215 continue; 216 RegistryIndexElement cachedElement = new RegistryIndexElement((String ) element.getKey(), extensionPoints, extensions); 217 cachedElements[cacheSize] = cachedElement; 218 cacheSize++; 219 } 220 221 outputNamespace.writeInt(cacheSize); 222 for (int i = 0; i < cacheSize; i++) { 223 RegistryIndexElement element = (RegistryIndexElement) cachedElements[i]; 224 writeStringOrNull((String ) element.getKey(), outputNamespace); 225 saveArray(element.getExtensionPoints(), outputNamespace); saveArray(element.getExtensions(), outputNamespace); } 228 outputNamespace.flush(); 229 fosNamespace.getFD().sync(); 230 outputNamespace.close(); 231 } 232 233 private void saveContributors(HashMap contributors) throws IOException { 234 FileOutputStream fosContributors = new FileOutputStream(contributorsFile); 235 DataOutputStream outputContributors = new DataOutputStream(new BufferedOutputStream(fosContributors)); 236 237 Collection entries = contributors.values(); 238 outputContributors.writeInt(entries.size()); 239 240 for (Iterator i = entries.iterator(); i.hasNext();) { 241 RegistryContributor contributor = (RegistryContributor) i.next(); 242 writeStringOrNull(contributor.getActualId(), outputContributors); 243 writeStringOrNull(contributor.getActualName(), outputContributors); 244 writeStringOrNull(contributor.getId(), outputContributors); 245 writeStringOrNull(contributor.getName(), outputContributors); 246 } 247 248 outputContributors.flush(); 249 fosContributors.getFD().sync(); 250 outputContributors.close(); 251 } 252 253 private void saveTables(long registryTimeStamp) throws IOException { 254 FileOutputStream fosTable = new FileOutputStream(tableFile); 255 DataOutputStream outputTable = new DataOutputStream(new BufferedOutputStream(fosTable)); 256 writeCacheHeader(outputTable, registryTimeStamp); 257 outputTable.writeInt(objectManager.getNextId()); 258 offsets.save(outputTable); 259 objectManager.getExtensionPoints().save(outputTable, objectManager); outputTable.flush(); 261 fosTable.getFD().sync(); 262 outputTable.close(); 263 } 264 265 private void writeCacheHeader(DataOutputStream output, long registryTimeStamp) throws IOException { 266 output.writeInt(TableReader.CACHE_VERSION); 267 output.writeLong(registry.computeState()); 268 output.writeLong(registryTimeStamp); 269 output.writeLong(mainDataFile.length()); 270 output.writeLong(extraDataFile.length()); 271 output.writeLong(contributionsFile.length()); 272 output.writeLong(contributorsFile.length()); 273 output.writeLong(namespacesFile.length()); 274 output.writeLong(orphansFile.length()); 275 output.writeUTF(RegistryProperties.getProperty(IRegistryConstants.PROP_OS, RegistryProperties.empty)); 276 output.writeUTF(RegistryProperties.getProperty(IRegistryConstants.PROP_WS, RegistryProperties.empty)); 277 output.writeUTF(RegistryProperties.getProperty(IRegistryConstants.PROP_NL, RegistryProperties.empty)); 278 } 279 280 private void saveArray(int[] array, DataOutputStream out) throws IOException { 281 if (array == null) { 282 out.writeInt(0); 283 return; 284 } 285 out.writeInt(array.length); 286 for (int i = 0; i < array.length; i++) { 287 out.writeInt(array[i]); 288 } 289 } 290 291 private void saveExtensionPoint(ExtensionPointHandle xpt) throws IOException { 292 if (!xpt.shouldPersist()) 293 return; 294 offsets.put(xpt.getId(), mainOutput.size()); 296 mainOutput.writeInt(xpt.getId()); 298 saveArray(filter(xpt.getObject().getRawChildren()), mainOutput); 299 mainOutput.writeInt(getExtraDataPosition()); 300 saveExtensionPointData(xpt); 301 302 saveExtensions(xpt.getExtensions(), mainOutput); 303 } 304 305 private void saveExtension(ExtensionHandle ext, DataOutputStream outputStream) throws IOException { 306 if (!ext.shouldPersist()) 307 return; 308 offsets.put(ext.getId(), outputStream.size()); 309 outputStream.writeInt(ext.getId()); 310 writeStringOrNull(ext.getSimpleIdentifier(), outputStream); 311 writeStringOrNull(ext.getNamespaceIdentifier(), outputStream); 312 saveArray(filter(ext.getObject().getRawChildren()), outputStream); 313 outputStream.writeInt(getExtraDataPosition()); 314 saveExtensionData(ext); 315 } 316 317 private void writeStringArray(String [] array, DataOutputStream outputStream) throws IOException { 318 outputStream.writeInt(array == null ? 0 : array.length); 319 for (int i = 0; i < (array == null ? 0 : array.length); i++) { 320 writeStringOrNull(array[i], outputStream); 321 } 322 } 323 324 private void saveConfigurationElement(ConfigurationElementHandle element, DataOutputStream outputStream, DataOutputStream extraOutputStream, int depth) throws IOException { 326 if (!element.shouldPersist()) 327 return; 328 DataOutputStream currentOutput = outputStream; 329 if (depth > 2) 330 currentOutput = extraOutputStream; 331 332 offsets.put(element.getId(), currentOutput.size()); 333 334 currentOutput.writeInt(element.getId()); 335 ConfigurationElement actualCe = (ConfigurationElement) element.getObject(); 336 337 writeStringOrNull(actualCe.getContributorId(), currentOutput); 338 writeStringOrNull(actualCe.getName(), currentOutput); 339 currentOutput.writeInt(actualCe.parentId); 340 currentOutput.writeByte(actualCe.parentType); 341 currentOutput.writeInt(depth > 1 ? extraOutputStream.size() : -1); 342 writeStringArray(actualCe.getPropertiesAndValue(), currentOutput); 343 saveArray(filter(actualCe.getRawChildren()), currentOutput); 345 346 ConfigurationElementHandle[] childrenCEs = (ConfigurationElementHandle[]) element.getChildren(); 347 for (int i = 0; i < childrenCEs.length; i++) { 348 saveConfigurationElement(childrenCEs[i], outputStream, extraOutputStream, depth + 1); 349 } 350 351 } 352 353 private void saveExtensions(IExtension[] exts, DataOutputStream outputStream) throws IOException { 354 for (int i = 0; i < exts.length; i++) { 355 saveExtension((ExtensionHandle) exts[i], outputStream); 356 } 357 358 for (int i = 0; i < exts.length; i++) { 359 if (!((ExtensionHandle) exts[i]).shouldPersist()) 360 continue; 361 IConfigurationElement[] ces = exts[i].getConfigurationElements(); 362 int countCElements = 0; 363 boolean[] save = new boolean[ces.length]; 364 for (int j = 0; j < ces.length; j++) { 365 if (((ConfigurationElementHandle) ces[j]).shouldPersist()) { 366 save[j] = true; 367 countCElements++; 368 } else 369 save[j] = false; 370 } 371 outputStream.writeInt(countCElements); 372 for (int j = 0; j < ces.length; j++) { 373 if (save[j]) 374 saveConfigurationElement((ConfigurationElementHandle) ces[j], outputStream, extraOutput, 1); 375 } 376 } 377 } 378 379 private void saveExtensionPointData(ExtensionPointHandle xpt) throws IOException { 380 writeStringOrNull(xpt.getLabel(), extraOutput); 381 writeStringOrNull(xpt.getSchemaReference(), extraOutput); 382 writeStringOrNull(xpt.getUniqueIdentifier(), extraOutput); 383 writeStringOrNull(xpt.getNamespaceIdentifier(), extraOutput); 384 writeStringOrNull(((ExtensionPoint) xpt.getObject()).getContributorId(), extraOutput); 385 } 386 387 private void saveExtensionData(ExtensionHandle extension) throws IOException { 388 writeStringOrNull(extension.getLabel(), extraOutput); 389 writeStringOrNull(extension.getExtensionPointUniqueIdentifier(), extraOutput); 390 writeStringOrNull(extension.getContributorId(), extraOutput); 391 } 392 393 private void writeStringOrNull(String string, DataOutputStream out) throws IOException { 394 if (string == null) 395 out.writeByte(TableReader.NULL); 396 else { 397 out.writeByte(TableReader.OBJECT); 398 out.writeUTF(string); 399 } 400 } 401 402 private void saveOrphans() throws IOException { 403 Map orphans = objectManager.getOrphanExtensions(); 404 Map filteredOrphans = new HashMap(); 405 for (Iterator iter = orphans.entrySet().iterator(); iter.hasNext();) { 406 Map.Entry entry = (Map.Entry) iter.next(); 407 int[] filteredValue = filter((int[]) entry.getValue()); 408 if (filteredValue.length != 0) 409 filteredOrphans.put(entry.getKey(), filteredValue); 410 } 411 FileOutputStream fosOrphan = new FileOutputStream(orphansFile); 412 DataOutputStream outputOrphan = new DataOutputStream(new BufferedOutputStream(fosOrphan)); 413 outputOrphan.writeInt(filteredOrphans.size()); 414 Set elements = filteredOrphans.entrySet(); 415 for (Iterator iter = elements.iterator(); iter.hasNext();) { 416 Map.Entry entry = (Map.Entry) iter.next(); 417 outputOrphan.writeUTF((String ) entry.getKey()); 418 saveArray((int[]) entry.getValue(), outputOrphan); 419 } 420 for (Iterator iter = elements.iterator(); iter.hasNext();) { 421 Map.Entry entry = (Map.Entry) iter.next(); 422 mainOutput.writeInt(((int[]) entry.getValue()).length); 423 saveExtensions((IExtension[]) objectManager.getHandles((int[]) entry.getValue(), RegistryObjectManager.EXTENSION), mainOutput); 424 } 425 outputOrphan.flush(); 426 fosOrphan.getFD().sync(); 427 outputOrphan.close(); 428 } 429 430 private void log(Status status) { 431 registry.log(status); 432 } 433 434 private int[] filter(int[] input) { 436 boolean[] save = new boolean[input.length]; 437 int resultSize = 0; 438 for (int i = 0; i < input.length; i++) { 439 if (objectManager.shouldPersist(input[i])) { 440 save[i] = true; 441 resultSize++; 442 } else 443 save[i] = false; 444 } 445 int[] result = new int[resultSize]; 446 int pos = 0; 447 for (int i = 0; i < input.length; i++) { 448 if (save[i]) { 449 result[pos] = input[i]; 450 pos++; 451 } 452 } 453 return result; 454 } 455 } 456 | Popular Tags |