KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > resources > Resource


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  * Dan Rubel <dan_rubel@instantiations.com> - Implementation of getLocalTimeStamp
11  * Red Hat Incorporated - get/setResourceAttribute code
12  *******************************************************************************/

13 package org.eclipse.core.internal.resources;
14
15 import java.net.URI JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import org.eclipse.core.filesystem.*;
19 import org.eclipse.core.internal.events.LifecycleEvent;
20 import org.eclipse.core.internal.localstore.FileSystemResourceManager;
21 import org.eclipse.core.internal.properties.IPropertyManager;
22 import org.eclipse.core.internal.utils.*;
23 import org.eclipse.core.internal.watson.*;
24 import org.eclipse.core.resources.*;
25 import org.eclipse.core.resources.team.IMoveDeleteHook;
26 import org.eclipse.core.runtime.*;
27 import org.eclipse.core.runtime.jobs.ISchedulingRule;
28 import org.eclipse.core.runtime.jobs.MultiRule;
29 import org.eclipse.osgi.util.NLS;
30
31 public abstract class Resource extends PlatformObject implements IResource, ICoreConstants, Cloneable JavaDoc, IPathRequestor {
32     /* package */IPath path;
33     /* package */Workspace workspace;
34
35     protected Resource(IPath path, Workspace workspace) {
36         this.path = path.removeTrailingSeparator();
37         this.workspace = workspace;
38     }
39
40     /* (non-Javadoc)
41      * @see IResource#accept(IResourceProxyVisitor, int)
42      */

43     public void accept(final IResourceProxyVisitor visitor, final int memberFlags) throws CoreException {
44         // it is invalid to call accept on a phantom when INCLUDE_PHANTOMS is not specified
45
final boolean includePhantoms = (memberFlags & IContainer.INCLUDE_PHANTOMS) != 0;
46         checkAccessible(getFlags(getResourceInfo(includePhantoms, false)));
47
48         final ResourceProxy proxy = new ResourceProxy();
49         IElementContentVisitor elementVisitor = new IElementContentVisitor() {
50             public boolean visitElement(ElementTree tree, IPathRequestor requestor, Object JavaDoc contents) {
51                 ResourceInfo info = (ResourceInfo) contents;
52                 if (!isMember(getFlags(info), memberFlags))
53                     return false;
54                 proxy.requestor = requestor;
55                 proxy.info = info;
56                 try {
57                     return visitor.visit(proxy);
58                 } catch (CoreException e) {
59                     //throw an exception to bail out of the traversal
60
throw new WrappedRuntimeException(e);
61                 } finally {
62                     proxy.reset();
63                 }
64             }
65         };
66         try {
67             new ElementTreeIterator(workspace.getElementTree(), getFullPath()).iterate(elementVisitor);
68         } catch (WrappedRuntimeException e) {
69             throw (CoreException) e.getTargetException();
70         } catch (OperationCanceledException e) {
71             throw e;
72         } catch (RuntimeException JavaDoc e) {
73             String JavaDoc msg = Messages.resources_errorVisiting;
74             IResourceStatus errorStatus = new ResourceStatus(IResourceStatus.INTERNAL_ERROR, getFullPath(), msg, e);
75             Policy.log(errorStatus);
76             throw new ResourceException(errorStatus);
77         } finally {
78             proxy.requestor = null;
79             proxy.info = null;
80         }
81     }
82
83     /* (non-Javadoc)
84      * @see IResource#accept(IResourceVisitor)
85      */

86     public void accept(IResourceVisitor visitor) throws CoreException {
87         accept(visitor, IResource.DEPTH_INFINITE, 0);
88     }
89
90     /* (non-Javadoc)
91      * @see IResource#accept(IResourceVisitor, int, boolean)
92      */

93     public void accept(IResourceVisitor visitor, int depth, boolean includePhantoms) throws CoreException {
94         accept(visitor, depth, includePhantoms ? IContainer.INCLUDE_PHANTOMS : 0);
95     }
96
97     /* (non-Javadoc)
98      * @see IResource#accept(IResourceVisitor, int, int)
99      */

100     public void accept(final IResourceVisitor visitor, int depth, int memberFlags) throws CoreException {
101         //use the fast visitor if visiting to infinite depth
102
if (depth == IResource.DEPTH_INFINITE) {
103             accept(new IResourceProxyVisitor() {
104                 public boolean visit(IResourceProxy proxy) throws CoreException {
105                     return visitor.visit(proxy.requestResource());
106                 }
107             }, memberFlags);
108             return;
109         }
110         // it is invalid to call accept on a phantom when INCLUDE_PHANTOMS is not specified
111
final boolean includePhantoms = (memberFlags & IContainer.INCLUDE_PHANTOMS) != 0;
112         ResourceInfo info = getResourceInfo(includePhantoms, false);
113         int flags = getFlags(info);
114         checkAccessible(flags);
115
116         //check that this resource matches the member flags
117
if (!isMember(flags, memberFlags))
118             return;
119         // visit this resource
120
if (!visitor.visit(this) || depth == DEPTH_ZERO)
121             return;
122         // get the info again because it might have been changed by the visitor
123
info = getResourceInfo(includePhantoms, false);
124         if (info == null)
125             return;
126         // thread safety: (cache the type to avoid changes -- we might not be inside an operation)
127
int type = info.getType();
128         if (type == FILE)
129             return;
130         // if we had a gender change we need to fix up the resource before asking for its members
131
IContainer resource = getType() != type ? (IContainer) workspace.newResource(getFullPath(), type) : (IContainer) this;
132         IResource[] members = resource.members(memberFlags);
133         for (int i = 0; i < members.length; i++)
134             members[i].accept(visitor, DEPTH_ZERO, memberFlags);
135     }
136
137     protected void assertCopyRequirements(IPath destination, int destinationType, int updateFlags) throws CoreException {
138         IStatus status = checkCopyRequirements(destination, destinationType, updateFlags);
139         if (!status.isOK()) {
140             // this assert is ok because the error cases generated by the
141
// check method above indicate assertion conditions.
142
Assert.isTrue(false, status.getChildren()[0].getMessage());
143         }
144     }
145
146     /**
147      * Throws an exception if the link preconditions are not met. Returns the file info
148      * for the file being linked to, or <code>null</code> if not available.
149      * @throws CoreException
150      */

151     protected IFileInfo assertLinkRequirements(URI JavaDoc localLocation, int updateFlags) throws CoreException {
152         boolean allowMissingLocal = (updateFlags & IResource.ALLOW_MISSING_LOCAL) != 0;
153         if ((updateFlags & IResource.REPLACE) == 0)
154             checkDoesNotExist(getFlags(getResourceInfo(false, false)), true);
155         IStatus locationStatus = workspace.validateLinkLocationURI(this, localLocation);
156         //we only tolerate an undefined path variable in the allow missing local case
157
final boolean variableUndefined = locationStatus.getCode() == IResourceStatus.VARIABLE_NOT_DEFINED_WARNING;
158         if (locationStatus.getSeverity() == IStatus.ERROR || (variableUndefined && !allowMissingLocal))
159             throw new ResourceException(locationStatus);
160         //check that the parent exists and is open
161
Container parent = (Container) getParent();
162         parent.checkAccessible(getFlags(parent.getResourceInfo(false, false)));
163         //if the variable is undefined we can't do any further checks
164
if (variableUndefined)
165             return null;
166         //check if the file exists
167
URI JavaDoc resolved = workspace.getPathVariableManager().resolveURI(localLocation);
168         IFileStore store = EFS.getStore(resolved);
169         IFileInfo fileInfo = store.fetchInfo();
170         boolean localExists = fileInfo.exists();
171         if (!allowMissingLocal && !localExists) {
172             String JavaDoc msg = NLS.bind(Messages.links_localDoesNotExist, store.toString());
173             throw new ResourceException(IResourceStatus.NOT_FOUND_LOCAL, getFullPath(), msg, null);
174         }
175         //resource type and file system type must match
176
if (localExists && ((getType() == IResource.FOLDER) != fileInfo.isDirectory())) {
177             String JavaDoc msg = NLS.bind(Messages.links_wrongLocalType, getFullPath());
178             throw new ResourceException(IResourceStatus.WRONG_TYPE_LOCAL, getFullPath(), msg, null);
179         }
180         return fileInfo;
181     }
182
183     protected void assertMoveRequirements(IPath destination, int destinationType, int updateFlags) throws CoreException {
184         IStatus status = checkMoveRequirements(destination, destinationType, updateFlags);
185         if (!status.isOK()) {
186             // this assert is ok because the error cases generated by the
187
// check method above indicate assertion conditions.
188
Assert.isTrue(false, status.getChildren()[0].getMessage());
189         }
190     }
191
192     public void checkAccessible(int flags) throws CoreException {
193         checkExists(flags, true);
194     }
195
196     /**
197      * This method reports errors in two different ways. It can throw a
198      * CoreException or return a status. CoreExceptions are used according to the
199      * specification of the copy method. Programming errors, that would usually be
200      * prevented by using an "Assert" code, are reported as an IStatus. We're doing
201      * this way because we have two different methods to copy resources:
202      * IResource#copy and IWorkspace#copy. The first one gets the error and throws
203      * its message in an AssertionFailureException. The second one just throws a
204      * CoreException using the status returned by this method.
205      *
206      * @see IResource#copy(IPath, int, IProgressMonitor)
207      */

208     public IStatus checkCopyRequirements(IPath destination, int destinationType, int updateFlags) throws CoreException {
209         String JavaDoc message = Messages.resources_copyNotMet;
210         MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INVALID_VALUE, message, null);
211         if (destination == null) {
212             message = Messages.resources_destNotNull;
213             return new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message);
214         }
215         destination = makePathAbsolute(destination);
216         if (getFullPath().isPrefixOf(destination)) {
217             message = NLS.bind(Messages.resources_copyDestNotSub, getFullPath());
218             status.add(new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message));
219         }
220         checkValidPath(destination, destinationType, false);
221
222         ResourceInfo info = getResourceInfo(false, false);
223         int flags = getFlags(info);
224         checkAccessible(flags);
225         checkLocal(flags, DEPTH_INFINITE);
226
227         Resource dest = workspace.newResource(destination, destinationType);
228         dest.checkDoesNotExist();
229
230         // ensure we aren't trying to copy a file to a project
231
if (getType() == IResource.FILE && destinationType == IResource.PROJECT) {
232             message = Messages.resources_fileToProj;
233             throw new ResourceException(IResourceStatus.INVALID_VALUE, getFullPath(), message, null);
234         }
235
236         // we can't copy into a closed project
237
if (destinationType != IResource.PROJECT) {
238             Project project = (Project) dest.getProject();
239             info = project.getResourceInfo(false, false);
240             project.checkAccessible(getFlags(info));
241             Container parent = (Container) dest.getParent();
242             if (!parent.equals(project)) {
243                 info = parent.getResourceInfo(false, false);
244                 parent.checkExists(getFlags(info), true);
245             }
246         }
247         if (isUnderLink() || dest.isUnderLink()) {
248             //make sure location is not null. This can occur with linked resources relative to
249
//undefined path variables
250
URI JavaDoc sourceLocation = getLocationURI();
251             if (sourceLocation == null) {
252                 message = NLS.bind(Messages.localstore_locationUndefined, getFullPath());
253                 throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL, getFullPath(), message, null);
254             }
255             URI JavaDoc destLocation = dest.getLocationURI();
256             if (destLocation == null) {
257                 message = NLS.bind(Messages.localstore_locationUndefined, dest.getFullPath());
258                 throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL, dest.getFullPath(), message, null);
259             }
260             //make sure location of source is not a prefix of the location of the destination
261
//this can occur if the source and/or destination is a linked resource
262
if (getStore().isParentOf(dest.getStore())) {
263                 message = NLS.bind(Messages.resources_copyDestNotSub, getFullPath());
264                 throw new ResourceException(IResourceStatus.INVALID_VALUE, getFullPath(), message, null);
265             }
266         }
267
268         return status.isOK() ? Status.OK_STATUS : (IStatus) status;
269     }
270
271     /**
272      * Checks that this resource does not exist. If the file system is not case
273      * sensitive, this method also checks for a case variant.
274      */

