1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.xmlrpc;
16  
17  import com.liferay.portal.kernel.log.Log;
18  import com.liferay.portal.kernel.log.LogFactoryUtil;
19  import com.liferay.portal.kernel.util.ContentTypes;
20  import com.liferay.portal.kernel.util.StringPool;
21  import com.liferay.portal.kernel.util.StringUtil;
22  import com.liferay.portal.kernel.util.Tuple;
23  import com.liferay.portal.kernel.xmlrpc.Method;
24  import com.liferay.portal.kernel.xmlrpc.Response;
25  import com.liferay.portal.kernel.xmlrpc.XmlRpcConstants;
26  import com.liferay.portal.kernel.xmlrpc.XmlRpcException;
27  import com.liferay.portal.kernel.xmlrpc.XmlRpcUtil;
28  import com.liferay.portal.util.PortalInstances;
29  import com.liferay.util.servlet.ServletResponseUtil;
30  
31  import java.io.IOException;
32  import java.io.InputStream;
33  
34  import java.util.HashMap;
35  import java.util.Map;
36  
37  import javax.servlet.http.HttpServlet;
38  import javax.servlet.http.HttpServletRequest;
39  import javax.servlet.http.HttpServletResponse;
40  
41  /**
42   * <a href="XmlRpcServlet.java.html"><b><i>View Source</i></b></a>
43   *
44   * @author Alexander Chow
45   * @author Brian Wing Shun Chan
46   */
47  public class XmlRpcServlet extends HttpServlet {
48  
49      public static void registerMethod(Method method) {
50          if (method == null) {
51              return;
52          }
53  
54          String token = method.getToken();
55          String methodName = method.getMethodName();
56  
57          Map<String, Method> tokenMethods = _methodRegistry.get(token);
58  
59          if (tokenMethods == null) {
60              tokenMethods = new HashMap<String, Method>();
61  
62              _methodRegistry.put(token, tokenMethods);
63          }
64  
65          Method registeredMethod = tokenMethods.get(methodName);
66  
67          if (registeredMethod != null) {
68              _log.error(
69                  "There is already an XML-RPC method registered with name " +
70                      methodName + " at " + token);
71          }
72          else {
73              tokenMethods.put(methodName, method);
74          }
75      }
76  
77      public static void unregisterMethod(Method method) {
78          if (method == null) {
79              return;
80          }
81  
82          String token = method.getToken();
83          String methodName = method.getMethodName();
84  
85          Map<String, Method> tokenMethods = _methodRegistry.get(token);
86  
87          if (tokenMethods == null) {
88              return;
89          }
90  
91          tokenMethods.remove(methodName);
92  
93          if (tokenMethods.isEmpty()) {
94              _methodRegistry.remove(token);
95          }
96      }
97  
98      protected void doPost(
99          HttpServletRequest request, HttpServletResponse response) {
100 
101         Response xmlRpcResponse = null;
102 
103         try {
104             long companyId = PortalInstances.getCompanyId(request);
105 
106             String token = getToken(request);
107 
108             InputStream is = request.getInputStream();
109 
110             String xml = StringUtil.read(is);
111 
112             Tuple methodTuple = XmlRpcParser.parseMethod(xml);
113 
114             String methodName = (String)methodTuple.getObject(0);
115             Object[] args = (Object[])methodTuple.getObject(1);
116 
117             xmlRpcResponse = invokeMethod(companyId, token, methodName, args);
118         }
119         catch (IOException ioe) {
120             xmlRpcResponse = XmlRpcUtil.createFault(
121                 XmlRpcConstants.NOT_WELL_FORMED, "XML is not well formed");
122 
123             if (_log.isDebugEnabled()) {
124                 _log.debug(ioe, ioe);
125             }
126         }
127         catch (XmlRpcException xmlrpce) {
128             _log.error(xmlrpce, xmlrpce);
129         }
130 
131         if (xmlRpcResponse == null) {
132             xmlRpcResponse = XmlRpcUtil.createFault(
133                 XmlRpcConstants.SYSTEM_ERROR, "Unknown error occurred");
134         }
135 
136         response.setCharacterEncoding(StringPool.UTF8);
137         response.setContentType(ContentTypes.TEXT_XML);
138         response.setStatus(HttpServletResponse.SC_OK);
139 
140         try {
141             ServletResponseUtil.write(response, xmlRpcResponse.toXml());
142         }
143         catch (Exception e) {
144             if (_log.isWarnEnabled()) {
145                 _log.warn(e, e);
146             }
147 
148             response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED);
149         }
150     }
151 
152     protected Method getMethod(String token, String methodName) {
153         Method method = null;
154 
155         Map<String, Method> tokenMethods = _methodRegistry.get(token);
156 
157         if (tokenMethods != null) {
158             method = tokenMethods.get(methodName);
159         }
160 
161         return method;
162     }
163 
164     protected String getToken(HttpServletRequest request) {
165         String token = request.getPathInfo();
166 
167         token = token.replaceAll("^/+", StringPool.BLANK);
168         token = token.replaceAll("/+$", StringPool.BLANK);
169 
170         return token;
171     }
172 
173     protected Response invokeMethod(
174             long companyId, String token, String methodName, Object[] arguments)
175         throws XmlRpcException {
176 
177         Method method = getMethod(token, methodName);
178 
179         if (method == null) {
180             return XmlRpcUtil.createFault(
181                 XmlRpcConstants.REQUESTED_METHOD_NOT_FOUND,
182                 "Requested method not found");
183         }
184 
185         if (!method.setArguments(arguments)) {
186             return XmlRpcUtil.createFault(
187                 XmlRpcConstants.INVALID_METHOD_PARAMETERS,
188                 "Method arguments are invalid");
189         }
190 
191         return method.execute(companyId);
192     }
193 
194     private static Log _log = LogFactoryUtil.getLog(XmlRpcServlet.class);
195 
196     private static Map<String, Map<String, Method>> _methodRegistry =
197         new HashMap<String, Map<String, Method>>();
198 
199 }