KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > localstore > RefreshLocalVisitor


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 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  *******************************************************************************/

11 package org.eclipse.core.internal.localstore;
12
13 import org.eclipse.core.internal.resources.*;
14 import org.eclipse.core.internal.utils.Messages;
15 import org.eclipse.core.internal.utils.Policy;
16 import org.eclipse.core.resources.*;
17 import org.eclipse.core.runtime.*;
18 import org.eclipse.osgi.util.NLS;
19
20 //
21
/**
22  * Visits a unified tree, and synchronizes the file system with the
23  * resource tree. After the visit is complete, the file system will
24  * be synchronized with the workspace tree with respect to
25  * resource existence, gender, and timestamp.
26  */

27 public class RefreshLocalVisitor implements IUnifiedTreeVisitor, ILocalStoreConstants {
28     /** control constants */
29     protected static final int RL_UNKNOWN = 0;
30     protected static final int RL_IN_SYNC = 1;
31     protected static final int RL_NOT_IN_SYNC = 2;
32
33
34     /*
35      * Fields for progress monitoring algorithm.
36      * Initially, give progress for every 4 resources, double
37      * this value at halfway point, then reset halfway point
38      * to be half of remaining work. (this gives an infinite
39      * series that converges at total work after an infinite
40      * number of resources).
41      */

42     public static final int TOTAL_WORK = 250;
43     private int currentIncrement = 4;
44     private int halfWay = TOTAL_WORK / 2;
45     private int nextProgress = currentIncrement;
46     private int worked = 0;
47
48
49     protected MultiStatus errors;
50     protected IProgressMonitor monitor;
51     protected boolean resourceChanged;
52     protected Workspace workspace;
53
54     public RefreshLocalVisitor(IProgressMonitor monitor) {
55         this.monitor = monitor;
56         workspace = (Workspace) ResourcesPlugin.getWorkspace();
57         resourceChanged = false;
58         String JavaDoc msg = Messages.resources_errorMultiRefresh;
59         errors = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.FAILED_READ_LOCAL, msg, null);
60     }
61
62     /**
63      * This method has the same implementation as resourceChanged but as they are different
64      * cases, we prefer to use different methods.
65      */

66     protected void contentAdded(UnifiedTreeNode node, Resource target) {
67         resourceChanged(node, target);
68     }
69
70     protected void createResource(UnifiedTreeNode node, Resource target) throws CoreException {
71         ResourceInfo info = target.getResourceInfo(false, false);
72         int flags = target.getFlags(info);
73         if (target.exists(flags, false))
74             return;
75         /* make sure target's parent exists */
76         if (node.getLevel() == 0) {
77             IContainer parent = target.getParent();
78             if (parent.getType() == IResource.FOLDER)
79                 ((Folder) target.getParent()).ensureExists(monitor);
80         }
81         /* Use the basic file creation protocol since we don't want to create any content on disk. */
82         info = workspace.createResource(target, false);
83         /* Mark this resource as having unknown children */
84         info.set(ICoreConstants.M_CHILDREN_UNKNOWN);
85         target.getLocalManager().updateLocalSync(info, node.getLastModified());
86     }
87
88     protected void deleteResource(UnifiedTreeNode node, Resource target) throws CoreException {
89         ResourceInfo info = target.getResourceInfo(false, false);
90         int flags = target.getFlags(info);
91         //don't delete linked resources
92
if (ResourceInfo.isSet(flags, ICoreConstants.M_LINK)) {
93             //just clear local sync info
94
info = target.getResourceInfo(false, true);
95             //handle concurrent deletion
96
if (info != null)
97                 info.clearModificationStamp();
98             return;
99         }
100         if (target.exists(flags, false))
101             target.deleteResource(true, errors);
102         node.setExistsWorkspace(false);
103     }
104
105     protected void fileToFolder(UnifiedTreeNode node, Resource target) throws CoreException {
106         ResourceInfo info = target.getResourceInfo(false, false);
107         int flags = target.getFlags(info);
108         if (target.exists(flags, true)) {
109             target = (Folder) ((File) target).changeToFolder();
110         } else {
111             if (!target.exists(flags, false)) {
112                 target = (Resource) workspace.getRoot().getFolder(target.getFullPath());
113                 // Use the basic file creation protocol since we don't want to create any content on disk.
114
workspace.createResource(target, false);
115             }
116         }
117         node.setResource(target);
118         info = target.getResourceInfo(false, true);
119         target.getLocalManager().updateLocalSync(info, node.getLastModified());
120     }
121
122     protected void folderToFile(UnifiedTreeNode node, Resource target) throws CoreException {
123         ResourceInfo info = target.getResourceInfo(false, false);
124         int flags = target.getFlags(info);
125         if (target.exists(flags, true))
126             target = (File) ((Folder) target).changeToFile();
127         else {
128             if (!target.exists(flags, false)) {
129                 target = (Resource) workspace.getRoot().getFile(target.getFullPath());
130                 // Use the basic file creation protocol since we don't want to
131
// create any content on disk.
132
workspace.createResource(target, false);
133             }
134         }
135         node.setResource(target);
136         info = target.getResourceInfo(false, true);
137         target.getLocalManager().updateLocalSync(info, node.getLastModified());
138     }
139
140     /**
141      * Returns the status of the nodes visited so far. This will be a multi-status
142      * that describes all problems that have occurred, or an OK status if everything
143      * went smoothly.
144      */