275     protected void checkDoesNotExist() throws CoreException {
276         checkDoesNotExist(getFlags(getResourceInfo(false, false)), false);
277     }
278
279     /**
280      * Checks that this resource does not exist. If the file system is not case
281      * sensitive, this method also checks for a case variant.
282      *
283      * @exception CoreException if this resource exists
284      */

285     public void checkDoesNotExist(int flags, boolean checkType) throws CoreException {
286         //if this exact resource exists we are done
287
if (exists(flags, checkType)) {
288             String JavaDoc message = NLS.bind(Messages.resources_mustNotExist, getFullPath());
289             throw new ResourceException(checkType ? IResourceStatus.RESOURCE_EXISTS : IResourceStatus.PATH_OCCUPIED, getFullPath(), message, null);
290         }
291         if (Workspace.caseSensitive)
292             return;
293         //now look for a matching case variant in the tree
294
IResource variant = findExistingResourceVariant(getFullPath());
295         if (variant == null)
296             return;
297         String JavaDoc msg = NLS.bind(Messages.resources_existsDifferentCase, variant.getFullPath());
298         throw new ResourceException(IResourceStatus.CASE_VARIANT_EXISTS, variant.getFullPath(), msg, null);
299     }
300
301     /**
302      * Checks that this resource exists.
303      * If checkType is true, the type of this resource and the one in the tree must match.
304      *
305      * @exception CoreException if this resource does not exist
306      */

307     public void checkExists(int flags, boolean checkType) throws CoreException {
308         if (!exists(flags, checkType)) {
309             String JavaDoc message = NLS.bind(Messages.resources_mustExist, getFullPath());
310             throw new ResourceException(IResourceStatus.RESOURCE_NOT_FOUND, getFullPath(), message, null);
311         }
312     }
313
314     /**
315      * Checks that this resource is local to the given depth.
316      *
317      * @exception CoreException if this resource is not local
318      */

319     public void checkLocal(int flags, int depth) throws CoreException {
320         if (!isLocal(flags, depth)) {
321             String JavaDoc message = NLS.bind(Messages.resources_mustBeLocal, getFullPath());
322             throw new ResourceException(IResourceStatus.RESOURCE_NOT_LOCAL, getFullPath(), message, null);
323         }
324     }
325
326     /**
327      * This method reports errors in two different ways. It can throw a
328      * CoreException or log a status. CoreExceptions are used according
329      * to the specification of the move method. Programming errors, that
330      * would usually be prevented by using an "Assert" code, are reported as
331      * an IStatus.
332      * We're doing this way because we have two different methods to move
333      * resources: IResource#move and IWorkspace#move. The first one gets
334      * the error and throws its message in an AssertionFailureException. The
335      * second one just throws a CoreException using the status returned
336      * by this method.
337      *
338      * @see IResource#move(IPath, int, IProgressMonitor)
339      */

340     protected IStatus checkMoveRequirements(IPath destination, int destinationType, int updateFlags) throws CoreException {
341         String JavaDoc message = Messages.resources_moveNotMet;
342         MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INVALID_VALUE, message, null);
343         if (destination == null) {
344             message = Messages.resources_destNotNull;
345             return new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message);
346         }
347         destination = makePathAbsolute(destination);
348         if (getFullPath().isPrefixOf(destination)) {
349             message = NLS.bind(Messages.resources_moveDestNotSub, getFullPath());
350             status.add(new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message));
351         }
352         checkValidPath(destination, destinationType, false);
353
354         ResourceInfo info = getResourceInfo(false, false);
355         int flags = getFlags(info);
356         checkAccessible(flags);
357         checkLocal(flags, DEPTH_INFINITE);
358
359         Resource dest = workspace.newResource(destination, destinationType);
360
361         // check if we are only changing case
362
IResource variant = Workspace.caseSensitive ? null : findExistingResourceVariant(destination);
363         if (variant == null || !this.equals(variant))
364             dest.checkDoesNotExist();
365
366         // ensure we aren't trying to move a file to a project
367
if (getType() == IResource.FILE && dest.getType() == IResource.PROJECT) {
368             message = Messages.resources_fileToProj;
369             throw new ResourceException(new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message));
370         }
371
372         // we can't move into a closed project
373
if (destinationType != IResource.PROJECT) {
374             Project project = (Project) dest.getProject();
375             info = project.getResourceInfo(false, false);
376             project.checkAccessible(getFlags(info));
377             Container parent = (Container) dest.getParent();
378             if (!parent.equals(project)) {
379                 info = parent.getResourceInfo(false, false);
380                 parent.checkExists(getFlags(info), true);
381             }
382         }
383         if (isUnderLink() || dest.isUnderLink()) {
384             //make sure location is not null. This can occur with linked resources relative to
385
//undefined path variables
386
URI JavaDoc sourceLocation = getLocationURI();
387             if (sourceLocation == null) {
388                 message = NLS.bind(Messages.localstore_locationUndefined, getFullPath());
389                 throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL, getFullPath(), message, null);
390             }
391             URI JavaDoc destLocation = dest.getLocationURI();
392             if (destLocation == null) {
393                 message = NLS.bind(Messages.localstore_locationUndefined, dest.getFullPath());
394                 throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL, dest.getFullPath(), message, null);
395             }
396             //make sure location of source is not a prefix of the location of the destination
397
//this can occur if the source and/or destination is a linked resource
398
if (getStore().isParentOf(dest.getStore())) {
399                 message = NLS.bind(Messages.resources_moveDestNotSub, getFullPath());
400                 throw new ResourceException(IResourceStatus.INVALID_VALUE, getFullPath(), message, null);
401             }
402         }
403
404         return status.isOK() ? Status.OK_STATUS : (IStatus) status;
405     }
406
407     /**
408      * Checks that the supplied path is valid according to Workspace.validatePath().
409      *
410      * @exception CoreException if the path is not valid
411      */

