KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > lib > cvsclient > file > WriteRcsDiffFilePreprocessor


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.lib.cvsclient.file;
21
22 import java.io.*;
23 import org.netbeans.lib.cvsclient.util.*;
24
25 /**
26  * File Processor that handles processing of rcs-diff response.
27  * (aka diff -n format) The original file is read and a merge is created.
28  * At the same time the correct line-ending is processed.
29  * It's possible to set the processor the preffered line-ending.
30  * The default is dependant on the platform.
31  *
32  * @author Milos Kleint
33  */

34 public class WriteRcsDiffFilePreprocessor implements WriteTextFilePreprocessor {
35
36     private static final int CHUNK_SIZE = 32768;
37
38     private static final int READ_REMAINING = -2;
39
40     /**
41      * line ending that will be used when writing the final result file.
42      */

43     private String JavaDoc lineEnding = System.getProperty("line.separator");
44
45     public WriteRcsDiffFilePreprocessor() {
46     }
47
48     /**
49      * Gets the value of lineending used when writing the resulting file.
50      * @return Value of property lineEnding.
51      */

52     public String JavaDoc getLineEnding() {
53         return lineEnding;
54     }
55
56     /**
57      * Setter for lineEnding used to write the file.
58      * @param lineEnding New value of property lineEnding.
59      */

60     public void setLineEnding(String JavaDoc lineEnding) {
61         this.lineEnding = lineEnding;
62     }
63
64     /**
65      * Processes the diff and merges it with the original file.
66      * @param processedInput the stored diff.
67      * @param fileToWrite the resulting file and
68      * the original that is merged as the same time.
69      * @param customOutput
70      * @throws IOException if any IO operation fails.
71      * The original file is replaced by the merge only if no excpetion is thrown.
72      */

73     public void copyTextFileToLocation(InputStream processedInput, File fileToWrite, OutputStreamProvider customOutput)
74             throws IOException {
75         // Here we read the temp file in again, doing any processing required
76
// (for example, unzipping). We must not convert the bytes to characters
77
// because this would corrupt files, that were written in an encoding
78
// different from the current encoding.
79
ReadInfo tempFileReader = null;
80         OutputStream out = null;
81         ReadInfo tempDiffReader = null;
82         File tempFile = null;
83         // BUGLOG.. assert the fileToWrite Exists.. otherwise it has no sense.
84

85         try {
86             tempDiffReader = new ReadInfo(new BufferedInputStream(processedInput));
87             tempFileReader = new ReadInfo(new BufferedInputStream(new FileInputStream(fileToWrite)));
88             tempFile = File.createTempFile(".#merg", "cvs"); //NOI18N
89

90             out = new BufferedOutputStream(new FileOutputStream(tempFile));
91
92             int fileStart = 0;
93             int diffCount = 0;
94             byte[] diff = tempDiffReader.readLine();
95             while (diff != null && diff.length > 0) {
96 // System.out.println("diffline=" + diff);
97
if (diff[0] == 'd') {
98                     // now do delete..
99
int startLine = getStart(diff);
100                     int count = getLength(diff);
101 // System.out.println("deleting. start =" + startLine + " count=" + count);
102
if (startLine >= 0 && count > 0) {
103                         // read from file only if deletion is not some
104
// from the beginning..
105
readToLine(startLine - 1, tempFileReader, out);
106                         readToLine(startLine - 1 + count, tempFileReader, null);
107                         // null skips the lines..
108
}
109                     else {
110                         // BugLog..
111
BugLog.getInstance().bug("wrong parsing.." + new String JavaDoc(diff));
112                         throw new IOException(); // Interrupt the merging process so that the file is not corrupted.
113
}
114                 }
115                 else if (diff[0] == 'a') {
116                     // now add lines from the diff..
117
int startLine = getStart(diff);
118                     int count = getLength(diff);
119 // System.out.println("adding.. start =" + startLine + " count=" + count);
120
if (startLine >= 0 && count > 0) {
121                         readToLine(startLine, tempFileReader, out);
122                         tempDiffReader.setLineNumber(0);
123                         readToLine(count, tempDiffReader, out);
124                     }
125                     else {
126                         // BugLog..
127
BugLog.getInstance().bug("wrong parsing.." + new String JavaDoc(diff));
128                         throw new IOException(); // Interrupt the merging process so that the file is not corrupted.
129
}
130                 }
131                 // now process next difference.
132
diff = tempDiffReader.readLine();
133             }
134             // read what's remaining..
135
readToLine(READ_REMAINING, tempFileReader, out);
136
137             if (tempFile != null) {
138                 tempFileReader.close();
139                 out.close();
140                 InputStream in = null;
141                 OutputStream customOutputStream = customOutput.createOutputStream();
142                 try {
143                     in = new BufferedInputStream(new FileInputStream(tempFile));
144                     while (true) {
145                         int ch = in.read();
146                         if (ch == -1) {
147                             break;
148                         }
149                         customOutputStream.write(ch);
150                     }
151                 } finally {
152                     if (in != null) {
153                         try {
154                             in.close();
155                         } catch (IOException ex) {
156                         }
157                     }
158                     try {
159                         customOutputStream.close();
160                     } catch (IOException ex) {
161                     }
162                 }
163             }
164         }
165         catch (Exception JavaDoc exc) {
166             BugLog.getInstance().showException(exc);
167         }
168         finally {
169             if (tempDiffReader != null) {
170                 try {
171                     tempDiffReader.close();
172                 }
173                 catch (IOException ex) {
174                     // ignore
175
}
176             }
177             if (tempFileReader != null) {
178                 try {
179                     tempFileReader.close();
180                 }
181                 catch (IOException ex) {
182                     // ignore
183
}
184             }
185             if (out != null) {
186                 try {
187                     out.close();
188                 }
189                 catch (IOException ex) {
190                     // ignore
191
}
192             }
193             if (tempFile != null) {
194                 tempFile.delete();
195             }
196         }
197     }
198
199     /**
200      * Reads lines from the reader until the specified line number is reached.
201      * Writes the lines to the writer
202      * @param finalLine the last line to read/write. Special value -2 reads
203      * all that is remaining in the reader.
204      * @param reader - does not accept null.
205      * @param writer the writer that the read lines are written to. Accepts null.
206      * In such a case the read lines are discarded.
207      */

208     private void readToLine(int finalLine, final ReadInfo reader,
209                                    final OutputStream out) throws IOException {
210         byte[] line;
211         while (reader.getLineNumber() < finalLine || finalLine == READ_REMAINING) {
212             line = reader.readLine();
213             if (line == null) {
214                 // end of file..
215
return;
216             }
217             if (out != null) {
218                 out.write(line);
219                 out.write(getLineEnding().getBytes());
220             }
221         }
222     }
223     
224     private static int indexOf(byte[] bytes, byte b) {
225         return indexOf(bytes, b, 0);
226     }
227     
228     private static int indexOf(byte[] bytes, byte b, int start) {
229         int index = -1;
230         for (int i = start; i < bytes.length; i++) {
231             if (bytes[i] == b) {
232                 index = i;
233                 break;
234             }
235         }
236         return index;
237     }
238
239     /**
240      * Extracts the line where the diff starts.
241      */

242     private static int getStart(byte[] diffLine) {
243         int spacePos = indexOf(diffLine, (byte) ' ');
244         if (spacePos > 0) {
245             String JavaDoc number = new String JavaDoc(diffLine, 1, spacePos - 1);
246             try {
247                 int toReturn = Integer.parseInt(number);
248                 return toReturn;
249             }
250             catch (NumberFormatException JavaDoc exc) {
251 // System.out.println("diffLine=" + diffLine);
252
return -1;
253             }
254         }
255 // System.out.println("no space in diffline=" + diffLine);
256
return -1;
257     }
258
259     /**
260      * Extracts the length of the diff.
261      * For "delete" it means how many lines to delete from original.
262      * For "add" it means how many lines are added from the diff to original file.
263      */

264     private static int getLength(byte[] diffLine) {
265         //String trimmed = diffLine.trim();
266
int spacePos = indexOf(diffLine, (byte) ' ');
267         if (spacePos > 0) {
268             int end = indexOf(diffLine, (byte) ' ', spacePos + 1);
269             if (end < 0) end = diffLine.length;
270             String JavaDoc number = new String JavaDoc(diffLine, spacePos + 1, end - spacePos - 1);
271             try {
272                 int toReturn = Integer.parseInt(number);
273                 return toReturn;
274             }
275             catch (NumberFormatException JavaDoc exc) {
276 // System.out.println("numformat exception..=" + diffLine);
277
return -1;
278             }
279         }
280 // System.out.println("no space in diffline=" + diffLine);
281
return -1;
282     }
283
284     private static class ReadInfo {
285         
286         private static final boolean crLines = "\r".equals(System.getProperty("line.separator"));
287         
288         private PushbackInputStream in;
289         private int readLength;
290         private int startIndex;
291         private int lineNumber;
292         private ByteArray line;
293
294         public ReadInfo(InputStream in) {
295             this.in = new PushbackInputStream(in, 1);
296             readLength = -1;
297             startIndex = 0;
298             lineNumber = 0;
299             line = new ByteArray();
300         }
301
302         public int getLineNumber() {
303             return lineNumber;
304         }
305
306         public void setLineNumber(int lineNumber) {
307             this.lineNumber = lineNumber;
308         }
309
310         /**
311          * Reads a line. The line-termination bytes are not added.
312          * @return null When the end of the stream is reached.
313          */

314         public byte[] readLine() throws IOException {
315             line.reset();
316             boolean end = false;
317             do {
318                 int b = in.read();
319                 if (b == -1) {
320                     end = true;
321                     break;
322                 }
323                 if (b == '\n') {
324                     lineNumber++;
325                     break;
326                 }
327                 if (b == '\r') {
328                     int next = in.read();
329                     if (next == '\n') {
330                         lineNumber++;
331                         break;
332                     }
333                     in.unread(next);
334                     if (crLines) {
335                         lineNumber++;
336                         break;
337                     }
338                 }
339                 line.add((byte) b);
340             } while (true);
341             byte[] bytes = line.getBytes();
342             if (end && bytes.length == 0) {
343                 bytes = null;
344             }
345             return bytes;
346 /*
347             StringBuffer toReturn = new StringBuffer();
348             while (true) {
349                 if (startIndex > readLength) {
350 // System.out.println("reading..");
351                     readLength = reader.read(cchunk);
352 // System.out.println("read=" + readLength);
353                     startIndex = 0;
354                 }
355                 if (startIndex >= readLength) {
356                     readLength = -1;
357                     if (toReturn.length() == 0) {
358                         return null;
359                     }
360                     else {
361                         lineNumber = lineNumber + 1;
362                         return toReturn.toString();
363                     }
364                 }
365 // System.out.println("startindex = " + startIndex + " length=" + readLength);
366                 for (int i = startIndex; i < readLength; i++) {
367                     if (cchunk[i] == '\n') {
368                         toReturn.append(WriteRcsDiffFilePreprocessor.this.getLineEnding());
369                         startIndex = i + 1;
370                         lineNumber = lineNumber + 1;
371 // System.out.println("linenum=" + lineNumber);
372 // System.out.println("line=" + toReturn.toString() + "--");
373                         return toReturn.toString();
374                     }
375                     else {
376                         // could be maybe made faster by appending the whole array when
377                         // read all or encountering the newline..
378                         toReturn.append(cchunk[i]);
379                     }
380                 }
381                 startIndex = readLength;
382             }
383  */

384         }
385
386         public void close() throws IOException {
387             if (in != null) {
388                 in.close();
389             }
390         }
391     } // end of inner class..
392

393 }
394
Popular Tags