145     public IStatus getErrorStatus() {
146         return errors;
147     }
148
149     protected void makeLocal(UnifiedTreeNode node, Resource target) {
150         ResourceInfo info = target.getResourceInfo(false, true);
151         if (info != null)
152             target.getLocalManager().updateLocalSync(info, node.getLastModified());
153     }
154
155     /**
156      * Refreshes the parent of a resource currently being synchronized.
157      */

158     protected void refresh(Container parent) throws CoreException {
159         parent.getLocalManager().refresh(parent, IResource.DEPTH_ZERO, false, null);
160     }
161
162     protected void resourceChanged(UnifiedTreeNode node, Resource target) {
163         ResourceInfo info = target.getResourceInfo(false, true);
164         if (info == null)
165             return;
166         target.getLocalManager().updateLocalSync(info, node.getLastModified());
167         info.incrementContentId();
168         // forget content-related caching flags
169
info.clear(ICoreConstants.M_CONTENT_CACHE);
170         workspace.updateModificationStamp(info);
171     }
172
173     public boolean resourcesChanged() {
174         return resourceChanged;
175     }
176
177     /**
178      * deletion or creation -- Returns:
179      * - RL_IN_SYNC - the resource is in-sync with the file system
180      * - RL_NOT_IN_SYNC - the resource is not in-sync with file system
181      * - RL_UNKNOWN - couldn't determine the sync status for this resource
182      */

183     protected int synchronizeExistence(UnifiedTreeNode node, Resource target) throws CoreException {
184         if (node.existsInWorkspace()) {
185             if (!node.existsInFileSystem()) {
186                 //non-local files are always in sync
187
if (target.isLocal(IResource.DEPTH_ZERO)) {
188                     deleteResource(node, target);
189                     resourceChanged = true;
190                     return RL_NOT_IN_SYNC;
191                 }
192                 return RL_IN_SYNC;
193             }
194         } else {
195             // do we have a gender variant in the workspace?
196
IResource genderVariant = workspace.getRoot().findMember(target.getFullPath());
197             if (genderVariant != null)
198                 return RL_UNKNOWN;
199             if (node.existsInFileSystem()) {
200                 Container parent = (Container) target.getParent();
201                 if (!parent.exists()) {
202                     refresh(parent);
203                     if (!parent.exists())
204                         return RL_NOT_IN_SYNC;
205                 }
206                 if (!target.getName().equals(node.getLocalName()))
207                     return RL_IN_SYNC;
208                 if (!Workspace.caseSensitive && node.getLevel() == 0) {
209                     // do we have any alphabetic variants in the workspace?
210
IResource variant = target.findExistingResourceVariant(target.getFullPath());
211                     if (variant != null) {
212                         deleteResource(node, ((Resource)variant));
213                         createResource(node, target);
214                         resourceChanged = true;
215                         return RL_NOT_IN_SYNC;
216                     }
217                 }
218                 createResource(node, target);
219                 resourceChanged = true;
220                 return RL_NOT_IN_SYNC;
221             }
222         }
223         return RL_UNKNOWN;
224     }
225
226     /**
227      * gender change -- Returns true if gender was in sync.
228      */

