KickJava   Java API By Example, From Geeks To Geeks.

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


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
14 import java.util.ArrayList JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.core.resources.IResource;
18 import org.eclipse.core.runtime.*;
19 import org.eclipse.osgi.util.NLS;
20 import org.eclipse.team.core.TeamException;
21 import org.eclipse.team.internal.ccvs.core.*;
22 import org.eclipse.team.internal.ccvs.core.client.*;
23 import org.eclipse.team.internal.ccvs.core.client.Command.GlobalOption;
24 import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
25 import org.eclipse.team.internal.ccvs.core.client.listeners.IUpdateMessageListener;
26 import org.eclipse.team.internal.ccvs.core.client.listeners.UpdateListener;
27 import org.eclipse.team.internal.ccvs.core.connection.CVSServerException;
28 import org.eclipse.team.internal.ccvs.core.syncinfo.*;
29 import org.eclipse.team.internal.ccvs.core.util.KnownRepositories;
30 import org.eclipse.team.internal.ccvs.core.util.Util;
31
32 /**
33  * This class provides the implementation of ICVSRemoteFolder
34  *
35  * The parent of the RemoteFolder represents the folders parent in a local configuration.
36  * For instance, the parent may correspond to the remote parent or may be a folder in the
37  * same repository that has no physical relationship to the RemoteFolder (resulting from the use
38  * of a module definition, for instance). A RemoteFolder may not have a parent, indicating that it is
39  * the root of the local configuration it represents.
40  *
41  * A RemoteFolder has the following:
42  * A name in the folder's local configuration
43  *
44  */

