1 /*
2 AntMake
3
4 Copyright (C) 2004 Jose San Leandro Armend?riz
5 jsanleandro@yahoo.es
6 chousz@yahoo.com
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22 Thanks to ACM S.L. for distributing this library under the GPL license.
23 Contact info: jsr000@terra.es
24 Postal Address: c/Playa de Lagoa, 1
25 Urb. Valdecaba?as
26 Boadilla del monte
27 28660 Madrid
28 Spain
29
30 ******************************************************************************
31 This class is based on ChangeLogParser
32 included in Ant distribution, and whose license details
33 are the following.
34
35 *
36 * The Apache Software License, Version 1.1
37 *
38 * Copyright (c) 2002 The Apache Software Foundation. All rights
39 * reserved.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 *
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 *
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in
50 * the documentation and/or other materials provided with the
51 * distribution.
52 *
53 * 3. The end-user documentation included with the redistribution, if
54 * any, must include the following acknowlegement:
55 * "This product includes software developed by the
56 * Apache Software Foundation (http://www.apache.org/)."
57 * Alternately, this acknowlegement may appear in the software itself,
58 * if and wherever such third-party acknowlegements normally appear.
59 *
60 * 4. The names "Ant" and "Apache Software
61 * Foundation" must not be used to endorse or promote products derived
62 * from this software without prior written permission. For written
63 * permission, please contact apache@apache.org.
64 *
65 * 5. Products derived from this software may not be called "Apache"
66 * nor may "Apache" appear in their names without prior written
67 * permission of the Apache Group.
68 *
69 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
70 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
71 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
72 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
73 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
74 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
75 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
76 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
77 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
78 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
79 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
80 * SUCH DAMAGE.
81 * ====================================================================
82 *
83 * This software consists of voluntary contributions made by many
84 * individuals on behalf of the Apache Software Foundation. For more
85 * information on the Apache Software Foundation, please see
86 * <http://www.apache.org/>.
87 *
88
89 ******************************************************************************
90 *
91 * Filename: $RCSfile: ChangeLogParser.java,v $
92 *
93 * Author: Jose San Leandro Armend?riz
94 *
95 * Description: Knows how to parse "cvs log" command output.
96 *
97 * Last modified by: $Author: chous $ at $Date: 2004/01/29 06:44:21 $
98 *
99 * File version: $Revision: 1.3 $
100 *
101 * Project version: $Name: $
102 *
103 * $Id: ChangeLogParser.java,v 1.3 2004/01/29 06:44:21 chous Exp $
104 *
105 */
106 package org.acmsl.antmake.cvslib;
107
108 /*
109 * Importing project classes.
110 */
111 import org.acmsl.antmake.cvslib.RcsFile;
112
113 /*
114 * Importing JDK classes.
115 */
116 import java.text.DateFormat;
117 import java.text.ParseException;
118 import java.text.SimpleDateFormat;
119 import java.util.ArrayList;
120 import java.util.Collection;
121 import java.util.Date;
122 import java.util.HashMap;
123 import java.util.Iterator;
124 import java.util.Map;
125 import java.util.TimeZone;
126
127 /*
128 * Importing Commons Logging classes.
129 */
130 import org.apache.commons.logging.LogFactory;
131
132 /***
133 * Knows how to parse "cvs log" command output.
134 * @author <a href="mailto:jsanleandro@yahoo.es"
135 >Jose San Leandro</a>, based on
136 * <a href="mailto:peter@apache.org">Peter Donald</a>'s
137 * ChangeLogParser. It's package-protected, so it had to be basically copied
138 * and pasted.
139 * @version $Revision: 1.3 $
140 * @see org.apache.tools.ant.taskdefs.cvslib.ChangeLogParser
141 */
142 public class ChangeLogParser
143 {
144 /***
145 * A cached empty CvsEntry array.
146 */
147 protected static final CvsEntry[] EMPTY_CVSENTRY_ARRAY = new CvsEntry[0];
148
149 //private static final int GET_ENTRY = 0;
150 private static final int GET_FILE = 1;
151 private static final int GET_DATE = 2;
152 private static final int GET_COMMENT = 3;
153 private static final int GET_REVISION = 4;
154 private static final int GET_PREVIOUS_REV = 5;
155
156 /***
157 * The date format returned by cvs log.
158 */
159 public static final DateFormat CVS_LOG_DATE_FORMAT =
160 new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
161
162 static
163 {
164 TimeZone t_TimeZone = TimeZone.getTimeZone("UTC");
165 CVS_LOG_DATE_FORMAT.setTimeZone(t_TimeZone);
166 }
167
168 /***
169 * The file name.
170 */
171 private String m__strName;
172
173 /***
174 * The date.
175 */
176 private String m__strDate;
177
178 /***
179 * The author.
180 */
181 private String m__strAuthor;
182
183 /***
184 * The comment.
185 */
186 private String m__strComment;
187
188 /***
189 * The revision.
190 */
191 private String m__strRevision;
192
193 /***
194 * The previous revision.
195 */
196 private String m__strPreviousRevision;
197
198 /***
199 * The variable indicating the current state.
200 */
201 private int m__iCurrentState;
202
203 /***
204 * The RCS files.
205 */
206 private Map m__mEntries;
207
208 /***
209 * Creates a ChangeLogParser.
210 */
211 public ChangeLogParser()
212 {
213 inmutableSetCurrentState(GET_FILE);
214 }
215
216 /***
217 * Specifies the name.
218 * @param name the name of the current CVS file being processed.
219 */
220 protected void setName(String name)
221 {
222 m__strName = name;
223 }
224
225 /***
226 * Retrieves the name of the current CVS file being processed.
227 * @return such information.
228 */
229 protected String getName()
230 {
231 return m__strName;
232 }
233
234 /***
235 * Specifies the date.
236 * @param date the date of the current CVS file being processed.
237 */
238 protected void setDate(String date)
239 {
240 m__strDate = date;
241 }
242
243 /***
244 * Retrieves the date of the current CVS file being processed.
245 * @return such information.
246 */
247 protected String getDate()
248 {
249 return m__strDate;
250 }
251
252 /***
253 * Specifies the author.
254 * @param author the author of the current CVS file being processed.
255 */
256 protected void setAuthor(String author)
257 {
258 m__strAuthor = author;
259 }
260
261 /***
262 * Retrieves the author of the current CVS file being processed.
263 * @return such information.
264 */
265 protected String getAuthor()
266 {
267 return m__strAuthor;
268 }
269
270 /***
271 * Specifies the comment.
272 * @param comment the comment of the CVS file being processed.
273 */
274 protected void setComment(String comment)
275 {
276 m__strComment = comment;
277 }
278
279 /***
280 * Retrieves the comment of the CVS file being processed.
281 * @return such information.
282 */
283 protected String getComment()
284 {
285 return m__strComment;
286 }
287
288 /***
289 * Specifies the revision.
290 * @param revision the revision of the current CVS file being processed.
291 */
292 protected void setRevision(String revision)
293 {
294 m__strRevision = revision;
295 }
296
297 /***
298 * Retrieves the revision of the current CVS file being processed.
299 * @return such information.
300 */
301 protected String getRevision()
302 {
303 return m__strRevision;
304 }
305
306 /***
307 * Specifies the previous revision.
308 * @param previousRevision the previous revision of the current CVS file
309 * being processed.
310 */
311 protected void setPreviousRevision(String previousRevision)
312 {
313 m__strPreviousRevision = previousRevision;
314 }
315
316 /***
317 * Retrieves the previous revision of the current CVS file being processed.
318 * @return such information.
319 */
320 protected String getPreviousRevision()
321 {
322 return m__strPreviousRevision;
323 }
324
325 /***
326 * Specifies the current state of the parser.
327 * @param state the current state of the parser.
328 */
329 private void inmutableSetCurrentState(int state)
330 {
331 m__iCurrentState = state;
332 }
333
334 /***
335 * Specifies the current state of the parser.
336 * @param state the current state of the parser.
337 */
338 protected void setCurrentState(int state)
339 {
340 inmutableSetCurrentState(state);
341 }
342
343 /***
344 * Retrieves the current state of the parser.
345 * @return such information.
346 */
347 protected int getCurrentState()
348 {
349 return m__iCurrentState;
350 }
351
352 /***
353 * Specifies the CVS entries map.
354 * @param map the map.
355 */
356 protected void setEntries(Map map)
357 {
358 m__mEntries = map;
359 }
360
361 /***
362 * Retrieves the CVS entries map.
363 * @return such map.
364 */
365 protected Map getEntries()
366 {
367 return m__mEntries;
368 }
369
370 /***
371 * Retrieves the list of RCS entries as an array.
372 * @return such items.
373 */
374 public CvsEntry[] getEntrySetAsArray()
375 {
376 CvsEntry[] result = EMPTY_CVSENTRY_ARRAY;
377
378 Map t_mEntries = getEntries();
379
380 if (t_mEntries != null)
381 {
382 result = new CvsEntry[t_mEntries.size()];
383
384 Collection t_cEntries = t_mEntries.values();
385
386 if (t_cEntries != null)
387 {
388 Iterator t_EntryIterator = t_cEntries.iterator();
389
390 int t_iEntryIndex = 0;
391
392 while ( (t_EntryIterator != null)
393 && (t_EntryIterator.hasNext()))
394 {
395 result[t_iEntryIndex++] =
396 (CvsEntry) t_EntryIterator.next();
397 }
398 }
399 }
400
401 return result;
402 }
403
404 /***
405 * Receives notification about the process writing
406 * to standard output.
407 * @param line the last line read.
408 */
409 public void stdout(String line)
410 {
411 switch(getCurrentState())
412 {
413 case GET_FILE:
414 // make sure attributes are reset when
415 // working on a 'new' file.
416 reset();
417 processFile(line);
418 break;
419
420 case GET_REVISION:
421 processRevision(line);
422 break;
423
424 case GET_DATE:
425 processDate(line);
426 break;
427
428 case GET_COMMENT:
429 processComment(line);
430 break;
431
432 case GET_PREVIOUS_REV:
433 processGetPreviousRevision(line);
434 break;
435 }
436 }
437
438 /***
439 * Processes a line while in <i>GET_COMMENT</i> state.
440 * @param line the line to process.
441 */
442 protected void processComment(String line)
443 {
444 if (line != null)
445 {
446 String t_strComment = getComment();
447
448 String t_strLineSeparator =
449 System.getProperty("line.separator");
450
451 int t_iEnd;
452
453 if (line.startsWith("======"))
454 {
455 setComment(
456 removeTrailing(
457 t_strComment,
458 t_strLineSeparator.length()));
459
460 //We have ended changelog for that particular file
461 //so we can save it
462 saveEntry();
463
464 setCurrentState(GET_FILE);
465
466 }
467 else if (line.startsWith("----------------------------"))
468 {
469 setComment(
470 removeTrailing(
471 t_strComment,
472 t_strLineSeparator.length()));
473
474 setCurrentState(GET_PREVIOUS_REV);
475 }
476 else
477 {
478 setComment(line + t_strLineSeparator);
479 }
480 }
481 }
482
483 /***
484 * Removes trailing substring.
485 * @param input the text to process.
486 * @param suffix the length of the substring to remove at the end.
487 * @return the updated input.
488 */
489 protected String removeTrailing(String input, int suffix)
490 {
491 String result = input;
492
493 if (input != null)
494 {
495 int t_iAmountToRemove =
496 Math.min(input.length(), suffix);
497
498 result = input.substring(0, input.length() - t_iAmountToRemove);
499 }
500
501 return result;
502 }
503
504 /***
505 * Processes a line while in <i>GET_FILE</i> state.
506 * @param line the line to process.
507 */
508 protected void processFile(String line)
509 {
510 if (line != null)
511 {
512 if (line.startsWith("Working file:"))
513 {
514 setName(line.substring(14, line.length()));
515
516 setCurrentState(GET_REVISION);
517 }
518 }
519 }
520
521 /***
522 * Processes a line while in <i>REVISION</i> state.
523 * @param line the line to process.
524 */
525 protected void processRevision(String line)
526 {
527 if (line != null)
528 {
529 if (line.startsWith("revision"))
530 {
531 setRevision(line.substring(9));
532
533 setCurrentState(GET_DATE);
534 }
535 else if (line.startsWith("======"))
536 {
537 //There was no revisions in this changelog
538 //entry so lets move unto next file
539 setCurrentState(GET_FILE);
540 }
541 }
542 }
543
544 /***
545 * Processes a line while in <i>DATE</i> state.
546 * @param line the line to process.
547 */
548 protected void processDate(String line)
549 {
550 if (line != null)
551 {
552 if (line.startsWith("date:"))
553 {
554 setDate(line.substring(6, 25));
555
556 String t_strLineData =
557 line.substring(line.indexOf(";") + 1);
558
559 setAuthor(
560 t_strLineData.substring(10, t_strLineData.indexOf(";")));
561
562 setCurrentState(GET_COMMENT);
563
564 //Reset comment to empty here as we can accumulate multiple lines
565 //in the processComment method
566 setComment("");
567 }
568 }
569 }
570
571 /***
572 * Processes a line while in <i>GET_PREVIOUS_REVISION</i> state.
573 * @param line the line to process.
574 */
575 protected void processGetPreviousRevision(String line)
576 {
577 if (line != null)
578 {
579 if (!line.startsWith("revision"))
580 {
581 throw new IllegalStateException(
582 "Unexpected line from CVS: " + line);
583 }
584 else
585 {
586 String t_strPreviousRevision = line.substring(9);
587
588 setPreviousRevision(t_strPreviousRevision);
589
590 saveEntry();
591
592 setRevision(t_strPreviousRevision);
593
594 setCurrentState(GET_DATE);
595 }
596 }
597 }
598
599 /***
600 * Saves the current entry.
601 */
602 protected void saveEntry()
603 {
604 CvsEntry t_Entry;
605
606 String t_strDate = getDate();
607 String t_strAuthor = getAuthor();
608 String t_strComment = getComment();
609
610 Object t_EntryKey = buildEntryKey(t_strDate, t_strAuthor, t_strComment);
611
612 Map t_mEntries = getEntries();
613
614 if (t_mEntries == null)
615 {
616 t_mEntries = new HashMap();
617 setEntries(t_mEntries);
618 }
619
620 if (t_mEntries.containsKey(t_EntryKey))
621 {
622 t_Entry = (CvsEntry) t_mEntries.get(t_EntryKey);
623 }
624 else
625 {
626 t_Entry =
627 new CvsEntry(
628 parseDate(t_strDate), t_strAuthor, t_strComment);
629
630 t_mEntries.put(t_EntryKey, t_Entry);
631 }
632
633 t_Entry.add(getName(), getRevision(), getPreviousRevision());
634 }
635
636 /***
637 * Parses date out from expected format.
638 * @param date the string holding the date.
639 * @return the date object or <code>null</code> if unknown date format.
640 */
641 protected Date parseDate(String date)
642 {
643 Date result = null;
644
645 try
646 {
647 result = CVS_LOG_DATE_FORMAT.parse(date);
648 }
649 catch (ParseException parseException)
650 {
651 LogFactory.getLog(ChangeLogParser.class).info(
652 "Couldn't parse date " + date,
653 parseException);
654 }
655
656 return result;
657 }
658
659 /***
660 * Builds a key for an entry.
661 * @param date the entry's date.
662 * @param author the author.
663 * @param comment the comment.
664 * @return a key for such entry.
665 */
666 protected Object buildEntryKey(String date, String author, String comment)
667 {
668 return date + author + comment;
669 }
670
671 /***
672 * Resets all internal attributes except current state.
673 */
674 protected void reset()
675 {
676 setName(null);
677 setDate(null);
678 setAuthor(null);
679 setComment(null);
680 setRevision(null);
681 setPreviousRevision(null);
682 }
683 }
684
This page was automatically generated by Maven