412     public void checkValidPath(IPath toValidate, int type, boolean lastSegmentOnly) throws CoreException {
413         IStatus result = workspace.locationValidator.validatePath(toValidate, type, lastSegmentOnly);
414         if (!result.isOK())
415             throw new ResourceException(result);
416     }
417
418     /* (non-Javadoc)
419      * @see IResource#clearHistory(IProgressMonitor)
420      */

421     public void clearHistory(IProgressMonitor monitor) {
422         getLocalManager().getHistoryStore().remove(getFullPath(), monitor);
423     }
424
425     /*
426      * (non-Javadoc)
427      * @see ISchedulingRule#contains(ISchedulingRule)
428      */

429     public boolean contains(ISchedulingRule rule) {
430         if (this == rule)
431             return true;
432         //must allow notifications to nest in all resource rules
433
if (rule.getClass().equals(WorkManager.NotifyRule.class))
434             return true;
435         if (rule instanceof MultiRule) {
436             MultiRule multi = (MultiRule) rule;
437             ISchedulingRule[] children = multi.getChildren();
438             for (int i = 0; i < children.length; i++)
439                 if (!contains(children[i]))
440                     return false;
441             return true;
442         }
443         if (!(rule instanceof IResource))
444             return false;
445         return path.isPrefixOf(((IResource) rule).getFullPath());
446     }
447
448     public void convertToPhantom() throws CoreException {
449         ResourceInfo info = getResourceInfo(false, true);
450         if (info == null || isPhantom(getFlags(info)))
451             return;
452         info.clearSessionProperties();
453         info.set(M_PHANTOM);
454         getLocalManager().updateLocalSync(info, I_NULL_SYNC_INFO);
455         info.clearModificationStamp();
456         // should already be done by the #deleteResource call but left in
457
// just to be safe and for code clarity.
458
info.setMarkers(null);
459     }
460
461     /* (non-Javadoc)
462      * @see IResource#copy(IPath, boolean, IProgressMonitor)
463      */

464     public void copy(IPath destination, boolean force, IProgressMonitor monitor) throws CoreException {
465         int updateFlags = force ? IResource.FORCE : IResource.NONE;
466         copy(destination, updateFlags, monitor);
467     }
468
469     /* (non-Javadoc)
470      * @see IResource#copy(IPath, int, IProgressMonitor)
471      */

472     public void copy(IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException {
473         try {
474             monitor = Policy.monitorFor(monitor);
475             String JavaDoc message = NLS.bind(Messages.resources_copying, getFullPath());
476             monitor.beginTask(message, Policy.totalWork);
477             Policy.checkCanceled(monitor);
478             destination = makePathAbsolute(destination);
479             checkValidPath(destination, getType(), false);
480             Resource destResource = workspace.newResource(destination, getType());
481             final ISchedulingRule rule = workspace.getRuleFactory().copyRule(this, destResource);
482             try {
483                 workspace.prepareOperation(rule, monitor);
484                 // The following assert method throws CoreExceptions as stated in the IResource.copy API
485
// and assert for programming errors. See checkCopyRequirements for more information.
486
assertCopyRequirements(destination, getType(), updateFlags);
487                 workspace.beginOperation(true);
488                 getLocalManager().copy(this, destResource, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork));
489             } catch (OperationCanceledException e) {
490                 workspace.getWorkManager().operationCanceled();
491                 throw e;
492             } finally {
493                 workspace.endOperation(rule, true, Policy.subMonitorFor(monitor, Policy.endOpWork));
494             }
495         } finally {
496             monitor.done();
497         }
498     }
499
500     /* (non-Javadoc)
501      * @see IResource#copy(IProjectDescription, boolean, IProgressMonitor)
502      */

503     public void copy(IProjectDescription destDesc, boolean force, IProgressMonitor monitor) throws CoreException {
504         int updateFlags = force ? IResource.FORCE : IResource.NONE;
505         copy(destDesc, updateFlags, monitor);
506     }
507
508     /* (non-Javadoc)
509      * Used when a folder is to be copied to a project.
510      * @see IResource#copy(IProjectDescription, int, IProgressMonitor)
511      */

512     public void copy(IProjectDescription destDesc, int updateFlags, IProgressMonitor monitor) throws CoreException {
513         Assert.isNotNull(destDesc);
514         monitor = Policy.monitorFor(monitor);
515         try {
516             String JavaDoc message = NLS.bind(Messages.resources_copying, getFullPath());
517             monitor.beginTask(message, Policy.totalWork);
518             try {
519                 workspace.prepareOperation(workspace.getRoot(), monitor);
520                 // The following assert method throws CoreExceptions as stated in the IResource.copy API
521
// and assert for programming errors. See checkCopyRequirements for more information.
522
IPath destPath = new Path(destDesc.getName()).makeAbsolute();
523                 assertCopyRequirements(destPath, getType(), updateFlags);
524                 Project destProject = (Project) workspace.getRoot().getProject(destPath.lastSegment());
525                 workspace.beginOperation(true);
526
527                 // create and open the new project
528
destProject.create(destDesc, Policy.subMonitorFor(monitor, Policy.opWork * 5 / 100));
529                 destProject.open(Policy.subMonitorFor(monitor, Policy.opWork * 5 / 100));
530
531                 // copy the children
532
// FIXME: fix the progress monitor here...create a sub monitor and do a worked(1) after each child instead
533
IResource[] children = ((IContainer) this).members(IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS);
534                 for (int i = 0; i < children.length; i++) {
535                     Resource child = (Resource) children[i];
536                     child.copy(destPath.append(child.getName()), updateFlags, Policy.subMonitorFor(monitor, Policy.opWork * 60 / 100 / children.length));
537                 }
538
539                 // copy over the properties
540
getPropertyManager().copy(this, destProject, DEPTH_ZERO);
541                 monitor.worked(Policy.opWork * 15 / 100);
542
543             } catch (OperationCanceledException e) {
544                 workspace.getWorkManager().operationCanceled();
545                 throw e;
546             } finally {
547                 workspace.endOperation(workspace.getRoot(), true, Policy.subMonitorFor(monitor, Policy.endOpWork));
548             }
549         } finally {
550             monitor.done();
551         }
552     }
553
554     /**
555      * Count the number of resources in the tree from this container to the
556      * specified depth. Include this resource. Include phantoms if
557      * the phantom boolean is true.
558      */

559     public int countResources(int depth, boolean phantom) {
560         return workspace.countResources(path, depth, phantom);
561     }
562
563     /* (non-Javadoc)
564      * @see org.eclipse.core.resources.IFolder#createLink(IPath, int, IProgressMonitor)
565      * @see org.eclipse.core.resources.IFile#createLink(IPath, int, IProgressMonitor)
566      */

567     public void createLink(IPath localLocation, int updateFlags, IProgressMonitor monitor) throws CoreException {
568         Assert.isNotNull(localLocation);
569         createLink(URIUtil.toURI(localLocation), updateFlags, monitor);
570     }
571
572     /* (non-Javadoc)
573      * @see org.eclipse.core.resources.IFolder#createLink(URI, int, IProgressMonitor)
574      * @see org.eclipse.core.resources.IFile#createLink(URI, int, IProgressMonitor)
575      */

576     public void createLink(URI JavaDoc localLocation, int updateFlags, IProgressMonitor monitor) throws CoreException {
577         Assert.isNotNull(localLocation);
578         monitor = Policy.monitorFor(monitor);
579         try {
580             String JavaDoc message = NLS.bind(Messages.links_creating, getFullPath());
581             monitor.beginTask(message, Policy.totalWork);
582             Policy.checkCanceled(monitor);
583             checkValidPath(path, FOLDER, true);
584             final ISchedulingRule rule = workspace.getRuleFactory().createRule(this);
585             try {
586                 workspace.prepareOperation(rule, monitor);
587                 IFileInfo fileInfo = assertLinkRequirements(localLocation, updateFlags);
588                 workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_LINK_CREATE, this));
589                 workspace.beginOperation(true);
590                 //replace existing resource, if applicable
591
if ((updateFlags & REPLACE) != 0) {
592                     IResource existing = workspace.getRoot().findMember(getFullPath());
593                     if (existing != null)
594                         workspace.deleteResource(existing);
595                 }
596                 ResourceInfo info = workspace.createResource(this, false);
597                 info.set(M_LINK);
598                 localLocation = FileUtil.canonicalURI(localLocation);
599                 getLocalManager().link(this, localLocation, fileInfo);
600                 monitor.worked(Policy.opWork * 5 / 100);
601                 //save the location in the project description
602
Project project = (Project) getProject();
603                 project.internalGetDescription().setLinkLocation(getProjectRelativePath(), new LinkDescription(this, localLocation));
604                 project.writeDescription(IResource.NONE);
605                 monitor.worked(Policy.opWork * 5 / 100);
606
607                 //refresh to discover any new resources below this linked location
608
if (getType() != IResource.FILE) {
609                     //refresh either in background or foreground
610
if ((updateFlags & IResource.BACKGROUND_REFRESH) != 0) {
611                         workspace.refreshManager.refresh(this);
612                         monitor.worked(Policy.opWork * 90 / 100);
613                     } else {
614                         refreshLocal(DEPTH_INFINITE, Policy.subMonitorFor(monitor, Policy.opWork * 90 / 100));
615                     }
616                 } else
617                     monitor.worked(Policy.opWork * 90 / 100);
618             } catch (OperationCanceledException e) {
619                 workspace.getWorkManager().operationCanceled();
620                 throw e;
621             } finally {
622                 workspace.endOperation(rule, true, Policy.subMonitorFor(monitor, Policy.endOpWork));
623             }
624         } finally {
625             monitor.done();
626         }
627     }
628
629     /* (non-Javadoc)
630      * @see IResource#createMarker(String)
631      */