45 public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, ICVSFolder {
46     
47     protected static final int CHILD_DOES_NOT_EXIST = 1000;
48     
49     protected FolderSyncInfo folderInfo;
50     private ICVSRemoteResource[] children;
51     private ICVSRepositoryLocation repository;
52     
53     public static RemoteFolder fromBytes(IResource local, byte[] bytes) throws CVSException {
54         Assert.isNotNull(bytes);
55         Assert.isTrue(local.getType() != IResource.FILE);
56         FolderSyncInfo syncInfo = FolderSyncInfo.getFolderSyncInfo(bytes);
57         return new RemoteFolder(null, local.getName(), KnownRepositories.getInstance().getRepository(syncInfo.getRoot()), syncInfo.getRepository(), syncInfo.getTag(), syncInfo.getIsStatic());
58     }
59     
60     /**
61      * Constructor for RemoteFolder.
62      */

63     public RemoteFolder(RemoteFolder parent, ICVSRepositoryLocation repository, String JavaDoc repositoryRelativePath, CVSTag tag) {
64         this(parent,
65             repositoryRelativePath == null ? "" : Util.getLastSegment(repositoryRelativePath), //$NON-NLS-1$
66
repository,
67             repositoryRelativePath,
68             tag,
69             false);
70     }
71     
72     public RemoteFolder(RemoteFolder parent, String JavaDoc name, ICVSRepositoryLocation repository, String JavaDoc repositoryRelativePath, CVSTag tag, boolean isStatic) {
73         super(parent, name);
74         if (repository != null) {
75             this.folderInfo = new FolderSyncInfo(repositoryRelativePath.toString(), repository.getLocation(false), tag, isStatic);
76         }
77         this.repository = repository;
78     }
79     
80     /**
81      * @see ICVSResource#accept(ICVSResourceVisitor)
82      */

83     public void accept(ICVSResourceVisitor visitor) throws CVSException {
84         visitor.visitFolder(this);
85     }
86
87     /**
88      * @see ICVSResource#accept(ICVSResourceVisitor, boolean)
89      */

90     public void accept(ICVSResourceVisitor visitor, boolean recurse) throws CVSException {
91         visitor.visitFolder(this);
92         ICVSResource[] resources;
93         if (recurse) {
94             resources = members(ICVSFolder.ALL_MEMBERS);
95         } else {
96             resources = members(ICVSFolder.FILE_MEMBERS);
97         }
98         for (int i = 0; i < resources.length; i++) {
99             resources[i].accept(visitor, recurse);
100         }
101     }
102     
103     /*
104      * @see ICVSRemoteResource#exists(IProgressMonitor)
105      */

106     public boolean exists(IProgressMonitor monitor) throws TeamException {
107         try {
108             members(monitor);
109             return true;
110         } catch (CVSException e) {
111             if (e.getStatus().getCode() == CVSStatus.DOES_NOT_EXIST) {
112                 return false;
113             } else {
114                 throw e;
115             }
116         }
117     }
118
119     /*
120      * Check whether the given resource is a child of the receiver remotely
121      */

122     protected boolean exists(ICVSRemoteResource child, IProgressMonitor monitor) throws CVSException {
123         return exists(child, getTag(), monitor);
124     }
125     
126     /*
127      * Check whether the child exists for the given tag. This additional method is required because
128      * CVS will signal an error if a folder only contains subfolders when a tag is used. If we get this
129      * error and we're looking for a folder, we need to reissue the command without a tag.
130      */

131     protected boolean exists(final ICVSRemoteResource child, CVSTag tag, IProgressMonitor monitor) throws CVSException {
132         final IProgressMonitor progress = Policy.monitorFor(monitor);
133         progress.beginTask(CVSMessages.RemoteFolder_exists, 100);
134         try {
135             // Create the listener for remote files and folders
136
final boolean[] exists = new boolean[] {true};
137             final IUpdateMessageListener listener = new IUpdateMessageListener() {
138                 public void directoryInformation(ICVSFolder parent, String JavaDoc path, boolean newDirectory) {
139                     exists[0] = true;
140                 }
141                 public void directoryDoesNotExist(ICVSFolder parent, String JavaDoc path) {
142                     exists[0] = false;
143                 }
144                 public void fileInformation(int type, ICVSFolder parent, String JavaDoc filename) {
145                     // We can't set exists true here as we may get a conflict on a deleted file.
146
// i.e. remote files are always communicated to the server as modified.
147
if (type == Update.STATE_ADDED_LOCAL)
148                         exists[0] = false;
149                 }
150                 public void fileDoesNotExist(ICVSFolder parent, String JavaDoc filename) {
151                     exists[0] = false;
152                 }
153             };
154             
155             // Build the local options
156
final List JavaDoc localOptions = new ArrayList JavaDoc();
157             localOptions.add(Update.RETRIEVE_ABSENT_DIRECTORIES);
158             if (tag != null && tag.getType() != CVSTag.HEAD)
159                 localOptions.add(Update.makeTagOption(tag));
160             
161             // Retrieve the children and any file revision numbers in a single connection
162
// Perform a "cvs -n update -d -r tagName folderName" with custom message and error handlers
163
boolean retry = false;
164             Session session = new Session(getRepository(), this, false /* output to console */);
165             session.open(Policy.subMonitorFor(progress, 10), false /* read-only */);
166             try {
167                 IStatus status = Command.UPDATE.execute(
168                     session,
169                     new GlobalOption[] { Command.DO_NOT_CHANGE },
170                     (LocalOption[]) localOptions.toArray(new LocalOption[localOptions.size()]),
171                     new ICVSResource[] { child }, new UpdateListener(listener),
172                     Policy.subMonitorFor(progress, 70));
173                 if (status.getCode() == CVSStatus.SERVER_ERROR) {
174                     CVSServerException e = new CVSServerException(status);
175                     if (e.isNoTagException() && child.isContainer()) {
176                         retry = true;
177                     } else {
178                         if (e.containsErrors()) {
179                             throw e;
180                         }
181                     }
182                 }
183             } finally {
184                 session.close();
185             }
186
187             // We now know that this is an exception caused by a cvs bug.
188
// If the folder has no files in it (just subfolders) CVS does not respond with the subfolders...
189
// Workaround: Retry the request with no tag to get the directory names (if any)
190
if (retry) {
191                 Policy.checkCanceled(progress);
192                 return exists(child, null, Policy.subMonitorFor(progress, 20));
193             }
194             return exists[0];
195         } finally {
196             progress.done();
197         }
198     }
199
200     /**
201      * @see ICVSRemoteFolder#getMembers()
202      */

203     public ICVSRemoteResource[] getMembers(IProgressMonitor monitor) throws TeamException {
204         return getMembers(getTag(), monitor);
205     }
206
207     /**
208      * This method gets the members for a given tag and returns them.
209      * During the execution of this method, the instance variable children
210      * will be used to contain the children. However, the variable is reset
211      * and the result returned. Thus, instances of RemoteFolder do not
212      * persist the children. Subclasses (namely RemoteFolderTree) may
213      * persist the children.
214      */

215     protected ICVSRemoteResource[] getMembers(CVSTag tag, IProgressMonitor monitor) throws CVSException {
216         // Fetch the children
217
RemoteFolderMemberFetcher fetcher = new RemoteFolderMemberFetcher(this, tag);
218         fetcher.fetchMembers(Policy.monitorFor(monitor));
219         // children is assigned in the InternalRemoteFolderMembersFetcher
220
return children;
221     }
222
223     /**
224      * @see ICVSFolder#members(int)
225      */

226     public ICVSResource[] members(int flags) throws CVSException {
227         final List JavaDoc result = new ArrayList JavaDoc();
228         ICVSRemoteResource[] resources = getChildren();
229         if (children == null) {
230             return new ICVSResource[0];
231         }
232         // RemoteFolders never have phantom members
233
if ((flags & EXISTING_MEMBERS) == 0 && (flags & PHANTOM_MEMBERS) == PHANTOM_MEMBERS) {
234             return new ICVSResource[0];
235         }
236         boolean includeFiles = (((flags & FILE_MEMBERS) != 0) || ((flags & (FILE_MEMBERS | FOLDER_MEMBERS)) == 0));
237         boolean includeFolders = (((flags & FOLDER_MEMBERS) != 0) || ((flags & (FILE_MEMBERS | FOLDER_MEMBERS)) == 0));
238         boolean includeManaged = (((flags & MANAGED_MEMBERS) != 0) || ((flags & (MANAGED_MEMBERS | UNMANAGED_MEMBERS | IGNORED_MEMBERS)) == 0));
239         boolean includeUnmanaged = (((flags & UNMANAGED_MEMBERS) != 0) || ((flags & (MANAGED_MEMBERS | UNMANAGED_MEMBERS | IGNORED_MEMBERS)) == 0));
240         boolean includeIgnored = ((flags & IGNORED_MEMBERS) != 0);
241         for (int i = 0; i < resources.length; i++) {
242             ICVSResource cvsResource = resources[i];
243             if ((includeFiles && ( ! cvsResource.isFolder()))
244                     || (includeFolders && (cvsResource.isFolder()))) {
245                 boolean isManaged = cvsResource.isManaged();
246                 boolean isIgnored = cvsResource.isIgnored();
247                 if ((isManaged && includeManaged)|| (isIgnored && includeIgnored)
248                         || ( ! isManaged && ! isIgnored && includeUnmanaged)) {
249                     result.add(cvsResource);
250                 }
251                         
252             }
253         }
254         return (ICVSResource[]) result.toArray(new ICVSResource[result.size()]);
255     }
256     
257     /**
258      * @see ICVSFolder#getFolder(String)
259      */

260     public ICVSFolder getFolder(String JavaDoc name) throws CVSException {
261         if (name.equals(Session.CURRENT_LOCAL_FOLDER) || name.equals(Session.CURRENT_LOCAL_FOLDER + Session.SERVER_SEPARATOR))
262             return this;
263         ICVSResource child = getChild(name);
264         if (child.isFolder())
265             return (ICVSFolder)child;
266         IStatus status = new CVSStatus(IStatus.ERROR, CHILD_DOES_NOT_EXIST, NLS.bind(CVSMessages.RemoteFolder_invalidChild, new String JavaDoc[] { name, getName() }),child.getIResource());
267         throw new CVSException(status);
268     }
269
270     /**
271      * @see ICVSFolder#getFile(String)
272      */

273     public ICVSFile getFile(String JavaDoc name) throws CVSException {
274         ICVSResource child = getChild(name);
275         if (!child.isFolder())
276             return (ICVSFile)child;
277         IStatus status = new CVSStatus(IStatus.ERROR, CHILD_DOES_NOT_EXIST, NLS.bind(CVSMessages.RemoteFolder_invalidChild, new String JavaDoc[] { name, getName() }),child.getIResource());
278         throw new CVSException(status);
279     }
280
281     public LocalOption[] getLocalOptions() {
282         return Command.NO_LOCAL_OPTIONS;
283     }
284     
285     public String JavaDoc getRepositoryRelativePath() {
286         // The REPOSITORY property of the folder info is the repository relative path
287
return getFolderSyncInfo().getRepository();
288     }
289     
290     /**
291      * @see ICVSResource#getRelativePath(ICVSFolder)
292      */

293     public String JavaDoc getRelativePath(ICVSFolder ancestor) throws CVSException {
294         // Check to see if the receiver is the ancestor
295
if (ancestor == this) return Session.CURRENT_LOCAL_FOLDER;
296         // Otherwise, we need a parent to continue
297
if (parent == null) {
298             IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind(CVSMessages.RemoteFolder_invalidChild, new String JavaDoc[] { getName(), ancestor.getName() }),this);
299             throw new CVSException(status);
300         }
301         return super.getRelativePath(ancestor);
302     }
303     
304     public ICVSRepositoryLocation getRepository() {
305         return repository;
306     }
307     
308     /**
309      * @see ICVSRemoteFolder#isExpandable()
310      */

