KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > core > resources > RemoteFolderMemberFetcher


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  *******************************************************************************/

11 package org.eclipse.team.internal.ccvs.core.resources;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.core.runtime.*;
18 import org.eclipse.osgi.util.NLS;
19 import org.eclipse.team.internal.ccvs.core.*;
20 import org.eclipse.team.internal.ccvs.core.client.*;
21 import org.eclipse.team.internal.ccvs.core.client.Command.*;
22 import org.eclipse.team.internal.ccvs.core.client.listeners.*;
23 import org.eclipse.team.internal.ccvs.core.connection.CVSServerException;
24 import org.eclipse.team.internal.ccvs.core.util.Util;
25
26 /**
27  * Fetch the children for the given parent folder. When fetchMembers is invoked,
28  * the children of the folder will be fecthced from the server and assigned to
29  * the children of the parent folder.
30  */

31 public class RemoteFolderMemberFetcher implements IUpdateMessageListener, IStatusListener {
32     
33     private final RemoteFolder parentFolder;
34     private CVSTag tag;
35     
36     List JavaDoc folders = new ArrayList JavaDoc(); // RemoteFolder
37
List JavaDoc files = new ArrayList JavaDoc(); // RemoteFile
38
boolean exists = true;
39     List JavaDoc exceptions = new ArrayList JavaDoc(); // CVSException
40

41     protected RemoteFolderMemberFetcher(RemoteFolder parentFolder, CVSTag tag) {
42         this.tag = tag;
43         this.parentFolder = parentFolder;
44     }
45     
46     /**
47      * Fetch the members for a given tag and returns them.
48      * During the execution of this method, the instance variable children
49      * will be used to contain the children. However, the variable is reset
50      * and the result returned. Thus, instances of RemoteFolder do not
51      * persist the children. Subclasses (namely RemoteFolderTree) may
52      * persist the children.
53      */

54     public void fetchMembers(IProgressMonitor monitor) throws CVSException {
55         fetchMembers(monitor, tag);
56     }
57     public void fetchMembers(IProgressMonitor monitor, CVSTag tag) throws CVSException {
58         final IProgressMonitor progress = Policy.monitorFor(monitor);
59         progress.beginTask(CVSMessages.RemoteFolder_getMembers, 100);
60         try {
61             // Update the parent folder children so there are no children
62
updateParentFolderChildren();
63             // Perform an update to retrieve the child files and folders
64
IStatus status = performUpdate(Policy.subMonitorFor(progress, 50), tag);
65             // Update the parent folder with the new children
66
updateParentFolderChildren();
67             Policy.checkCanceled(monitor);
68             
69             // Handle any errors that were identified by the listener
70
performErrorCheck(status, CVSMessages.RemoteFolder_errorFetchingMembers);
71             
72             // Get the revision numbers for the files
73
ICVSFile[] remoteFiles = getFiles();
74             if (remoteFiles.length > 0) {
75                 updateFileRevisions(remoteFiles, Policy.subMonitorFor(progress, 50));
76             } else {
77                 progress.worked(50);
78             }
79         } catch (CVSServerException e) {
80             if ( ! e.isNoTagException() && e.containsErrors())
81                 throw e;
82             if (tag == null)
83                 throw e;
84             // we now know that this is an exception caused by a cvs bug.
85
// if the folder has no files in it (just subfolders) cvs does not respond with the subfolders...
86
// workaround: retry the request with no tag to get the directory names (if any)
87
Policy.checkCanceled(progress);
88             fetchMembers(Policy.subMonitorFor(progress, 50), null);
89         } finally {
90             progress.done();
91         }
92     }
93
94     protected IStatus performUpdate(IProgressMonitor progress, CVSTag tag) throws CVSException {
95         progress.beginTask(null, 100);
96         Session session = new Session(parentFolder.getRepository(), parentFolder, false /* output to console */);
97         session.open(Policy.subMonitorFor(progress, 10), false /* read-only */);
98         try {
99             // Build the local options
100
final List JavaDoc localOptions = new ArrayList JavaDoc();
101             localOptions.add(Update.RETRIEVE_ABSENT_DIRECTORIES);
102             if (tag != null) localOptions.add(Update.makeTagOption(tag));
103             
104             return Command.UPDATE.execute(
105                 session,
106                 new GlobalOption[] { Command.DO_NOT_CHANGE },
107                 (LocalOption[])localOptions.toArray(new LocalOption[localOptions.size()]),
108                 new ICVSResource[] { parentFolder },
109                 new UpdateListener(this),
110             Policy.subMonitorFor(progress, 90));
111         } finally {
112             session.close();
113         }
114     }
115     
116     protected void updateFileRevisions(final ICVSFile[] files, IProgressMonitor monitor) throws CVSException {
117             
118         // Perform a "cvs status..." with a listener
119
monitor = Policy.monitorFor(monitor);
120         monitor.beginTask(null, 100);
121         QuietOption quietness = CVSProviderPlugin.getPlugin().getQuietness();
122         try {
123             CVSProviderPlugin.getPlugin().setQuietness(Command.VERBOSE);
124             Session session = new Session(parentFolder.getRepository(), parentFolder, false /* output to console */);
125             session.open(Policy.subMonitorFor(monitor, 10), false /* read-only */);
126             try {
127                 IStatus status = Command.STATUS.execute(
128                     session,
129                     Command.NO_GLOBAL_OPTIONS,
130                     Command.NO_LOCAL_OPTIONS,
131                     files,
132                     new StatusListener(this),
133                     Policy.subMonitorFor(monitor, 90));
134                 performErrorCheck(status, CVSMessages.RemoteFolder_errorFetchingRevisions);
135                 // TODO: Ensure all files have a revision?
136
} finally {
137                 session.close();
138             }
139         } finally {
140             CVSProviderPlugin.getPlugin().setQuietness(quietness);
141         }
142     }
143
144     private void performErrorCheck(IStatus status, String JavaDoc errorTitle) throws CVSException {
145         if (status.getCode() == CVSStatus.SERVER_ERROR) {
146             // Only throw the exception if no files or folders were found
147
if (folders.size() + files.size() == 0) {
148                 throw new CVSServerException(status);
149             } else {
150                 CVSProviderPlugin.log(new CVSServerException(status));
151             }
152         }
153         if (!exists) {
154             IStatus notExistStatus = new CVSStatus(IStatus.ERROR, CVSStatus.DOES_NOT_EXIST, NLS.bind(CVSMessages.RemoteFolder_doesNotExist, new String JavaDoc[] { this.parentFolder.getRepositoryRelativePath() }), parentFolder);
155             throw new CVSException(notExistStatus);
156         }
157         
158         // Report any internal exceptions that occured fetching the members
159
if ( ! exceptions.isEmpty()) {
160             if (exceptions.size() == 1) {
161                 throw (CVSException)exceptions.get(0);
162             } else {
163                 MultiStatus multi = new MultiStatus(CVSProviderPlugin.ID, 0, errorTitle, null);
164                 for (int i = 0; i < exceptions.size(); i++) {
165                     multi.merge(((CVSException)exceptions.get(i)).getStatus());
166                 }
167                 throw new CVSException(multi);
168             }
169         }
170     }
171     
172     /* (non-Javadoc)
173      * @see org.eclipse.team.internal.ccvs.core.client.listeners.IUpdateMessageListener#directoryInformation(org.eclipse.team.internal.ccvs.core.ICVSFolder, java.lang.String, boolean)
174      */

175     public void directoryInformation(ICVSFolder commandRoot, String JavaDoc stringPath, boolean newDirectory) {
176         try {
177             IPath path = this.parentFolder.getRelativePathFromRootRelativePath(commandRoot, new Path(null, stringPath));
178             if (path.segmentCount() == 1) {
179                 String JavaDoc pathName = path.lastSegment();
180                 if (!pathName.equals(".")) { //$NON-NLS-1$
181
recordFolder(path.lastSegment());
182                 }
183             }
184         } catch (CVSException e) {
185             exceptions.add(e);
186         }
187     }
188
189     /* (non-Javadoc)
190      * @see org.eclipse.team.internal.ccvs.core.client.listeners.IUpdateMessageListener#directoryDoesNotExist(org.eclipse.team.internal.ccvs.core.ICVSFolder, java.lang.String)
191      */

192     public void directoryDoesNotExist(ICVSFolder parent, String JavaDoc stringPath) {
193         try {
194             IPath path = this.parentFolder.getRelativePathFromRootRelativePath(parent, new Path(null, stringPath));
195             if (path.isEmpty()) {
196                 parentDoesNotExist();
197             }
198         } catch (CVSException e) {
199             exceptions.add(e);
200         }
201     }
202
203     /* (non-Javadoc)
204      * @see org.eclipse.team.internal.ccvs.core.client.listeners.IUpdateMessageListener#fileInformation(int, org.eclipse.team.internal.ccvs.core.ICVSFolder, java.lang.String)
205      */

206     public void fileInformation(int type, ICVSFolder parent, String JavaDoc filename) {
207         try {
208             IPath filePath = new Path(null, filename);
209             filePath = this.parentFolder.getRelativePathFromRootRelativePath(parent, filePath);
210             if( filePath.segmentCount() == 1 ) {
211                 String JavaDoc properFilename = filePath.lastSegment();
212                 recordFile(properFilename);
213             }
214         } catch (CVSException e) {
215             exceptions.add(e);
216         }
217     }
218
219     /* (non-Javadoc)
220      * @see org.eclipse.team.internal.ccvs.core.client.listeners.IUpdateMessageListener#fileDoesNotExist(org.eclipse.team.internal.ccvs.core.ICVSFolder, java.lang.String)
221      */

222     public void fileDoesNotExist(ICVSFolder parent, String JavaDoc filename) {
223     }
224
225     /* (non-Javadoc)
226      * @see org.eclipse.team.internal.ccvs.core.client.listeners.IStatusListener#fileStatus(org.eclipse.team.internal.ccvs.core.ICVSFolder, java.lang.String, java.lang.String)
227      */

228     public void fileStatus(ICVSFolder commandRoot, String JavaDoc path, String JavaDoc remoteRevision) {
229         if (remoteRevision == IStatusListener.FOLDER_REVISION)
230             // Ignore any folders
231
return;
232         try {
233             ((RemoteFile)parentFolder.getChild(Util.getLastSegment(path))).setRevision(remoteRevision);
234         } catch (CVSException e) {
235             exceptions.add(e);
236         }
237     }
238     
239     /**
240      * This method is invoked for each child folder as the reponses are being recieved from
241      * the server. Default behavior is to record the folder for later retrieval using <code>getChilren()</code>.
242      * Subclasses may override but should invoke the inherited method to ensure the folder gets recorded.
243      * @param name the name of the child folder
244      */

245     protected RemoteFolder recordFolder(String JavaDoc name) {
246         RemoteFolder folder = new RemoteFolder(
247             parentFolder,
248             parentFolder.getRepository(),
249             Util.appendPath(parentFolder.getRepositoryRelativePath(), name),
250             tag);
251         folders.add(folder);
252         return folder;
253     }
254
255     /**
256      * This method is invoked for each child file as the reponses are being recieved from
257      * the server. Default behavior is to record the file for later retrieval using <code>getChildren()</code>.
258      * Subclasses may override but should invoke the inherited method to ensure the file gets recorded.
259      * This is important because the file revisions for any files are fetched subsequent to the fecthing
260      * of the children.
261      * @param name the name of the child folder
262      */

263     protected RemoteFile recordFile(String JavaDoc name) {
264         RemoteFile file = new RemoteFile(
265             parentFolder,
266             Update.STATE_NONE,
267             name,
268             null, /* revision unknown */
269             null, /* keyword mode unknown */
270             tag);
271         files.add(file);
272         return file;
273     }
274     
275     /**
276      * This method is invoked to indicate that the parent beig queried for children
277      * does not exist. Subclasses may override to get early notification of this but
278      * should still invoke the inherited method.
279      */

280     protected void parentDoesNotExist() {
281         exists = false;
282     }
283
284     /**
285      * Update the parent folder such that it's children are the
286      * children that have been fecthed by the reciever.
287      */

288     protected void updateParentFolderChildren() {
289         parentFolder.setChildren(getFetchedChildren());
290     }
291     
292     /**
293      * Return the child files fetched from the server.
294      * @return
295      */

296     protected ICVSFile[] getFiles() {
297         return (ICVSFile[]) files.toArray(new ICVSFile[files.size()]);
298     }
299     
300     /**
301      * Return an array of all fecthed children.
302      * @return
303      */

304     public ICVSRemoteResource[] getFetchedChildren() {
305         ICVSRemoteResource[] resources = new ICVSRemoteResource[folders.size() + files.size()];
306         int count = 0;
307         for (Iterator JavaDoc iter = folders.iterator(); iter.hasNext();) {
308             ICVSRemoteResource resource = (ICVSRemoteResource) iter.next();
309             resources[count++] = resource;
310         }
311         for (Iterator JavaDoc iter = files.iterator(); iter.hasNext();) {
312             ICVSRemoteResource resource = (ICVSRemoteResource) iter.next();
313             resources[count++] = resource;
314         }
315         return resources;
316     }
317
318 }
319
Popular Tags