229     protected boolean synchronizeGender(UnifiedTreeNode node, Resource target) throws CoreException {
230         if (!node.existsInWorkspace()) {
231             //may be an existing resource in the workspace of different gender
232
IResource genderVariant = workspace.getRoot().findMember(target.getFullPath());
233             if (genderVariant != null)
234                 target = (Resource) genderVariant;
235         }
236         if (target.getType() == IResource.FILE) {
237             if (node.isFolder()) {
238                 fileToFolder(node, target);
239                 resourceChanged = true;
240                 return false;
241             }
242         } else {
243             if (!node.isFolder()) {
244                 folderToFile(node, target);
245                 resourceChanged = true;
246                 return false;
247             }
248         }
249         return true;
250     }
251
252     /**
253      * lastModified
254      */

255     protected void synchronizeLastModified(UnifiedTreeNode node, Resource target) {
256         if (target.isLocal(IResource.DEPTH_ZERO))
257             resourceChanged(node, target);
258         else
259             contentAdded(node, target);
260         resourceChanged = true;
261     }
262
263     public boolean visit(UnifiedTreeNode node) throws CoreException {
264         Policy.checkCanceled(monitor);
265         try {
266             Resource target = (Resource) node.getResource();
267             int targetType = target.getType();
268             if (targetType == IResource.PROJECT)
269                 return true;
270             if (node.existsInWorkspace() && node.existsInFileSystem()) {
271                 /* for folders we only care about updating local status */
272                 if (targetType == IResource.FOLDER && node.isFolder()) {
273                     // if not local, mark as local
274
if (!target.isLocal(IResource.DEPTH_ZERO))
275                         makeLocal(node, target);
276                     return true;
277                 }
278                 /* compare file last modified */
279                 if (targetType == IResource.FILE && !node.isFolder()) {
280                     ResourceInfo info = target.getResourceInfo(false, false);
281                     if (info != null && info.getLocalSyncInfo() == node.getLastModified())
282                         return true;
283                 }
284             } else {
285                 if (node.existsInFileSystem() && !Path.EMPTY.isValidSegment(node.getLocalName())) {
286                     String JavaDoc message = NLS.bind(Messages.resources_invalidResourceName, node.getLocalName());
287                     errors.merge(new ResourceStatus(IResourceStatus.INVALID_RESOURCE_NAME, message));
288                     return false;
289                 }
290                 int state = synchronizeExistence(node, target);
291                 if (state == RL_IN_SYNC || state == RL_NOT_IN_SYNC) {
292                     if (targetType == IResource.FILE) {
293                         try {
294                             ((File) target).updateMetadataFiles();
295                         } catch (CoreException e) {
296                             errors.merge(e.getStatus());
297                         }
298                     }
299                     return true;
300                 }
301             }
302             if (synchronizeGender(node, target))
303                 synchronizeLastModified(node, target);
304             if (targetType == IResource.FILE) {
305                 try {
306                     ((File) target).updateMetadataFiles();
307                 } catch (CoreException e) {
308                     errors.merge(e.getStatus());
309                 }
310             }
311             return true;
312         } finally {
313             if (--nextProgress <= 0) {
314                 //we have exhausted the current increment, so report progress
315
monitor.worked(1);
316                 worked++;
317                 if (worked >= halfWay) {
318                     //we have passed the current halfway point, so double the
319
//increment and reset the halfway point.
320
currentIncrement *= 2;
321                     halfWay += (TOTAL_WORK - halfWay) / 2;
322                 }
323                 //reset the progress counter to another full increment
324
nextProgress = currentIncrement;
325             }
326         }
327     }
328 }
329
Popular Tags