1
/* Copyright 2002, 2003 Elliotte Rusty Harold
3
This library is free software; you can redistribute it and/or modify
4
it under the terms of version 2.1 of the GNU Lesser General Public
5
License as published by the Free Software Foundation.
7
This library is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU Lesser General Public License for more details.
12
You should have received a copy of the GNU Lesser General Public
13
License along with this library; if not, write to the
14
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
15
Boston, MA 02111-1307 USA
17
You can contact Elliotte Rusty Harold by sending e-mail to
18
elharo@metalab.unc.edu. Please include the word "XOM" in the
19
subject line. The XOM home page is located at http://www.xom.nu/
22
package nu.xom.samples;
24
import java.io.IOException;
25
import java.io.InputStream;
26
import java.io.OutputStream;
27
import java.math.BigInteger;
29
import javax.servlet.ServletException;
30
import javax.servlet.SingleThreadModel;
31
import javax.servlet.http.HttpServlet;
32
import javax.servlet.http.HttpServletRequest;
33
import javax.servlet.http.HttpServletResponse;
35
import nu.xom.Builder;
36
import nu.xom.Document;
37
import nu.xom.Element;
38
import nu.xom.Serializer;
39
import nu.xom.XMLException;
43
* Demonstrates a servlet that receives and
44
* responds to XML-RPC requests.
47
* @author Elliotte Rusty Harold
51
public class FibonacciXOMXMLRPCServlet extends HttpServlet
52
implements SingleThreadModel {
55
public final static int MALFORMED_REQUEST_DOCUMENT = 1;
56
public final static int INVALID_REQUEST_DOCUMENT = 2;
57
public final static int INDEX_MISSING = 3;
58
public final static int NON_POSITIVE_INDEX = 4;
59
public final static int BAD_INTEGER_FORMAT = 5;
60
public final static int UNEXPECTED_PROBLEM = 255;
62
private transient Builder parser;
64
// Load a parser, transformer, and implementation
65
public void init() throws ServletException {
68
this.parser = new Builder();
70
catch (Exception ex) {
71
throw new ServletException(
72
"Could not locate a JAXP parser", ex);
77
// Respond to an XML-RPC request
78
public void doPost(HttpServletRequest servletRequest,
79
HttpServletResponse servletResponse)
80
throws ServletException, IOException {
82
servletResponse.setContentType("application/xml; charset=UTF-8");
83
OutputStream out = servletResponse.getOutputStream();
84
InputStream in = servletRequest.getInputStream();
89
request = parser.build(in);
90
Element methodCall = request.getRootElement();
91
Element params = methodCall.getFirstChildElement("params");
92
String generations = params.getValue().trim();
93
int numberOfGenerations = Integer.parseInt(generations);
94
BigInteger result = calculateFibonacci(numberOfGenerations);
95
response = makeResponseDocument(result);
97
catch (XMLException ex) {
98
response = makeFaultDocument(MALFORMED_REQUEST_DOCUMENT, ex.getMessage());
100
catch (NullPointerException ex) {
101
response = makeFaultDocument(INDEX_MISSING, ex.getMessage());
103
catch (NumberFormatException ex) {
104
response = makeFaultDocument(BAD_INTEGER_FORMAT, ex.getMessage());
106
catch (Exception ex) {
107
response = makeFaultDocument(UNEXPECTED_PROBLEM, ex.getMessage());
110
// Transform onto the OutputStream
112
Serializer output = new Serializer(out, "US-ASCII");
113
output.write(response);
114
servletResponse.flushBuffer();
117
catch (Exception ex) {
118
// If we get an exception at this point, it's too late to
119
// switch over to an XML-RPC fault.
120
throw new ServletException(ex);
125
// If performance is an issue, this could be pre-built in the
126
// init() method and then cached. You'd just change one text
127
// node each time. This would only work in a SingleThreadModel
129
public Document makeResponseDocument(BigInteger result) {
131
Element methodResponse = new Element("methodResponse");
132
Element params = new Element("params");
133
Element param = new Element("param");
134
Element value = new Element("value");
135
Element doubleElement = new Element("double");
137
methodResponse.appendChild(params);
138
params.appendChild(param);
139
param.appendChild(value);
140
value.appendChild(doubleElement);
141
doubleElement.appendChild(result.toString());
143
return new Document(methodResponse);
147
public Document makeFaultDocument(int faultCode, String faultString) {
149
Element methodResponse = new Element("methodResponse");
151
Element fault = new Element("fault");
152
Element value = new Element("value");
153
Element struct = new Element("struct");
154
Element memberCode = new Element("member");
155
Element nameCode = new Element("name");
156
Element valueCode = new Element("value");
157
Element intCode = new Element("int");
158
Element memberString = new Element("member");
159
Element valueString = new Element("value");
160
Element stringString = new Element("string");
162
methodResponse.appendChild(fault);
163
fault.appendChild(value);
164
value.appendChild(struct);
165
struct.appendChild(memberCode);
166
struct.appendChild(memberString);
167
memberCode.appendChild(nameCode);
168
memberCode.appendChild(valueCode);
169
memberString.appendChild("name");
170
memberString.appendChild(valueString);
171
nameCode.appendChild("faultCode");
172
valueCode.appendChild(intCode);
173
valueString.appendChild(stringString);
174
intCode.appendChild(String.valueOf(faultCode));
175
stringString.appendChild(faultString);
177
Document faultDoc = new Document(methodResponse);
183
public static BigInteger calculateFibonacci(int generations)
184
throws IndexOutOfBoundsException {
186
if (generations < 1) {
187
throw new IndexOutOfBoundsException(
188
"Fibonacci numbers are not defined for " + generations
189
+ "or any other number less than one.");
191
BigInteger low = BigInteger.ONE;
192
BigInteger high = BigInteger.ONE;
193
for (int i = 2; i <= generations; i++) {
194
BigInteger temp = high;
195
high = high.add(low);