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.HttpUtil;
21  import com.liferay.portal.kernel.util.StringPool;
22  import com.liferay.portal.kernel.util.StringUtil;
23  import com.liferay.portal.kernel.util.Tuple;
24  import com.liferay.portal.kernel.xmlrpc.Method;
25  import com.liferay.portal.kernel.xmlrpc.Response;
26  import com.liferay.portal.kernel.xmlrpc.XmlRpcConstants;
27  import com.liferay.portal.kernel.xmlrpc.XmlRpcException;
28  import com.liferay.portal.kernel.xmlrpc.XmlRpcUtil;
29  import com.liferay.portal.util.PortalInstances;
30  import com.liferay.util.servlet.ServletResponseUtil;
31  
32  import java.io.IOException;
33  import java.io.InputStream;
34  
35  import java.util.HashMap;
36  import java.util.Map;
37  
38  import javax.servlet.http.HttpServlet;
39  import javax.servlet.http.HttpServletRequest;
40  import javax.servlet.http.HttpServletResponse;
41  
42  /**
43   * <a href="XmlRpcServlet.java.html"><b><i>View Source</i></b></a>
44   *
45   * @author Alexander Chow
46   * @author Brian Wing Shun Chan
47   */
48  public class XmlRpcServlet extends HttpServlet {
49  
50      public static void registerMethod(Method method) {
51          if (method == null) {
52              return;
53          }
54  
55          String token = method.getToken();
56          String methodName = method.getMethodName();
57  
58          Map<String, Method> tokenMethods = _methodRegistry.get(token);
59  
60          if (tokenMethods == null) {
61              tokenMethods = new HashMap<String, Method>();
62  
63              _methodRegistry.put(token, tokenMethods);
64          }
65  
66          Method registeredMethod = tokenMethods.get(methodName);
67  
68          if (registeredMethod != null) {
69              _log.error(
70                  "There is already an XML-RPC method registered with name " +
71                      methodName + " at " + token);
72          }
73          else {
74              tokenMethods.put(methodName, method);
75          }
76      }
77  
78      public static void unregisterMethod(Method method) {
79          if (method == null) {
80              return;
81          }
82  
83          String token = method.getToken();
84          String methodName = method.getMethodName();
85  
86          Map<String, Method> tokenMethods = _methodRegistry.get(token);
87  
88          if (tokenMethods == null) {
89              return;
90          }
91  
92          tokenMethods.remove(methodName);
93  
94          if (tokenMethods.isEmpty()) {
95              _methodRegistry.remove(token);
96          }
97      }
98  
99      protected void doPost(
100         HttpServletRequest request, HttpServletResponse response) {
101 
102         Response xmlRpcResponse = null;
103 
104         try {
105             long companyId = PortalInstances.getCompanyId(request);
106 
107             String token = getToken(request);
108 
109             InputStream is = request.getInputStream();
110 
111             String xml = StringUtil.read(is);
112 
113             Tuple methodTuple = XmlRpcParser.parseMethod(xml);
114 
115             String methodName = (String)methodTuple.getObject(0);
116             Object[] args = (Object[])methodTuple.getObject(1);
117 
118             xmlRpcResponse = invokeMethod(companyId, token, methodName, args);
119         }
120         catch (IOException ioe) {
121             xmlRpcResponse = XmlRpcUtil.createFault(
122                 XmlRpcConstants.NOT_WELL_FORMED, "XML is not well formed");
123 
124             if (_log.isDebugEnabled()) {
125                 _log.debug(ioe, ioe);
126             }
127         }
128         catch (XmlRpcException xmlrpce) {
129             _log.error(xmlrpce, xmlrpce);
130         }
131 
132         if (xmlRpcResponse == null) {
133             xmlRpcResponse = XmlRpcUtil.createFault(
134                 XmlRpcConstants.SYSTEM_ERROR, "Unknown error occurred");
135         }
136 
137         response.setCharacterEncoding(StringPool.UTF8);
138         response.setContentType(ContentTypes.TEXT_XML);
139         response.setStatus(HttpServletResponse.SC_OK);
140 
141         try {
142             ServletResponseUtil.write(response, xmlRpcResponse.toXml());
143         }
144         catch (Exception e) {
145             if (_log.isWarnEnabled()) {
146                 _log.warn(e, e);
147             }
148 
149             response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED);
150         }
151     }
152 
153     protected Method getMethod(String token, String methodName) {
154         Method method = null;
155 
156         Map<String, Method> tokenMethods = _methodRegistry.get(token);
157 
158         if (tokenMethods != null) {
159             method = tokenMethods.get(methodName);
160         }
161 
162         return method;
163     }
164 
165     protected String getToken(HttpServletRequest request) {
166         String token = request.getPathInfo();
167 
168         return HttpUtil.fixPath(token);
169     }
170 
171     protected Response invokeMethod(
172             long companyId, String token, String methodName, Object[] arguments)
173         throws XmlRpcException {
174 
175         Method method = getMethod(token, methodName);
176 
177         if (method == null) {
178             return XmlRpcUtil.createFault(
179                 XmlRpcConstants.REQUESTED_METHOD_NOT_FOUND,
180                 "Requested method not found");
181         }
182 
183         if (!method.setArguments(arguments)) {
184             return XmlRpcUtil.createFault(
185                 XmlRpcConstants.INVALID_METHOD_PARAMETERS,
186                 "Method arguments are invalid");
187         }
188 
189         return method.execute(companyId);
190     }
191 
192     private static Log _log = LogFactoryUtil.getLog(XmlRpcServlet.class);
193 
194     private static Map<String, Map<String, Method>> _methodRegistry =
195         new HashMap<String, Map<String, Method>>();
196 
197 }