001: /*
002: JSPWiki - a JSP-based WikiWiki clone.
003:
004: Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
005:
006: This program is free software; you can redistribute it and/or modify
007: it under the terms of the GNU Lesser General Public License as published by
008: the Free Software Foundation; either version 2.1 of the License, or
009: (at your option) any later version.
010:
011: This program is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: GNU Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public License
017: along with this program; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020: package com.ecyrd.jspwiki.xmlrpc;
021:
022: import java.util.*;
023:
024: import org.apache.xmlrpc.XmlRpcException;
025:
026: import com.ecyrd.jspwiki.LinkCollector;
027: import com.ecyrd.jspwiki.WikiContext;
028: import com.ecyrd.jspwiki.WikiEngine;
029: import com.ecyrd.jspwiki.WikiPage;
030: import com.ecyrd.jspwiki.attachment.Attachment;
031: import com.ecyrd.jspwiki.auth.permissions.PagePermission;
032: import com.ecyrd.jspwiki.auth.permissions.PermissionFactory;
033:
034: /**
035: * Provides handlers for all RPC routines. These routines are used by
036: * the UTF-8 interface.
037: *
038: * @author Janne Jalkanen
039: * @since 1.6.13
040: */
041:
042: public class RPCHandlerUTF8 extends AbstractRPCHandler {
043: public String getApplicationName() {
044: checkPermission(PagePermission.VIEW);
045:
046: return m_engine.getApplicationName();
047: }
048:
049: public Vector getAllPages() {
050: checkPermission(PagePermission.VIEW);
051:
052: Collection pages = m_engine.getRecentChanges();
053: Vector result = new Vector();
054:
055: for (Iterator i = pages.iterator(); i.hasNext();) {
056: WikiPage p = (WikiPage) i.next();
057:
058: if (!(p instanceof Attachment)) {
059: result.add(p.getName());
060: }
061: }
062:
063: return result;
064: }
065:
066: /**
067: * Encodes a single wiki page info into a Hashtable.
068: */
069: protected Hashtable encodeWikiPage(WikiPage page) {
070: Hashtable ht = new Hashtable();
071:
072: ht.put("name", page.getName());
073:
074: Date d = page.getLastModified();
075:
076: //
077: // Here we reset the DST and TIMEZONE offsets of the
078: // calendar. Unfortunately, I haven't thought of a better
079: // way to ensure that we're getting the proper date
080: // from the XML-RPC thingy, except to manually adjust the date.
081: //
082:
083: Calendar cal = Calendar.getInstance();
084: cal.setTime(d);
085: cal.add(Calendar.MILLISECOND,
086: -(cal.get(Calendar.ZONE_OFFSET) + (cal.getTimeZone()
087: .inDaylightTime(d) ? cal
088: .get(Calendar.DST_OFFSET) : 0)));
089:
090: ht.put("lastModified", cal.getTime());
091: ht.put("version", new Integer(page.getVersion()));
092:
093: if (page.getAuthor() != null) {
094: ht.put("author", page.getAuthor());
095: }
096:
097: return ht;
098: }
099:
100: public Vector getRecentChanges(Date since) {
101: checkPermission(PagePermission.VIEW);
102:
103: Collection pages = m_engine.getRecentChanges();
104: Vector result = new Vector();
105:
106: Calendar cal = Calendar.getInstance();
107: cal.setTime(since);
108:
109: //
110: // Convert UTC to our time.
111: //
112: cal.add(Calendar.MILLISECOND,
113: (cal.get(Calendar.ZONE_OFFSET) + (cal.getTimeZone()
114: .inDaylightTime(since) ? cal
115: .get(Calendar.DST_OFFSET) : 0)));
116: since = cal.getTime();
117:
118: for (Iterator i = pages.iterator(); i.hasNext();) {
119: WikiPage page = (WikiPage) i.next();
120:
121: if (page.getLastModified().after(since)
122: && !(page instanceof Attachment)) {
123: result.add(encodeWikiPage(page));
124: }
125: }
126:
127: return result;
128: }
129:
130: /**
131: * Simple helper method, turns the incoming page name into
132: * normal Java string, then checks page condition.
133: *
134: * @param pagename Page Name as an RPC string (URL-encoded UTF-8)
135: * @return Real page name, as Java string.
136: * @throws XmlRpcException, if there is something wrong with the page.
137: */
138: private String parsePageCheckCondition(String pagename)
139: throws XmlRpcException {
140: if (!m_engine.pageExists(pagename)) {
141: throw new XmlRpcException(ERR_NOPAGE, "No such page '"
142: + pagename + "' found, o master.");
143: }
144:
145: WikiPage p = m_engine.getPage(pagename);
146:
147: checkPermission(PermissionFactory.getPagePermission(p,
148: PagePermission.VIEW_ACTION));
149: return pagename;
150: }
151:
152: public Hashtable getPageInfo(String pagename)
153: throws XmlRpcException {
154: pagename = parsePageCheckCondition(pagename);
155:
156: return encodeWikiPage(m_engine.getPage(pagename));
157: }
158:
159: public Hashtable getPageInfoVersion(String pagename, int version)
160: throws XmlRpcException {
161: pagename = parsePageCheckCondition(pagename);
162:
163: return encodeWikiPage(m_engine.getPage(pagename, version));
164: }
165:
166: public String getPage(String pagename) throws XmlRpcException {
167: pagename = parsePageCheckCondition(pagename);
168:
169: String text = m_engine.getPureText(pagename, -1);
170:
171: return text;
172: }
173:
174: public String getPageVersion(String pagename, int version)
175: throws XmlRpcException {
176: pagename = parsePageCheckCondition(pagename);
177:
178: return m_engine.getPureText(pagename, version);
179: }
180:
181: public String getPageHTML(String pagename) throws XmlRpcException {
182: pagename = parsePageCheckCondition(pagename);
183:
184: return m_engine.getHTML(pagename);
185: }
186:
187: public String getPageHTMLVersion(String pagename, int version)
188: throws XmlRpcException {
189: pagename = parsePageCheckCondition(pagename);
190:
191: return m_engine.getHTML(pagename, version);
192: }
193:
194: public Vector listLinks(String pagename) throws XmlRpcException {
195: pagename = parsePageCheckCondition(pagename);
196:
197: WikiPage page = m_engine.getPage(pagename);
198: String pagedata = m_engine.getPureText(page);
199:
200: LinkCollector localCollector = new LinkCollector();
201: LinkCollector extCollector = new LinkCollector();
202: LinkCollector attCollector = new LinkCollector();
203:
204: WikiContext context = new WikiContext(m_engine, page);
205: context.setVariable(WikiEngine.PROP_REFSTYLE, "absolute");
206:
207: m_engine.textToHTML(context, pagedata, localCollector,
208: extCollector, attCollector);
209:
210: Vector result = new Vector();
211:
212: // FIXME: Contains far too much common with RPCHandler. Refactor!
213:
214: //
215: // Add local links.
216: //
217: for (Iterator i = localCollector.getLinks().iterator(); i
218: .hasNext();) {
219: String link = (String) i.next();
220: Hashtable ht = new Hashtable();
221: ht.put("page", link);
222: ht.put("type", LINK_LOCAL);
223:
224: if (m_engine.pageExists(link)) {
225: ht.put("href", context.getViewURL(link));
226: } else {
227: ht.put("href", context.getURL(WikiContext.EDIT, link));
228: }
229:
230: result.add(ht);
231: }
232:
233: //
234: // Add links to inline attachments
235: //
236: for (Iterator i = attCollector.getLinks().iterator(); i
237: .hasNext();) {
238: String link = (String) i.next();
239:
240: Hashtable ht = new Hashtable();
241:
242: ht.put("page", link);
243: ht.put("type", LINK_LOCAL);
244: ht.put("href", context.getURL(WikiContext.ATTACH, link));
245:
246: result.add(ht);
247: }
248:
249: //
250: // External links don't need to be changed into XML-RPC strings,
251: // simply because URLs are by definition ASCII.
252: //
253:
254: for (Iterator i = extCollector.getLinks().iterator(); i
255: .hasNext();) {
256: String link = (String) i.next();
257:
258: Hashtable ht = new Hashtable();
259:
260: ht.put("page", link);
261: ht.put("type", LINK_EXTERNAL);
262: ht.put("href", link);
263:
264: result.add(ht);
265: }
266:
267: return result;
268: }
269: }
|