632     public IMarker createMarker(String JavaDoc type) throws CoreException {
633         Assert.isNotNull(type);
634         final ISchedulingRule rule = workspace.getRuleFactory().markerRule(this);
635         try {
636             workspace.prepareOperation(rule, null);
637             checkAccessible(getFlags(getResourceInfo(false, false)));
638             workspace.beginOperation(true);
639             MarkerInfo info = new MarkerInfo();
640             info.setType(type);
641             info.setCreationTime(System.currentTimeMillis());
642             workspace.getMarkerManager().add(this, info);
643             return new Marker(this, info.getId());
644         } finally {
645             workspace.endOperation(rule, false, null);
646         }
647     }
648
649     public IResourceProxy createProxy() {
650         ResourceProxy result = new ResourceProxy();
651         result.info = getResourceInfo(false, false);
652         result.requestor = this;
653         result.resource = this;
654         return result;
655     }
656
657     /* (non-Javadoc)
658      * @see IProject#delete(boolean, boolean, IProgressMonitor)
659      * @see IWorkspaceRoot#delete(boolean, boolean, IProgressMonitor)
660      * N.B. This is not an IResource method!
661      */

662     public void delete(boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException {
663         int updateFlags = force ? IResource.FORCE : IResource.NONE;
664         updateFlags |= keepHistory ? IResource.KEEP_HISTORY : IResource.NONE;
665         delete(updateFlags, monitor);
666     }
667
668     /* (non-Javadoc)
669      * @see IResource#delete(boolean, IProgressMonitor)
670      */

671     public void delete(boolean force, IProgressMonitor monitor) throws CoreException {
672         delete(force ? IResource.FORCE : IResource.NONE, monitor);
673     }
674
675     /* (non-Javadoc)
676      * @see IResource#delete(int, IProgressMonitor)
677      */

678     public void delete(int updateFlags, IProgressMonitor monitor) throws CoreException {
679         monitor = Policy.monitorFor(monitor);
680         try {
681             String JavaDoc message = NLS.bind(Messages.resources_deleting, getFullPath());
682             monitor.beginTask("", Policy.totalWork * 1000); //$NON-NLS-1$
683
monitor.subTask(message);
684             final ISchedulingRule rule = workspace.getRuleFactory().deleteRule(this);
685             try {
686                 workspace.prepareOperation(rule, monitor);
687                 // if there is no resource then there is nothing to delete so just return
688
if (!exists())
689                     return;
690                 workspace.beginOperation(true);
691                 final IFileStore originalStore = getStore();
692                 boolean wasLinked = isLinked();
693                 message = Messages.resources_deleteProblem;
694                 MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.FAILED_DELETE_LOCAL, message, null);
695                 WorkManager workManager = workspace.getWorkManager();
696                 ResourceTree tree = new ResourceTree(workspace.getFileSystemManager(), workManager.getLock(), status, updateFlags);
697                 int depth = 0;
698                 try {
699                     depth = workManager.beginUnprotected();
700                     unprotectedDelete(tree, updateFlags, monitor);
701                 } finally {
702                     workManager.endUnprotected(depth);
703                 }
704                 if (getType() == ROOT) {
705                     // need to clear out the root info
706
workspace.getMarkerManager().removeMarkers(this, IResource.DEPTH_ZERO);
707                     getPropertyManager().deleteProperties(this, IResource.DEPTH_ZERO);
708                     getResourceInfo(false, false).clearSessionProperties();
709                 }
710                 // Invalidate the tree for further use by clients.
711
tree.makeInvalid();
712                 if (!tree.getStatus().isOK())
713                     throw new ResourceException(tree.getStatus());
714                 //update any aliases of this resource
715
//note that deletion of a linked resource cannot affect other resources
716
if (!wasLinked)
717                     workspace.getAliasManager().updateAliases(this, originalStore, IResource.DEPTH_INFINITE, monitor);
718                 //make sure the rule factory is cleared on project deletion
719
if (getType() == PROJECT)
720                     ((Rules) workspace.getRuleFactory()).setRuleFactory((IProject) this, null);
721             } catch (OperationCanceledException e) {
722                 workspace.getWorkManager().operationCanceled();
723                 throw e;
724             } finally {
725                 workspace.endOperation(rule, true, Policy.subMonitorFor(monitor, Policy.endOpWork * 1000));
726             }
727         } finally {
728             monitor.done();
729         }
730     }
731
732     /* (non-Javadoc)
733      * @see IResource#deleteMarkers(String, boolean, int)
734      */

735     public void deleteMarkers(String JavaDoc type, boolean includeSubtypes, int depth) throws CoreException {
736         final ISchedulingRule rule = workspace.getRuleFactory().markerRule(this);
737         try {
738             workspace.prepareOperation(rule, null);
739             ResourceInfo info = getResourceInfo(false, false);
740             checkAccessible(getFlags(info));
741
742             workspace.beginOperation(true);
743             workspace.getMarkerManager().removeMarkers(this, type, includeSubtypes, depth);
744         } finally {
745             workspace.endOperation(rule, false, null);
746         }
747     }
748
749     /**
750      * This method should be called to delete a resource from the tree because it will also
751      * delete its properties and markers. If a status object is provided, minor exceptions are
752      * added, otherwise they are thrown. If major exceptions occur, they are always thrown.
753      */

754     public void deleteResource(boolean convertToPhantom, MultiStatus status) throws CoreException {
755         // remove markers on this resource and its descendents
756
if (exists())
757             getMarkerManager().removeMarkers(this, IResource.DEPTH_INFINITE);
758         // if this is a linked resource, remove the entry from the project description
759
final boolean wasLinked = isLinked();
760         //pre-delete notification to internal infrastructure
761
if (wasLinked)
762             workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_LINK_DELETE, this));
763
764         // check if we deleted a preferences file
765
ProjectPreferences.deleted(this);
766
767         /* if we are synchronizing, do not delete the resource. Convert it
768          into a phantom. Actual deletion will happen when we refresh or push. */

769         if (convertToPhantom && getType() != PROJECT && synchronizing(getResourceInfo(true, false)))
770             convertToPhantom();
771         else
772             workspace.deleteResource(this);
773
774         //update project description for linked resource
775
if (wasLinked) {
776             Project project = (Project) getProject();
777             ProjectDescription description = project.internalGetDescription();
778             description.setLinkLocation(getProjectRelativePath(), null);
779             project.internalSetDescription(description, true);
780             project.writeDescription(IResource.FORCE);
781         }
782
783         // Delete properties after the resource is deleted from the tree. See bug 84584.
784
CoreException err = null;
785         try {
786             getPropertyManager().deleteResource(this);
787         } catch (CoreException e) {
788             if (status != null)
789                 status.add(e.getStatus());
790             else
791                 err = e;
792         }
793         if (err != null)
794             throw err;
795     }
796
797     /* (non-Javadoc)
798      * @see IResource#equals(Object)
799      */

800     public boolean equals(Object JavaDoc target) {
801         if (this == target)
802             return true;
803         if (!(target instanceof Resource))
804             return false;
805         Resource resource = (Resource) target;
806         return getType() == resource.getType() && path.equals(resource.path) && workspace.equals(resource.workspace);
807     }
808
809     /* (non-Javadoc)
810      * @see IResource#exists()
811      */

812     public boolean exists() {
813         ResourceInfo info = getResourceInfo(false, false);
814         return exists(getFlags(info), true);
815     }
816
817     public boolean exists(int flags, boolean checkType) {
818         return flags != NULL_FLAG && !(checkType && ResourceInfo.getType(flags) != getType());
819     }
820
821     /**
822      * Helper method for case insensitive file systems. Returns
823      * an existing resource whose path differs only in case from
824      * the given path, or null if no such resource exists.
825      */

