Source code: org/apache/xmlrpc/XmlRpcResponseProcessor.java
1 /*
2 * Copyright 1999,2005 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 package org.apache.xmlrpc;
19
20 import java.io.ByteArrayOutputStream;
21 import java.io.UnsupportedEncodingException;
22 import java.io.IOException;
23 import java.util.Hashtable;
24
25 /**
26 * Process an Object and produce byte array that represents the specified
27 * encoding of the output as an XML-RPC response. This is NOT thread safe.
28 *
29 * @author <a href="mailto:andrew@kungfoocoder.org">Andrew Evers</a>
30 * @author <a href="mailto:hannes@apache.org">Hannes Wallnoefer</a>
31 * @author Daniel L. Rall
32 * @since 1.2
33 */
34 public class XmlRpcResponseProcessor
35 {
36 private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
37
38 /**
39 * Creates a new instance.
40 */
41 public XmlRpcResponseProcessor()
42 {
43 }
44
45 /**
46 * Process a successful response, and return output in the
47 * specified encoding.
48 *
49 * @param responseParam The response to process.
50 * @param encoding The output encoding.
51 * @return byte[] The XML-RPC response.
52 */
53 public byte[] encodeResponse(Object responseParam, String encoding)
54 throws IOException, UnsupportedEncodingException, XmlRpcException
55 {
56 long now = 0;
57 if (XmlRpc.debug)
58 {
59 now = System.currentTimeMillis();
60 }
61
62 try
63 {
64 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
65 XmlWriter writer = new XmlWriter(buffer, encoding);
66 writeResponse(responseParam, writer);
67 writer.flush();
68 return buffer.toByteArray();
69 }
70 finally
71 {
72 if (XmlRpc.debug)
73 {
74 System.out.println("Spent " + (System.currentTimeMillis() - now)
75 + " millis encoding response");
76 }
77 }
78 }
79
80 /**
81 * Process an exception, and return output in the specified
82 * encoding.
83 *
84 * @param e The exception to process;
85 * @param encoding The output encoding.
86 * @param code The XML-RPC faultCode.
87 * @return byte[] The XML-RPC response.
88 */
89 public byte[] encodeException(Exception x, String encoding, int code)
90 {
91 if (XmlRpc.debug)
92 {
93 x.printStackTrace();
94 }
95 // Ensure that if there is anything in the buffer, it
96 // is cleared before continuing with the writing of exceptions.
97 // It is possible that something is in the buffer
98 // if there were an exception during the writeResponse()
99 // call above.
100 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
101
102 XmlWriter writer = null;
103 try
104 {
105 writer = new XmlWriter(buffer, encoding);
106 }
107 catch (UnsupportedEncodingException encx)
108 {
109 System.err.println("XmlRpcServer attempted to use "
110 + "unsupported encoding: " + encx);
111 // NOTE: If we weren't already using the default
112 // encoding, we could try it here.
113 }
114 catch (IOException iox)
115 {
116 System.err.println("XmlRpcServer experienced I/O error "
117 + "writing error response: " + iox);
118 }
119
120 String message = x.toString();
121 // Retrieve XmlRpcException error code(if possible).
122 try
123 {
124 writeError(code, message, writer);
125 writer.flush();
126 }
127 catch (Exception e)
128 {
129 // Unlikely to occur, as we just sent a struct
130 // with an int and a string.
131 System.err.println("Unable to send error response to "
132 + "client: " + e);
133 }
134
135 return (writer != null ? buffer.toByteArray() : EMPTY_BYTE_ARRAY);
136 }
137
138 /**
139 * Process an exception, and return output in the specified
140 * encoding.
141 *
142 * @param e The exception to process;
143 * @param encoding The output encoding.
144 * @return byte[] The XML-RPC response.
145 */
146 public byte[] encodeException(Exception x, String encoding)
147 {
148 return encodeException(x, encoding, (x instanceof XmlRpcException) ? ((XmlRpcException) x).code : 0);
149 }
150 /**
151 * Writes an XML-RPC response to the XML writer.
152 */
153 void writeResponse(Object param, XmlWriter writer)
154 throws XmlRpcException, IOException
155 {
156 writer.startElement("methodResponse");
157 // if (param == null) param = ""; // workaround for Frontier bug
158 writer.startElement("params");
159 writer.startElement("param");
160 writer.writeObject(param);
161 writer.endElement("param");
162 writer.endElement("params");
163 writer.endElement("methodResponse");
164 }
165
166 /**
167 * Writes an XML-RPC error response to the XML writer.
168 */
169 void writeError(int code, String message, XmlWriter writer)
170 throws XmlRpcException, IOException
171 {
172 // System.err.println("error: "+message);
173 Hashtable h = new Hashtable();
174 h.put("faultCode", new Integer(code));
175 h.put("faultString", message);
176 writer.startElement("methodResponse");
177 writer.startElement("fault");
178 writer.writeObject(h);
179 writer.endElement("fault");
180 writer.endElement("methodResponse");
181 }
182 }