1 11 package org.eclipse.core.internal.properties; 12 13 import java.io.*; 14 import java.util.*; 15 import org.eclipse.core.internal.localstore.Bucket; 16 import org.eclipse.core.internal.resources.ResourceException; 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 public class PropertyBucket extends Bucket { 23 public static class PropertyEntry extends Entry { 24 25 private final static Comparator COMPARATOR = new Comparator() { 26 public int compare(Object o1, Object o2) { 27 int qualifierComparison = ((String []) o1)[0].compareTo(((String []) o2)[0]); 28 return qualifierComparison != 0 ? qualifierComparison : ((String []) o1)[1].compareTo(((String []) o2)[1]); 29 } 30 }; 31 private static final String [][] EMPTY_DATA = new String [0][]; 32 35 private String [][] value; 36 37 42 static String [][] delete(String [][] existing, QualifiedName propertyName) { 43 if (existing.length == 1) 45 return (existing[0][0].equals(propertyName.getQualifier()) && existing[0][1].equals(propertyName.getLocalName())) ? null : existing; 46 int deletePosition = search(existing, propertyName); 48 if (deletePosition < 0) 49 return existing; 51 String [][] newValue = new String [existing.length - 1][]; 52 if (deletePosition > 0) 53 System.arraycopy(existing, 0, newValue, 0, deletePosition); 55 if (deletePosition < existing.length - 1) 56 System.arraycopy(existing, deletePosition + 1, newValue, deletePosition, newValue.length - deletePosition); 58 return newValue; 59 } 60 61 static String [][] insert(String [][] existing, QualifiedName propertyName, String propertyValue) { 62 int index = search(existing, propertyName); 64 if (index >= 0) { 65 existing[index][2] = propertyValue; 67 return existing; 68 } 69 int insertPosition = -index - 1; 71 String [][] newValue = new String [existing.length + 1][]; 72 if (insertPosition > 0) 73 System.arraycopy(existing, 0, newValue, 0, insertPosition); 74 newValue[insertPosition] = new String [] {propertyName.getQualifier(), propertyName.getLocalName(), propertyValue}; 75 if (insertPosition < existing.length) 76 System.arraycopy(existing, insertPosition, newValue, insertPosition + 1, existing.length - insertPosition); 77 return newValue; 78 } 79 80 83 static Object merge(String [][] base, String [][] additions) { 84 int additionPointer = 0; 85 int basePointer = 0; 86 int added = 0; 87 String [][] result = new String [base.length + additions.length][]; 88 while (basePointer < base.length && additionPointer < additions.length) { 89 int comparison = COMPARATOR.compare(base[basePointer], additions[additionPointer]); 90 if (comparison == 0) { 91 result[added++] = additions[additionPointer++]; 92 basePointer++; 94 } else if (comparison < 0) 95 result[added++] = base[basePointer++]; 96 else 97 result[added++] = additions[additionPointer++]; 98 } 99 String [][] remaining = basePointer == base.length ? additions : base; 101 int remainingPointer = basePointer == base.length ? additionPointer : basePointer; 102 int remainingCount = remaining.length - remainingPointer; 103 System.arraycopy(remaining, remainingPointer, result, added, remainingCount); 104 added += remainingCount; 105 if (added == base.length + additions.length) 106 return result; 108 String [][] finalResult = new String [added][]; 110 System.arraycopy(result, 0, finalResult, 0, finalResult.length); 111 return finalResult; 112 } 113 114 private static int search(String [][] existing, QualifiedName propertyName) { 115 return Arrays.binarySearch(existing, new String [] {propertyName.getQualifier(), propertyName.getLocalName(), null}, COMPARATOR); 116 } 117 118 public PropertyEntry(IPath path, PropertyEntry base) { 119 super(path); 120 int xLen = base.value.length; 122 this.value = new String [xLen][]; 123 for (int i = 0; i < xLen; i++) { 124 int yLen = base.value[i].length; 125 this.value[i] = new String [yLen]; 126 System.arraycopy(base.value[i], 0, value[i], 0, yLen); 127 } 128 } 129 130 134 protected PropertyEntry(IPath path, String [][] value) { 135 super(path); 136 this.value = value; 137 } 138 139 143 private void compact() { 144 if (!isDirty()) 145 return; 146 int occurrences = 0; 147 for (int i = 0; i < value.length; i++) 148 if (value[i] != null) 149 value[occurrences++] = value[i]; 150 if (occurrences == value.length) 151 return; 153 if (occurrences == 0) { 154 value = EMPTY_DATA; 156 delete(); 157 return; 158 } 159 String [][] result = new String [occurrences][]; 160 System.arraycopy(value, 0, result, 0, occurrences); 161 value = result; 162 } 163 164 public int getOccurrences() { 165 return value == null ? 0 : value.length; 166 } 167 168 public String getProperty(QualifiedName name) { 169 int index = search(value, name); 170 return index < 0 ? null : value[index][2]; 171 } 172 173 public Object getPropertyName(int i) { 174 return new QualifiedName(this.value[i][0], this.value[i][1]); 175 } 176 177 public Object getPropertyValue(int i) { 178 return this.value[i][2]; 179 } 180 181 public Object getValue() { 182 return value; 183 } 184 185 public void visited() { 186 compact(); 187 } 188 } 189 190 public static final byte INDEX = 1; 191 192 public static final byte QNAME = 2; 193 194 211 private static final byte VERSION = 1; 212 213 private final List qualifierIndex = new ArrayList(); 214 215 public PropertyBucket() { 216 super(); 217 } 218 219 protected Entry createEntry(IPath path, Object value) { 220 return new PropertyEntry(path, (String [][]) value); 221 } 222 223 private PropertyEntry getEntry(IPath path) { 224 String pathAsString = path.toString(); 225 String [][] existing = (String [][]) getEntryValue(pathAsString); 226 if (existing == null) 227 return null; 228 return new PropertyEntry(path, existing); 229 } 230 231 234 protected String getIndexFileName() { 235 return "properties.index"; } 237 238 public String getProperty(IPath path, QualifiedName name) { 239 PropertyEntry entry = getEntry(path); 240 if (entry == null) 241 return null; 242 return entry.getProperty(name); 243 } 244 245 protected byte getVersion() { 246 return VERSION; 247 } 248 249 252 protected String getVersionFileName() { 253 return "properties.version"; } 255 256 public void load(String newProjectName, File baseLocation, boolean force) throws CoreException { 257 qualifierIndex.clear(); 258 super.load(newProjectName, baseLocation, force); 259 } 260 261 protected Object readEntryValue(DataInputStream source) throws IOException, CoreException { 262 int length = source.readUnsignedShort(); 263 String [][] properties = new String [length][3]; 264 for (int j = 0; j < properties.length; j++) { 265 byte constant = source.readByte(); 267 switch (constant) { 268 case QNAME : 269 properties[j][0] = source.readUTF(); 270 qualifierIndex.add(properties[j][0]); 271 break; 272 case INDEX : 273 properties[j][0] = (String ) qualifierIndex.get(source.readInt()); 274 break; 275 default : 276 IPath resourcePath = projectName == null ? Path.ROOT : Path.ROOT.append(projectName); 278 String msg = NLS.bind(Messages.properties_readProperties, resourcePath.toString()); 279 throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, null, msg, null); 280 } 281 properties[j][1] = source.readUTF(); 283 properties[j][2] = source.readUTF(); 285 } 286 return properties; 287 } 288 289 public void save() throws CoreException { 290 qualifierIndex.clear(); 291 super.save(); 292 } 293 294 public void setProperties(PropertyEntry entry) { 295 IPath path = entry.getPath(); 296 String [][] additions = (String [][]) entry.getValue(); 297 String pathAsString = path.toString(); 298 String [][] existing = (String [][]) getEntryValue(pathAsString); 299 if (existing == null) { 300 setEntryValue(pathAsString, additions); 301 return; 302 } 303 setEntryValue(pathAsString, PropertyEntry.merge(existing, additions)); 304 } 305 306 public void setProperty(IPath path, QualifiedName name, String value) { 307 String pathAsString = path.toString(); 308 String [][] existing = (String [][]) getEntryValue(pathAsString); 309 if (existing == null) { 310 if (value != null) 311 setEntryValue(pathAsString, new String [][] {{name.getQualifier(), name.getLocalName(), value}}); 312 return; 313 } 314 String [][] newValue; 315 if (value != null) 316 newValue = PropertyEntry.insert(existing, name, value); 317 else 318 newValue = PropertyEntry.delete(existing, name); 319 setEntryValue(pathAsString, newValue); 321 } 322 323 protected void writeEntryValue(DataOutputStream destination, Object entryValue) throws IOException { 324 String [][] properties = (String [][]) entryValue; 325 destination.writeShort(properties.length); 326 for (int j = 0; j < properties.length; j++) { 327 int index = qualifierIndex.indexOf(properties[j][0]); 329 if (index == -1) { 330 destination.writeByte(QNAME); 331 destination.writeUTF(properties[j][0]); 332 qualifierIndex.add(properties[j][0]); 333 } else { 334 destination.writeByte(INDEX); 335 destination.writeInt(index); 336 } 337 destination.writeUTF(properties[j][1]); 339 destination.writeUTF(properties[j][2]); 341 } 342 } 343 } 344 | Popular Tags |