826     public IResource findExistingResourceVariant(IPath target) {
827         if (!workspace.tree.includesIgnoreCase(target))
828             return null;
829         //ignore phantoms
830
ResourceInfo info = (ResourceInfo) workspace.tree.getElementDataIgnoreCase(target);
831         if (info != null && info.isSet(M_PHANTOM))
832             return null;
833         //resort to slow lookup to find exact case variant
834
IPath result = Path.ROOT;
835         int segmentCount = target.segmentCount();
836         for (int i = 0; i < segmentCount; i++) {
837             String JavaDoc[] childNames = workspace.tree.getNamesOfChildren(result);
838             String JavaDoc name = findVariant(target.segment(i), childNames);
839             if (name == null)
840                 return null;
841             result = result.append(name);
842         }
843         return workspace.getRoot().findMember(result);
844     }
845
846     /* (non-Javadoc)
847      * @see IResource#findMarker(long)
848      */

849     public IMarker findMarker(long id) {
850         return workspace.getMarkerManager().findMarker(this, id);
851     }
852
853     /* (non-Javadoc)
854      * @see IResource#findMarkers(String, boolean, int)
855      */

856     public IMarker[] findMarkers(String JavaDoc type, boolean includeSubtypes, int depth) throws CoreException {
857         ResourceInfo info = getResourceInfo(false, false);
858         checkAccessible(getFlags(info));
859         // It might happen that from this point the resource is not accessible anymore.
860
// But markers have the #exists method that callers can use to check if it is
861
// still valid.
862
return workspace.getMarkerManager().findMarkers(this, type, includeSubtypes, depth);
863     }
864
865     /* (non-Javadoc)
866      * @see IResource#findMaxProblemSeverity(String, boolean, int)
867      */

868     public int findMaxProblemSeverity(String JavaDoc type, boolean includeSubtypes, int depth) throws CoreException {
869         ResourceInfo info = getResourceInfo(false, false);
870         checkAccessible(getFlags(info));
871         // It might happen that from this point the resource is not accessible anymore.
872
// But markers have the #exists method that callers can use to check if it is
873
// still valid.
874
return workspace.getMarkerManager().findMaxProblemSeverity(this, type, includeSubtypes, depth);
875     }
876
877     /**
878      * Searches for a variant of the given target in the list,
879      * that differs only in case. Returns the variant from
880      * the list if one is found, otherwise returns null.
881      */

882     private String JavaDoc findVariant(String JavaDoc target, String JavaDoc[] list) {
883         for (int i = 0; i < list.length; i++) {
884             if (target.equalsIgnoreCase(list[i]))
885                 return list[i];
886         }
887         return null;
888     }
889
890     protected void fixupAfterMoveSource() throws CoreException {
891         ResourceInfo info = getResourceInfo(true, true);
892         //if a linked resource is moved, we need to remove the location info from the .project
893
if (isLinked()) {
894             Project project = (Project) getProject();
895             project.internalGetDescription().setLinkLocation(getProjectRelativePath(), null);
896             project.writeDescription(IResource.NONE);
897         }
898
899         // check if we deleted a preferences file
900
ProjectPreferences.deleted(this);
901
902         if (!synchronizing(info)) {
903             workspace.deleteResource(this);
904             return;
905         }
906         info.clearSessionProperties();
907         info.clear(M_LOCAL_EXISTS);
908         info.setLocalSyncInfo(I_NULL_SYNC_INFO);
909         info.set(M_PHANTOM);
910         info.clearModificationStamp();
911         info.setMarkers(null);
912     }
913
914     /* (non-Javadoc)
915      * @see IResource#getFileExtension()
916      */

917     public String JavaDoc getFileExtension() {
918         String JavaDoc name = getName();
919         int index = name.lastIndexOf('.');
920         if (index == -1)
921             return null;
922         if (index == (name.length() - 1))
923             return ""; //$NON-NLS-1$
924
return name.substring(index + 1);
925     }
926
927     public int getFlags(ResourceInfo info) {
928         return (info == null) ? NULL_FLAG : info.getFlags();
929     }
930
931     /* (non-Javadoc)
932      * @see IResource#getFullPath()
933      */

934     public IPath getFullPath() {
935         return path;
936     }
937
938     public FileSystemResourceManager getLocalManager() {
939         return workspace.getFileSystemManager();
940     }
941
942     /* (non-Javadoc)
943      * @see IResource#getLocalTimeStamp()
944      */

945     public long getLocalTimeStamp() {
946         ResourceInfo info = getResourceInfo(false, false);
947         return info == null ? IResource.NULL_STAMP : info.getLocalSyncInfo();
948     }
949
950     /* (non-Javadoc)
951      * @see IResource#getLocation()
952      */

953     public IPath getLocation() {
954         IProject project = getProject();
955         if (project != null && !project.exists())
956             return null;
957         return getLocalManager().locationFor(this);
958     }
959
960     /* (non-Javadoc)
961      * @see IResource#getLocation()
962      */

963     public URI JavaDoc getLocationURI() {
964         IProject project = getProject();
965         if (project != null && !project.exists())
966             return null;
967         return getLocalManager().locationURIFor(this);
968     }
969
970     /* (non-Javadoc)
971      * @see IResource#getMarker(long)
972      */

973     public IMarker getMarker(long id) {
974         return new Marker(this, id);
975     }
976
977     protected MarkerManager getMarkerManager() {
978         return workspace.getMarkerManager();
979     }
980
981     /* (non-Javadoc)
982      * @see IResource#getModificationStamp()
983      */

984     public long getModificationStamp() {
985         ResourceInfo info = getResourceInfo(false, false);
986         return info == null ? IResource.NULL_STAMP : info.getModificationStamp();
987     }
988
989     /* (non-Javadoc)
990      * @see IResource#getName()
991      */

992     public String JavaDoc getName() {
993         return path.lastSegment();
994     }
995
996     /* (non-Javadoc)
997      * @see IResource#getParent()
998      */

999     public IContainer getParent() {
1000        int segments = path.segmentCount();
1001        //zero and one segments handled by subclasses
1002
Assert.isLegal(segments > 1, path.toString());
1003        if (segments == 2)
1004            return workspace.getRoot().getProject(path.segment(0));
1005        return (IFolder) workspace.newResource(path.removeLastSegments(1), IResource.FOLDER);
1006    }
1007
1008    /* (non-Javadoc)
1009     * @see IResource#getPersistentProperty(QualifiedName)
1010     */

1011    public String JavaDoc getPersistentProperty(QualifiedName key) throws CoreException {
1012        ResourceInfo info = getResourceInfo(false, false);
1013        int flags = getFlags(info);
1014        checkAccessible(flags);
1015        checkLocal(flags, DEPTH_ZERO);
1016        return getPropertyManager().getProperty(this, key);
1017    }
1018
1019    /* (non-Javadoc)
1020     * @see IResource#getProject()
1021     */

1022    public IProject getProject() {
1023        return workspace.getRoot().getProject(path.segment(0));
1024    }
1025
1026    /* (non-Javadoc)
1027     * @see IResource#getProjectRelativePath()
1028     */

1029    public IPath getProjectRelativePath() {
1030        return getFullPath().removeFirstSegments(ICoreConstants.PROJECT_SEGMENT_LENGTH);
1031    }
1032
1033    public IPropertyManager getPropertyManager() {
1034        return workspace.getPropertyManager();
1035    }
1036
1037    /* (non-Javadoc)
1038     * @see IResource#getRawLocation()
1039     */

1040    public IPath getRawLocation() {
1041        if (isLinked())
1042            return FileUtil.toPath(((Project) getProject()).internalGetDescription().getLinkLocationURI(getProjectRelativePath()));
1043        return getLocation();
1044    }
1045
1046    /* (non-Javadoc)
1047     * @see IResource#getRawLocation()
1048     */

1049    public URI JavaDoc getRawLocationURI() {
1050        if (isLinked())
1051            return ((Project) getProject()).internalGetDescription().getLinkLocationURI(getProjectRelativePath());
1052        return getLocationURI();
1053    }
1054
1055    /* (non-Javadoc)
1056     * @see IResource#getResourceAttributes()
1057     */

1058    public ResourceAttributes getResourceAttributes() {
1059        if (!isAccessible())
1060            return null;
1061        return getLocalManager().attributes(this);
1062    }
1063
1064    /**
1065     * Returns the resource info. Returns null if the resource doesn't exist.
1066     * If the phantom flag is true, phantom resources are considered.
1067     * If the mutable flag is true, a mutable info is returned.
1068     */

1069    public ResourceInfo getResourceInfo(boolean phantom, boolean mutable) {
1070        return workspace.getResourceInfo(getFullPath(), phantom, mutable);
1071    }
1072
1073    /* (non-Javadoc)
1074     * @see IResource#getSessionProperty(QualifiedName)
1075     */