311     public boolean isExpandable() {
312         return true;
313     }
314     
315     /**
316      * @see ICVSResource#isFolder()
317      */

318     public boolean isFolder() {
319         return true;
320     }
321     
322     /**
323      * @see ICVSFolder#childExists(String)
324      */

325     public boolean childExists(String JavaDoc path) {
326         try {
327             return getChild(path) != null;
328         } catch (CVSException e) {
329             return false;
330         }
331     }
332
333     /**
334      * @see ICVSFolder#getChild(String)
335      *
336      * This getChild is geared to work with the Command hierarchy. Therefore it only returns
337      * children that were previously fetched by a call to getMembers(). If the request child
338      * does not exist, an exception is thrown.
339      */

340     public ICVSResource getChild(String JavaDoc path) throws CVSException {
341         if (path.equals(Session.CURRENT_LOCAL_FOLDER) || path.length() == 0)
342             return this;
343         if (path.indexOf(Session.SERVER_SEPARATOR) != -1) {
344             IPath p = new Path(null, path);
345             try {
346                 return ((RemoteFolder)getChild(p.segment(0))).getChild(p.removeFirstSegments(1).toString());
347             } catch (CVSException e) {
348                 // regenerate the exception to give as much info as possible
349
IStatus status = new CVSStatus(IStatus.ERROR, CHILD_DOES_NOT_EXIST, NLS.bind(CVSMessages.RemoteFolder_invalidChild, new String JavaDoc[] { path, getName() }),e,repository);
350                 throw new CVSException(status);
351             }
352         } else {
353             ICVSRemoteResource[] children = getChildren();
354             if (children == null){
355                 IStatus status = new CVSStatus(IStatus.ERROR, CHILD_DOES_NOT_EXIST, NLS.bind(CVSMessages.RemoteFolder_invalidChild, new String JavaDoc[] { path, getName() }),repository);
356                 throw new CVSException(status);
357             }
358             for (int i=0;i<children.length;i++) {
359                 if (children[i].getName().equals(path))
360                     return children[i];
361             }
362         }
363         IStatus status = new CVSStatus(IStatus.ERROR, CHILD_DOES_NOT_EXIST, NLS.bind(CVSMessages.RemoteFolder_invalidChild, new String JavaDoc[] { path, getName() }),repository);
364         throw new CVSException(status);
365     }
366
367     /**
368      * @see ICVSFolder#mkdir()
369      */

