001: /**
002: * @author Tobias Schulz-Hess (sourceforge@schulz-hess.de)
003: * 12/04/2003 20:33:31
004: */package vqwiki.servlets;
005:
006: import org.apache.log4j.Logger;
007: import vqwiki.*;
008: import vqwiki.users.Usergroup;
009: import vqwiki.utils.JSPUtils;
010: import vqwiki.utils.Utilities;
011:
012: import javax.servlet.ServletException;
013: import javax.servlet.http.HttpServlet;
014: import javax.servlet.http.HttpServletRequest;
015: import javax.servlet.http.HttpServletResponse;
016: import java.io.IOException;
017: import java.io.OutputStream;
018: import java.io.StringReader;
019: import java.text.SimpleDateFormat;
020: import java.util.ArrayList;
021: import java.util.Calendar;
022: import java.util.Collection;
023: import java.util.Iterator;
024:
025: /**
026: * This servlet generates a RSS Stream for the default wiki.
027: * You can add a parameter "virutal-wiki", which then generates
028: * an RSS Stream on a particular virtual wiki.<p>
029: *
030: * For more details on RSS see:
031: * http://www.xml.com/pub/a/2002/12/18/dive-into-xml.html
032: * <p>
033: *
034: * The code of the RSS Generator is taken from
035: * JSPWiki. Author: Janne Jalkanen
036: * JSPWiki is licenced under GPL.
037: * For more information on JSPWiki see:
038: * http://www.ecyrd.com/~jalkanen/JSPWiki/
039: * <P>
040: * We use the 1.0 spec, including the wiki-specific extensions. Wiki extensions
041: * have been defined in <A HREF="http://usemod.com/cgi-bin/mb.pl?ModWiki">UseMod:ModWiki</A>.
042: *
043: *
044: * @author Tobias Schulz-Hess (sourceforge@schulz-hess.de)
045: */
046: public class RSSServlet extends HttpServlet {
047:
048: /** Logging */
049: private static final Logger logger = Logger
050: .getLogger(RSSServlet.class);
051:
052: /**
053: * Handle post request.
054: * Generate a RSS feed and send it back as XML.
055: *
056: * @param request The current http request
057: * @param response What the servlet will send back as response
058: *
059: * @throws ServletException If something goes wrong during servlet execution
060: * @throws IOException If the output stream cannot be accessed
061: *
062: */
063: protected void doPost(HttpServletRequest request,
064: HttpServletResponse response) throws ServletException,
065: IOException {
066: String virtualWiki = null;
067: String topicName = null;
068: try {
069: virtualWiki = (String) request.getAttribute("virtual-wiki");
070: if (virtualWiki == null || virtualWiki.length() < 1) {
071: virtualWiki = WikiBase.DEFAULT_VWIKI;
072: }
073: // get the latest pages
074: int howManyDatesToGoBack = Environment.getInstance()
075: .getIntSetting(
076: Environment.PROPERTY_RECENT_CHANGES_DAYS);
077: if (howManyDatesToGoBack == 0)
078: howManyDatesToGoBack = 5;
079: ChangeLog cl = WikiBase.getInstance()
080: .getChangeLogInstance();
081: Collection changed = new ArrayList();
082: if (cl != null) {
083: Calendar historycal = Calendar.getInstance();
084: for (int i = 0; i < howManyDatesToGoBack; i++) {
085: try {
086: Collection col = cl.getChanges(virtualWiki,
087: historycal.getTime());
088: if (col != null) {
089: changed.addAll(col);
090: }
091: } catch (Exception e) {
092: logger.fatal("Cannot get changes", e);
093: }
094: historycal.add(Calendar.DATE, -1);
095: }
096: }
097: String wikiServerHostname = Environment.getInstance()
098: .getStringSetting(
099: Environment.PROPERTY_WIKI_SERVER_HOSTNAME);
100: String baseURL = JSPUtils.createRootPath(request,
101: virtualWiki, wikiServerHostname);
102: // generate rss
103: // --------- BEGIN CODE BY Janne Jalken ---------------
104: StringBuffer result = new StringBuffer();
105: SimpleDateFormat iso8601fmt = new SimpleDateFormat(
106: "yyyy-MM-dd'T'HH:mm:ss'Z'");
107: //
108: // Preamble
109: //
110: result
111: .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
112: result
113: .append("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n"
114: + " xmlns=\"http://purl.org/rss/1.0/\"\n"
115: + " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n"
116: + " xmlns:wiki=\"http://purl.org/rss/1.0/modules/wiki/\">\n");
117: //
118: // Channel.
119: //
120: result.append(" <channel rdf:about=\"" + baseURL + "\">\n");
121: result.append(" <title><![CDATA[Wiki running on "
122: + request.getServerName() + "]]></title>\n");
123: // FIXME: This might fail in case the base url is not defined.
124: result.append(" <link><![CDATA[").append(baseURL).append(
125: "]]></link>\n");
126: result.append(" <description><![CDATA[");
127: result.append("Wiki running on " + request.getServerName());
128: result.append("]]></description>\n");
129: //
130: // Now, list items.
131: //
132: // We need two lists, which is why we gotta make a separate list if
133: // we want to do just a single pass.
134: StringBuffer itemBuffer = new StringBuffer();
135: result.append(" <items>\n <rdf:Seq>\n");
136: Usergroup usergroup = WikiBase.getInstance()
137: .getUsergroupInstance();
138: int items = 0;
139: for (Iterator i = changed.iterator(); i.hasNext()
140: && items < 15; items++) {
141: Change change = (Change) i.next();
142: topicName = change.getTopic();
143: Topic topicObject = new Topic(topicName);
144: String userid = change.getUser();
145: if (userid == null || "".equals(userid)) {
146: userid = topicObject
147: .getMostRecentAuthor(virtualWiki);
148: }
149: String author = null;
150: if (userid != null) {
151: author = usergroup.getFullnameById(userid);
152: }
153: java.util.Date lastRevisionDate = topicObject
154: .getMostRecentRevisionDate(virtualWiki);
155: String url = baseURL + "Wiki?" + topicName;
156: result.append(" <rdf:li rdf:resource=\"" + url
157: + "\" />\n");
158: itemBuffer
159: .append(" <item rdf:about=\"" + url + "\">\n");
160: itemBuffer.append(" <title><![CDATA[");
161: itemBuffer.append(topicName);
162: itemBuffer.append("]]></title>\n");
163: itemBuffer.append(" <link><![CDATA[");
164: itemBuffer.append(url);
165: itemBuffer.append("]]></link>\n");
166: itemBuffer.append(" <description>");
167: itemBuffer.append("<![CDATA[<p>");
168: if (author == null)
169: author = "An unknown author";
170: int numberOfVersions = topicObject
171: .getRevision(virtualWiki);
172: if (numberOfVersions != 1) {
173: itemBuffer
174: .append(author
175: + " changed this page on "
176: + topicObject
177: .getMostRecentRevisionDate(virtualWiki));
178: } else {
179: itemBuffer
180: .append(author
181: + " created this page on "
182: + topicObject
183: .getMostRecentRevisionDate(virtualWiki));
184: }
185: // itemBuffer.append("<p>\n<![CDATA[");
186: // String content = WikiBase.getInstance().readRaw(virtualWiki, topicName);
187: itemBuffer.append("</p><br /><div id=content>");
188: String content = WikiBase.getInstance().readCooked(
189: virtualWiki, topicName);
190: /* if (content.length() > 200) {
191: content = content.substring(0, 197) + "...";
192: }*/
193: itemBuffer.append(content).append("\n");
194: //itemBuffer.append("]]></p></description>\n");
195: itemBuffer.append("</div>]]></description>\n");
196: if (numberOfVersions != -1) {
197: itemBuffer.append(" <wiki:version>"
198: + numberOfVersions + "</wiki:version>\n");
199: }
200: //
201: // Modification date.
202: //
203: if (Environment.getInstance().isVersioningOn()) {
204: try {
205: if (lastRevisionDate != null) {
206: itemBuffer.append(" <dc:date>");
207: Calendar cal = Calendar.getInstance();
208: cal.setTime(lastRevisionDate);
209: cal.add(Calendar.MILLISECOND, -(cal
210: .get(Calendar.ZONE_OFFSET) + (cal
211: .getTimeZone().inDaylightTime(
212: lastRevisionDate) ? cal
213: .get(Calendar.DST_OFFSET) : 0)));
214: itemBuffer.append(iso8601fmt.format(cal
215: .getTime()));
216: itemBuffer.append("</dc:date>\n");
217: }
218: } catch (Exception e) {
219: logger.warn(e);
220: }
221: }
222: //
223: // Author.
224: //
225: itemBuffer.append(" <dc:contributor>\n");
226: itemBuffer.append(" <rdf:Description");
227: if (WikiBase.getInstance().exists(virtualWiki, author)) {
228: itemBuffer.append(" link=\"" + baseURL + "Wiki?"
229: + author + "\"");
230: }
231: itemBuffer.append(">\n");
232: itemBuffer.append(" <rdf:value>" + author
233: + "</rdf:value>\n");
234: itemBuffer.append(" </rdf:Description>\n");
235: itemBuffer.append(" </dc:contributor>\n");
236: // PageHistory
237: itemBuffer.append(" <wiki:history>");
238: itemBuffer.append(format(baseURL + "Wiki?topic="
239: + topicName + "&action="
240: + WikiServlet.ACTION_HISTORY + "&type=all"));
241: itemBuffer.append("</wiki:history>\n");
242: // Close up.
243: itemBuffer.append(" </item>\n");
244: }
245: result.append(" </rdf:Seq>\n </items>\n");
246: result.append(" </channel>\n");
247: result.append(itemBuffer.toString());
248: //
249: // In the end, add a search box for JSPWiki
250: //
251: String searchURL = baseURL + "Wiki?WikiSearch";
252: result.append(" <textinput rdf:about=\"" + searchURL
253: + "\">\n");
254: result.append(" <title>Search</title>\n");
255: result
256: .append(" <description>Search this Wiki</description>\n");
257: result.append(" <name>query</name>\n");
258: result.append(" <link>" + searchURL + "</link>\n");
259: result.append(" </textinput>\n");
260: //
261: // Be a fine boy and close things.
262: //
263: result.append("</rdf:RDF>");
264: // --------- END CODE BY Janne Jalken ---------------
265: byte[] utf_result = result.toString().getBytes("UTF-8");
266: response.setContentType("text/xml; charset=UTF-8");
267: response.setHeader("Expires", "0");
268: response.setHeader("Pragma", "no-cache");
269: response.setHeader("Keep-Alive", "timeout=15, max=100");
270: response.setHeader("Connection", "Keep-Alive");
271: response.setContentLength(utf_result.length);
272: OutputStream out = response.getOutputStream();
273: out.write(utf_result);
274: out.flush();
275: out.close();
276: } catch (Exception e) {
277: throw new ServletException(e.getMessage(), e);
278: }
279: }
280:
281: /**
282: * Handle get request.
283: * The request is handled the same way as the post request.
284: *
285: * @see doPost()
286: *
287: * @param httpServletRequest The current http request
288: * @param httpServletResponse What the servlet will send back as response
289: *
290: * @throws ServletException If something goes wrong during servlet execution
291: * @throws IOException If the output stream cannot be accessed
292: *
293: */
294: protected void doGet(HttpServletRequest httpServletRequest,
295: HttpServletResponse httpServletResponse)
296: throws ServletException, IOException {
297: this .doPost(httpServletRequest, httpServletResponse);
298: }
299:
300: /**
301: * Does the required formatting and entity replacement for XML.
302: * @param s The source String to format
303: * @return The String formatted
304: */
305: private String format(String s) {
306: s = Utilities.replaceString(s, "&", "&");
307: s = Utilities.replaceString(s, "<", "<");
308: s = Utilities.replaceString(s, "]]>", "]]>");
309: return s;
310: }
311: }
|