1076    public Object JavaDoc getSessionProperty(QualifiedName key) throws CoreException {
1077        ResourceInfo info = getResourceInfo(false, false);
1078        int flags = getFlags(info);
1079        checkAccessible(flags);
1080        checkLocal(flags, DEPTH_ZERO);
1081        return info.getSessionProperty(key);
1082    }
1083
1084    public IFileStore getStore() {
1085        return getLocalManager().getStore(this);
1086    }
1087
1088    /* (non-Javadoc)
1089     * @see IResource#getType()
1090     */

1091    public abstract int getType();
1092
1093    public String JavaDoc getTypeString() {
1094        switch (getType()) {
1095            case FILE :
1096                return "L"; //$NON-NLS-1$
1097
case FOLDER :
1098                return "F"; //$NON-NLS-1$
1099
case PROJECT :
1100                return "P"; //$NON-NLS-1$
1101
case ROOT :
1102                return "R"; //$NON-NLS-1$
1103
}
1104        return ""; //$NON-NLS-1$
1105
}
1106
1107    /* (non-Javadoc)
1108     * @see IResource#getWorkspace()
1109     */

1110    public IWorkspace getWorkspace() {
1111        return workspace;
1112    }
1113
1114    public int hashCode() {
1115        // the container may be null if the identified resource
1116
// does not exist so don't bother with it in the hash
1117
return getFullPath().hashCode();
1118    }
1119
1120    /**
1121     * Sets the M_LOCAL_EXISTS flag. Is internal so we don't have
1122     * to begin an operation.
1123     */

1124    protected void internalSetLocal(boolean flag, int depth) throws CoreException {
1125        ResourceInfo info = getResourceInfo(true, true);
1126        //only make the change if it's not already in desired state
1127
if (info.isSet(M_LOCAL_EXISTS) != flag) {
1128            if (flag && !isPhantom(getFlags(info))) {
1129                info.set(M_LOCAL_EXISTS);
1130                workspace.updateModificationStamp(info);
1131            } else {
1132                info.clear(M_LOCAL_EXISTS);
1133                info.clearModificationStamp();
1134            }
1135        }
1136        if (getType() == IResource.FILE || depth == IResource.DEPTH_ZERO)
1137            return;
1138        if (depth == IResource.DEPTH_ONE)
1139            depth = IResource.DEPTH_ZERO;
1140        IResource[] children = ((IContainer) this).members();
1141        for (int i = 0; i < children.length; i++)
1142            ((Resource) children[i]).internalSetLocal(flag, depth);
1143    }
1144
1145    /* (non-Javadoc)
1146     * @see IResource#isAccessible()
1147     */

1148    public boolean isAccessible() {
1149        return exists();
1150    }
1151
1152    /* (non-Javadoc)
1153     * @see ISchedulingRule#isConflicting(ISchedulingRule)
1154     */

1155    public boolean isConflicting(ISchedulingRule rule) {
1156        //must not schedule at same time as notification
1157
if (rule.getClass().equals(WorkManager.NotifyRule.class))
1158            return true;
1159        if (!(rule instanceof IResource))
1160            return false;
1161        IPath otherPath = ((IResource) rule).getFullPath();
1162        return path.isPrefixOf(otherPath) || otherPath.isPrefixOf(path);
1163    }
1164
1165    /* (non-Javadoc)
1166     * @see IResource#isDerived()
1167     */

1168    public boolean isDerived() {
1169        ResourceInfo info = getResourceInfo(false, false);
1170        return isDerived(getFlags(info));
1171    }
1172
1173    /**
1174     * Returns whether the derived flag is set in the given resource info flags.
1175     *
1176     * @param flags resource info flags (bitwise or of M_* constants)
1177     * @return <code>true</code> if the derived flag is set, and <code>false</code>
1178     * if the derived flag is not set or if the flags are <code>NULL_FLAG</code>
1179     */

1180    public boolean isDerived(int flags) {
1181        return flags != NULL_FLAG && ResourceInfo.isSet(flags, ICoreConstants.M_DERIVED);
1182    }
1183
1184    /* (non-Javadoc)
1185     * @see IResource#isLinked()
1186     */

1187    public boolean isLinked() {
1188        return isLinked(NONE);
1189    }
1190
1191    /* (non-Javadoc)
1192     * @see IResource#isLinked()
1193     */

1194    public boolean isLinked(int options) {
1195        if ((options & CHECK_ANCESTORS) != 0) {
1196            IProject project = getProject();
1197            if (project == null)
1198                return false;
1199            ProjectDescription desc = ((Project) project).internalGetDescription();
1200            if (desc == null)
1201                return false;
1202            HashMap JavaDoc links = desc.getLinks();
1203            if (links == null)
1204                return false;
1205            IPath myPath = getProjectRelativePath();
1206            for (Iterator JavaDoc it = links.values().iterator(); it.hasNext();) {
1207                if (((LinkDescription) it.next()).getProjectRelativePath().isPrefixOf(myPath))
1208                    return true;
1209            }
1210            return false;
1211        }
1212        //the no ancestor checking case
1213
ResourceInfo info = getResourceInfo(false, false);
1214        return info != null && info.isSet(M_LINK);
1215    }
1216
1217    /**
1218     * @see IResource#isLocal(int)
1219     * @deprecated
1220     */

1221    public boolean isLocal(int depth) {
1222        ResourceInfo info = getResourceInfo(false, false);
1223        return isLocal(getFlags(info), depth);
1224    }
1225
1226    /**
1227     * Note the depth parameter is intentionally ignored because
1228     * this method is over-ridden by Container.isLocal().
1229     * @deprecated
1230     */

1231    public boolean isLocal(int flags, int depth) {
1232        return flags != NULL_FLAG && ResourceInfo.isSet(flags, M_LOCAL_EXISTS);
1233    }
1234
1235    /**
1236     * Returns whether a resource should be included in a traversal
1237     * based on the provided member flags.
1238     *
1239     * @param flags The resource info flags
1240     * @param memberFlags The member flag mask
1241     * @return Whether the resource is included
1242     */

1243    protected boolean isMember(int flags, int memberFlags) {
1244        int excludeMask = 0;
1245        if ((memberFlags & IContainer.INCLUDE_PHANTOMS) == 0)
1246            excludeMask |= M_PHANTOM;
1247        if ((memberFlags & IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS) == 0)
1248            excludeMask |= M_TEAM_PRIVATE_MEMBER;
1249        if ((memberFlags & IContainer.EXCLUDE_DERIVED) != 0)
1250            excludeMask |= M_DERIVED;
1251        //the resource is a matching member if it matches none of the exclude flags
1252
return flags != NULL_FLAG && (flags & excludeMask) == 0;
1253    }
1254
1255    /* (non-Javadoc)
1256     * @see IResource#isPhantom()
1257     */

1258    public boolean isPhantom() {
1259        ResourceInfo info = getResourceInfo(true, false);
1260        return isPhantom(getFlags(info));
1261    }
1262
1263    public boolean isPhantom(int flags) {
1264        return flags != NULL_FLAG && ResourceInfo.isSet(flags, M_PHANTOM);
1265    }
1266
1267    /** (non-Javadoc)
1268     * @see IResource#isReadOnly()
1269     * @deprecated
1270     */

1271    public boolean isReadOnly() {
1272        final ResourceAttributes attributes = getResourceAttributes();
1273        return attributes == null ? false : attributes.isReadOnly();
1274    }
1275
1276    /* (non-Javadoc)
1277     * @see IResource#isSynchronized(int)
1278     */

1279    public boolean isSynchronized(int depth) {
1280        return getLocalManager().isSynchronized(this, depth);
1281    }
1282
1283    /* (non-Javadoc)
1284     * @see IResource#isTeamPrivateMember()
1285     */

1286    public boolean isTeamPrivateMember() {
1287        ResourceInfo info = getResourceInfo(false, false);
1288        int flags = getFlags(info);
1289        return flags != NULL_FLAG && ResourceInfo.isSet(flags, ICoreConstants.M_TEAM_PRIVATE_MEMBER);
1290    }
1291
1292    /**
1293     * Returns true if this resource is a linked resource, or a child of a linked
1294     * resource, and false otherwise.
1295     */

1296    public boolean isUnderLink() {
1297        int depth = path.segmentCount();
1298        if (depth < 2)
1299            return false;
1300        if (depth == 2)
1301            return isLinked();
1302        //check if parent at depth two is a link
1303
IPath linkParent = path.removeLastSegments(depth - 2);
1304        return workspace.getResourceInfo(linkParent, false, false).isSet(ICoreConstants.M_LINK);
1305    }
1306
1307    protected IPath makePathAbsolute(IPath target) {
1308        if (target.isAbsolute())
1309            return target;
1310        return getParent().getFullPath().append(target);
1311    }
1312
1313    /* (non-Javadoc)
1314     * @see IFile#move(IPath, boolean, boolean, IProgressMonitor)
1315     * @see IFolder#move(IPath, boolean, boolean, IProgressMonitor)
1316     */

