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.response;
044:
045: import java.io.*;
046: import java.util.*;
047: import java.text.*;
048:
049: import org.netbeans.lib.cvsclient.admin.*;
050: import org.netbeans.lib.cvsclient.event.*;
051: import org.netbeans.lib.cvsclient.file.*;
052: import org.netbeans.lib.cvsclient.util.*;
053: import org.netbeans.lib.cvsclient.command.DefaultFileInfoContainer;
054:
055: /**
056: * Sends a new copy of a particular file, indicating that the file currently
057: * checked-out needs to be updated with the one sent with this response.
058: * @author Robert Greig
059: */
060: class UpdatedResponse implements Response {
061: private static final boolean DEBUG = false;
062:
063: /**
064: * The local path of the new file.
065: */
066: private String localPath;
067:
068: /**
069: * The full repository path of the file.
070: */
071: private String repositoryPath;
072:
073: /**
074: * The entry line.
075: */
076: private String entryLine;
077:
078: /**
079: * The mode.
080: */
081: private String mode;
082:
083: /**
084: * fullpath to the file being processed. Is used in Merged response when sending EnhancedMessageEvent
085: */
086: protected String localFile;
087:
088: /**
089: * The date Formatter used to parse and format dates.
090: * Format is: "EEE MMM dd HH:mm:ss yyyy"
091: */
092: private DateFormat dateFormatter;
093:
094: /**
095: * Process the data for the response.
096: * @param r the buffered reader allowing the client to read the server's
097: * response. Note that the actual response name has already been read
098: * and the reader is positioned just before the first argument, if any.
099: * @param services various services that are useful to response handlers
100: * @throws ResponseException if something goes wrong handling this response
101: */
102: public void process(LoggedDataInputStream dis,
103: ResponseServices services) throws ResponseException {
104: try {
105: localPath = dis.readLine();
106: repositoryPath = dis.readLine();
107: entryLine = dis.readLine();
108: mode = dis.readLine();
109:
110: String nextLine = dis.readLine();
111:
112: boolean useGzip = (nextLine.charAt(0) == 'z');
113:
114: int length = Integer.parseInt(useGzip ? nextLine
115: .substring(1) : nextLine);
116:
117: if (DEBUG) {
118: System.err.println("Got update response."); //NOI18N
119: System.err.println("LocalPath is : "
120: + localPath); //NOI18N
121: System.err.println("Repository path is : "
122: + repositoryPath); //NOI18N
123: System.err.println("Entries line is : "
124: + entryLine); //NOI18N
125: System.err.println("Mode is : " + mode); //NOI18N
126: System.err.println("Next line (length) is : "
127: + nextLine); //NOI18N
128: System.err.println("File length is : " + length); //NOI18N
129: }
130:
131: // now read in the file
132: final String filePath = services.convertPathname(localPath,
133: repositoryPath);
134:
135: final File newFile = new File(filePath);
136: localFile = newFile.getAbsolutePath();
137:
138: if (services.getGlobalOptions().isExcluded(newFile)) {
139: skip(dis, length);
140: return;
141: }
142:
143: if (this instanceof CreatedResponse) {
144: if (newFile.exists()) {
145: skip(dis, length);
146: // Fire "C file.txt" type of event. This event is caught directly by clients of the library
147: DefaultFileInfoContainer fic = new DefaultFileInfoContainer();
148: fic.setType("C");
149: fic.setFile(newFile);
150: services.getEventManager().fireCVSEvent(
151: new FileInfoEvent(this , fic));
152: return;
153: }
154: }
155:
156: final Entry entry = new Entry(entryLine);
157:
158: FileHandler fileHandler = useGzip ? services
159: .getGzipFileHandler() : services
160: .getUncompressedFileHandler();
161: fileHandler.setNextFileDate(services.getNextFileDate());
162:
163: // check if the file is binary
164: if (entry.isBinary()) {
165: fileHandler
166: .writeBinaryFile(filePath, mode, dis, length);
167: } else {
168: fileHandler.writeTextFile(filePath, mode, dis, length);
169: }
170:
171: // we set the date the file was last modified in the Entry line
172: // so that we can easily determine whether the file has been
173: // untouched
174: // for files with conflicts skip the setting of the conflict field.
175: String conflictString = null;
176: if ((entry.getConflict() != null)
177: && (entry.getConflict().charAt(0) == Entry.HAD_CONFLICTS)) {
178: if (entry.getConflict().charAt(1) == Entry.TIMESTAMP_MATCHES_FILE) {
179: final Date d = new Date(newFile.lastModified());
180: conflictString = getEntryConflict(d, true);
181: } else {
182: conflictString = entry.getConflict().substring(1);
183: }
184: } else {
185: final Date d = new Date(newFile.lastModified());
186: conflictString = getEntryConflict(d, false);
187: }
188: entry.setConflict(conflictString);
189: // fix for correctly merging files that are added in other branches.
190: if (entry.isNewUserFile()) {
191: entry.setConflict(Entry.DUMMY_TIMESTAMP);
192: }
193: // update the admin files (i.e. within the CVS directory)
194: services.updateAdminData(localPath, repositoryPath, entry);
195:
196: // now fire the appropriate event
197: if (newFile.exists()) {
198: FileAddedEvent e = new FileAddedEvent(this , filePath);
199: services.getEventManager().fireCVSEvent(e);
200: } else {
201: FileUpdatedEvent e = new FileUpdatedEvent(this ,
202: filePath);
203: services.getEventManager().fireCVSEvent(e);
204: }
205: //System.err.println("Finished writing file");
206: } catch (IOException e) {
207: throw new ResponseException(e);
208: }
209: }
210:
211: private void skip(LoggedDataInputStream dis, int length)
212: throws IOException {
213: while (length > 0) {
214: length -= dis.skip(length);
215:
216: }
217: }
218:
219: /**
220: * Returns the Conflict field for the file's entry.
221: * Can be overriden by subclasses.
222: * (For example the MergedResponse that sets the "result of merge" there.)
223: * @param date the date to put in
224: * @param hadConflicts if there were conflicts (e.g after merge)
225: * @return the conflict field
226: */
227: protected String getEntryConflict(Date date, boolean hadConflicts) {
228: return getDateFormatter().format(date);
229: }
230:
231: /**
232: * Returns the DateFormatter instance that parses and formats date Strings.
233: * The exact format matches the one in Entry.getLastModifiedDateFormatter() method.
234: *
235: */
236: protected DateFormat getDateFormatter() {
237: if (dateFormatter == null) {
238: dateFormatter = Entry.getLastModifiedDateFormatter();
239: }
240: return dateFormatter;
241: }
242:
243: /**
244: * Is this a terminal response, i.e. should reading of responses stop
245: * after this response. This is true for responses such as OK or
246: * an error response
247: */
248: public boolean isTerminalResponse() {
249: return false;
250: }
251: }
|