Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 139267ef8510565f893be30baaeaedb21fa65cbd (plain) (tree)


































































































                                                                                                       
                                                                                      





























                                                                                                        
                                                                                                                 



























































                                                                                                                                                                  
/*******************************************************************************
 * Copyright (c) 2002 IBM Corporation and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 * IBM - Initial API and implementation
 ******************************************************************************/
package org.eclipse.team.internal.ccvs.core.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.team.ccvs.core.CVSProviderPlugin;
import org.eclipse.team.ccvs.core.CVSStatus;
import org.eclipse.team.internal.ccvs.core.CVSException;
import org.eclipse.team.internal.ccvs.core.Policy;
import org.eclipse.team.internal.ccvs.core.client.listeners.ICommandOutputListener;
import org.eclipse.team.internal.ccvs.core.client.listeners.IConsoleListener;

/**
 * Abstract base class for requests that are to be sent to the server.
 */
public abstract class Request {
	public static final ExpandModules EXPAND_MODULES = new ExpandModules();
	public static final ValidRequests VALID_REQUESTS = new ValidRequests();

	/*** Response handler map ***/
	private static final Map responseHandlers = new HashMap();
	static {
		registerResponseHandler(new CheckedInHandler());
		registerResponseHandler(new CopyHandler());
		registerResponseHandler(new ModTimeHandler());
		registerResponseHandler(new NewEntryHandler());
		registerResponseHandler(new RemovedHandler());
		registerResponseHandler(new RemoveEntryHandler());
		registerResponseHandler(new StaticHandler(true));
		registerResponseHandler(new StaticHandler(false));
		registerResponseHandler(new StickyHandler(true));
		registerResponseHandler(new StickyHandler(false));
		registerResponseHandler(new UpdatedHandler(UpdatedHandler.HANDLE_UPDATED));
		registerResponseHandler(new UpdatedHandler(UpdatedHandler.HANDLE_UPDATE_EXISTING));
		registerResponseHandler(new UpdatedHandler(UpdatedHandler.HANDLE_CREATED));
		registerResponseHandler(new UpdatedHandler(UpdatedHandler.HANDLE_MERGED));
		registerResponseHandler(new ValidRequestsHandler());
		registerResponseHandler(new ModuleExpansionHandler());		
	}
	private static void registerResponseHandler(ResponseHandler handler) {
		responseHandlers.put(handler.getResponseID(), handler);
	}
	private static ResponseHandler getResponseHandler(String responseID) {
		return (ResponseHandler)responseHandlers.get(responseID);
	}

	/**
	 * Prevents client code from instantiating us.
	 */
	protected Request() { }

	/**
	 * Returns the string used to invoke this request on the server.
	 * [template method]
	 * 
	 * @return the request identifier string
	 */
	protected abstract String getRequestId();

