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.io.unsync.UnsyncStringReader;
18  import com.liferay.portal.kernel.util.CharPool;
19  import com.liferay.portal.kernel.util.GetterUtil;
20  import com.liferay.portal.kernel.util.StringBundler;
21  import com.liferay.portal.kernel.util.StringPool;
22  import com.liferay.portal.kernel.util.Tuple;
23  import com.liferay.portal.kernel.xmlrpc.Response;
24  import com.liferay.portal.kernel.xmlrpc.XmlRpcException;
25  import com.liferay.portal.kernel.xmlrpc.XmlRpcUtil;
26  import com.liferay.portal.xml.StAXReaderUtil;
27  
28  import java.io.IOException;
29  
30  import java.util.ArrayList;
31  import java.util.List;
32  
33  import javax.xml.stream.XMLInputFactory;
34  import javax.xml.stream.XMLStreamConstants;
35  import javax.xml.stream.XMLStreamReader;
36  
37  /**
38   * <a href="XmlRpcParser.java.html"><b><i>View Source</i></b></a>
39   *
40   * @author Alexander Chow
41   * @author Brian Wing Shun Chan
42   */
43  public class XmlRpcParser {
44  
45      public static String buildMethod(String methodName, Object[] arguments)
46          throws XmlRpcException {
47  
48          StringBundler sb = new StringBundler(arguments.length * 3 + 8);
49  
50          sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
51  
52          sb.append("<methodCall>");
53          sb.append("<methodName>");
54          sb.append(methodName);
55          sb.append("</methodName>");
56          sb.append("<params>");
57  
58          for (Object argument : arguments) {
59              sb.append("<param>");
60              sb.append(wrapValue(argument));
61              sb.append("</param>");
62          }
63  
64          sb.append("</params>");
65          sb.append("</methodCall>");
66  
67          return sb.toString();
68      }
69  
70      public static Tuple parseMethod(String xml) throws IOException {
71          XMLStreamReader xmlStreamReader = null;
72  
73          try {
74              XMLInputFactory xmlInputFactory =
75                  StAXReaderUtil.getXMLInputFactory();
76  
77              xmlStreamReader = xmlInputFactory.createXMLStreamReader(
78                  new UnsyncStringReader(xml));
79  
80              xmlStreamReader.nextTag();
81              xmlStreamReader.nextTag();
82              xmlStreamReader.next();
83  
84              String methodName = xmlStreamReader.getText();
85              List<Object> arguments = new ArrayList<Object>();
86  
87              xmlStreamReader.nextTag();
88  
89              String name = xmlStreamReader.getLocalName();
90  
91              while (!name.equals("methodCall")) {
92                  xmlStreamReader.nextTag();
93  
94                  name = xmlStreamReader.getLocalName();
95  
96                  if (name.equals("param")) {
97                      xmlStreamReader.nextTag();
98  
99                      name = xmlStreamReader.getLocalName();
100 
101                     int event = xmlStreamReader.next();
102 
103                     if (event == XMLStreamConstants.START_ELEMENT) {
104                         name = xmlStreamReader.getLocalName();
105 
106                         xmlStreamReader.next();
107 
108                         String text = xmlStreamReader.getText();
109 
110                         if (name.equals("string")) {
111                             arguments.add(text);
112                         }
113                         else if (name.equals("int") || name.equals("i4")) {
114                             arguments.add(GetterUtil.getInteger(text));
115                         }
116                         else if (name.equals("double")) {
117                             arguments.add(GetterUtil.getDouble(text));
118                         }
119                         else if (name.equals("boolean")) {
120                             arguments.add(GetterUtil.getBoolean(text));
121                         }
122                         else {
123                             throw new IOException(
124                                 "XML-RPC not implemented for " + name);
125                         }
126 
127                         xmlStreamReader.nextTag();
128                         xmlStreamReader.nextTag();
129                         xmlStreamReader.nextTag();
130                     }
131                     else {
132                         String text = xmlStreamReader.getText();
133 
134                         arguments.add(text);
135 
136                         xmlStreamReader.nextTag();
137                         xmlStreamReader.nextTag();
138                     }
139 
140                     name = xmlStreamReader.getLocalName();
141                 }
142             }
143 
144             return new Tuple(methodName, arguments.toArray());
145         }
146         catch (Exception e) {
147             throw new IOException(e.getMessage());
148         }
149         finally {
150             if (xmlStreamReader != null) {
151                 try {
152                     xmlStreamReader.close();
153                 }
154                 catch (Exception e) {
155                 }
156             }
157         }
158     }
159 
160     public static Response parseResponse(String xml) throws XmlRpcException {
161         XMLStreamReader xmlStreamReader = null;
162 
163         try {
164             XMLInputFactory xmlInputFactory =
165                 StAXReaderUtil.getXMLInputFactory();
166 
167             xmlStreamReader = xmlInputFactory.createXMLStreamReader(
168                 new UnsyncStringReader(xml));
169 
170             xmlStreamReader.nextTag();
171             xmlStreamReader.nextTag();
172 
173             String name = xmlStreamReader.getLocalName();
174 
175             if (name.equals("params")) {
176                 String description = null;
177 
178                 xmlStreamReader.nextTag();
179                 xmlStreamReader.nextTag();
180 
181                 int event = xmlStreamReader.next();
182 
183                 if (event == XMLStreamConstants.START_ELEMENT) {
184                     xmlStreamReader.next();
185 
186                     description = xmlStreamReader.getText();
187                 }
188                 else {
189                     description = xmlStreamReader.getText();
190                 }
191 
192                 return XmlRpcUtil.createSuccess(description);
193             }
194             else if (name.equals("fault")) {
195                 int code = 0;
196                 String description = null;
197 
198                 xmlStreamReader.nextTag();
199                 xmlStreamReader.nextTag();
200 
201                 for (int i = 0; i < 2; i++) {
202                     xmlStreamReader.nextTag();
203                     xmlStreamReader.nextTag();
204 
205                     xmlStreamReader.next();
206 
207                     String valueName = xmlStreamReader.getText();
208 
209                     if (valueName.equals("faultCode")) {
210                         xmlStreamReader.nextTag();
211                         xmlStreamReader.nextTag();
212                         xmlStreamReader.nextTag();
213 
214                         name = xmlStreamReader.getLocalName();
215 
216                         if (name.equals("int") || name.equals("i4")) {
217                             xmlStreamReader.next();
218 
219                             code = GetterUtil.getInteger(
220                                 xmlStreamReader.getText());
221                         }
222 
223                         xmlStreamReader.nextTag();
224                         xmlStreamReader.nextTag();
225                         xmlStreamReader.nextTag();
226                     }
227                     else if (valueName.equals("faultString")) {
228                         xmlStreamReader.nextTag();
229                         xmlStreamReader.nextTag();
230 
231                         int event = xmlStreamReader.next();
232 
233                         if (event == XMLStreamConstants.START_ELEMENT) {
234                             xmlStreamReader.next();
235 
236                             description = xmlStreamReader.getText();
237 
238                             xmlStreamReader.nextTag();
239                         }
240                         else {
241                             description = xmlStreamReader.getText();
242                         }
243 
244                         xmlStreamReader.nextTag();
245                         xmlStreamReader.nextTag();
246                     }
247                 }
248 
249                 return XmlRpcUtil.createFault(code, description);
250             }
251 
252             return null;
253         }
254         catch (Exception e) {
255             throw new XmlRpcException(xml, e);
256         }
257         finally {
258             if (xmlStreamReader != null) {
259                 try {
260                     xmlStreamReader.close();
261                 }
262                 catch (Exception e) {
263                 }
264             }
265         }
266     }
267 
268     public static String wrapValue(Object value) throws XmlRpcException {
269         if (value == null) {
270             return StringPool.BLANK;
271         }
272 
273         StringBundler sb = new StringBundler(5);
274 
275         sb.append("<value>");
276 
277         if (value instanceof String) {
278             sb.append("<string>");
279             sb.append(value.toString());
280             sb.append("</string>");
281         }
282         else if ((value instanceof Integer) || (value instanceof Short)) {
283             sb.append("<i4>");
284             sb.append(value.toString());
285             sb.append("</i4>");
286         }
287         else if ((value instanceof Double) || (value instanceof Float)) {
288             sb.append("<double>");
289             sb.append(value.toString());
290             sb.append("</double>");
291         }
292         else if (value instanceof Boolean) {
293             sb.append("<boolean>");
294 
295             if ((Boolean)value) {
296                 sb.append(CharPool.NUMBER_1);
297             }
298             else {
299                 sb.append(CharPool.NUMBER_0);
300             }
301 
302             sb.append("</boolean>");
303         }
304         else {
305             throw new XmlRpcException("Unsupported type " + value.getClass());
306         }
307 
308         sb.append("</value>");
309 
310         return sb.toString();
311     }
312 
313 }