1 11 12 package org.eclipse.core.internal.registry; 13 14 import java.io.*; 15 import java.util.ArrayList ; 16 import java.util.List ; 17 import org.eclipse.core.internal.runtime.InternalPlatform; 18 import org.eclipse.core.internal.runtime.Policy; 19 import org.eclipse.core.runtime.*; 20 21 31 public class RegistryCacheReader { 32 33 MultiStatus problems = null; 34 protected List objectTable = null; 39 private boolean lazilyLoadExtensions; 40 private boolean flushableExtensions = true; 41 private boolean failed; 43 protected File cacheFile; 44 45 public static final byte REGISTRY_CACHE_VERSION = 7; 46 public static final byte NULL = 0; 47 public static final byte OBJECT = 1; 48 public static final byte INDEX = 2; 49 50 public RegistryCacheReader(File cacheFile, MultiStatus problems, boolean lazilyLoadExtensions, boolean flushable) { 51 super(); 52 this.cacheFile = cacheFile; 53 this.problems = problems; 54 this.lazilyLoadExtensions = lazilyLoadExtensions; 55 this.flushableExtensions = flushable; 56 objectTable = new ArrayList (); 57 } 58 59 public RegistryCacheReader(File cacheFile, MultiStatus problems) { 60 this(cacheFile, problems, false, true); 61 } 62 63 private int addToObjectTable(Object object) { 64 objectTable.add(object); 65 return (objectTable.size() - 1); 67 } 68 69 private void debug(String msg) { 70 System.out.println("RegistryCacheReader: " + msg); } 72 73 private boolean readHeaderInformation(DataInputStream in, long expectedTimestamp) throws InvalidRegistryCacheException { 74 try { 75 if (in.readInt() != REGISTRY_CACHE_VERSION) 76 return false; 77 long installStamp = in.readLong(); 78 long registryStamp = in.readLong(); 79 String osStamp = in.readUTF(); 80 String windowsStamp = in.readUTF(); 81 String localeStamp = in.readUTF(); 82 InternalPlatform info = InternalPlatform.getDefault(); 83 return ((expectedTimestamp == 0 || expectedTimestamp == registryStamp) && (installStamp == info.getStateTimeStamp()) && (osStamp.equals(info.getOS())) && (windowsStamp.equals(info.getWS())) && (localeStamp.equals(info.getNL()))); 84 } catch (IOException e) { 85 throw new InvalidRegistryCacheException(Policy.bind("meta.regCacheIOExceptionReading", "HeaderInformation"), e); } 87 } 88 89 private void skipConfigurationElement(RegistryModelObject parent, DataInputStream in) throws IOException { 90 readCachedString(in, false); skipString(in); 93 int length = in.readInt(); 94 for (int i = 0; i < length; i++) { 95 skipConfigurationProperty(in); 96 } 97 length = in.readInt(); 98 for (int i = 0; i < length; i++) { 99 skipConfigurationElement(null, in); 100 } 101 } 102 103 private ConfigurationElement readConfigurationElement(RegistryModelObject parent, DataInputStream in) throws IOException { 104 ConfigurationElement result = new ConfigurationElement(); 105 result.setParent(parent); 106 result.setName(readCachedString(in, false)); 107 result.setValue(readString(in, false)); 108 109 int length = in.readInt(); 110 ConfigurationProperty[] properties = new ConfigurationProperty[length]; 111 for (int i = 0; i < length; i++) { 112 properties[i] = readConfigurationProperty(in); 113 } 114 result.setProperties(properties); 115 116 length = in.readInt(); 117 IConfigurationElement[] elements = new ConfigurationElement[length]; 118 for (int i = 0; i < length; i++) { 119 elements[i] = readConfigurationElement(result, in); 120 } 121 result.setChildren(elements); 122 return result; 123 } 124 125 private void skipConfigurationProperty(DataInputStream in) throws IOException { 126 readCachedString(in, false); skipString(in); } 129 130 private ConfigurationProperty readConfigurationProperty(DataInputStream in) throws IOException { 131 String name = readCachedString(in, false); 132 ConfigurationProperty result = new ConfigurationProperty(); 133 result.setName(name); 134 result.setValue(readString(in, false)); 135 return result; 136 } 137 138 private Extension readExtension(DataInputStream in) throws InvalidRegistryCacheException { 139 Extension result = null; 140 try { 141 result = (Extension) readIndex(in); 142 if (result != null) 143 return result; 144 result = flushableExtensions ? new FlushableExtension() : new Extension(); 145 addToObjectTable(result); 146 result.setSimpleIdentifier(readString(in, false)); 147 result.setParent(readBundleModel(in)); 148 result.setName(readString(in, false)); 149 result.setExtensionPointIdentifier(readCachedString(in, false)); 150 result.setSubElements(readSubElements(result, in)); 151 return result; 152 } catch (IOException e) { 153 String extensionId = null; 154 if (result != null && result.getParent() != null) 155 extensionId = result.getParentIdentifier() + "." + result.getSimpleIdentifier(); throw new InvalidRegistryCacheException(Policy.bind("meta.regCacheIOExceptionReading", "extension: " + extensionId), e); } 158 } 159 160 private ExtensionPoint readExtensionPoint(Namespace bundle, DataInputStream in) throws InvalidRegistryCacheException { 161 ExtensionPoint result = null; 162 try { 163 result = (ExtensionPoint) readIndex(in); 164 if (result != null) 165 return result; 166 result = new ExtensionPoint(); 167 addToObjectTable(result); 168 result.setParent(bundle); 169 result.setSimpleIdentifier(readString(in, true)); 170 result.setName(readString(in, false)); 171 result.setSchema(readString(in, false)); 172 173 int length = in.readInt(); 175 IExtension[] extensions = new Extension[length]; 176 for (int i = 0; i < length; i++) 177 extensions[i] = readExtension(in); 178 result.setExtensions(extensions); 179 return result; 180 } catch (IOException e) { 181 String extensionPointId = null; 182 if (result != null && result.getParent() != null) 183 extensionPointId = result.getUniqueIdentifier(); 184 throw new InvalidRegistryCacheException(Policy.bind("meta.regCacheIOExceptionReading", "extension point: " + extensionPointId), e); } 186 } 187 188 private Namespace readBundleModel(DataInputStream in) throws InvalidRegistryCacheException { 189 Namespace result = null; 190 try { 191 result = (Namespace) readIndex(in); 192 if (result != null) 193 return result; 194 result = new Namespace(); 195 addToObjectTable(result); 196 result.setUniqueIdentifier(readCachedString(in, true)); 197 result.setBundle(InternalPlatform.getDefault().getBundleContext().getBundle(in.readLong())); 198 result.setParent(readRegistry(in)); 199 result.setHostIdentifier(readCachedString(in, false)); 200 201 int length = in.readInt(); 203 IExtensionPoint[] extensionPoints = new ExtensionPoint[length]; 204 for (int i = 0; i < length; i++) 205 extensionPoints[i] = readExtensionPoint(result, in); 206 result.setExtensionPoints(extensionPoints); 207 208 length = in.readInt(); 210 IExtension[] extensions = flushableExtensions ? new FlushableExtension[length] : new Extension[length]; 211 for (int i = 0; i < length; i++) 212 extensions[i] = readExtension(in); 213 result.setExtensions(extensions); 214 return result; 215 } catch (IOException e) { 216 String bundleId = (result == null || result.getUniqueIdentifier() == null) ? "<not available>" : result.getUniqueIdentifier(); throw new InvalidRegistryCacheException(Policy.bind("meta.regCacheIOExceptionReading", "plugin: " + bundleId), e); } 219 } 220 221 private ExtensionRegistry readCache(DataInputStream in, long expectedTimestamps) throws InvalidRegistryCacheException { 222 if (!readHeaderInformation(in, expectedTimestamps)) { 223 if (InternalPlatform.DEBUG_REGISTRY) 224 debug("Cache header information out of date - ignoring cache"); return null; 226 } 227 return readRegistry(in); 228 } 229 230 private ExtensionRegistry readRegistry(DataInputStream in) throws InvalidRegistryCacheException { 231 try { 232 ExtensionRegistry result = (ExtensionRegistry) readIndex(in); 233 if (result != null) 234 return result; 235 236 result = new ExtensionRegistry(); 237 if (lazilyLoadExtensions) 238 result.setCacheReader(this); 239 addToObjectTable(result); 240 int length = in.readInt(); 243 if (length == 0) 244 return null; 245 for (int i = 0; i < length; i++) 246 result.basicAdd(readBundleModel(in), false); 247 if (lazilyLoadExtensions) 248 result.setCacheReader(this); 249 return result; 250 } catch (IOException e) { 251 throw new InvalidRegistryCacheException(Policy.bind("meta.regCacheIOExceptionReading", "ExtensionRegistry"), e); } 253 } 254 255 private ConfigurationElement[] readSubElements(Extension parent, DataInputStream in) throws IOException { 256 int type = in.readByte(); 257 if (type == NULL) 258 return null; 259 260 int offset = in.readInt(); 263 264 if (lazilyLoadExtensions) { 265 Extension extension = parent; 266 extension.setSubElementsCacheOffset(offset); 267 skipBasicSubElements(parent, in); 268 extension.setFullyLoaded(false); 269 return null; 270 } 271 return readBasicSubElements(parent, in); 272 } 273 274 private void skipBasicSubElements(Extension parent, DataInputStream in) throws IOException { 275 int length = in.readInt(); 276 for (int i = 0; i < length; i++) { 277 skipConfigurationElement(parent, in); 278 } 279 } 280 281 private ConfigurationElement[] readBasicSubElements(Extension parent, DataInputStream in) throws IOException { 282 int length = in.readInt(); 284 285 ConfigurationElement[] result = new ConfigurationElement[length]; 286 for (int i = 0; i < length; i++) { 287 result[i] = readConfigurationElement(parent, in); 288 } 289 return result; 290 } 291 292 private String readString(DataInputStream in, boolean intern) throws IOException { 293 byte type = in.readByte(); 294 if (type == NULL) 295 return null; 296 if (intern) 297 return in.readUTF().intern(); 298 else 299 return in.readUTF(); 300 } 301 302 private void skipString(DataInputStream in) throws IOException { 303 byte type = in.readByte(); 304 if (type == NULL) 305 return; 306 int utfLength = in.readUnsignedShort(); 307 byte bytearr[] = new byte[utfLength]; 308 in.readFully(bytearr, 0, utfLength); 309 } 310 311 private String readCachedString(DataInputStream in, boolean intern) throws IOException { 312 byte type = in.readByte(); 313 if (type == NULL) 314 return null; 315 316 if (type == INDEX) 317 return (String ) objectTable.get(in.readInt()); 318 319 String stringRead = null; 320 if (intern) 321 stringRead = in.readUTF().intern(); 322 else 323 stringRead = in.readUTF(); 324 addToObjectTable(stringRead); 325 return stringRead; 326 } 327 328 private Object readIndex(DataInputStream in) throws IOException { 329 byte type = in.readByte(); 330 return type == INDEX ? objectTable.get(in.readInt()) : null; 331 } 332 333 private DataInputStream openCacheFile() throws IOException { 334 return new DataInputStream(new BufferedInputStream(new FileInputStream(cacheFile), 2048)); 335 } 336 337 340 public final ConfigurationElement[] loadConfigurationElements(Extension parent, int offset) { 341 DataInputStream in = null; 342 try { 343 in = openCacheFile(); 344 in.skipBytes(offset); 345 in.readInt(); return readBasicSubElements(parent, in); 347 } catch (IOException e) { 348 Throwable exception = InternalPlatform.DEBUG_REGISTRY ? e : null; 349 String message = Policy.bind("meta.unableToReadCache"); InternalPlatform.getDefault().log(new Status(IStatus.WARNING, Platform.PI_RUNTIME, 0, message, exception)); 351 } catch (OutOfMemoryError oome) { 352 logError(oome); 354 } catch (RuntimeException re) { 355 logError(re); 357 } finally { 358 try { 359 if (in != null) 360 in.close(); 361 } catch (IOException e) { 362 } 364 } 365 failed = true; 367 return new ConfigurationElement[0]; 368 } 369 370 boolean hasFailed() { 371 return failed; 372 } 373 374 private void logError(Throwable t) { 375 String message = Policy.bind("meta.registryCacheReadProblems"); InternalPlatform.getDefault().log(new Status(IStatus.WARNING, Platform.PI_RUNTIME, 0, message, null)); 378 Throwable exceptionToLog = InternalPlatform.DEBUG_REGISTRY ? t : null; 380 InternalPlatform.getDefault().log(new Status(IStatus.WARNING, Platform.PI_RUNTIME, 0, t.toString(), exceptionToLog)); 381 } 382 383 public final ExtensionRegistry loadCache() { 384 return this.loadCache(0); 385 } 386 387 390 public final ExtensionRegistry loadCache(long expectedTimestamp) { 391 DataInputStream in = null; 392 try { 393 in = openCacheFile(); 394 } catch (IOException e) { 395 Throwable exception = InternalPlatform.DEBUG_REGISTRY ? e : null; 396 String message = Policy.bind("meta.unableToReadCache"); InternalPlatform.getDefault().log(new Status(IStatus.WARNING, Platform.PI_RUNTIME, 0, message, exception)); 398 return null; 399 } 400 try { 401 return readCache(in, expectedTimestamp); 402 } catch (InvalidRegistryCacheException e) { 403 Throwable exception = InternalPlatform.DEBUG_REGISTRY ? e.getCause() : null; 404 InternalPlatform.getDefault().log(new Status(IStatus.WARNING, Platform.PI_RUNTIME, 0, e.getMessage(), exception)); 405 } catch (OutOfMemoryError oome) { 406 logError(oome); 408 } catch (RuntimeException re) { 409 logError(re); 411 } finally { 412 try { 413 if (in != null) 414 in.close(); 415 } catch (IOException e) { 416 } 418 } 419 return null; 420 } 421 422 public class InvalidRegistryCacheException extends Exception { 423 Throwable cause = null; 424 425 public InvalidRegistryCacheException(String msg, Throwable cause) { 426 super(msg); 427 this.cause = cause; 428 } 429 430 public InvalidRegistryCacheException(String string) { 431 super(string); 432 } 433 434 public Throwable getCause() { 435 return cause; 436 } 437 } 438 } | Popular Tags |