1 11 package org.eclipse.core.internal.localstore; 12 13 import java.io.*; 14 import java.util.*; 15 import org.eclipse.core.internal.resources.ResourceException; 16 import org.eclipse.core.internal.resources.ResourceStatus; 17 import org.eclipse.core.internal.utils.Messages; 18 import org.eclipse.core.resources.IResourceStatus; 19 import org.eclipse.core.runtime.*; 20 import org.eclipse.osgi.util.NLS; 21 22 28 public abstract class Bucket { 29 30 public static abstract class Entry { 31 36 private final static int STATE_CLEAR = 0; 37 42 private final static int STATE_DELETED = 0x02; 43 48 private final static int STATE_DIRTY = 0x01; 49 50 54 private IPath path; 55 56 63 private byte state = STATE_CLEAR; 64 65 protected Entry(IPath path) { 66 this.path = path; 67 } 68 69 public void delete() { 70 state = STATE_DELETED; 71 } 72 73 public abstract int getOccurrences(); 74 75 public IPath getPath() { 76 return path; 77 } 78 79 public abstract Object getValue(); 80 81 public boolean isDeleted() { 82 return state == STATE_DELETED; 83 } 84 85 public boolean isDirty() { 86 return state == STATE_DIRTY; 87 } 88 89 public boolean isEmpty() { 90 return getOccurrences() == 0; 91 } 92 93 public void markDirty() { 94 Assert.isTrue(state != STATE_DELETED); 95 state = STATE_DIRTY; 96 } 97 98 101 public void visited() { 102 } 104 } 105 106 109 public static abstract class Visitor { 110 public final static int CONTINUE = 0; 112 public final static int RETURN = 2; 114 115 118 public void afterSaving(Bucket bucket) throws CoreException { 119 } 121 122 public void beforeSaving(Bucket bucket) throws CoreException { 123 } 125 126 129 public abstract int visit(Entry entry); 130 } 131 132 135 static final String INDEXES_DIR_NAME = ".indexes"; 137 142 private final Map entries; 143 146 private File location; 147 150 private boolean needSaving = false; 151 154 protected String projectName; 155 156 public Bucket() { 157 this.entries = new HashMap(); 158 } 159 160 168 public final int accept(Visitor visitor, IPath filter, int depth) throws CoreException { 169 if (entries.isEmpty()) 170 return Visitor.CONTINUE; 171 try { 172 for (Iterator i = entries.entrySet().iterator(); i.hasNext();) { 173 Map.Entry mapEntry = (Map.Entry) i.next(); 174 IPath path = new Path((String ) mapEntry.getKey()); 175 int matchingSegments = filter.matchingFirstSegments(path); 177 if (!filter.isPrefixOf(path) || path.segmentCount() - matchingSegments > depth) 178 continue; 179 Entry bucketEntry = createEntry(path, mapEntry.getValue()); 181 int outcome = visitor.visit(bucketEntry); 183 bucketEntry.visited(); 185 if (bucketEntry.isDeleted()) { 186 needSaving = true; 187 i.remove(); 188 } else if (bucketEntry.isDirty()) { 189 needSaving = true; 190 mapEntry.setValue(bucketEntry.getValue()); 191 } 192 if (outcome != Visitor.CONTINUE) 193 return outcome; 194 } 195 return Visitor.CONTINUE; 196 } finally { 197 visitor.beforeSaving(this); 198 save(); 199 visitor.afterSaving(this); 200 } 201 } 202 203 206 private void cleanUp(File toDelete) { 207 if (!toDelete.delete()) 208 return; 210 if (toDelete.getName().equals(INDEXES_DIR_NAME)) 212 return; 213 cleanUp(toDelete.getParentFile()); 215 } 216 217 220 protected abstract Entry createEntry(IPath path, Object value); 221 222 226 public void flush() { 227 projectName = null; 228 location = null; 229 entries.clear(); 230 needSaving = false; 231 } 232 233 236 public final int getEntryCount() { 237 return entries.size(); 238 } 239 240 243 public final Object getEntryValue(String path) { 244 return entries.get(path); 245 } 246 247 250 protected abstract String getIndexFileName(); 251 252 255 protected abstract byte getVersion(); 256 257 260 protected abstract String getVersionFileName(); 261 262 265 public void load(String newProjectName, File baseLocation) throws CoreException { 266 load(newProjectName, baseLocation, false); 267 } 268 269 274 public void load(String newProjectName, File baseLocation, boolean force) throws CoreException { 275 try { 276 if (!force && this.location != null && baseLocation.equals(this.location.getParentFile()) && (projectName == null ? (newProjectName == null) : projectName.equals(newProjectName))) { 278 this.projectName = newProjectName; 279 return; 280 } 281 save(); 283 this.projectName = newProjectName; 284 this.location = new File(baseLocation, getIndexFileName()); 285 this.entries.clear(); 286 if (!this.location.isFile()) 287 return; 288 DataInputStream source = new DataInputStream(new BufferedInputStream(new FileInputStream(location), 8192)); 289 try { 290 int version = source.readByte(); 291 if (version != getVersion()) { 292 String message = NLS.bind(Messages.resources_readMetaWrongVersion, location.getAbsolutePath(), Integer.toString(version)); 294 ResourceStatus status = new ResourceStatus(IResourceStatus.FAILED_READ_METADATA, message); 295 throw new ResourceException(status); 296 } 297 int entryCount = source.readInt(); 298 for (int i = 0; i < entryCount; i++) 299 this.entries.put(readEntryKey(source), readEntryValue(source)); 300 } finally { 301 source.close(); 302 } 303 } catch (IOException ioe) { 304 String message = NLS.bind(Messages.resources_readMeta, location.getAbsolutePath()); 305 ResourceStatus status = new ResourceStatus(IResourceStatus.FAILED_READ_METADATA, null, message, ioe); 306 throw new ResourceException(status); 307 } 308 } 309 310 private String readEntryKey(DataInputStream source) throws IOException { 311 if (projectName == null) 312 return source.readUTF(); 313 return IPath.SEPARATOR + projectName + source.readUTF(); 314 } 315 316 319 protected abstract Object readEntryValue(DataInputStream source) throws IOException, CoreException; 320 321 324 public void save() throws CoreException { 325 if (!needSaving) 326 return; 327 try { 328 if (entries.isEmpty()) { 329 needSaving = false; 330 cleanUp(location); 331 return; 332 } 333 File parent = location.getParentFile(); 335 if (parent == null) 336 throw new IOException(); parent.mkdirs(); 338 DataOutputStream destination = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(location), 8192)); 339 try { 340 destination.write(getVersion()); 341 destination.writeInt(entries.size()); 342 for (Iterator i = entries.entrySet().iterator(); i.hasNext();) { 343 Map.Entry entry = (Map.Entry) i.next(); 344 writeEntryKey(destination, (String ) entry.getKey()); 345 writeEntryValue(destination, entry.getValue()); 346 } 347 } finally { 348 destination.close(); 349 } 350 needSaving = false; 351 } catch (IOException ioe) { 352 String message = NLS.bind(Messages.resources_writeMeta, location.getAbsolutePath()); 353 ResourceStatus status = new ResourceStatus(IResourceStatus.FAILED_WRITE_METADATA, null, message, ioe); 354 throw new ResourceException(status); 355 } 356 } 357 358 362 public final void setEntryValue(String path, Object value) { 363 if (value == null) 364 entries.remove(path); 365 else 366 entries.put(path, value); 367 needSaving = true; 368 } 369 370 private void writeEntryKey(DataOutputStream destination, String path) throws IOException { 371 if (projectName == null) { 372 destination.writeUTF(path); 373 return; 374 } 375 int pathLength = path.length(); 377 int projectLength = projectName.length(); 378 String key = (pathLength == projectLength + 1) ? "" : path.substring(projectLength + 1); destination.writeUTF(key); 380 } 381 382 385 protected abstract void writeEntryValue(DataOutputStream destination, Object entryValue) throws IOException, CoreException; 386 } 387 | Popular Tags |