001: /*****************************************************************************
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is the CVS Client Library.
027: * The Initial Developer of the Original Software is Robert Greig.
028: * Portions created by Robert Greig are Copyright (C) 2000.
029: * All Rights Reserved.
030: *
031: * If you wish your version of this file to be governed by only the CDDL
032: * or only the GPL Version 2, indicate your decision by adding
033: * "[Contributor] elects to include this software in this distribution
034: * under the [CDDL or GPL Version 2] license." If you do not indicate a
035: * single choice of license, a recipient has the option to distribute
036: * your version of this file under either the CDDL, the GPL Version 2 or
037: * to extend the choice of license to its licensees as provided above.
038: * However, if you add GPL Version 2 code and therefore, elected the GPL
039: * Version 2 license, then the option applies only if the new code is
040: * made subject to such option by the copyright holder.
041: *
042: * Contributor(s): Robert Greig.
043: *****************************************************************************/package org.netbeans.lib.cvsclient.command;
044:
045: import org.netbeans.lib.cvsclient.*;
046: import org.netbeans.lib.cvsclient.connection.*;
047: import org.netbeans.lib.cvsclient.event.*;
048:
049: import java.io.UnsupportedEncodingException;
050:
051: /**
052: * A class that provides common functionality for many of the CVS command
053: * that send similar sequences of requests.
054: * @author Robert Greig
055: */
056: public abstract class BuildableCommand extends Command {
057:
058: /**
059: * An implementation of Builder interface that constructs a FileContainerInfo object from
060: * the server's output..
061: */
062: protected Builder builder;
063:
064: private final StringBuffer taggedLineBuffer = new StringBuffer();
065:
066: /**
067: * A boolean value indicating if the user has used the setBuilder() method.
068: */
069: private boolean builderSet;
070:
071: /**
072: * Execute a command. This implementation sends a Root request, followed
073: * by as many Directory and Entry requests as is required by the recurse
074: * setting and the file arguments that have been set. Subclasses should
075: * call this first, and tag on the end of the requests list any further
076: * requests and, finally, the actually request that does the command (e.g.
077: * <pre>update</pre>, <pre>status</pre> etc.)
078: * @param client the client services object that provides any necessary
079: * services to this command, including the ability to actually process
080: * all the requests
081: * @throws CommandException if an error occurs executing the command
082: */
083: public void execute(ClientServices client, EventManager eventManager)
084: throws CommandException, AuthenticationException {
085: super .execute(client, eventManager);
086:
087: if (builder == null && !isBuilderSet()) {
088: builder = createBuilder(eventManager);
089: }
090: }
091:
092: /**
093: * Method that is called while the command is being executed.
094: * Descendants can override this method to return a Builder instance
095: * that will parse the server's output and create data structures.
096: */
097: public Builder createBuilder(EventManager eventManager) {
098: return null;
099: }
100:
101: public void messageSent(BinaryMessageEvent e) {
102: super .messageSent(e);
103:
104: if (builder == null) {
105: return;
106: }
107:
108: if (builder instanceof BinaryBuilder) { // XXX assert it?
109: BinaryBuilder binaryBuilder = (BinaryBuilder) builder;
110: binaryBuilder.parseBytes(e.getMessage(), e
111: .getMessageLength());
112: }
113: }
114:
115: public void messageSent(MessageEvent e) {
116: super .messageSent(e);
117: if (builder == null) {
118: return;
119: }
120:
121: if (e instanceof EnhancedMessageEvent) {
122: EnhancedMessageEvent eEvent = (EnhancedMessageEvent) e;
123: builder.parseEnhancedMessage(eEvent.getKey(), eEvent
124: .getValue());
125: return;
126: }
127:
128: if (e.isTagged()) {
129: String message = MessageEvent.parseTaggedMessage(
130: taggedLineBuffer, e.getMessage());
131: if (message != null) {
132: builder.parseLine(message, false);
133: taggedLineBuffer.setLength(0);
134: }
135: } else {
136: if (taggedLineBuffer.length() > 0) {
137: builder.parseLine(taggedLineBuffer.toString(), false);
138: taggedLineBuffer.setLength(0);
139: }
140: //#67337 do not interpret piped data using platform default encoding
141: // UTF-8 causes problems as raw data (non UTf-8) can contain confusing sequences
142: // use safe encoding that does not interpret byte sequences
143: if (builder instanceof PipedFilesBuilder
144: && e.isError() == false) {
145: try {
146: String iso88591 = new String(e.getRawData(),
147: "ISO-8859-1");
148: builder.parseLine(iso88591, e.isError());
149: } catch (UnsupportedEncodingException e1) {
150: assert false;
151: }
152: } else {
153: builder.parseLine(e.getMessage(), e.isError());
154: }
155: }
156: }
157:
158: /**
159: * Returns whether the builder is set.
160: */
161: protected boolean isBuilderSet() {
162: return builderSet;
163: }
164:
165: /**
166: * Used for setting user-defined builder.
167: * Can be also set null, in that case the builder mechanism is not used at
168: * all.
169: */
170: public void setBuilder(Builder builder) {
171: this .builder = builder;
172: builderSet = true;
173: }
174:
175: /**
176: * Called when server responses with "ok" or "error", (when the command finishes).
177: */
178: public void commandTerminated(TerminationEvent e) {
179: if (builder == null) {
180: return;
181: }
182:
183: if (taggedLineBuffer.length() > 0) {
184: builder.parseLine(taggedLineBuffer.toString(), false);
185: taggedLineBuffer.setLength(0);
186: }
187: builder.outputDone();
188: }
189: }
|