1 11 package org.eclipse.jdt.apt.core.internal.generatedfile; 12 13 import java.io.BufferedInputStream ; 14 import java.io.BufferedOutputStream ; 15 import java.io.DataInputStream ; 16 import java.io.DataOutputStream ; 17 import java.io.File ; 18 import java.io.FileInputStream ; 19 import java.io.FileOutputStream ; 20 import java.io.IOException ; 21 import java.util.Collections ; 22 import java.util.EnumSet ; 23 import java.util.HashMap ; 24 import java.util.Map ; 25 import java.util.Set ; 26 import java.util.Map.Entry; 27 28 import org.eclipse.core.resources.IFile; 29 import org.eclipse.core.resources.IProject; 30 import org.eclipse.core.runtime.IPath; 31 import org.eclipse.core.runtime.Path; 32 import org.eclipse.jdt.apt.core.internal.AptPlugin; 33 import org.eclipse.jdt.apt.core.internal.util.ManyToMany; 34 35 40 public class GeneratedFileMap extends ManyToMany<IFile, IFile> { 41 42 public enum Flags { 43 44 NONSOURCE; 45 } 46 47 private static final int SERIALIZATION_VERSION = 2; 49 50 private final IProject _proj; 51 52 private final Map <IFile, Set <Flags>> _flags = new HashMap <IFile, Set <Flags>>(); 53 54 public GeneratedFileMap(IProject proj) { 55 _proj = proj; 56 readState(); 57 } 58 59 62 @Override 63 public synchronized boolean clear() { 64 _flags.clear(); 65 return super.clear(); 66 } 67 68 71 @Override 72 public synchronized boolean remove(IFile key, IFile value) { 73 boolean removed = super.remove(key, value); 74 if (removed) { 75 if (!containsValue(value)) { 76 _flags.remove(value); 77 } 78 } 79 return removed; 80 } 81 82 85 @Override 86 public synchronized boolean removeKey(IFile key) { 87 Set <IFile> values = getValues(key); 88 boolean removed = super.removeKey(key); 89 if (removed) { 90 for (IFile value : values) { 91 if (!containsValue(value)) { 92 _flags.remove(value); 93 } 94 } 95 } 96 return removed; 97 } 98 99 102 @Override 103 public synchronized boolean removeValue(IFile value) { 104 boolean removed = super.removeValue(value); 105 if (removed) { 106 _flags.remove(value); 107 } 108 return removed; 109 } 110 111 115 public synchronized void clearState() { 116 clear(); 117 File state = getStateFile(_proj); 118 if (state != null) { 119 boolean successfullyDeleted = state.delete(); 120 if (!successfullyDeleted && state.exists()) { 121 AptPlugin.log(new IOException ("Could not delete apt dependency state file"), state.getPath()); 123 } 124 } 125 clearDirtyBit(); 126 } 127 128 131 @Override 132 public boolean put(IFile parent, IFile generated) { 133 return put(parent, generated, Collections.<Flags>emptySet()); 134 } 135 136 139 public boolean put(IFile parent, IFile generated, boolean isSource) { 140 return put(parent, generated, isSource ? Collections.<Flags>emptySet() : EnumSet.of(Flags.NONSOURCE)); 141 } 142 143 149 public synchronized boolean put(IFile parent, IFile generated, Set <Flags> flags) { 150 if (flags.isEmpty()) { 151 _flags.remove(generated); 152 } 153 else { 154 _flags.put(generated, flags); 155 } 156 return super.put(parent, generated); 157 } 158 159 public Set <Flags> getFlags(IFile generated) { 160 Set <Flags> flags = _flags.get(generated); 161 return flags == null ? Collections.<Flags>emptySet() : flags; 162 } 163 164 168 public boolean isSource(IFile generated) { 169 return !getFlags(generated).contains(Flags.NONSOURCE); 170 } 171 172 175 private String convertIFileToPath(IFile file) { 176 IPath path = file.getProjectRelativePath(); 177 return path.toOSString(); 178 } 179 180 183 private IFile convertPathToIFile(String projectRelativeString) { 184 IPath path = new Path(projectRelativeString); 185 return _proj.getFile(path); 186 } 187 188 192 private File getStateFile(IProject project) { 193 if (!project.exists()) return null; 194 IPath workingLocation = project.getWorkingLocation(AptPlugin.PLUGIN_ID); 195 return workingLocation.append("state.dat").toFile(); } 197 198 213 private void readState() { 214 File file = getStateFile(_proj); 215 if (file == null || !file.exists()) { 216 return; 218 } 219 DataInputStream in = null; 220 try { 221 in= new DataInputStream (new BufferedInputStream (new FileInputStream (file))); 222 int version = in.readInt(); 223 if (version != SERIALIZATION_VERSION) { 224 throw new IOException ("Dependency map file version does not match. Expected " + SERIALIZATION_VERSION + ", but found " + version); } 227 int sizeOfMap = in.readInt(); 228 229 for (int parentIndex=0; parentIndex<sizeOfMap; parentIndex++) { 232 String parentPath = in.readUTF(); 233 IFile parent = convertPathToIFile(parentPath); 234 int numChildren = in.readInt(); 235 for (int childIndex = 0; childIndex<numChildren; childIndex++) { 236 String childPath = in.readUTF(); 237 IFile child = convertPathToIFile(childPath); 238 put(parent, child); 240 } 241 } 242 243 int sizeOfFlags = in.readInt(); 245 for (int i = 0; i < sizeOfFlags; ++i) { 246 String childPath = in.readUTF(); 247 IFile child = convertPathToIFile(childPath); 248 if (!containsValue(child)) { 249 throw new IOException ("Error in generated file attributes: did not expect file " + childPath); } 251 252 int attributeCount = in.readInt(); 253 EnumSet <Flags> flags = EnumSet.noneOf(Flags.class); 254 for (int j = 0; j < attributeCount; ++j) { 255 String attr = in.readUTF(); 256 Flags f = Flags.valueOf(attr); 257 flags.add(f); 258 } 259 _flags.put(child, flags); 260 } 261 262 clearDirtyBit(); 264 } 265 catch (IOException ioe) { 266 clear(); 268 AptPlugin.logWarning(ioe, "Could not read APT dependencies: generated files may not be deleted until the next clean"); } 271 catch (IllegalArgumentException iae) { 272 clear(); 274 AptPlugin.logWarning(iae, "Could not read APT dependencies: generated files may not be deleted until the next clean"); } 277 finally { 278 if (in != null) { 279 try {in.close();} catch (IOException ioe) {} 280 } 281 } 282 } 283 284 287 public synchronized void writeState() { 288 if (!isDirty()) { 289 return; 290 } 291 File file = getStateFile(_proj); 292 if (file == null) { 293 return; 295 } 296 file.delete(); 297 298 DataOutputStream out = null; 299 try { 300 out = new DataOutputStream (new BufferedOutputStream (new FileOutputStream (file))); 301 302 out.writeInt(SERIALIZATION_VERSION); 303 304 Set <IFile> parents = getKeySet(); 306 out.writeInt(parents.size()); 307 308 for (IFile parent : parents) { 310 311 out.writeUTF(convertIFileToPath(parent)); 313 314 Set <IFile> children = getValues(parent); 315 316 out.writeInt(children.size()); 318 319 for (IFile child : children) { 321 out.writeUTF(convertIFileToPath(child)); 323 } 324 } 325 326 out.writeInt(_flags.size()); 328 329 for (Entry<IFile, Set <Flags>> entry : _flags.entrySet()) { 331 out.writeUTF(convertIFileToPath(entry.getKey())); 333 334 Set <Flags> flags = entry.getValue(); 335 out.writeInt(flags.size()); 337 for (Flags f : flags) { 338 out.writeUTF(f.name()); 340 } 341 } 342 343 clearDirtyBit(); 345 out.flush(); 346 } 347 catch (IOException ioe) { 348 AptPlugin.logWarning(ioe, "Could not serialize APT dependencies"); } 351 finally { 352 if (out != null) { 353 try { 354 out.close(); 355 } 356 catch (IOException ioe) { 357 } 359 } 360 } 361 } 362 363 364 } 365 | Popular Tags |