1 11 package org.eclipse.core.internal.resources; 12 13 import java.io.*; 14 import java.util.*; 15 import org.eclipse.core.internal.preferences.EclipsePreferences; 16 import org.eclipse.core.internal.preferences.ExportedPreferences; 17 import org.eclipse.core.internal.utils.*; 18 import org.eclipse.core.resources.*; 19 import org.eclipse.core.runtime.*; 20 import org.eclipse.core.runtime.jobs.ISchedulingRule; 21 import org.eclipse.core.runtime.jobs.MultiRule; 22 import org.eclipse.core.runtime.preferences.IEclipsePreferences; 23 import org.eclipse.core.runtime.preferences.IExportedPreferences; 24 import org.eclipse.osgi.util.NLS; 25 import org.osgi.service.prefs.BackingStoreException; 26 import org.osgi.service.prefs.Preferences; 27 28 34 public class ProjectPreferences extends EclipsePreferences { 35 36 class SortedProperties extends Properties { 37 38 class IteratorWrapper implements Enumeration { 39 Iterator iterator; 40 41 public IteratorWrapper(Iterator iterator) { 42 this.iterator = iterator; 43 } 44 45 public boolean hasMoreElements() { 46 return iterator.hasNext(); 47 } 48 49 public Object nextElement() { 50 return iterator.next(); 51 } 52 } 53 54 private static final long serialVersionUID = 1L; 55 56 59 public synchronized Enumeration keys() { 60 TreeSet set = new TreeSet(); 61 for (Enumeration e = super.keys(); e.hasMoreElements();) 62 set.add(e.nextElement()); 63 return new IteratorWrapper(set.iterator()); 64 } 65 } 66 67 70 protected static Set loadedNodes = new HashSet(); 71 private IFile file; 72 private boolean initialized = false; 73 77 private boolean isReading; 78 82 private boolean isWriting; 83 private IEclipsePreferences loadLevel; 84 private IProject project; 85 private String qualifier; 86 87 private int segmentCount; 89 90 static void deleted(IFile file) throws CoreException { 91 IPath path = file.getFullPath(); 92 int count = path.segmentCount(); 93 if (count != 3) 94 return; 95 if (!EclipsePreferences.DEFAULT_PREFERENCES_DIRNAME.equals(path.segment(1))) 97 return; 98 Preferences root = Platform.getPreferencesService().getRootNode(); 99 String project = path.segment(0); 100 String qualifier = path.removeFileExtension().lastSegment(); 101 ProjectPreferences projectNode = (ProjectPreferences) root.node(ProjectScope.SCOPE).node(project); 102 try { 104 if (!projectNode.nodeExists(qualifier)) 105 return; 106 } catch (BackingStoreException e) { 107 } 109 110 String childPath = projectNode.absolutePath() + IPath.SEPARATOR + qualifier; 114 if (projectNode.isAlreadyLoaded(childPath)) 115 removeNode(projectNode.node(qualifier)); 116 else 117 projectNode.removeNode(qualifier); 118 119 if (qualifier.equals(ResourcesPlugin.PI_RESOURCES)) 121 preferencesChanged(file.getProject()); 122 } 123 124 static void deleted(IFolder folder) throws CoreException { 125 IPath path = folder.getFullPath(); 126 int count = path.segmentCount(); 127 if (count != 2) 128 return; 129 if (!EclipsePreferences.DEFAULT_PREFERENCES_DIRNAME.equals(path.segment(1))) 131 return; 132 Preferences root = Platform.getPreferencesService().getRootNode(); 133 String project = path.segment(0); 136 Preferences projectNode = root.node(ProjectScope.SCOPE).node(project); 137 boolean hasResourcesSettings = getFile(folder, ResourcesPlugin.PI_RESOURCES).exists(); 139 removeNode(projectNode); 141 if (hasResourcesSettings) 143 preferencesChanged(folder.getProject()); 144 } 145 146 149 static void deleted(IProject project) throws CoreException { 150 Preferences root = Platform.getPreferencesService().getRootNode(); 155 Preferences projectNode = root.node(ProjectScope.SCOPE).node(project.getName()); 156 boolean hasResourcesSettings = getFile(project, ResourcesPlugin.PI_RESOURCES).exists(); 158 removeNode(projectNode); 160 if (hasResourcesSettings) 162 preferencesChanged(project); 163 } 164 165 static void deleted(IResource resource) throws CoreException { 166 switch (resource.getType()) { 167 case IResource.FILE : 168 deleted((IFile) resource); 169 return; 170 case IResource.FOLDER : 171 deleted((IFolder) resource); 172 return; 173 case IResource.PROJECT : 174 deleted((IProject) resource); 175 return; 176 } 177 } 178 179 182 static IFile getFile(IFolder folder, String qualifier) { 183 Assert.isLegal(folder.getName().equals(DEFAULT_PREFERENCES_DIRNAME)); 184 return folder.getFile(new Path(qualifier).addFileExtension(PREFS_FILE_EXTENSION)); 185 } 186 187 190 static IFile getFile(IProject project, String qualifier) { 191 return project.getFile(new Path(DEFAULT_PREFERENCES_DIRNAME).append(qualifier).addFileExtension(PREFS_FILE_EXTENSION)); 192 } 193 194 private static Properties loadProperties(IFile file) throws BackingStoreException { 195 if (Policy.DEBUG_PREFERENCES) 196 Policy.debug("Loading preferences from file: " + file.getFullPath()); Properties result = new Properties(); 198 InputStream input = null; 199 try { 200 input = new BufferedInputStream(file.getContents(true)); 201 result.load(input); 202 } catch (CoreException e) { 203 String message = NLS.bind(Messages.preferences_loadException, file.getFullPath()); 204 log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, e)); 205 throw new BackingStoreException(message); 206 } catch (IOException e) { 207 String message = NLS.bind(Messages.preferences_loadException, file.getFullPath()); 208 log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, e)); 209 throw new BackingStoreException(message); 210 } finally { 211 FileUtil.safeClose(input); 212 } 213 return result; 214 } 215 216 private static void preferencesChanged(IProject project) { 217 Workspace workspace = ((Workspace) ResourcesPlugin.getWorkspace()); 218 workspace.getCharsetManager().projectPreferencesChanged(project); 219 workspace.getContentDescriptionManager().projectPreferencesChanged(project); 220 } 221 222 private static void read(ProjectPreferences node, IFile file) throws BackingStoreException, CoreException { 223 if (file == null || !file.exists()) { 224 if (Policy.DEBUG_PREFERENCES) 225 Policy.debug("Unable to determine preference file or file does not exist for node: " + node.absolutePath()); return; 227 } 228 Properties fromDisk = loadProperties(file); 229 if (fromDisk.isEmpty()) 231 return; 232 IExportedPreferences myNode = (IExportedPreferences) ExportedPreferences.newRoot().node(node.absolutePath()); 234 convertFromProperties((EclipsePreferences) myNode, fromDisk, false); 235 boolean oldIsReading = node.isReading; 237 node.isReading = true; 238 try { 239 Platform.getPreferencesService().applyPreferences(myNode); 240 } finally { 241 node.isReading = oldIsReading; 242 } 243 } 244 245 static void removeNode(Preferences node) throws CoreException { 246 String message = NLS.bind(Messages.preferences_removeNodeException, node.absolutePath()); 247 try { 248 node.removeNode(); 249 } catch (BackingStoreException e) { 250 IStatus status = new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, e); 251 throw new CoreException(status); 252 } 253 String path = node.absolutePath(); 254 for (Iterator i = loadedNodes.iterator(); i.hasNext();) { 255 String key = (String ) i.next(); 256 if (key.startsWith(path)) 257 i.remove(); 258 } 259 } 260 261 public static void updatePreferences(IFile file) throws CoreException { 262 IPath path = file.getFullPath(); 263 if (!PREFS_FILE_EXTENSION.equals(path.getFileExtension())) 266 return; 267 268 String project = path.segment(0); 269 String qualifier = path.removeFileExtension().lastSegment(); 270 Preferences root = Platform.getPreferencesService().getRootNode(); 271 Preferences node = root.node(ProjectScope.SCOPE).node(project).node(qualifier); 272 String message = null; 273 try { 274 message = NLS.bind(Messages.preferences_syncException, node.absolutePath()); 275 if (!(node instanceof ProjectPreferences)) 276 return; 277 ProjectPreferences projectPrefs = (ProjectPreferences) node; 278 if (projectPrefs.isWriting) 279 return; 280 read(projectPrefs, file); 281 if (ResourcesPlugin.PI_RESOURCES.equals(qualifier)) 284 preferencesChanged(file.getProject()); 285 } catch (BackingStoreException e) { 286 IStatus status = new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, e); 287 throw new CoreException(status); 288 } 289 } 290 291 294 public ProjectPreferences() { 295 super(null, null); 296 } 297 298 private ProjectPreferences(EclipsePreferences parent, String name) { 299 super(parent, name); 300 301 String path = absolutePath(); 303 segmentCount = getSegmentCount(path); 304 305 if (segmentCount == 1) 306 return; 307 308 String projectName = getSegment(path, 1); 310 if (projectName != null) 311 project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); 312 313 if (segmentCount > 2) 315 qualifier = getSegment(path, 2); 316 317 if (segmentCount != 2) 318 return; 319 320 if (initialized) 322 return; 323 try { 324 synchronized (this) { 325 String [] names = computeChildren(); 326 for (int i = 0; i < names.length; i++) 327 addChild(names[i], null); 328 } 329 } finally { 330 initialized = true; 331 } 332 } 333 334 338 private String [] computeChildren() { 339 if (project == null) 340 return EMPTY_STRING_ARRAY; 341 IFolder folder = project.getFolder(DEFAULT_PREFERENCES_DIRNAME); 342 if (!folder.exists()) 343 return EMPTY_STRING_ARRAY; 344 IResource[] members = null; 345 try { 346 members = folder.members(); 347 } catch (CoreException e) { 348 return EMPTY_STRING_ARRAY; 349 } 350 ArrayList result = new ArrayList(); 351 for (int i = 0; i < members.length; i++) { 352 IResource resource = members[i]; 353 if (resource.getType() == IResource.FILE && PREFS_FILE_EXTENSION.equals(resource.getFullPath().getFileExtension())) 354 result.add(resource.getFullPath().removeFileExtension().lastSegment()); 355 } 356 return (String []) result.toArray(EMPTY_STRING_ARRAY); 357 } 358 359 public void flush() throws BackingStoreException { 360 if (isReading) 361 return; 362 isWriting = true; 363 try { 364 super.flush(); 365 } finally { 366 isWriting = false; 367 } 368 } 369 370 private IFile getFile() { 371 if (file == null) { 372 if (project == null || qualifier == null) 373 return null; 374 file = getFile(project, qualifier); 375 } 376 return file; 377 } 378 379 382 protected IEclipsePreferences getLoadLevel() { 383 if (loadLevel == null) { 384 if (project == null || qualifier == null) 385 return null; 386 EclipsePreferences node = this; 390 for (int i = 3; i < segmentCount; i++) 391 node = (EclipsePreferences) node.parent(); 392 loadLevel = node; 393 } 394 return loadLevel; 395 } 396 397 405 protected IPath getLocation() { 406 if (project == null || qualifier == null) 407 return null; 408 IPath path = project.getLocation(); 409 return computeLocation(path, qualifier); 410 } 411 412 protected EclipsePreferences internalCreate(EclipsePreferences nodeParent, String nodeName, Object context) { 413 return new ProjectPreferences(nodeParent, nodeName); 414 } 415 416 protected boolean isAlreadyLoaded(IEclipsePreferences node) { 417 return loadedNodes.contains(node.absolutePath()); 418 } 419 420 protected boolean isAlreadyLoaded(String path) { 421 return loadedNodes.contains(path); 422 } 423 424 protected void load() throws BackingStoreException { 425 IFile localFile = getFile(); 426 if (localFile == null || !localFile.exists()) { 427 if (Policy.DEBUG_PREFERENCES) 428 Policy.debug("Unable to determine preference file or file does not exist for node: " + absolutePath()); return; 430 } 431 if (Policy.DEBUG_PREFERENCES) 432 Policy.debug("Loading preferences from file: " + localFile.getFullPath()); Properties fromDisk = new Properties(); 434 InputStream input = null; 435 try { 436 input = new BufferedInputStream(localFile.getContents(true)); 437 fromDisk.load(input); 438 } catch (CoreException e) { 439 String message = NLS.bind(Messages.preferences_loadException, localFile.getFullPath()); 440 log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, e)); 441 throw new BackingStoreException(message); 442 } catch (IOException e) { 443 String message = NLS.bind(Messages.preferences_loadException, localFile.getFullPath()); 444 log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, e)); 445 throw new BackingStoreException(message); 446 } finally { 447 FileUtil.safeClose(input); 448 } 449 convertFromProperties(this, fromDisk, true); 450 } 451 452 protected void loaded() { 453 loadedNodes.add(absolutePath()); 454 } 455 456 463 public boolean nodeExists(String path) throws BackingStoreException { 464 if (segmentCount != 1) 465 return super.nodeExists(path); 466 if (path.length() == 0) 467 return super.nodeExists(path); 468 if (path.charAt(0) == IPath.SEPARATOR) 469 return super.nodeExists(path); 470 if (path.indexOf(IPath.SEPARATOR) != -1) 471 return super.nodeExists(path); 472 return ResourcesPlugin.getWorkspace().getRoot().getProject(path).exists() || super.nodeExists(path); 475 } 476 477 protected void save() throws BackingStoreException { 478 final IFile fileInWorkspace = getFile(); 479 if (fileInWorkspace == null) { 480 if (Policy.DEBUG_PREFERENCES) 481 Policy.debug("Not saving preferences since there is no file for node: " + absolutePath()); return; 483 } 484 Properties table = convertToProperties(new SortedProperties(), ""); IWorkspace workspace = ResourcesPlugin.getWorkspace(); 486 IResourceRuleFactory factory = workspace.getRuleFactory(); 487 try { 488 if (table.isEmpty()) { 489 IWorkspaceRunnable operation = new IWorkspaceRunnable() { 490 public void run(IProgressMonitor monitor) throws CoreException { 491 if (fileInWorkspace.exists()) { 493 if (Policy.DEBUG_PREFERENCES) 494 Policy.debug("Deleting preference file: " + fileInWorkspace.getFullPath()); if (fileInWorkspace.isReadOnly()) { 496 IStatus status = fileInWorkspace.getWorkspace().validateEdit(new IFile[] {fileInWorkspace}, IWorkspace.VALIDATE_PROMPT); 497 if (!status.isOK()) 498 throw new CoreException(status); 499 } 500 try { 501 fileInWorkspace.delete(true, null); 502 } catch (CoreException e) { 503 String message = NLS.bind(Messages.preferences_deleteException, fileInWorkspace.getFullPath()); 504 log(new Status(IStatus.WARNING, ResourcesPlugin.PI_RESOURCES, IStatus.WARNING, message, null)); 505 } 506 } 507 } 508 }; 509 ISchedulingRule rule = factory.deleteRule(fileInWorkspace); 510 try { 511 ResourcesPlugin.getWorkspace().run(operation, rule, IResource.NONE, null); 512 } catch (OperationCanceledException e) { 513 throw new BackingStoreException(Messages.preferences_operationCanceled); 514 } 515 return; 516 } 517 table.put(VERSION_KEY, VERSION_VALUE); 518 ByteArrayOutputStream output = new ByteArrayOutputStream(); 519 try { 520 table.store(output, null); 521 } catch (IOException e) { 522 String message = NLS.bind(Messages.preferences_saveProblems, absolutePath()); 523 log(new Status(IStatus.ERROR, Platform.PI_RUNTIME, IStatus.ERROR, message, e)); 524 throw new BackingStoreException(message); 525 } finally { 526 try { 527 output.close(); 528 } catch (IOException e) { 529 } 531 } 532 final InputStream input = new BufferedInputStream(new ByteArrayInputStream(output.toByteArray())); 533 IWorkspaceRunnable operation = new IWorkspaceRunnable() { 534 public void run(IProgressMonitor monitor) throws CoreException { 535 if (fileInWorkspace.exists()) { 536 if (Policy.DEBUG_PREFERENCES) 537 Policy.debug("Setting preference file contents for: " + fileInWorkspace.getFullPath()); if (fileInWorkspace.isReadOnly()) { 539 IStatus status = fileInWorkspace.getWorkspace().validateEdit(new IFile[] {fileInWorkspace}, IWorkspace.VALIDATE_PROMPT); 540 if (!status.isOK()) 541 throw new CoreException(status); 542 } 543 fileInWorkspace.setContents(input, IResource.KEEP_HISTORY, null); 545 } else { 546 IFolder folder = (IFolder) fileInWorkspace.getParent(); 548 if (!folder.exists()) { 549 if (Policy.DEBUG_PREFERENCES) 550 Policy.debug("Creating parent preference directory: " + folder.getFullPath()); folder.create(IResource.NONE, true, null); 552 } 553 if (Policy.DEBUG_PREFERENCES) 554 Policy.debug("Creating preference file: " + fileInWorkspace.getLocation()); fileInWorkspace.create(input, IResource.NONE, null); 556 } 557 } 558 }; 559 try { 561 if (((Workspace) workspace).getWorkManager().isLockAlreadyAcquired()) { 562 operation.run(null); 563 } else { 564 ISchedulingRule rule = MultiRule.combine(factory.createRule(fileInWorkspace.getParent()), factory.modifyRule(fileInWorkspace)); 566 workspace.run(operation, rule, IResource.NONE, null); 567 } 568 } catch (OperationCanceledException e) { 569 throw new BackingStoreException(Messages.preferences_operationCanceled); 570 } 571 } catch (CoreException e) { 572 String message = NLS.bind(Messages.preferences_saveProblems, fileInWorkspace.getFullPath()); 573 log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, e)); 574 throw new BackingStoreException(message); 575 } 576 } 577 } 578 | Popular Tags |