Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderMemberFetcher.java')
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderMemberFetcher.java316
1 files changed, 316 insertions, 0 deletions
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderMemberFetcher.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderMemberFetcher.java
new file mode 100644
index 000000000..7897e831c
--- /dev/null
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderMemberFetcher.java
@@ -0,0 +1,316 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.internal.ccvs.core.resources;
+
+import java.util.*;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.team.internal.ccvs.core.*;
+import org.eclipse.team.internal.ccvs.core.client.*;
+import org.eclipse.team.internal.ccvs.core.client.Command.*;
+import org.eclipse.team.internal.ccvs.core.client.listeners.*;
+import org.eclipse.team.internal.ccvs.core.connection.CVSServerException;
+import org.eclipse.team.internal.ccvs.core.util.Util;
+
+/**
+ * Fetch the children for the given parent folder. When fetchMembers is invoked,
+ * the children of the folder will be fetched from the server and assigned to
+ * the children of the parent folder.
+ */
+public class RemoteFolderMemberFetcher implements IUpdateMessageListener, IStatusListener {
+
+ private final RemoteFolder parentFolder;
+ private CVSTag tag;
+
+ List folders = new ArrayList(); // RemoteFolder
+ List files = new ArrayList(); // RemoteFile
+ boolean exists = true;
+ List exceptions = new ArrayList(); // CVSException
+
+ protected RemoteFolderMemberFetcher(RemoteFolder parentFolder, CVSTag tag) {
+ this.tag = tag;
+ this.parentFolder = parentFolder;
+ }
+
+ /**
+ * Fetch the members for a given tag and returns them.
+ * During the execution of this method, the instance variable children
+ * will be used to contain the children. However, the variable is reset
+ * and the result returned. Thus, instances of RemoteFolder do not
+ * persist the children. Subclasses (namely RemoteFolderTree) may
+ * persist the children.
+ */
+ public void fetchMembers(IProgressMonitor monitor) throws CVSException {
+ fetchMembers(monitor, tag);
+ }
+ public void fetchMembers(IProgressMonitor monitor, CVSTag tag) throws CVSException {
+ final IProgressMonitor progress = Policy.monitorFor(monitor);
+ progress.beginTask(CVSMessages.RemoteFolder_getMembers, 100);
+ try {
+ // Update the parent folder children so there are no children
+ updateParentFolderChildren();
+ // Perform an update to retrieve the child files and folders
+ IStatus status = performUpdate(Policy.subMonitorFor(progress, 50), tag);
+ // Update the parent folder with the new children
+ updateParentFolderChildren();
+ Policy.checkCanceled(monitor);
+
+ // Handle any errors that were identified by the listener
+ performErrorCheck(status, CVSMessages.RemoteFolder_errorFetchingMembers);
+
+ // Get the revision numbers for the files
+ ICVSFile[] remoteFiles = getFiles();
+ if (remoteFiles.length > 0) {
+ updateFileRevisions(remoteFiles, Policy.subMonitorFor(progress, 50));
+ } else {
+ progress.worked(50);
+ }
+ } catch (CVSServerException e) {
+ if ( ! e.isNoTagException() && e.containsErrors())
+ throw e;
+ if (tag == null)
+ throw e;
+ // we now know that this is an exception caused by a cvs bug.
+ // if the folder has no files in it (just subfolders) cvs does not respond with the subfolders...
+ // workaround: retry the request with no tag to get the directory names (if any)
+ Policy.checkCanceled(progress);
+ fetchMembers(Policy.subMonitorFor(progress, 50), null);
+ } finally {
+ progress.done();
+ }
+ }
+
+ protected IStatus performUpdate(IProgressMonitor progress, CVSTag tag) throws CVSException {
+ progress.beginTask(null, 100);
+ Session session = new Session(parentFolder.getRepository(), parentFolder, false /* output to console */);
+ session.open(Policy.subMonitorFor(progress, 10), false /* read-only */);
+ try {
+ // Build the local options
+ final List localOptions = new ArrayList();
+ localOptions.add(Update.RETRIEVE_ABSENT_DIRECTORIES);
+ if (tag != null) localOptions.add(Update.makeTagOption(tag));
+
+ return Command.UPDATE.execute(
+ session,
+ new GlobalOption[] { Command.DO_NOT_CHANGE },
+ (LocalOption[])localOptions.toArray(new LocalOption[localOptions.size()]),
+ new ICVSResource[] { parentFolder },
+ new UpdateListener(this),
+ Policy.subMonitorFor(progress, 90));
+ } finally {
+ session.close();
+ }
+ }
+
+ protected void updateFileRevisions(final ICVSFile[] files, IProgressMonitor monitor) throws CVSException {
+
+ // Perform a "cvs status..." with a listener
+ monitor = Policy.monitorFor(monitor);
+ monitor.beginTask(null, 100);
+ QuietOption quietness = CVSProviderPlugin.getPlugin().getQuietness();
+ try {
+ CVSProviderPlugin.getPlugin().setQuietness(Command.VERBOSE);
+ Session session = new Session(parentFolder.getRepository(), parentFolder, false /* output to console */);
+ session.open(Policy.subMonitorFor(monitor, 10), false /* read-only */);
+ try {
+ IStatus status = Command.STATUS.execute(
+ session,
+ Command.NO_GLOBAL_OPTIONS,
+ Command.NO_LOCAL_OPTIONS,
+ files,
+ new StatusListener(this),
+ Policy.subMonitorFor(monitor, 90));
+ performErrorCheck(status, CVSMessages.RemoteFolder_errorFetchingRevisions);
+ // TODO: Ensure all files have a revision?
+ } finally {
+ session.close();
+ }
+ } finally {
+ CVSProviderPlugin.getPlugin().setQuietness(quietness);
+ }
+ }
+
+ private void performErrorCheck(IStatus status, String errorTitle) throws CVSException {
+ if (status.getCode() == CVSStatus.SERVER_ERROR) {
+ // Only throw the exception if no files or folders were found
+ if (folders.size() + files.size() == 0) {
+ throw new CVSServerException(status);
+ } else {
+ CVSProviderPlugin.log(new CVSServerException(status));
+ }
+ }
+ if (!exists) {
+ IStatus notExistStatus = new CVSStatus(IStatus.ERROR, CVSStatus.DOES_NOT_EXIST, NLS.bind(CVSMessages.RemoteFolder_doesNotExist, new String[] { this.parentFolder.getRepositoryRelativePath() }), parentFolder);
+ throw new CVSException(notExistStatus);
+ }
+
+ // Report any internal exceptions that occurred fetching the members
+ if ( ! exceptions.isEmpty()) {
+ if (exceptions.size() == 1) {
+ throw (CVSException)exceptions.get(0);
+ } else {
+ MultiStatus multi = new MultiStatus(CVSProviderPlugin.ID, 0, errorTitle, null);
+ for (int i = 0; i < exceptions.size(); i++) {
+ multi.merge(((CVSException)exceptions.get(i)).getStatus());
+ }
+ throw new CVSException(multi);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.ccvs.core.client.listeners.IUpdateMessageListener#directoryInformation(org.eclipse.team.internal.ccvs.core.ICVSFolder, java.lang.String, boolean)
+ */
+ public void directoryInformation(ICVSFolder commandRoot, String stringPath, boolean newDirectory) {
+ try {
+ IPath path = this.parentFolder.getRelativePathFromRootRelativePath(commandRoot, new Path(null, stringPath));
+ if (path.segmentCount() == 1) {
+ String pathName = path.lastSegment();
+ if (!pathName.equals(".")) { //$NON-NLS-1$
+ recordFolder(path.lastSegment());
+ }
+ }
+ } catch (CVSException e) {
+ exceptions.add(e);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.ccvs.core.client.listeners.IUpdateMessageListener#directoryDoesNotExist(org.eclipse.team.internal.ccvs.core.ICVSFolder, java.lang.String)
+ */
+ public void directoryDoesNotExist(ICVSFolder parent, String stringPath) {
+ try {
+ IPath path = this.parentFolder.getRelativePathFromRootRelativePath(parent, new Path(null, stringPath));
+ if (path.isEmpty()) {
+ parentDoesNotExist();
+ }
+ } catch (CVSException e) {
+ exceptions.add(e);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.ccvs.core.client.listeners.IUpdateMessageListener#fileInformation(int, org.eclipse.team.internal.ccvs.core.ICVSFolder, java.lang.String)
+ */
+ public void fileInformation(int type, ICVSFolder parent, String filename) {
+ try {
+ IPath filePath = new Path(null, filename);
+ filePath = this.parentFolder.getRelativePathFromRootRelativePath(parent, filePath);
+ if( filePath.segmentCount() == 1 ) {
+ String properFilename = filePath.lastSegment();
+ recordFile(properFilename);
+ }
+ } catch (CVSException e) {
+ exceptions.add(e);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.ccvs.core.client.listeners.IUpdateMessageListener#fileDoesNotExist(org.eclipse.team.internal.ccvs.core.ICVSFolder, java.lang.String)
+ */
+ public void fileDoesNotExist(ICVSFolder parent, String filename) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.ccvs.core.client.listeners.IStatusListener#fileStatus(org.eclipse.team.internal.ccvs.core.ICVSFolder, java.lang.String, java.lang.String)
+ */
+ public void fileStatus(ICVSFolder commandRoot, String path, String remoteRevision) {
+ if (remoteRevision == IStatusListener.FOLDER_REVISION)
+ // Ignore any folders
+ return;
+ try {
+ ((RemoteFile)parentFolder.getChild(Util.getLastSegment(path))).setRevision(remoteRevision);
+ } catch (CVSException e) {
+ exceptions.add(e);
+ }
+ }
+
+ /**
+ * This method is invoked for each child folder as the responses are being received from
+ * the server. Default behavior is to record the folder for later retrieval using <code>getChilren()</code>.
+ * Subclasses may override but should invoke the inherited method to ensure the folder gets recorded.
+ * @param name the name of the child folder
+ */
+ protected RemoteFolder recordFolder(String name) {
+ RemoteFolder folder = new RemoteFolder(
+ parentFolder,
+ parentFolder.getRepository(),
+ Util.appendPath(parentFolder.getRepositoryRelativePath(), name),
+ tag);
+ folders.add(folder);
+ return folder;
+ }
+
+ /**
+ * This method is invoked for each child file as the responses are being received from
+ * the server. Default behavior is to record the file for later retrieval using <code>getChildren()</code>.
+ * Subclasses may override but should invoke the inherited method to ensure the file gets recorded.
+ * This is important because the file revisions for any files are fetched subsequent to the fetching
+ * of the children.
+ * @param name the name of the child folder
+ */
+ protected RemoteFile recordFile(String name) {
+ RemoteFile file = new RemoteFile(
+ parentFolder,
+ Update.STATE_NONE,
+ name,
+ null, /* revision unknown */
+ null, /* keyword mode unknown */
+ tag);
+ files.add(file);
+ return file;
+ }
+
+ /**
+ * This method is invoked to indicate that the parent being queried for children
+ * does not exist. Subclasses may override to get early notification of this but
+ * should still invoke the inherited method.
+ */
+ protected void parentDoesNotExist() {
+ exists = false;
+ }
+
+ /**
+ * Update the parent folder such that it's children are the
+ * children that have been fetched by the receiver.
+ */
+ protected void updateParentFolderChildren() {
+ parentFolder.setChildren(getFetchedChildren());
+ }
+
+ /**
+ * Return the child files fetched from the server.
+ * @return
+ */
+ protected ICVSFile[] getFiles() {
+ return (ICVSFile[]) files.toArray(new ICVSFile[files.size()]);
+ }
+
+ /**
+ * Return an array of all fetched children.
+ * @return
+ */
+ public ICVSRemoteResource[] getFetchedChildren() {
+ ICVSRemoteResource[] resources = new ICVSRemoteResource[folders.size() + files.size()];
+ int count = 0;
+ for (Iterator iter = folders.iterator(); iter.hasNext();) {
+ ICVSRemoteResource resource = (ICVSRemoteResource) iter.next();
+ resources[count++] = resource;
+ }
+ for (Iterator iter = files.iterator(); iter.hasNext();) {
+ ICVSRemoteResource resource = (ICVSRemoteResource) iter.next();
+ resources[count++] = resource;
+ }
+ return resources;
+ }
+
+}

Back to the top