KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > openedit > modules > changelog > ChangeLog


1 /*
2 Copyright (c) 2003 eInnovation Inc. All rights reserved
3
4 This library is free software; you can redistribute it and/or modify it under the terms
5 of the GNU Lesser General Public License as published by the Free Software Foundation;
6 either version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the GNU Lesser General Public License for more details.
11 */

12
13 /*
14  * Created on Apr 18, 2003
15  */

16 package com.openedit.modules.changelog;
17
18 import java.io.Reader JavaDoc;
19 import java.io.StringWriter JavaDoc;
20 import java.text.SimpleDateFormat JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Collections JavaDoc;
23 import java.util.Date JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.dom4j.Attribute;
30 import org.dom4j.Document;
31 import org.dom4j.DocumentHelper;
32 import org.dom4j.Element;
33 import org.dom4j.io.OutputFormat;
34 import org.dom4j.io.SAXReader;
35 import org.dom4j.io.XMLWriter;
36 import org.openedit.repository.ContentItem;
37 import org.openedit.repository.filesystem.StringItem;
38
39 import com.openedit.OpenEditException;
40 import com.openedit.PageAccessListener;
41 import com.openedit.page.Page;
42 import com.openedit.page.manage.PageManager;
43 import com.openedit.util.PathUtilities;
44 import com.openedit.util.XmlUtil;
45
46
47 /**
48  * update the change log each time something changes there should probably a MAX length for the
49  * change log. This would be configured TODO: We should consider using
50  * org.apache.log4j.xml.XMLLayout for performance reasons
51  *
52  * @author cburkey
53  */

