KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > core > client > AbstractStructureVisitor


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  * Matt McCutchen <hashproduct+eclipse@gmail.com> - Bug 178874 Test failure against CVS 1.11.22
11  *******************************************************************************/

12 package org.eclipse.team.internal.ccvs.core.client;
13
14 import java.util.*;
15
16 import org.eclipse.core.resources.IResource;
17 import org.eclipse.core.runtime.IProgressMonitor;
18 import org.eclipse.core.runtime.IStatus;
19 import org.eclipse.core.runtime.jobs.Job;
20 import org.eclipse.osgi.util.NLS;
21 import org.eclipse.team.internal.ccvs.core.*;
22 import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
23 import org.eclipse.team.internal.ccvs.core.resources.CVSEntryLineTag;
24 import org.eclipse.team.internal.ccvs.core.syncinfo.*;
25 import org.eclipse.team.internal.ccvs.core.util.Util;
26
27 /**
28  * An ICVSResourceVisitor that is superclass to all ICVSResourceVisitor's used
29  * by Command and it's subclasses.
30  * Provides helper methods to send files and folders with modifications
31  * to the server.
32  *
33  * This class does not perform a beginTask of done on the provided monitor.
34  * It is used only to signal worl and subTask.
35  */

36 abstract class AbstractStructureVisitor implements ICVSResourceVisitor {
37     
38     protected Session session;
39     private ICVSFolder lastFolderSent;
40     protected IProgressMonitor monitor;
41     protected boolean sendQuestionable;
42     protected boolean sendModifiedContents;
43     private boolean sendBinary;
44     
45     private boolean recurse = true;
46
47     public AbstractStructureVisitor(Session session, LocalOption[] localOptions, boolean sendQuestionable, boolean sendModifiedContents) {
48         this(session, localOptions, sendQuestionable, sendModifiedContents, true);
49     }
50
51     public AbstractStructureVisitor(Session session, LocalOption[] localOptions, boolean sendQuestionable, boolean sendModifiedContents, boolean sendBinary) {
52         this.session = session;
53         this.sendQuestionable = sendQuestionable;
54         this.sendModifiedContents = sendModifiedContents;
55         this.sendBinary = sendBinary;
56         if (Command.DO_NOT_RECURSE.isElementOf(localOptions))
57             recurse = false;
58     }
59         
60     /**
61      * Helper method to indicate if a directory has already been sent to the server
62      */

63     protected boolean isLastSent(ICVSFolder folder) {
64         return folder.equals(lastFolderSent);
65     }
66     
67     /**
68      * Helper method to record if a directory has already been sent to the server
69      */

70     protected void recordLastSent(ICVSFolder folder) {
71         lastFolderSent = folder;
72     }
73     
74     /**
75      * Helper which indicates if a folder is an orphaned subtree.
76      * That is, a directory which contains a CVS subdirectory but is
77      * not managed by its parent. The root directory of the session
78      * is not considered orphaned even if it is not managed by its
79      * parent.
80      */

81     protected boolean isOrphanedSubtree(ICVSFolder mFolder) throws CVSException {
82         return mFolder.isCVSFolder() && ! mFolder.isManaged() && ! mFolder.equals(session.getLocalRoot()) && mFolder.getParent().isCVSFolder();
83     }
84     
85     /**
86      * Send the folder relative to the root to the server. Send all
87      * appropiate modifier like Sticky, Questionable, Static-directory.
88      * <br>
89      * Folders will only be sent once.
90      */

91     protected void sendFolder(ICVSFolder mFolder) throws CVSException {
92
93         Policy.checkCanceled(monitor);
94         
95         boolean exists = mFolder.exists();
96         FolderSyncInfo info = mFolder.getFolderSyncInfo();
97         boolean isCVSFolder = info != null;
98         
99         // We are only interested in folders that exist or are CVS folders
100
// A folder could be a non-existant CVS folder if it is a holder for outgoing file deletions
101
if ( ! exists && ! isCVSFolder) return;
102         
103         // Do not send the same folder twice
104
if (isLastSent(mFolder)) return;
105         
106         // Do not send virtual directories
107
if (isCVSFolder && info.isVirtualDirectory()) {
108             return;
109         }
110
111         String JavaDoc localPath = mFolder.getRelativePath(session.getLocalRoot());
112         
113         monitor.subTask(NLS.bind(CVSMessages.AbstractStructureVisitor_sendingFolder, new String JavaDoc[] { Util.toTruncatedPath(mFolder, session.getLocalRoot(), 3) }));
114         
115         // Deal with questionable directories
116
boolean isQuestionable = exists && (! isCVSFolder || isOrphanedSubtree(mFolder));
117         if (isQuestionable) {
118             if (sendQuestionable) {
119                 // We need to make sure the parent folder was sent
120
sendFolder(mFolder.getParent());
121                 session.sendQuestionable(mFolder);
122             }
123             return;
124         }
125
126         // Send the directory to the server
127
String JavaDoc remotePath = mFolder.getRemoteLocation(session.getLocalRoot());
128         if (remotePath == null) {
129             IStatus status = new CVSStatus(IStatus.ERROR,CVSStatus.ERROR, CVSMessages.AbstractStructureVisitor_noRemote, session.getLocalRoot());
130             throw new CVSException(status);
131         }
132         session.sendDirectory(localPath, remotePath);
133
134         // Send any directory properties to the server
135
if (info != null) {
136
137             if (info.getIsStatic()) {
138                 session.sendStaticDirectory();
139             }
140
141             CVSEntryLineTag tag = info.getTag();
142
143             if (tag != null && tag.getType() != CVSTag.HEAD) {
144                 session.sendSticky(tag.toEntryLineFormat(false));
145             }
146         }
147
148         // Record that we sent this folder
149
recordLastSent(mFolder);
150         
151         monitor.worked(1);
152     }
153
154     /**
155      * Send the information about the file to the server.
156      *
157      * If the file is modified, its contents are sent as well.
158      */

159     protected void sendFile(ICVSFile mFile) throws CVSException {
160
161         Policy.checkCanceled(monitor);
162
163         // Send the parent folder if it hasn't been sent already
164
sendFolder(mFile.getParent());
165         
166         // Send the file's entry line to the server
167
byte[] syncBytes = mFile.getSyncBytes();
168         boolean isManaged = syncBytes != null;
169         
170         if (isManaged) {
171             sendPendingNotification(mFile);
172         } else {
173             // If the file is not managed, send a questionable to the server if the file exists locally
174
// A unmanaged, locally non-existant file results from the explicit use of the file name as a command argument
175
if (sendQuestionable) {
176                 if (mFile.exists()) {
177                     session.sendQuestionable(mFile);
178                 }
179                 return;
180             }
181             // else we are probably doing an import so send the file contents below
182
}
183         
184         // Determine if we need to send the contents.
185
// If the file is unmodified since a conflict, we need to not send the
186
// contents so that the server rejects the file (bug 178874).
187
boolean sendContents = mFile.exists() && mFile.isModified(monitor)
188             && !mFile.getSyncInfo().isNeedsMerge(mFile.getTimeStamp());
189         if (ResourceSyncInfo.isDeletion(syncBytes)) {
190             sendEntryLineToServer(mFile, syncBytes);
191         } else if (sendContents) {
192             // Perform the send of modified contents in a sheduling rule to ensure that
193
// the contents are not modified while we are sending them
194
final IResource resource = mFile.getIResource();
195             try {
196                 if (resource != null)
197                     Job.getJobManager().beginRule(resource, monitor);
198                 
199                 sendEntryLineToServer(mFile, syncBytes);
200                 if (mFile.exists() && mFile.isModified(null)) {
201                     boolean binary = ResourceSyncInfo.isBinary(syncBytes);
202                     if (sendModifiedContents) {
203                         session.sendModified(mFile, binary, sendBinary, monitor);
204                     } else {
205                         session.sendIsModified(mFile, binary, monitor);
206                     }
207                 } else {
208                     session.sendUnchanged(mFile);
209                 }
210             } finally {
211                 if (resource != null)
212                     Job.getJobManager().endRule(resource);
213             }
214         } else {
215             sendEntryLineToServer(mFile, syncBytes);
216             session.sendUnchanged(mFile);
217         }
218         
219         monitor.worked(1);
220     }
221
222     private void sendEntryLineToServer(ICVSFile mFile, byte[] syncBytes) throws CVSException {
223         if (syncBytes != null) {
224             String JavaDoc syncBytesToServer = ResourceSyncInfo.getTimestampToServer(syncBytes, mFile.getTimeStamp());
225             session.sendEntry(syncBytes, syncBytesToServer);
226         }
227     }
228
229     protected void sendPendingNotification(ICVSFile mFile) throws CVSException {
230         NotifyInfo notify = mFile.getPendingNotification();
231         if (notify != null) {
232             sendFolder(mFile.getParent());
233             session.sendNotify(mFile.getParent(), notify);
234         }
235     }
236     
237     /**
238      * This method is used to visit a set of ICVSResources. Using it ensures
239      * that a common parent between the set of resources is only sent once
240      */

241     public void visit(Session session, ICVSResource[] resources, IProgressMonitor monitor) throws CVSException {
242         
243         // Sort the resources to avoid sending the same directory multiple times
244
List resourceList = new ArrayList(resources.length);
245         resourceList.addAll(Arrays.asList(resources));
246         final ICVSFolder localRoot = session.getLocalRoot();
247         Collections.sort(resourceList, new Comparator() {
248             public int compare(Object JavaDoc object1, Object JavaDoc object2) {
249                 ICVSResource resource1 = (ICVSResource)object1;
250                 ICVSResource resource2 = (ICVSResource)object2;
251                 try {
252                     String JavaDoc path1 = resource1.getParent().getRelativePath(localRoot);
253                     String JavaDoc path2 = resource2.getParent().getRelativePath(localRoot);
254                     int pathCompare = path1.compareTo(path2);
255                     if (pathCompare == 0) {
256                         if (resource1.isFolder() == resource2.isFolder()) {
257                             return resource1.getName().compareTo(resource2.getName());
258                         } else if (resource1.isFolder()) {
259                             return 1;
260                         } else {
261                             return -1;
262                         }
263                     } else {
264                         return pathCompare;
265                     }
266                 } catch (CVSException e) {
267                     return resource1.getName().compareTo(resource2.getName());
268                 }
269             }
270         });
271
272         // Create a progress monitor suitable for the visit
273
int resourceHint = 64;
274         monitor.beginTask(null, resourceHint);
275         this.monitor = Policy.infiniteSubMonitorFor(monitor, resourceHint);
276         try {
277             // Visit all the resources
278
this.monitor.beginTask(null, resourceHint);
279             session.setSendFileTitleKey(getSendFileMessage());
280             for (int i = 0; i < resourceList.size(); i++) {
281                 ((ICVSResource)resourceList.get(i)).accept(this);
282             }
283         } finally {
284             monitor.done();
285         }
286     }
287     
288     /**
289      * Return a send file message that contains one argument slot
290      * for the file name.
291      * @return a send file message that contains one argument slot
292      * for the file name
293      */

294     protected String JavaDoc getSendFileMessage() {
295         return CVSMessages.AbstractStructureVisitor_sendingFile;
296     }
297     public boolean isRecurse() {
298         return recurse;
299     }
300 }
301
Popular Tags