001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.xmlrpc;
016    
017    import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
018    import com.liferay.portal.kernel.util.CharPool;
019    import com.liferay.portal.kernel.util.GetterUtil;
020    import com.liferay.portal.kernel.util.StringBundler;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.Tuple;
023    import com.liferay.portal.kernel.xmlrpc.Response;
024    import com.liferay.portal.kernel.xmlrpc.XmlRpcException;
025    import com.liferay.portal.kernel.xmlrpc.XmlRpcUtil;
026    import com.liferay.portal.xml.StAXReaderUtil;
027    
028    import java.io.IOException;
029    
030    import java.util.ArrayList;
031    import java.util.List;
032    
033    import javax.xml.stream.XMLInputFactory;
034    import javax.xml.stream.XMLStreamConstants;
035    import javax.xml.stream.XMLStreamReader;
036    
037    /**
038     * @author Alexander Chow
039     * @author Brian Wing Shun Chan
040     */
041    public class XmlRpcParser {
042    
043            public static String buildMethod(String methodName, Object[] arguments)
044                    throws XmlRpcException {
045    
046                    StringBundler sb = new StringBundler(arguments.length * 3 + 8);
047    
048                    sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
049    
050                    sb.append("<methodCall>");
051                    sb.append("<methodName>");
052                    sb.append(methodName);
053                    sb.append("</methodName>");
054                    sb.append("<params>");
055    
056                    for (Object argument : arguments) {
057                            sb.append("<param>");
058                            sb.append(wrapValue(argument));
059                            sb.append("</param>");
060                    }
061    
062                    sb.append("</params>");
063                    sb.append("</methodCall>");
064    
065                    return sb.toString();
066            }
067    
068            public static Tuple parseMethod(String xml) throws IOException {
069                    XMLStreamReader xmlStreamReader = null;
070    
071                    try {
072                            XMLInputFactory xmlInputFactory =
073                                    StAXReaderUtil.getXMLInputFactory();
074    
075                            xmlStreamReader = xmlInputFactory.createXMLStreamReader(
076                                    new UnsyncStringReader(xml));
077    
078                            xmlStreamReader.nextTag();
079                            xmlStreamReader.nextTag();
080                            xmlStreamReader.next();
081    
082                            String methodName = xmlStreamReader.getText();
083                            List<Object> arguments = new ArrayList<Object>();
084    
085                            xmlStreamReader.nextTag();
086    
087                            String name = xmlStreamReader.getLocalName();
088    
089                            while (!name.equals("methodCall")) {
090                                    xmlStreamReader.nextTag();
091    
092                                    name = xmlStreamReader.getLocalName();
093    
094                                    if (name.equals("param")) {
095                                            xmlStreamReader.nextTag();
096    
097                                            name = xmlStreamReader.getLocalName();
098    
099                                            int event = xmlStreamReader.next();
100    
101                                            if (event == XMLStreamConstants.START_ELEMENT) {
102                                                    name = xmlStreamReader.getLocalName();
103    
104                                                    xmlStreamReader.next();
105    
106                                                    String text = xmlStreamReader.getText();
107    
108                                                    if (name.equals("string")) {
109                                                            arguments.add(text);
110                                                    }
111                                                    else if (name.equals("int") || name.equals("i4")) {
112                                                            arguments.add(GetterUtil.getInteger(text));
113                                                    }
114                                                    else if (name.equals("double")) {
115                                                            arguments.add(GetterUtil.getDouble(text));
116                                                    }
117                                                    else if (name.equals("boolean")) {
118                                                            arguments.add(GetterUtil.getBoolean(text));
119                                                    }
120                                                    else {
121                                                            throw new IOException(
122                                                                    "XML-RPC not implemented for " + name);
123                                                    }
124    
125                                                    xmlStreamReader.nextTag();
126                                                    xmlStreamReader.nextTag();
127                                                    xmlStreamReader.nextTag();
128                                            }
129                                            else {
130                                                    String text = xmlStreamReader.getText();
131    
132                                                    arguments.add(text);
133    
134                                                    xmlStreamReader.nextTag();
135                                                    xmlStreamReader.nextTag();
136                                            }
137    
138                                            name = xmlStreamReader.getLocalName();
139                                    }
140                            }
141    
142                            return new Tuple(methodName, arguments.toArray());
143                    }
144                    catch (Exception e) {
145                            throw new IOException(e.getMessage());
146                    }
147                    finally {
148                            if (xmlStreamReader != null) {
149                                    try {
150                                            xmlStreamReader.close();
151                                    }
152                                    catch (Exception e) {
153                                    }
154                            }
155                    }
156            }
157    
158            public static Response parseResponse(String xml) throws XmlRpcException {
159                    XMLStreamReader xmlStreamReader = null;
160    
161                    try {
162                            XMLInputFactory xmlInputFactory =
163                                    StAXReaderUtil.getXMLInputFactory();
164    
165                            xmlStreamReader = xmlInputFactory.createXMLStreamReader(
166                                    new UnsyncStringReader(xml));
167    
168                            xmlStreamReader.nextTag();
169                            xmlStreamReader.nextTag();
170    
171                            String name = xmlStreamReader.getLocalName();
172    
173                            if (name.equals("params")) {
174                                    String description = null;
175    
176                                    xmlStreamReader.nextTag();
177                                    xmlStreamReader.nextTag();
178    
179                                    int event = xmlStreamReader.next();
180    
181                                    if (event == XMLStreamConstants.START_ELEMENT) {
182                                            xmlStreamReader.next();
183    
184                                            description = xmlStreamReader.getText();
185                                    }
186                                    else {
187                                            description = xmlStreamReader.getText();
188                                    }
189    
190                                    return XmlRpcUtil.createSuccess(description);
191                            }
192                            else if (name.equals("fault")) {
193                                    int code = 0;
194                                    String description = null;
195    
196                                    xmlStreamReader.nextTag();
197                                    xmlStreamReader.nextTag();
198    
199                                    for (int i = 0; i < 2; i++) {
200                                            xmlStreamReader.nextTag();
201                                            xmlStreamReader.nextTag();
202    
203                                            xmlStreamReader.next();
204    
205                                            String valueName = xmlStreamReader.getText();
206    
207                                            if (valueName.equals("faultCode")) {
208                                                    xmlStreamReader.nextTag();
209                                                    xmlStreamReader.nextTag();
210                                                    xmlStreamReader.nextTag();
211    
212                                                    name = xmlStreamReader.getLocalName();
213    
214                                                    if (name.equals("int") || name.equals("i4")) {
215                                                            xmlStreamReader.next();
216    
217                                                            code = GetterUtil.getInteger(
218                                                                    xmlStreamReader.getText());
219                                                    }
220    
221                                                    xmlStreamReader.nextTag();
222                                                    xmlStreamReader.nextTag();
223                                                    xmlStreamReader.nextTag();
224                                            }
225                                            else if (valueName.equals("faultString")) {
226                                                    xmlStreamReader.nextTag();
227                                                    xmlStreamReader.nextTag();
228    
229                                                    int event = xmlStreamReader.next();
230    
231                                                    if (event == XMLStreamConstants.START_ELEMENT) {
232                                                            xmlStreamReader.next();
233    
234                                                            description = xmlStreamReader.getText();
235    
236                                                            xmlStreamReader.nextTag();
237                                                    }
238                                                    else {
239                                                            description = xmlStreamReader.getText();
240                                                    }
241    
242                                                    xmlStreamReader.nextTag();
243                                                    xmlStreamReader.nextTag();
244                                            }
245                                    }
246    
247                                    return XmlRpcUtil.createFault(code, description);
248                            }
249    
250                            return null;
251                    }
252                    catch (Exception e) {
253                            throw new XmlRpcException(xml, e);
254                    }
255                    finally {
256                            if (xmlStreamReader != null) {
257                                    try {
258                                            xmlStreamReader.close();
259                                    }
260                                    catch (Exception e) {
261                                    }
262                            }
263                    }
264            }
265    
266            public static String wrapValue(Object value) throws XmlRpcException {
267                    if (value == null) {
268                            return StringPool.BLANK;
269                    }
270    
271                    StringBundler sb = new StringBundler(5);
272    
273                    sb.append("<value>");
274    
275                    if (value instanceof String) {
276                            sb.append("<string>");
277                            sb.append(value.toString());
278                            sb.append("</string>");
279                    }
280                    else if ((value instanceof Integer) || (value instanceof Short)) {
281                            sb.append("<i4>");
282                            sb.append(value.toString());
283                            sb.append("</i4>");
284                    }
285                    else if ((value instanceof Double) || (value instanceof Float)) {
286                            sb.append("<double>");
287                            sb.append(value.toString());
288                            sb.append("</double>");
289                    }
290                    else if (value instanceof Boolean) {
291                            sb.append("<boolean>");
292    
293                            if ((Boolean)value) {
294                                    sb.append(CharPool.NUMBER_1);
295                            }
296                            else {
297                                    sb.append(CharPool.NUMBER_0);
298                            }
299    
300                            sb.append("</boolean>");
301                    }
302                    else {
303                            throw new XmlRpcException("Unsupported type " + value.getClass());
304                    }
305    
306                    sb.append("</value>");
307    
308                    return sb.toString();
309            }
310    
311    }