54 public class ChangeLog implements PageAccessListener
55 {
56     protected Log log = LogFactory.getLog(ChangeLog.class);
57     protected SimpleDateFormat JavaDoc fieldFormat = new SimpleDateFormat JavaDoc("yyyy-MM-dd HH:mm:ss");
58     protected SimpleDateFormat JavaDoc fieldRSSFormat = new SimpleDateFormat JavaDoc("EEE, d MMM yyyy HH:mm:ss Z");
59     protected List JavaDoc fieldChangeStack;
60     protected List JavaDoc fieldNewChanges;
61     protected String JavaDoc fieldChangeFilePath = "/openedit/stats/changelog.xml";
62     protected int fieldMaxLength = 50;
63     protected PageManager fieldPageManager;
64     protected int fieldTimeStampCounter;
65     
66     /**
67      * DOCUMENT ME!
68      *
69      * @param string
70      */

71     public void setChangeFilePath(String JavaDoc string)
72     {
73         fieldChangeFilePath = string;
74     }
75
76     /**
77      * DOCUMENT ME!
78      *
79      * @return
80      */

81     public String JavaDoc getChangeFilePath()
82     {
83         return fieldChangeFilePath;
84     }
85
86     /**
87      * DOCUMENT ME!
88      *
89      * @param i
90      */

91     public void setMaxLength(int i)
92     {
93         fieldMaxLength = i;
94     }
95
96     /**
97      * DOCUMENT ME!
98      *
99      * @return
100      */

101     public int getMaxLength()
102     {
103         return fieldMaxLength;
104     }
105
106     /**
107      * DOCUMENT ME!
108      *
109      * @param inStack
110      */

111     public void setNewChanges(List JavaDoc inStack)
112     {
113         fieldNewChanges = inStack;
114     }
115
116     /**
117      * DOCUMENT ME!
118      *
119      * @return
120      */

121     public List JavaDoc getNewChanges()
122     {
123         if (fieldNewChanges == null)
124         {
125             fieldNewChanges = new ArrayList JavaDoc();
126         }
127
128         return fieldNewChanges;
129     }
130
131     /**
132      * DOCUMENT ME!
133      *
134      * @return
135      */

136     public int changeCount()
137     {
138         return getChangeStack().size();
139     }
140
141     /**
142      * DOCUMENT ME!
143      *
144      * @return
145      */

146     public int changeNotificationCount()
147     {
148         return getNewChanges().size();
149     }
150
151     /**
152      * DOCME
153      */

154     public void clearNotifications()
155     {
156         getNewChanges().clear();
157     }
158
159     /**
160      * DOCUMENT ME!
161      *
162      * @throws Exception DOCUMENT ME!
163      * @throws RuntimeException DOCUMENT ME!
164      */

165     public void init() throws Exception JavaDoc
166     {
167         setChangeStack(new ArrayList JavaDoc());
168
169         Reader JavaDoc reader = null;
170         try
171         {
172             Page page = getPageManager().getPage( getChangeFilePath());
173
174             if (page.exists())
175             {
176                 reader = page.getReader();
177                 Document doc = new SAXReader(false).read(reader );
178                 
179                 //newst ones come first
180
List JavaDoc changes = doc.getRootElement().elements("Change");
181
182                 for (int i = 0; (i < getMaxLength()) && (i < changes.size()); i++)
183                 {
184                     Element change = (Element) changes.get(i);
185                     addChange(change);
186                 }
187                 //Put the first elements back in the top of the list
188
Collections.reverse( getChangeStack() );
189                 
190 // save the time stamp counter
191
Attribute counterAttribute = doc.getRootElement().attribute("timeStampCounter");
192                 if (counterAttribute != null)
193                 {
194                     String JavaDoc counter = counterAttribute.getValue();
195                     if (counter != null && counter.length() > 0)
196                     {
197                         setTimeStampCounter(Integer.parseInt(counter));
198                     }
199                 }
200                 else
201                 {
202                     setTimeStampCounter(0);
203                 }
204                 
205             }
206         }
207         catch (Exception JavaDoc e)
208         {
209             throw new RuntimeException JavaDoc("Could not load changelog " + e);
210         }
211         finally
212         {
213             if ( reader != null)
214             {
215                 reader.close();
216             }
217         }
218         
219         //TODO: Save the last notified time someplace
220

221         //this is good after a reboot to get us back where we where
222
/*
223         GregorianCalendar yesterday = new GregorianCalendar();
224         yesterday.set(GregorianCalendar.HOUR_OF_DAY, 24);
225         yesterday.set(GregorianCalendar.MINUTE, 0);
226         yesterday.set(GregorianCalendar.SECOND, 0);
227         yesterday.add(GregorianCalendar.DAY_OF_YEAR, -1);
228         getChangeLog().resetNotificationsToDate(yesterday.getTime());
229         */

230
231         clearNotifications();
232
233         getPageManager().addPageAccessListener(this);
234     }
235
236
237     /**
238      * DOCUMENT ME!
239      *
240      * @param inPage
241      * @param inRevision
242      *
243      * @throws OpenEditException
244      */

245     public void pageAdded(Page inPage)
246     {
247         ContentItem item = inPage.getContentItem();
248         if ( shouldMakeVersion(inPage) )
249         {
250             logCopy(item);
251             save();
252         }
253
254     }
255     
256     public boolean shouldMakeVersion(Page inPage)
257     {
258         String JavaDoc path = inPage.getPath();
259         return (!path.startsWith("/openedit/stats/"));
260     }
261
262     /**
263      * DOCUMENT ME!
264      *
265      * @param inPage
266      * @param inRevision
267      *
268      * @throws OpenEditException
269      */

270     public void pageModified(Page inPage)
271     {
272         //check count
273
ContentItem item = inPage.getContentItem();
274         if ( shouldMakeVersion(inPage) )
275         {
276             logCopy(item);
277             save();
278         }
279     }
280
281     /**
282      * DOCUMENT ME!
283      *
284      * @param inPage
285      * @param inRevision
286      *
287      * @throws OpenEditException
288      */

289     public void pageRemoved(Page inPage)
290     {
291         ContentItem item = inPage.getContentItem();
292         if ( shouldMakeVersion(inPage) )
293         {
294             RevisionItem revision = new RevisionItem();
295
296             revision.setType(item.getType());
297             
298             revision.setDate(new Date JavaDoc() );
299
300             revision.setPath(item.getPath());
301
302             revision.setAuthor(item.getAuthor());
303             revision.setMessage(item.getMessage());
304             revision.setVersion(item.getVersion());
305             log( revision );
306             
307             save();
308         }
309     }
310
311     /**
312      * DOCUMENT ME!
313      *
314      * @param inPage
315      *
316      * @throws OpenEditException
317      */

318     public void pageRequested(Page inPage)
319     {
320     }
321
322     /**
323      * Only keep notifications that are after a certain date
324      *
325      * @param inDate
326      */

327     public void resetNotificationsToDate(Date JavaDoc inDate)
328     {
329         // TODO Auto-generated method stub
330
List JavaDoc changes = new ArrayList JavaDoc();
331
332         for (Iterator JavaDoc iter = getNewChanges().iterator(); iter.hasNext();)
333         {
334             RevisionItem rev = (RevisionItem) iter.next();
335
336             if (rev.lastModified() != null && rev.lastModified().getTime() > inDate.getTime())
337             {
338                 changes.add(rev);
339             }
340         }
341
342         clearNotifications();
343         getNewChanges().addAll(changes);
344     }
345
346     /**
347      * Save the list of changes to the days change log file
348      *
349      */

350     public void save()
351     {
352         incrementTimeStampCounter();
353         try
354         {
355             Page page = getPageManager().getPage(getChangeFilePath());
356             StringWriter JavaDoc out = new StringWriter JavaDoc();
357             
358             new XmlUtil().saveXml(toXmlDocument(), out, page.getCharacterEncoding());
359             
360             StringItem item = new StringItem(getChangeFilePath(),out.toString(),page.getCharacterEncoding());
361             item.setMakeVersion(false);
362             page.setContentItem(item);
363             getPageManager().putPage(page);
364
365
366             if (getTimeStampCounter() >= getMaxLength())
367             {
368                 setTimeStampCounter(0);
369                 String JavaDoc stampedFileName = "changelog-"
370                                             + new SimpleDateFormat JavaDoc("yyyy-MM-dd-H-m-s").format(new Date JavaDoc())
371                                             + ".xml";
372                 String JavaDoc stampedPath = PathUtilities.extractDirectoryPath(getChangeFilePath())
373                                             + "/" + stampedFileName;
374                 Page stampedPage = getPageManager().getPage(stampedPath);
375                 stampedPage.getContentItem().setMakeVersion(false);
376                 getPageManager().copyPage(page, stampedPage);
377
378             
379                 new XmlUtil().saveXml(toXmlDocument(), out, page.getCharacterEncoding());
380                 
381                 item = new StringItem(getChangeFilePath(),out.toString(),page.getCharacterEncoding());
382                 item.setMakeVersion(false);
383                 page.setContentItem(item);
384                 getPageManager().putPage(page);
385
386             }
387         }
388         catch (Exception JavaDoc ex)
389         {
390             log.error(ex);
391             return;
392         }
393     }
394
395     /**
396      * DOCUMENT ME!
397      *
398      * @return
399      */

400     public Document toNotifyXmlDocument()
401     {
402         // TODO Auto-generated method stub
403
return buildDocument(getNewChanges());
404     }
405
406     /**
407      * Outputs the changes as an XML element, in UTF-8 encoding.
408      *
409      * TODO: This should move to using a generator
410      */

411     public String JavaDoc toNotifyXmlString() throws Exception JavaDoc
412     {
413         StringWriter JavaDoc out = new StringWriter JavaDoc();
414         new XMLWriter(out, OutputFormat.createPrettyPrint()).write(
415             buildDocument(getNewChanges()).getRootElement());
416
417         return out.toString();
418     }
419
420     /**
421      * DOCUMENT ME!
422      *
423      * @return
424      */

425     public Document toXmlDocument()
426     {
427         return buildDocument(getChangeStack());
428     }
429
430     /**
431      * DOCUMENT ME!
432      *
433      * @param stack
434      */

435     protected void setChangeStack(List JavaDoc stack)
436     {
437         fieldChangeStack = stack;
438     }
439
440     /**
441      * DOCUMENT ME!
442      *
443      * @return
444      */

445     public List JavaDoc getChangeStack()
446     {
447         return fieldChangeStack;
448     }
449
450     /**
451      * DOCUMENT ME!
452      *
453      * @param inFormat
454      */

455     protected void setFormat(SimpleDateFormat JavaDoc inFormat)
456     {
457         fieldFormat = inFormat;
458     }
459
460     /**
461      * DOCUMENT ME!
462      *
463      * @return
464      */

465     protected SimpleDateFormat JavaDoc getFormat()
466     {
467         return fieldFormat;
468     }
469     public String JavaDoc formatDate(RevisionItem inItem)
470     {
471         if( inItem.lastModified() == null)
472         {
473             return "";
474         }
475         return SimpleDateFormat.getDateTimeInstance().format(inItem.lastModified());
476     }
477     
478     public String JavaDoc formatRssDate(RevisionItem inItem)
479     {
480         Date JavaDoc date = inItem.lastModified();
481         if( date == null)
482         {
483             return "no date";
484         }
485         else
486         {
487             return getRSSFormat().format(date);
488         }
489     }
490     
491     /**
492      * DOCUMENT ME!
493      *
494      * @param inChange
495      *
496      * @throws Exception DOCUMENT ME!
497      */

498     protected void addChange(Element inChange) throws Exception JavaDoc
499     {
500         RevisionItem revision = new RevisionItem();
501         revision.setType(inChange.attributeValue("type"));
502
503         String JavaDoc text = inChange.elementText("Date");
504         revision.setDate(fieldFormat.parse(text));
505
506         String JavaDoc path = inChange.elementText("Url");
507         revision.setPath(path);
508
509         revision.setAuthor(inChange.elementText("Author"));
510         revision.setMessage(inChange.elementText("Message"));
511         revision.setVersion(inChange.elementText("Version"));
512         
513
514         log(revision);
515     }
516
517     protected Document buildDocument(List JavaDoc inStack)
518     {
519         Element root = DocumentHelper.createElement("ChangeLog");
520         root.addAttribute("timeStampCounter", "" + getTimeStampCounter());
521
522         for (Iterator JavaDoc iter = inStack.iterator(); iter.hasNext();)
523         {
524             ContentItem revision = (ContentItem) iter.next();
525             Element change = root.addElement("Change");
526
527             if (revision.getType() != null)
528             {
529                 change.addAttribute("type", revision.getType());
530             }
531
532             Element date = change.addElement("Date");
533             date.addAttribute("type", "xsd:date");
534
535             if (revision.lastModified() == null)
536             {
537                 date.setText(fieldFormat.format(new Date JavaDoc()));
538             }
539             else
540             {
541                 date.setText(fieldFormat.format(revision.lastModified()));
542             }
543
544             if (revision.getAuthor() != null)
545             {
546                 change.addElement("Author").setText(
547                     revision.getAuthor());
548             }
549             if (revision.getMessage() != null)
550             {
551                 change.addElement("Message").setText(
552                     revision.getMessage());
553             }
554             if (revision.getVersion() != null)
555             {
556                 change.addElement("Version").setText(
557                     revision.getVersion());
558             }
559
560             change.addElement("Url").setText(revision.getPath());
561         }
562
563         return DocumentHelper.createDocument(root);
564     }
565
566     /**
567      * DOCUMENT ME!
568      *
569      * @param revision
570      */

571     protected void log(ContentItem revision)
572     {
573         
574         if ( getChangeStack().size() > 0)
575         {
576             getChangeStack().add(0,revision);
577         }
578         else
579         {
580             getChangeStack().add(revision);
581         }
582
583         if (getChangeStack().size() > getMaxLength())
584         {
585             getChangeStack().remove(getChangeStack().size() - 1);
586         }
587         if ( getNewChanges().size() > 0)
588         {
589             getNewChanges().add(0,revision);
590         }
591         else
592         {
593             getNewChanges().add(revision);
594         }
595     }
596     /**
597      * We need to make a copy because otherwise the record could be modified. (i.e. last modified date)
598      * @param inItem
599      */

600     protected void logCopy( ContentItem inItem)
601     {
602         RevisionItem revision = new RevisionItem();
603         revision.setType(inItem.getType());
604         
605         Date JavaDoc date = inItem.lastModified();
606         if( date == null)
607         {
608             date = new Date JavaDoc();
609         }
610         revision.setDate(date);
611
612         revision.setPath(inItem.getPath());
613
614         revision.setAuthor(inItem.getAuthor());
615         revision.setMessage(inItem.getMessage());
616         revision.setVersion(inItem.getVersion());
617         log( revision );
618     }
619     public PageManager getPageManager()
620     {
621         return fieldPageManager;
622     }
623     public void setPageManager(PageManager inPageManager)
624     {
625         fieldPageManager = inPageManager;
626     }
627
628     public int getTimeStampCounter()
629     {
630         return fieldTimeStampCounter;
631     }
632
633     public void setTimeStampCounter(int inTimeStampCounter)
634     {
635         fieldTimeStampCounter = inTimeStampCounter;
636     }
637     
638     public void incrementTimeStampCounter()
639     {
640         setTimeStampCounter(getTimeStampCounter() + 1);
641     }
642
643     public SimpleDateFormat JavaDoc getRSSFormat()
644     {
645         return fieldRSSFormat;
646     }
647 }
648
Popular Tags