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.io.IOException;
023: import java.io.OutputStream;
024: import java.io.OutputStreamWriter;
025: import java.io.PrintWriter;
026: import java.util.Vector;
027:
028: import javax.servlet.ServletConfig;
029: import javax.servlet.ServletException;
030: import javax.servlet.http.HttpServlet;
031: import javax.servlet.http.HttpServletRequest;
032: import javax.servlet.http.HttpServletResponse;
033:
034: import org.apache.log4j.Logger;
035: import org.apache.xmlrpc.*;
036:
037: import com.ecyrd.jspwiki.WikiContext;
038: import com.ecyrd.jspwiki.WikiEngine;
039:
040: /**
041: * Handles all incoming servlet requests for XML-RPC calls.
042: * <P>
043: * Uses two initialization parameters:
044: * <UL>
045: * <LI><B>handler</B> : the class which is used to handle the RPC calls.
046: * <LI><B>prefix</B> : The command prefix for that particular handler.
047: * </UL>
048: *
049: * @author Janne Jalkanen
050: * @since 1.6.6
051: */
052: public class RPCServlet extends HttpServlet {
053: private static final long serialVersionUID = 3976735878410416180L;
054:
055: /** This is what is appended to each command, if the handler has
056: not been specified. */
057: // FIXME: Should this be $default?
058: public static final String XMLRPC_PREFIX = "wiki";
059:
060: private WikiEngine m_engine;
061: private XmlRpcServer m_xmlrpcServer = new XmlRpcServer();
062:
063: static Logger log = Logger.getLogger(RPCServlet.class);
064:
065: public void initHandler(String prefix, String handlerName)
066: throws ClassNotFoundException, InstantiationException,
067: IllegalAccessException {
068: /*
069: Class handlerClass = Class.forName( handlerName );
070: WikiRPCHandler rpchandler = (WikiRPCHandler) handlerClass.newInstance();
071: rpchandler.initialize( m_engine );
072: m_xmlrpcServer.addHandler( prefix, rpchandler );
073: */
074: Class handlerClass = Class.forName(handlerName);
075: m_xmlrpcServer.addHandler(prefix,
076: new LocalHandler(handlerClass));
077: }
078:
079: /**
080: * Initializes the servlet.
081: */
082: public void init(ServletConfig config) throws ServletException {
083: m_engine = WikiEngine.getInstance(config);
084:
085: String handlerName = config.getInitParameter("handler");
086: String prefix = config.getInitParameter("prefix");
087:
088: if (handlerName == null)
089: handlerName = "com.ecyrd.jspwiki.xmlrpc.RPCHandler";
090: if (prefix == null)
091: prefix = XMLRPC_PREFIX;
092:
093: try {
094: initHandler(prefix, handlerName);
095:
096: //
097: // FIXME: The metaweblog API should be possible to turn off.
098: //
099: initHandler("metaWeblog",
100: "com.ecyrd.jspwiki.xmlrpc.MetaWeblogHandler");
101: } catch (Exception e) {
102: log.fatal("Unable to start RPC interface: ", e);
103: throw new ServletException("No RPC interface", e);
104: }
105: }
106:
107: /**
108: * Handle HTTP POST. This is an XML-RPC call, and we'll just forward
109: * the query to an XmlRpcServer.
110: */
111: public void doPost(HttpServletRequest request,
112: HttpServletResponse response) throws ServletException {
113: log.debug("Received POST to RPCServlet");
114:
115: try {
116: WikiContext ctx = m_engine.createContext(request,
117: WikiContext.NONE);
118:
119: XmlRpcContext xmlrpcContext = new WikiXmlRpcContext(
120: m_xmlrpcServer.getHandlerMapping(), ctx);
121:
122: byte[] result = m_xmlrpcServer.execute(request
123: .getInputStream(), xmlrpcContext);
124:
125: //
126: // I think it's safe to write the output as UTF-8:
127: // The XML-RPC standard never creates other than USASCII
128: // (which is UTF-8 compatible), and our special UTF-8
129: // hack just creates UTF-8. So in all cases our butt
130: // should be covered.
131: //
132: response.setContentType("text/xml; charset=utf-8");
133: response.setContentLength(result.length);
134:
135: OutputStream out = response.getOutputStream();
136: out.write(result);
137: out.flush();
138:
139: // log.debug("Result = "+new String(result) );
140: } catch (IOException e) {
141: throw new ServletException("Failed to build RPC result", e);
142: }
143: }
144:
145: /**
146: * Handles HTTP GET. However, we do not respond to GET requests,
147: * other than to show an explanatory text.
148: */
149: public void doGet(HttpServletRequest request,
150: HttpServletResponse response) throws ServletException {
151: log.debug("Received HTTP GET to RPCServlet");
152:
153: try {
154: String msg = "We do not support HTTP GET here. Sorry.";
155: response.setContentType("text/plain");
156: response.setContentLength(msg.length());
157:
158: PrintWriter writer = new PrintWriter(
159: new OutputStreamWriter(response.getOutputStream()));
160:
161: writer.println(msg);
162: writer.flush();
163: } catch (IOException e) {
164: throw new ServletException("Failed to build RPC result", e);
165: }
166: }
167:
168: private class LocalHandler implements ContextXmlRpcHandler {
169: private Class m_clazz;
170:
171: public LocalHandler(Class clazz) {
172: m_clazz = clazz;
173: }
174:
175: public Object execute(String method, Vector params,
176: XmlRpcContext context) throws Exception {
177: WikiRPCHandler rpchandler = (WikiRPCHandler) m_clazz
178: .newInstance();
179: rpchandler.initialize(((WikiXmlRpcContext) context)
180: .getWikiContext());
181:
182: Invoker invoker = new Invoker(rpchandler);
183:
184: return invoker.execute(method, params);
185: }
186: }
187:
188: private static class WikiXmlRpcContext implements XmlRpcContext {
189: private XmlRpcHandlerMapping m_mapping;
190: private WikiContext m_context;
191:
192: public WikiXmlRpcContext(XmlRpcHandlerMapping map,
193: WikiContext ctx) {
194: m_mapping = map;
195: m_context = ctx;
196: }
197:
198: public XmlRpcHandlerMapping getHandlerMapping() {
199: return m_mapping;
200: }
201:
202: public String getPassword() {
203: // TODO Auto-generated method stub
204: return null;
205: }
206:
207: public String getUserName() {
208: // TODO Auto-generated method stub
209: return null;
210: }
211:
212: public WikiContext getWikiContext() {
213: return m_context;
214: }
215: }
216: }
|