001: // Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
002: // Released under the terms of the GNU General Public License version 2 or later.
003: package fitnesse.responders;
004:
005: import java.io.ByteArrayOutputStream;
006: import java.text.ParsePosition;
007: import java.text.SimpleDateFormat;
008: import java.util.regex.Matcher;
009: import java.util.regex.Pattern;
010:
011: import org.w3c.dom.Document;
012: import org.w3c.dom.Element;
013:
014: import fitnesse.FitNesseContext;
015: import fitnesse.Responder;
016: import fitnesse.components.XmlWriter;
017: import fitnesse.http.Request;
018: import fitnesse.http.Response;
019: import fitnesse.http.SimpleResponse;
020: import fitnesse.util.XmlUtil;
021: import fitnesse.wiki.PageData;
022: import fitnesse.wiki.PathParser;
023: import fitnesse.wiki.WikiPage;
024:
025: public class RssResponder implements Responder {
026: protected Element channelElement;
027: private String resource;
028: private WikiPage contextPage;
029:
030: public Response makeResponse(FitNesseContext context,
031: Request request) throws Exception {
032: Document rssDocument = buildRssHeader();
033:
034: resource = request.getResource();
035: contextPage = context.root.getPageCrawler().getPage(
036: context.root, PathParser.parse(resource));
037: XmlUtil.addTextNode(rssDocument, channelElement, "title",
038: "FitNesse:");
039: WikiPage page = context.root.getChildPage("RecentChanges");
040: buildItemReport(page, rssDocument, request.getResource());
041: SimpleResponse response = responseFrom(rssDocument);
042: return response;
043: }
044:
045: protected void buildItemReport(WikiPage page, Document rssDocument,
046: String resource) throws Exception {
047: if (page != null) {
048: String[] lines = getLines(page);
049: for (int i = 0; i < lines.length; i++) {
050: String[] fields = lines[i].split("\\|");
051: String path = fields[1];
052: String author = fields[2];
053: String pubDate = fields[3];
054: pubDate = convertDateFormat(pubDate);
055:
056: if (shouldReportItem(resource, path))
057: buildItem(rssDocument, path, author, pubDate);
058: }
059: }
060: }
061:
062: protected String[] getLines(WikiPage page) throws Exception {
063: PageData data = page.getData();
064: String recentChanges = data.getContent();
065: String[] lines = recentChanges.split("\n");
066: return lines;
067: }
068:
069: protected boolean shouldReportItem(String resource, String title) {
070: return !exists(resource) || title.startsWith(resource);
071: }
072:
073: private void buildItem(Document rssDocument, String title,
074: String author, String pubDate) throws Exception {
075: Element itemElement1 = rssDocument.createElement("item");
076: makeNodes(rssDocument, itemElement1, title, author, pubDate);
077: buildLink(rssDocument, itemElement1, title);
078:
079: String description = makeDescription(author, pubDate);
080: XmlUtil.addTextNode(rssDocument, itemElement1, "description",
081: description);
082: Element itemElement = itemElement1;
083: channelElement.appendChild(itemElement);
084: }
085:
086: protected void makeNodes(Document rssDocument,
087: Element itemElement1, String title, String author,
088: String pubDate) {
089: XmlUtil.addTextNode(rssDocument, itemElement1, "title", title);
090: XmlUtil
091: .addTextNode(rssDocument, itemElement1, "author",
092: author);
093: XmlUtil.addTextNode(rssDocument, itemElement1, "pubDate",
094: pubDate);
095: }
096:
097: protected void buildLink(Document rssDocument,
098: Element itemElement1, String pageName) throws Exception {
099: String hostName = java.net.InetAddress.getLocalHost()
100: .getHostName();
101: String prefix = "http://" + hostName + "/";
102: if (contextPage != null) {
103: PageData data = contextPage.getData();
104: String prefixVariable = data.getVariable("RSS_PREFIX");
105: prefix = prefixVariable == null ? prefix : prefixVariable;
106: }
107: String link = prefix + pageName;
108:
109: XmlUtil.addTextNode(rssDocument, itemElement1, "link", link);
110: }
111:
112: protected String makeDescription(String author, String pubDate) {
113: String description;
114: String authoredBy = "";
115: if (exists(author))
116: authoredBy = author + ":";
117: description = authoredBy + pubDate;
118: return description;
119: }
120:
121: protected boolean exists(String author) {
122: return author != null && author.length() > 0;
123: }
124:
125: private SimpleResponse responseFrom(Document rssDocument)
126: throws Exception {
127: byte[] bytes = toByteArray(rssDocument);
128: SimpleResponse response = new SimpleResponse();
129: response.setContent(bytes);
130: response.setContentType("text/xml");
131: return response;
132: }
133:
134: private byte[] toByteArray(Document rssDocument) throws Exception {
135: ByteArrayOutputStream os = new ByteArrayOutputStream();
136: XmlWriter writer = new XmlWriter(os);
137: writer.write(rssDocument);
138: writer.close();
139: byte[] bytes = os.toByteArray();
140: return bytes;
141: }
142:
143: private Document buildRssHeader() throws Exception {
144: Document rssDocument = XmlUtil.newDocument();
145: Element rssDocumentElement = rssDocument.createElement("rss");
146: rssDocument.appendChild(rssDocumentElement);
147: channelElement = rssDocument.createElement("channel");
148: rssDocumentElement.setAttribute("version", "2.0");
149: rssDocumentElement.appendChild(channelElement);
150: return rssDocument;
151: }
152:
153: protected String convertDateFormat(String dateIn) {
154: // format matched kk:mm:ss EEE, MMM dd, yyyy
155: Pattern timePattern = Pattern
156: .compile("\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");
157: Matcher m = timePattern.matcher(dateIn);
158: if (m.matches())
159: return (new SimpleDateFormat(
160: FitNesseContext.rfcCompliantDateFormat))
161: .format((new SimpleDateFormat(
162: FitNesseContext.recentChangesDateFormat))
163: .parse(dateIn, new ParsePosition(0)));
164: else
165: return dateIn;
166: }
167: }
|