370     public void mkdir() throws CVSException {
371         IStatus status = new CVSStatus(IStatus.ERROR, CVSMessages.RemoteResource_invalidOperation);
372         throw new CVSException(status);
373     }
374
375     /**
376      * @see ICVSFolder#flush(boolean)
377      */

378     public void flush(boolean deep) {
379     }
380
381     /**
382      * @see ICVSFolder#getFolderInfo()
383      */

384     public FolderSyncInfo getFolderSyncInfo() {
385         return folderInfo;
386     }
387
388     /**
389      * @see ICVSResource#getRemoteLocation(ICVSFolder)
390      */

391     public String JavaDoc getRemoteLocation(ICVSFolder stopSearching) throws CVSException {
392         if (folderInfo == null) {
393             return Util.appendPath(parent.getRemoteLocation(stopSearching), getName());
394         }
395         return folderInfo.getRemoteLocation();
396     }
397     
398     /**
399      * @see ICVSFolder#isCVSFolder()
400      */

401     public boolean isCVSFolder() {
402         return folderInfo != null;
403     }
404
405     /**
406      * @see ICVSFolder#acceptChildren(ICVSResourceVisitor)
407      */

408     public void acceptChildren(ICVSResourceVisitor visitor) throws CVSException {
409         IStatus status = new CVSStatus(IStatus.ERROR, CVSMessages.RemoteResource_invalidOperation);
410         throw new CVSException(status);
411     }
412     
413     /*
414      * @see IRemoteResource#isContainer()
415      */