1317    public void move(IPath destination, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException {
1318        int updateFlags = force ? IResource.FORCE : IResource.NONE;
1319        updateFlags |= keepHistory ? IResource.KEEP_HISTORY : IResource.NONE;
1320        move(destination, updateFlags, monitor);
1321    }
1322
1323    /* (non-Javadoc)
1324     * @see IResource#move(IPath, boolean, IProgressMonitor)
1325     */

1326    public void move(IPath destination, boolean force, IProgressMonitor monitor) throws CoreException {
1327        move(destination, force ? IResource.FORCE : IResource.NONE, monitor);
1328    }
1329
1330    /* (non-Javadoc)
1331     * @see IResource#move(IPath, int, IProgressMonitor)
1332     */

1333    public void move(IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException {
1334        monitor = Policy.monitorFor(monitor);
1335        try {
1336            String JavaDoc message = NLS.bind(Messages.resources_moving, getFullPath());
1337            monitor.beginTask(message, Policy.totalWork);
1338            Policy.checkCanceled(monitor);
1339            destination = makePathAbsolute(destination);
1340            checkValidPath(destination, getType(), false);
1341            Resource destResource = workspace.newResource(destination, getType());
1342            final ISchedulingRule rule = workspace.getRuleFactory().moveRule(this, destResource);
1343            try {
1344                workspace.prepareOperation(rule, monitor);
1345                // The following assert method throws CoreExceptions as stated in the IResource.move API
1346
// and assert for programming errors. See checkMoveRequirements for more information.
1347
assertMoveRequirements(destination, getType(), updateFlags);
1348                workspace.beginOperation(true);
1349                IFileStore originalStore = getStore();
1350                message = Messages.resources_moveProblem;
1351                MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, null);
1352                WorkManager workManager = workspace.getWorkManager();
1353                ResourceTree tree = new ResourceTree(workspace.getFileSystemManager(), workManager.getLock(), status, updateFlags);
1354                boolean success = false;
1355                int depth = 0;
1356                try {
1357                    depth = workManager.beginUnprotected();
1358                    success = unprotectedMove(tree, destResource, updateFlags, monitor);
1359                } finally {
1360                    workManager.endUnprotected(depth);
1361                }
1362                // Invalidate the tree for further use by clients.
1363
tree.makeInvalid();
1364                //update any aliases of this resource and the destination
1365
if (success) {
1366                    workspace.getAliasManager().updateAliases(this, originalStore, IResource.DEPTH_INFINITE, monitor);
1367                    workspace.getAliasManager().updateAliases(destResource, destResource.getStore(), IResource.DEPTH_INFINITE, monitor);
1368                }
1369                if (!tree.getStatus().isOK())
1370                    throw new ResourceException(tree.getStatus());
1371            } catch (OperationCanceledException e) {
1372                workspace.getWorkManager().operationCanceled();
1373                throw e;
1374            } finally {
1375                workspace.endOperation(rule, true, Policy.subMonitorFor(monitor, Policy.endOpWork));
1376            }
1377        } finally {
1378            monitor.done();
1379        }
1380    }
1381
1382    /* (non-Javadoc)
1383     * @see IResource#move(IProjectDescription, boolean, IProgressMonitor)
1384     */

1385    public void move(IProjectDescription description, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException {
1386        int updateFlags = force ? IResource.FORCE : IResource.NONE;
1387        updateFlags |= keepHistory ? IResource.KEEP_HISTORY : IResource.NONE;
1388        move(description, updateFlags, monitor);
1389    }
1390
1391    /* (non-Javadoc)
1392     * @see IResource#move(IPath, int, IProgressMonitor)
1393     */

1394    public void move(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException {
1395        Assert.isNotNull(description);
1396        if (getType() != IResource.PROJECT) {
1397            String JavaDoc message = NLS.bind(Messages.resources_moveNotProject, getFullPath(), description.getName());
1398            throw new ResourceException(IResourceStatus.INVALID_VALUE, getFullPath(), message, null);
1399        }
1400        ((Project) this).move(description, updateFlags, monitor);
1401    }
1402
1403    /* (non-Javadoc)
1404     * @see IResource#refreshLocal(int, IProgressMonitor)
1405     */

1406    public void refreshLocal(int depth, IProgressMonitor monitor) throws CoreException {
1407        monitor = Policy.monitorFor(monitor);
1408        try {
1409            boolean isRoot = getType() == ROOT;
1410            String JavaDoc message = isRoot ? Messages.resources_refreshingRoot : NLS.bind(Messages.resources_refreshing, getFullPath());
1411            monitor.beginTask("", Policy.totalWork); //$NON-NLS-1$
1412
monitor.subTask(message);
1413            boolean build = false;
1414            final ISchedulingRule rule = workspace.getRuleFactory().refreshRule(this);
1415            try {
1416                workspace.prepareOperation(rule, monitor);
1417                if (!isRoot && !getProject().isAccessible())
1418                    return;
1419                workspace.beginOperation(true);
1420                build = getLocalManager().refresh(this, depth, true, Policy.subMonitorFor(monitor, Policy.opWork));
1421            } catch (OperationCanceledException e) {
1422                workspace.getWorkManager().operationCanceled();
1423                throw e;
1424            } catch (Error JavaDoc e) {
1425                //support to track down Bug 95089
1426
Policy.log(e);
1427                throw e;
1428            } catch (RuntimeException JavaDoc e) {
1429                //support to track down Bug 95089
1430
Policy.log(e);
1431                throw e;
1432            } finally {
1433                workspace.endOperation(rule, build, Policy.subMonitorFor(monitor, Policy.endOpWork));
1434            }
1435        } finally {
1436            monitor.done();
1437        }
1438    }
1439
1440    /* (non-Javadoc)
1441     * Method declared on {@link IPathRequestor}.
1442     */

1443    public String JavaDoc requestName() {
1444        return getName();
1445    }
1446
1447    /* (non-Javadoc)
1448     * Method declared on {@link IPathRequestor}.
1449     */

1450    public IPath requestPath() {
1451        return getFullPath();
1452    }
1453
1454    /* (non-Javadoc)
1455     * @see IResource#revertModificationStamp
1456     */

1457    public void revertModificationStamp(long value) throws CoreException {
1458        if (value < 0)
1459            throw new IllegalArgumentException JavaDoc("Illegal value: " + value); //$NON-NLS-1$
1460
// fetch the info but don't bother making it mutable even though we are going
1461
// to modify it. It really doesn't matter as the change we are doing does not show up in deltas.
1462
ResourceInfo info = getResourceInfo(false, false);
1463        int flags = getFlags(info);
1464        checkAccessible(flags);
1465        checkLocal(flags, DEPTH_ZERO);
1466        info.setModificationStamp(value);
1467    }
1468
1469    /* (non-Javadoc)
1470     * @see IResource#setDerived(boolean)
1471     */

1472    public void setDerived(boolean isDerived) throws CoreException {
1473        // fetch the info but don't bother making it mutable even though we are going
1474
// to modify it. We don't know whether or not the tree is open and it really doesn't
1475
// matter as the change we are doing does not show up in deltas.
1476
ResourceInfo info = getResourceInfo(false, false);
1477        int flags = getFlags(info);
1478        checkAccessible(flags);
1479        // ignore attempts to set derived flag on anything except files and folders
1480
if (info.getType() == FILE || info.getType() == FOLDER) {
1481            if (isDerived) {
1482                info.set(ICoreConstants.M_DERIVED);
1483            } else {
1484                info.clear(ICoreConstants.M_DERIVED);
1485            }
1486        }
1487    }
1488
1489    /**
1490     * @see IResource#setLocal(boolean, int, IProgressMonitor)
1491     * @deprecated
1492     */

1493    public void setLocal(boolean flag, int depth, IProgressMonitor monitor) throws CoreException {
1494        monitor = Policy.monitorFor(monitor);
1495        try {
1496            String JavaDoc message = Messages.resources_setLocal;
1497            monitor.beginTask(message, Policy.totalWork);
1498            try {
1499                workspace.prepareOperation(null, monitor);
1500                workspace.beginOperation(true);
1501                internalSetLocal(flag, depth);
1502                monitor.worked(Policy.opWork);
1503            } finally {
1504                workspace.endOperation(null, true, Policy.subMonitorFor(monitor, Policy.endOpWork));
1505            }
1506        } finally {
1507            monitor.done();
1508        }
1509    }
1510
1511    /* (non-Javadoc)
1512     * @see IResource#setLocalTimeStamp(long)
1513     */

1514    public long setLocalTimeStamp(long value) throws CoreException {
1515        if (value < 0)
1516            throw new IllegalArgumentException JavaDoc("Illegal value: " + value); //$NON-NLS-1$
1517
// fetch the info but don't bother making it mutable even though we are going
1518
// to modify it. It really doesn't matter as the change we are doing does not show up in deltas.
1519
ResourceInfo info = getResourceInfo(false, false);
1520        int flags = getFlags(info);
1521        checkAccessible(flags);
1522        checkLocal(flags, DEPTH_ZERO);
1523        return getLocalManager().setLocalTimeStamp(this, info, value);
1524    }
1525
1526    /* (non-Javadoc)
1527     * @see IResource#setPersistentProperty(QualifiedName, String)
1528     */

1529    public void setPersistentProperty(QualifiedName key, String JavaDoc value) throws CoreException {
1530        ResourceInfo info = getResourceInfo(false, false);
1531        int flags = getFlags(info);
1532        checkAccessible(flags);
1533        checkLocal(flags, DEPTH_ZERO);
1534        getPropertyManager().setProperty(this, key, value);
1535    }
1536
1537    /** (non-Javadoc)
1538     * @see IResource#setReadOnly(boolean)
1539     * @deprecated
1540     */

1541    public void setReadOnly(boolean readonly) {
1542        ResourceAttributes attributes = new ResourceAttributes();
1543        attributes.setReadOnly(readonly);
1544        try {
1545            setResourceAttributes(attributes);
1546        } catch (CoreException e) {
1547            //failure is not an option
1548
}
1549    }
1550
1551    /* (non-Javadoc)
1552     * @see org.eclipse.core.resources.IResource#setResourceAttributes(org.eclipse.core.resources.ResourceAttributes)
1553     */

1554    public void setResourceAttributes(ResourceAttributes attributes) throws CoreException {
1555        ResourceInfo info = getResourceInfo(false, false);
1556        int flags = getFlags(info);
1557        checkAccessible(flags);
1558        checkLocal(flags, DEPTH_ZERO);
1559        getLocalManager().setResourceAttributes(this, attributes);
1560    }
1561
1562    /* (non-Javadoc)
1563     * @see IResource#setSessionProperty(QualifiedName, Object)
1564     */

1565    public void setSessionProperty(QualifiedName key, Object JavaDoc value) throws CoreException {
1566        // fetch the info but don't bother making it mutable even though we are going
1567
// to modify it. We don't know whether or not the tree is open and it really doesn't
1568
// matter as the change we are doing does not show up in deltas.
1569
ResourceInfo info = getResourceInfo(false, false);
1570        int flags = getFlags(info);
1571        checkAccessible(flags);
1572        checkLocal(flags, DEPTH_ZERO);
1573        info.setSessionProperty(key, value);
1574    }
1575
1576    /* (non-Javadoc)
1577     * @see IResource#setTeamPrivateMember(boolean)
1578     */

1579    public void setTeamPrivateMember(boolean isTeamPrivate) throws CoreException {
1580        // fetch the info but don't bother making it mutable even though we are going
1581
// to modify it. We don't know whether or not the tree is open and it really doesn't
1582
// matter as the change we are doing does not show up in deltas.
1583
ResourceInfo info = getResourceInfo(false, false);
1584        int flags = getFlags(info);
1585        checkAccessible(flags);
1586        // ignore attempts to set team private member flag on anything except files and folders
1587
if (info.getType() == FILE || info.getType() == FOLDER) {
1588            if (isTeamPrivate) {
1589                info.set(ICoreConstants.M_TEAM_PRIVATE_MEMBER);
1590            } else {
1591                info.clear(ICoreConstants.M_TEAM_PRIVATE_MEMBER);
1592            }
1593        }
1594    }
1595
1596    /**
1597     * Returns true if this resource has the potential to be
1598     * (or have been) synchronized.
1599     */

1600    public boolean synchronizing(ResourceInfo info) {
1601        return info != null && info.getSyncInfo(false) != null;
1602    }
1603
1604    /* (non-Javadoc)
1605     * @see Object#toString()
1606     */

1607    public String JavaDoc toString() {
1608        return getTypeString() + getFullPath().toString();
1609    }
1610
1611    /* (non-Javadoc)
1612     * @see IResource#touch(IProgressMonitor)
1613     */

1614    public void touch(IProgressMonitor monitor) throws CoreException {
1615        monitor = Policy.monitorFor(monitor);
1616        try {
1617            String JavaDoc message = NLS.bind(Messages.resources_touch, getFullPath());
1618            monitor.beginTask(message, Policy.totalWork);
1619            final ISchedulingRule rule = workspace.getRuleFactory().modifyRule(this);
1620            try {
1621                workspace.prepareOperation(rule, monitor);
1622                ResourceInfo info = getResourceInfo(false, false);
1623                int flags = getFlags(info);
1624                checkAccessible(flags);
1625                checkLocal(flags, DEPTH_ZERO);
1626
1627                workspace.beginOperation(true);
1628                // fake a change by incrementing the content ID
1629
info = getResourceInfo(false, true);
1630                info.incrementContentId();
1631                // forget content-related caching flags
1632
info.clear(M_CONTENT_CACHE);
1633                workspace.updateModificationStamp(info);
1634                monitor.worked(Policy.opWork);
1635            } catch (OperationCanceledException e) {
1636                workspace.getWorkManager().operationCanceled();
1637                throw e;
1638            } finally {
1639                workspace.endOperation(rule, true, Policy.subMonitorFor(monitor, Policy.endOpWork));
1640            }
1641        } finally {
1642            monitor.done();
1643        }
1644    }
1645
1646    /**
1647     * Calls the move/delete hook to perform the deletion. Since this method calls
1648     * client code, it is run "unprotected", so the workspace lock is not held.
1649     */

1650    private void unprotectedDelete(ResourceTree tree, int updateFlags, IProgressMonitor monitor) throws CoreException {
1651        IMoveDeleteHook hook = workspace.getMoveDeleteHook();
1652        switch (getType()) {
1653            case IResource.FILE :
1654                if (!hook.deleteFile(tree, (IFile) this, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork * 1000 / 2)))
1655                    tree.standardDeleteFile((IFile) this, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork * 1000));
1656                break;
1657            case IResource.FOLDER :
1658                if (!hook.deleteFolder(tree, (IFolder) this, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork * 1000 / 2)))
1659                    tree.standardDeleteFolder((IFolder) this, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork * 1000));
1660                break;
1661            case IResource.PROJECT :
1662                workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_PROJECT_DELETE, this));
1663                if (!hook.deleteProject(tree, (IProject) this, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork * 1000 / 2)))
1664                    tree.standardDeleteProject((IProject) this, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork * 1000));
1665                break;
1666            case IResource.ROOT :
1667                IProject[] projects = ((IWorkspaceRoot) this).getProjects();
1668                for (int i = 0; i < projects.length; i++) {
1669                    workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_PROJECT_DELETE, projects[i]));
1670                    if (!hook.deleteProject(tree, projects[i], updateFlags, Policy.subMonitorFor(monitor, Policy.opWork * 1000 / projects.length / 2)))
1671                        tree.standardDeleteProject(projects[i], updateFlags, Policy.subMonitorFor(monitor, Policy.opWork * 1000 / projects.length));
1672                }
1673        }
1674    }
1675
1676    /**
1677     * Calls the move/delete hook to perform the move. Since this method calls
1678     * client code, it is run "unprotected", so the workspace lock is not held.
1679     * Returns true if resources were actually moved, and false otherwise.
1680     */