	/**
	 * Executes a request and processes the responses.
	 * 
	 * @param session the open CVS session
	 * @param listener the command output listener, or null to discard all messages
	 * @param monitor the progress monitor
	 * @return a status code indicating success or failure of the operation
	 */
	protected IStatus executeRequest(Session session, ICommandOutputListener listener,
		IProgressMonitor monitor) throws CVSException {
		// send request
		session.sendRequest(getRequestId());

		// This number can be tweaked if the monitor is judged to move too
		// quickly or too slowly. After some experimentation this is a good
		// number for both large projects (it doesn't move so quickly as to
		// give a false sense of speed) and smaller projects (it actually does
		// move some rather than remaining still and then jumping to 100).
		final int TOTAL_WORK = 300;
		monitor.beginTask(Policy.bind("Command.receivingResponses"), TOTAL_WORK); //$NON-NLS-1$
		int halfWay = TOTAL_WORK / 2;
		int currentIncrement = 4;
		int nextProgress = currentIncrement;
		int worked = 0;
		boolean isCVSNT = CVSProviderPlugin.getPlugin().isCustomizeForCVSNT();

		List accumulatedStatus = new ArrayList();
		for (;;) {
			// update monitor work amount
			if (--nextProgress <= 0) {
				monitor.worked(1);
				worked++;
				if (worked >= halfWay) {
					// we have passed the current halfway point, so double the
					// increment and reset the halfway point.
					currentIncrement *= 2;
					halfWay += (TOTAL_WORK - halfWay) / 2;				
				}
				// reset the progress counter to another full increment
				nextProgress = currentIncrement;
			}			
			Policy.checkCanceled(monitor);

			// retrieve a response line
			String response = session.readLine();
			int spacePos = response.indexOf(' ');
			String argument;
			if (spacePos != -1) {
				argument = response.substring(spacePos + 1);
				response = response.substring(0, spacePos);
			} else argument = "";  //$NON-NLS-1$

			// handle completion responses
			if (response.equals("ok")) {  //$NON-NLS-1$
				break;
			} else if (response.equals("error") || (isCVSNT && response.equals(""))) {  //$NON-NLS-1$
				if (argument.trim().length() == 0) {
					argument = Policy.bind("Command.serverError", Policy.bind("Command." + getRequestId()));  //$NON-NLS-1$  //$NON-NLS-2$
				}
				if (accumulatedStatus.isEmpty()) {
					accumulatedStatus.add(new CVSStatus(CVSStatus.ERROR, CVSStatus.SERVER_ERROR, Policy.bind("Command.noMoreInfoAvailable")));
				}
				return new MultiStatus(CVSProviderPlugin.ID, CVSStatus.SERVER_ERROR, 
					(IStatus[]) accumulatedStatus.toArray(new IStatus[accumulatedStatus.size()]),
					argument, null);
			// handle message responses
			} else if (response.equals("M")) {  //$NON-NLS-1$
				IStatus status = listener.messageLine(argument, session.getLocalRoot(), monitor);
				if (status != ICommandOutputListener.OK) accumulatedStatus.add(status);
				if (session.isOutputToConsole()) {
					IConsoleListener consoleListener = CVSProviderPlugin.getPlugin().getConsoleListener();
					if (consoleListener != null) consoleListener.messageLineReceived(argument);
				}
			} else if (response.equals("E")) { //$NON-NLS-1$
				IStatus status = listener.errorLine(argument, session.getLocalRoot(), monitor);
				if (status != ICommandOutputListener.OK) accumulatedStatus.add(status);
				if (session.isOutputToConsole()) {
					IConsoleListener consoleListener = CVSProviderPlugin.getPlugin().getConsoleListener();
					if (consoleListener != null) consoleListener.errorLineReceived(argument);
				}
			// handle other responses
			} else {
				ResponseHandler handler = (ResponseHandler) responseHandlers.get(response);
				if (handler != null) {
					handler.handle(session, argument, monitor);
				} else {
					throw new CVSException(new org.eclipse.core.runtime.Status(IStatus.ERROR,
						CVSProviderPlugin.ID, CVSException.IO_FAILED,
						Policy.bind("Command.unsupportedResponse", response, argument), null)); //$NON-NLS-1$
				}
			}
		}
		if (accumulatedStatus.isEmpty()) {
			return ICommandOutputListener.OK;
		} else {
			return new MultiStatus(CVSProviderPlugin.ID, CVSStatus.INFO,
				(IStatus[]) accumulatedStatus.toArray(new IStatus[accumulatedStatus.size()]),
				Policy.bind("Command.warnings", Policy.bind("Command." + getRequestId())), null);  //$NON-NLS-1$  //$NON-NLS-2$
		}
	}
	
	/**
	 * Makes a list of all valid responses; for initializing a session.
	 * @return a space-delimited list of all valid response strings
	 */
	static String makeResponseList() {
		StringBuffer result = new StringBuffer("ok error M E");  //$NON-NLS-1$
		Iterator elements = responseHandlers.keySet().iterator();
		while (elements.hasNext()) {
			result.append(' ');
			result.append((String) elements.next());
		}
		
		return result.toString();
	}
}

Back to the top