416     public boolean isContainer() {
417         return true;
418     }
419     
420     /*
421      * @see IRemoteResource#members(IProgressMonitor)
422      */

423     public ICVSRemoteResource[] members(IProgressMonitor progress) throws TeamException {
424         return getMembers(progress);
425     }
426
427     /*
428      * Answers the immediate cached children of this remote folder or null if the remote folder
429      * handle has not yet queried the server for the its children.
430      */

431     public ICVSRemoteResource[] getChildren() {
432         return children;
433     }
434     /*
435      * This allows subclass to set the children
436      */

437     protected void setChildren(ICVSRemoteResource[] children) {
438         this.children = children;
439     }
440     /*
441      * @see ICVSRemoteFolder#setTag(String)
442      */

443     public void setTag(CVSTag tag) {
444         MutableFolderSyncInfo newInfo = folderInfo.cloneMutable();
445         newInfo.setTag(tag);
446         setFolderSyncInfo(newInfo);
447     }
448
449     /*
450      * @see ICVSRemoteFolder#getTag()
451      */

452     public CVSTag getTag() {
453         if (folderInfo == null) return null;
454         return folderInfo.getTag();
455     }
456     /*
457      * @see ICVSFolder#setFolderInfo(FolderSyncInfo)
458      */

459     public void setFolderSyncInfo(FolderSyncInfo folderInfo) {
460         this.folderInfo = folderInfo.asImmutable();
461     }
462     
463     /*
464      * @see ICVSFolder#run(ICVSRunnable, IProgressMonitor)
465      */

466     public void run(ICVSRunnable job, IProgressMonitor monitor) throws CVSException {
467         job.run(monitor);
468     }
469     
470     /*
471      * @see ICVSFolder#tag(CVSTag, LocalOption[], IProgressMonitor)
472      */

473     public IStatus tag(final CVSTag tag, final LocalOption[] localOptions, IProgressMonitor monitor) throws CVSException {
474         monitor = Policy.monitorFor(monitor);
475         monitor.beginTask(null, 100);
476         Session session = new Session(getRepository(), this, true /* output to console */);
477         session.open(Policy.subMonitorFor(monitor, 10), true /* open for modification */);
478         try {
479             return Command.RTAG.execute(
480                 session,
481                 Command.NO_GLOBAL_OPTIONS,
482                 localOptions,
483                 folderInfo.getTag(),
484                 tag,
485                 new ICVSRemoteResource[] { RemoteFolder.this },
486             Policy.subMonitorFor(monitor, 90));
487         } finally {
488             session.close();
489         }
490      }
491      
492     /**
493      * @see ICVSFolder#fetchChildren(IProgressMonitor)
494      */

