1 package org.apache.maven.changelog;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import java.text.SimpleDateFormat;
22
23 import java.util.Date;
24 import java.util.Enumeration;
25 import java.util.Vector;
26
27 /**
28 * Change Log Entry - holds details about revisions to a file.
29 *
30 * @task add time of change to the entry
31 * @task investigate betwixt for toXML method
32 * @author <a href="mailto:dion@multitask.com.au">dIon Gillard</a>
33 * @version $Id: ChangeLogEntry.java 532339 2007-04-25 12:28:56Z ltheussl $
34 */
35 public class ChangeLogEntry
36 {
37 /**
38 * Escaped <code><</code> entity
39 */
40 public static final String LESS_THAN_ENTITY = "<";
41
42 /**
43 * Escaped <code>></code> entity
44 */
45 public static final String GREATER_THAN_ENTITY = ">";
46
47 /**
48 * Escaped <code>&</code> entity
49 */
50 public static final String AMPERSAND_ENTITY = "&";
51
52 /**
53 * Escaped <code>'</code> entity
54 */
55 public static final String APOSTROPHE_ENTITY = "'";
56
57 /**
58 * Escaped <code>"</code> entity
59 */
60 public static final String QUOTE_ENTITY = """;
61
62 /**
63 * Formatter used by the getDateFormatted method.
64 */
65 private static final SimpleDateFormat DATE_FORMAT =
66 new SimpleDateFormat( "yyyy-MM-dd" );
67
68 /**
69 * Formatter used by the getTimeFormatted method.
70 */
71 private static final SimpleDateFormat TIME_FORMAT =
72 new SimpleDateFormat( "HH:mm:ss" );
73
74 /** Date the changes were committed */
75 private Date date;
76
77 /** User who made changes */
78 private String author;
79
80 /** comment provided at commit time */
81 private String comment = "";
82
83 /** ChangeLogFiles committed on the date, by the author, with comment*/
84 private Vector files = new Vector();
85
86 /**
87 * Constructor used when attributes aren't available until later
88 */
89 public ChangeLogEntry()
90 {
91 }
92
93 /**
94 * Adds a file to the list for this entry
95 * @param file a {@link ChangeLogFile}
96 */
97 public void addFile( ChangeLogFile file )
98 {
99 files.addElement( file );
100 }
101
102 /**
103 * Adds a feature to the File attribute of the Entry object.
104 * @param file the file name committed
105 * @param revision the revision of the latest change
106 */
107 public void addFile( String file, String revision )
108 {
109 files.addElement( new ChangeLogFile( file, revision ) );
110 }
111
112 /**
113 * @return a string representation of the entry
114 */
115 public String toString()
116 {
117 return author + "\n" + date + "\n" + files + "\n" + comment;
118 }
119
120 /**
121 * Provide the changelog entry as an XML snippet.
122 *
123 * @task make sure comment doesn't contain CDATA tags - MAVEN114
124 * @return a changelog-entry in xml format
125 */
126 public String toXML()
127 {
128 StringBuffer buffer = new StringBuffer();
129
130 buffer.append( "\t<changelog-entry>\n" ).append( "\t\t<date>" )
131 .append( getDateFormatted() ).append( "</date>\n" )
132 .append( "\t\t<time>" ).append( getTimeFormatted() )
133 .append( "</time>\n" ).append( "\t\t<author><![CDATA[" )
134 .append( author ).append( "]]></author>\n" );
135
136 for ( Enumeration e = files.elements(); e.hasMoreElements(); )
137 {
138 ChangeLogFile file = (ChangeLogFile) e.nextElement();
139
140 buffer.append( "\t\t<file>\n" ).append( "\t\t\t<name>" )
141 .append( escapeValue( file.getName() ) ).append( "</name>\n" )
142 .append( "\t\t\t<revision>" ).append( file.getRevision() )
143 .append( "</revision>\n" );
144 buffer.append( "\t\t</file>\n" );
145 }
146
147 buffer.append( "\t\t<msg><![CDATA[" ).append( removeCDataEnd( comment ) )
148 .append( "]]></msg>\n" );
149 buffer.append( "\t</changelog-entry>\n" );
150
151 return buffer.toString();
152 }
153
154 /**
155 * Getter for property author.
156 * @return Value of property author.
157 */
158 public String getAuthor()
159 {
160 return author;
161 }
162
163 /**
164 * Setter for property author.
165 * @param author New value of property author.
166 */
167 public void setAuthor( String author )
168 {
169 this.author = author;
170 }
171
172 /**
173 * Getter for property comment.
174 * @return Value of property comment.
175 */
176 public String getComment()
177 {
178 return comment;
179 }
180
181 /**
182 * Setter for property comment.
183 * @param comment New value of property comment.
184 */
185 public void setComment( String comment )
186 {
187 this.comment = comment;
188 }
189
190 /**
191 * Getter for property date.
192 * @return Value of property date.
193 */
194 public Date getDate()
195 {
196 return (Date) date.clone();
197 }
198
199 /**
200 * Setter for property date.
201 * @param date New value of property date.
202 */
203 public void setDate( Date date )
204 {
205 this.date = new Date( date.getTime() );
206 }
207
208 /**
209 * @return date in yyyy-mm-dd format
210 */
211 public String getDateFormatted()
212 {
213 return DATE_FORMAT.format( getDate() );
214 }
215
216 /**
217 * @return time in HH:mm:ss format
218 */
219 public String getTimeFormatted()
220 {
221 return TIME_FORMAT.format( getDate() );
222 }
223
224 /**
225 * remove a <code>]]></code> from comments (replace it with <code>] ] ></code>).
226 * @param message
227 * @return
228 */
229 private String removeCDataEnd( String message )
230 {
231
232 int endCdata;
233
234 while ( ( message != null )
235 && ( ( endCdata = message.indexOf( "]]>" ) ) > -1 ) )
236 {
237 message =
238 message.substring( 0, endCdata ) + "] ] >"
239 + message.substring( endCdata + 3, message.length() );
240 }
241
242 return message;
243 }
244
245 /**
246 * <p>Escape the <code>toString</code> of the given object.
247 * For use in an attribute value.</p>
248 *
249 * swiped from jakarta-commons/betwixt -- XMLUtils.java
250 *
251 * @param value escape <code>value.toString()</code>
252 * @return text with characters restricted (for use in attributes) escaped
253 */
254 public static final String escapeValue( Object value )
255 {
256 StringBuffer buffer = new StringBuffer( value.toString() );
257
258 for ( int i = 0, size = buffer.length(); i < size; i++ )
259 {
260 switch ( buffer.charAt( i ) )
261 {
262 case '<' :
263 buffer.replace( i, i + 1, LESS_THAN_ENTITY );
264 size += 3;
265 i += 3;
266
267 break;
268
269 case '>' :
270 buffer.replace( i, i + 1, GREATER_THAN_ENTITY );
271 size += 3;
272 i += 3;
273
274 break;
275
276 case '&' :
277 buffer.replace( i, i + 1, AMPERSAND_ENTITY );
278 size += 4;
279 i += 4;
280
281 break;
282
283 case '\'' :
284 buffer.replace( i, i + 1, APOSTROPHE_ENTITY );
285 size += 4;
286 i += 4;
287
288 break;
289
290 case '\"' :
291 buffer.replace( i, i + 1, QUOTE_ENTITY );
292 size += 5;
293 i += 5;
294
295 break;
296 }
297 }
298
299 return buffer.toString();
300 }
301 }