1681    private boolean unprotectedMove(ResourceTree tree, final IResource destination, int updateFlags, IProgressMonitor monitor) throws CoreException, ResourceException {
1682        IMoveDeleteHook hook = workspace.getMoveDeleteHook();
1683        switch (getType()) {
1684            case IResource.FILE :
1685                if (isLinked())
1686                    workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_LINK_MOVE, this, destination, updateFlags));
1687                if (!hook.moveFile(tree, (IFile) this, (IFile) destination, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork / 2)))
1688                    tree.standardMoveFile((IFile) this, (IFile) destination, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork));
1689                break;
1690            case IResource.FOLDER :
1691                if (isLinked())
1692                    workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_LINK_MOVE, this, destination, updateFlags));
1693                if (!hook.moveFolder(tree, (IFolder) this, (IFolder) destination, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork / 2)))
1694                    tree.standardMoveFolder((IFolder) this, (IFolder) destination, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork));
1695                break;
1696            case IResource.PROJECT :
1697                IProject project = (IProject) this;
1698                // if there is no change in name, there is nothing to do so return.
1699
if (getName().equals(destination.getName()))
1700                    return false;
1701                //we are deleting the source project so notify.
1702
workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_PROJECT_MOVE, this, destination, updateFlags));
1703                IProjectDescription description = project.getDescription();
1704                description.setName(destination.getName());
1705                if (!hook.moveProject(tree, project, description, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork / 2)))
1706                    tree.standardMoveProject(project, description, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork));
1707                break;
1708            case IResource.ROOT :
1709                String JavaDoc msg = Messages.resources_moveRoot;
1710                throw new ResourceException(new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), msg));
1711        }
1712        return true;
1713    }
1714}
1715
Popular Tags