495     public ICVSResource[] fetchChildren(IProgressMonitor monitor) throws CVSException {
496         try {
497             return getMembers(monitor);
498         } catch(TeamException e) {
499             throw new CVSException(e.getStatus());
500         }
501     }
502     
503     public boolean equals(Object JavaDoc target) {
504         if ( ! super.equals(target)) return false;
505         RemoteFolder folder = (RemoteFolder)target;
506         // A simple folder is never equal to a defined module
507
if (folder.isDefinedModule() != isDefinedModule()) return false;
508         CVSTag tag1 = getTag();
509         CVSTag tag2 = folder.getTag();
510         if (tag1 == null) tag1 = CVSTag.DEFAULT;
511         if (tag2 == null) tag2 = CVSTag.DEFAULT;
512         return tag1.equals(tag2);
513     }
514     
515     /**
516      * @see java.lang.Object#hashCode()
517      */

518     public int hashCode() {
519         CVSTag tag = getTag();
520         if (tag == null) tag = CVSTag.DEFAULT;
521         return super.hashCode() | tag.getName().hashCode();
522     }
523     
524     /*
525      * The given root must be an ancestor of the receiver (or the receiver)
526      * and the path of the receiver must be a prefix of the provided path.
527      */

528     protected IPath getRelativePathFromRootRelativePath(ICVSFolder root, IPath path) throws CVSException {
529         // If the root is the receiver, then the path is already relative to the receiver
530
if (root == this) {
531             return path;
532         }
533         Assert.isTrue( ! path.isEmpty());
534         return getRelativePathFromRootRelativePath((ICVSFolder)root.getChild(path.segment(0)), path.removeFirstSegments(1));
535     }
536
537     /**
538      * @see ICVSRemoteFolder#forTag(CVSTag)
539      */

540     public ICVSRemoteResource forTag(ICVSRemoteFolder parent, CVSTag tagName) {
541         return new RemoteFolder((RemoteFolder)parent, getName(), repository, folderInfo.getRepository(), tagName, folderInfo.getIsStatic());
542     }
543     
544     /**
545      * @see ICVSRemoteFolder#forTag(CVSTag)
546      */

547     public ICVSRemoteResource forTag(CVSTag tagName) {
548         return (ICVSRemoteFolder)forTag(null, tagName);
549     }
550
551     /**
552      * @see org.eclipse.team.internal.ccvs.core.ICVSRemoteFolder#isDefinedModule()
553      */

554     public boolean isDefinedModule() {
555         return false;
556     }
557     
558     /**
559      * @see org.eclipse.team.internal.ccvs.core.resources.RemoteResource#getSyncInfo()
560      */

561     public ResourceSyncInfo getSyncInfo() {
562         return new ResourceSyncInfo(getName());
563     }
564
565     /* (non-Javadoc)
566      * @see org.eclipse.team.internal.ccvs.core.resources.RemoteResource#getSyncBytes()
567      */

568     public byte[] getSyncBytes() {
569         try {
570             return folderInfo.getBytes();
571         } catch (CVSException e) {
572             // This shouldn't even happen
573
return null;
574         }
575     }
576
577     /* (non-Javadoc)
578      * @see org.eclipse.team.core.sync.IRemoteResource#getContentIdentifier()
579      */

580     public String JavaDoc getContentIdentifier() {
581         return getTag().getName();
582     }
583     
584     /* (non-Javadoc)
585      * @see org.eclipse.team.internal.ccvs.core.ICVSResource#isManaged()
586      */

587     public boolean isManaged() {
588         return super.isManaged() && isCVSFolder();
589     }
590
591     /* (non-Javadoc)
592      * @see org.eclipse.team.core.synchronize.ResourceVariant#fetchContents(org.eclipse.core.runtime.IProgressMonitor)
593      */

594     protected void fetchContents(IProgressMonitor monitor) throws TeamException {
595         // This should not get called for folders
596
}
597
598 }
599
Popular Tags