1 package org.apache.turbine.services.xmlrpc;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Turbine" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache Turbine", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import helma.xmlrpc.WebServer;
58 import helma.xmlrpc.XmlRpc;
59 import helma.xmlrpc.XmlRpcClient;
60 import helma.xmlrpc.XmlRpcException;
61 import helma.xmlrpc.XmlRpcServer;
62 import helma.xmlrpc.secure.SecureWebServer;
63 import java.io.IOException;
64 import java.io.InputStream;
65 import java.net.InetAddress;
66 import java.net.Socket;
67 import java.net.URL;
68 import java.util.Iterator;
69 import java.util.Vector;
70 import javax.servlet.ServletConfig;
71 import org.apache.commons.configuration.Configuration;
72 import org.apache.turbine.services.InitializationException;
73 import org.apache.turbine.services.TurbineBaseService;
74 import org.apache.turbine.services.xmlrpc.util.FileTransfer;
75 import org.apache.turbine.util.Log;
76 import org.apache.turbine.util.TurbineException;
77
78
79 /***
80 * This is a service which will make an xml-rpc call to a remote
81 * server.
82 *
83 * Here's an example of how it would be done:
84 * <blockquote><code><pre>
85 * XmlRpcService xs =
86 * (XmlRpcService)TurbineServices.getInstance()
87 * .getService(XmlRpcService.XMLRPC_SERVICE_NAME);
88 * Vector vec = new Vector();
89 * vec.addElement(new Integer(5));
90 * URL url = new URL("http://betty.userland.com/RPC2");
91 * String name = (String)xs.executeRpc(url, "examples.getStateName", vec);
92 * </pre></code></blockquote>
93 *
94 * @author <a href="mailto:josh@stonecottage.com">Josh Lucas</a>
95 * @author <a href="mailto:magnus@handtolvur.is">Magnús Þór Torfason</a>
96 * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
97 * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
98 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
99 * @version $Id: TurbineXmlRpcService.java,v 1.5 2002/07/11 16:53:22 mpoeschl Exp $
100 */
101 public class TurbineXmlRpcService
102 extends TurbineBaseService
103 implements XmlRpcService
104 {
105 /*** The standalone xmlrpc server. */
106 private WebServer webserver = null;
107
108 /*** The encapsulated xmlrpc server. */
109 private XmlRpcServer server = null;
110
111 /*** The xmlrpc client. */
112 private XmlRpcClient client = null;
113
114 /*** The port to listen on. */
115 private int port = 0;
116
117 /***
118 * This function initializes the XmlRpcService.
119 */
120 public void init(ServletConfig config) throws InitializationException
121 {
122 try
123 {
124 server = new XmlRpcServer();
125
126 // Set the port for the service
127 port = getConfiguration().getInt("port", 0);
128
129 if(port != 0)
130 {
131 if (getConfiguration().getBoolean("secure.server", false))
132 {
133 // Get the values for the JSSE system properties
134 // that we must set for use in the SecureWebServer
135 // and the URL https connection handler that is
136 // used in XmlRpcClient.
137
138 Configuration secureServerOptions =
139 getConfiguration().subset("secure.server.option");
140
141 Iterator i = secureServerOptions.getKeys();
142
143 while (i.hasNext())
144 {
145 String option = (String) i.next();
146 String value = secureServerOptions.getString(option);
147
148 Log.debug("JSSE option: " + option + " => " + value);
149
150 System.setProperty(option, value);
151 }
152
153 webserver = new SecureWebServer(port);
154 }
155 else
156 {
157 webserver = new WebServer(port);
158 }
159 }
160
161 // Set the XML driver to the correct SAX parser class
162 String saxParserClass = getConfiguration().getString("parser",
163 "org.apache.xerces.parsers.SAXParser");
164
165 XmlRpc.setDriver ( saxParserClass );
166
167 // Check if there are any handlers to register at startup
168 Iterator keys = getConfiguration().getKeys("handler");
169 while ( keys.hasNext() )
170 {
171 String handler = (String)keys.next();
172 String handlerName = handler.substring(handler.indexOf(".")+1);
173 String handlerClass = getConfiguration().getString(handler);
174 registerHandler(handlerName, handlerClass);
175 }
176
177 /*
178 * Turn on paranoia for the webserver if requested.
179 */
180 boolean stateOfParanoia = getConfiguration().getBoolean("paranoid", false);
181
182 if (stateOfParanoia)
183 {
184 webserver.setParanoid(stateOfParanoia);
185 Log.info(XmlRpcService.SERVICE_NAME +
186 ": Operating in a state of paranoia");
187
188 /*
189 * Only set the accept/deny client lists if we
190 * are in a state of paranoia as they will just
191 * be ignored so there's no point in setting them.
192 */
193
194 /*
195 * Set the list of clients that can connect
196 * to the xmlrpc server. The accepted client list
197 * will only be consulted if we are paranoid.
198 */
199 Vector acceptedClients = getConfiguration().getVector("acceptClient");
200
201 for (int i = 0; i < acceptedClients.size(); i++)
202 {
203 String acceptClient = (String) acceptedClients.get(i);
204
205 if (acceptClient != null && ! acceptClient.equals(""))
206 {
207 webserver.acceptClient(acceptClient);
208 Log.info(XmlRpcService.SERVICE_NAME +
209 ": Accepting client -> " + acceptClient);
210 }
211 }
212
213 /*
214 * Set the list of clients that can connect
215 * to the xmlrpc server. The denied client list
216 * will only be consulted if we are paranoid.
217 */
218 Vector deniedClients = getConfiguration().getVector("denyClient");
219
220 for (int i = 0; i < deniedClients.size(); i++)
221 {
222 String denyClient = (String) deniedClients.get(i);
223
224 if (denyClient != null && ! denyClient.equals(""))
225 {
226 webserver.denyClient(denyClient);
227 Log.info(XmlRpcService.SERVICE_NAME +
228 ": Denying client -> " + denyClient);
229 }
230 }
231 }
232 }
233 catch (Exception e)
234 {
235 throw new InitializationException
236 ("XMLRPCService failed to initialize", e);
237 }
238
239 setInit(true);
240 }
241
242 /***
243 * Register an Object as a default handler for the service.
244 *
245 * @param handler The handler to use.
246 * @exception XmlRpcException.
247 * @exception IOException.
248 */
249 public void registerHandler(Object handler)
250 throws XmlRpcException,
251 IOException
252 {
253 registerHandler("$default", handler);
254 }
255
256 /***
257 * Register an Object as a handler for the service.
258 *
259 * @param handlerName The name the handler is registered under.
260 * @param handler The handler to use.
261 * @exception XmlRpcException.
262 * @exception IOException.
263 */
264 public void registerHandler(String handlerName,
265 Object handler)
266 throws XmlRpcException,
267 IOException
268 {
269 if(webserver != null)
270 {
271 webserver.addHandler(handlerName, handler);
272 }
273
274 server.addHandler(handlerName, handler);
275 }
276
277 /***
278 * A helper method that tries to initialize a handler and register it.
279 * The purpose is to check for all the exceptions that may occur in
280 * dynamic class loading and throw an InitializationException on
281 * error.
282 *
283 * @param handlerName The name the handler is registered under.
284 * @param handlerClass The name of the class to use as a handler.
285 * @exception TurbineException Couldn't instantiate handler.
286 */
287 public void registerHandler(String handlerName, String handlerClass)
288 throws TurbineException
289 {
290 try
291 {
292 Object handler = Class.forName(handlerClass).newInstance();
293
294 if(webserver != null)
295 {
296 webserver.addHandler(handlerName,handler);
297 }
298
299 server.addHandler(handlerName,handler);
300 }
301 // those two errors must be passed to the VM
302 catch( ThreadDeath t )
303 {
304 throw t;
305 }
306 catch( OutOfMemoryError t )
307 {
308 throw t;
309 }
310
311 catch( Throwable t )
312 {
313 throw new TurbineException
314 ("Failed to instantiate " + handlerClass, t);
315 }
316 }
317
318 /***
319 * Unregister a handler.
320 *
321 * @param handlerName The name of the handler to unregister.
322 */
323 public void unregisterHandler(String handlerName)
324 {
325 if(webserver != null)
326 {
327 webserver.removeHandler(handlerName);
328 }
329
330 server.removeHandler(handlerName);
331 }
332
333 /***
334 * Handle an XML-RPC request using the encapsulated server.
335 *
336 * You can use this method to handle a request from within
337 * a Turbine screen.
338 *
339 * @param is the stream to read request data from.
340 * @return the response body that needs to be sent to the client.
341 */
342 public byte[] handleRequest(InputStream is)
343 {
344 return server.execute(is);
345 }
346
347 /***
348 * Handle an XML-RPC request using the encapsulated server with user
349 * authentication.
350 *
351 * You can use this method to handle a request from within
352 * a Turbine screen.
353 *
354 * <p> Note that the handlers need to implement AuthenticatedXmlRpcHandler
355 * interface to access the authentication infomration.
356 *
357 * @param is the stream to read request data from.
358 * @param user the user that is making the request.
359 * @param password the password given by user.
360 * @return the response body that needs to be sent to the client.
361 */
362 public byte[] handleRequest(InputStream is, String user, String password)
363 {
364 return server.execute(is, user, password);
365 }
366
367 /***
368 * Client's interface to XML-RPC.
369 *
370 * The return type is Object which you'll need to cast to
371 * whatever you are expecting.
372 *
373 * @param url A URL.
374 * @param methodName A String with the method name.
375 * @param params A Vector with the parameters.
376 * @return An Object.
377 * @exception XmlRpcException.
378 * @exception IOException.
379 */
380 public Object executeRpc(URL url,
381 String methodName,
382 Vector params)
383 throws TurbineException
384 {
385 try
386 {
387 XmlRpcClient client = new XmlRpcClient ( url );
388 return client.execute(methodName, params);
389 }
390 catch (Exception e)
391 {
392 throw new TurbineException("XML-RPC call failed", e);
393 }
394 }
395
396 /***
397 * Client's Authenticated interface to XML-RPC.
398 *
399 * The return type is Object which you'll need to cast to
400 * whatever you are expecting.
401 *
402 * @param url A URL.
403 * @param username The username to try and authenticate with
404 * @param password The password to try and authenticate with
405 * @param methodName A String with the method name.
406 * @param params A Vector with the parameters.
407 * @return An Object.
408 * @exception XmlRpcException.
409 * @exception IOException.
410 */
411 public Object executeAuthenticatedRpc(URL url,
412 String username,
413 String password,
414 String methodName,
415 Vector params)
416 throws TurbineException
417 {
418 try
419 {
420 XmlRpcClient client = new XmlRpcClient ( url );
421 client.setBasicAuthentication(username, password);
422 return client.execute(methodName, params);
423 }
424 catch (Exception e)
425 {
426 throw new TurbineException("XML-RPC call failed", e);
427 }
428 }
429
430 /***
431 * Method to allow a client to send a file to a server.
432 *
433 * @param serverURL
434 * @param sourceLocationProperty
435 * @param sourceFileName
436 * @param destinationLocationProperty
437 * @param destinationFileName
438 */
439 public void send(String serverURL,
440 String sourceLocationProperty,
441 String sourceFileName,
442 String destinationLocationProperty,
443 String destinationFileName)
444 throws Exception
445 {
446 FileTransfer.send(serverURL,
447 sourceLocationProperty,
448 sourceFileName,
449 destinationLocationProperty,
450 destinationFileName);
451 }
452
453 /***
454 * Method to allow a client to send a file to a server that
455 * requires authentication
456 *
457 * @param serverURL
458 * @param username
459 * @param password
460 * @param sourceLocationProperty
461 * @param sourceFileName
462 * @param destinationLocationProperty
463 * @param destinationFileName
464 */
465 public void send(String serverURL,
466 String username,
467 String password,
468 String sourceLocationProperty,
469 String sourceFileName,
470 String destinationLocationProperty,
471 String destinationFileName)
472 throws Exception
473 {
474 FileTransfer.send(serverURL,
475 username,
476 password,
477 sourceLocationProperty,
478 sourceFileName,
479 destinationLocationProperty,
480 destinationFileName);
481 }
482
483 /***
484 * Method to allow a client to get a file to a server.
485 *
486 * @param serverURL
487 * @param sourceLocationProperty
488 * @param sourceFileName
489 * @param destinationLocationProperty
490 * @param destinationFileName
491 */
492 public void get(String serverURL,
493 String sourceLocationProperty,
494 String sourceFileName,
495 String destinationLocationProperty,
496 String destinationFileName)
497 throws Exception
498 {
499 FileTransfer.get(serverURL,
500 sourceLocationProperty,
501 sourceFileName,
502 destinationLocationProperty,
503 destinationFileName);
504 }
505
506 /***
507 * Method to allow a client to get a file from a server that
508 * requires authentication.
509 *
510 * @param serverURL
511 * @param username
512 * @param password
513 * @param sourceLocationProperty
514 * @param sourceFileName
515 * @param destinationLocationProperty
516 * @param destinationFileName
517 */
518 public void get(String serverURL,
519 String username,
520 String password,
521 String sourceLocationProperty,
522 String sourceFileName,
523 String destinationLocationProperty,
524 String destinationFileName)
525 throws Exception
526 {
527 FileTransfer.get(serverURL,
528 username,
529 password,
530 sourceLocationProperty,
531 sourceFileName,
532 destinationLocationProperty,
533 destinationFileName);
534 }
535
536 /***
537 * Method to allow a client to remove a file from
538 * the server
539 *
540 * @param serverURL
541 * @param sourceLocationProperty
542 * @param sourceFileName
543 */
544 public void remove(String serverURL,
545 String sourceLocationProperty,
546 String sourceFileName)
547 throws Exception
548 {
549 FileTransfer.remove(serverURL,
550 sourceLocationProperty,
551 sourceFileName);
552 }
553
554 /***
555 * Method to allow a client to remove a file from
556 * a server that requires authentication.
557 *
558 * @param serverURL
559 * @param username
560 * @param password
561 * @param sourceLocationProperty
562 * @param sourceFileName
563 */
564 public void remove(String serverURL,
565 String username,
566 String password,
567 String sourceLocationProperty,
568 String sourceFileName)
569 throws Exception
570 {
571 FileTransfer.remove(serverURL,
572 username,
573 password,
574 sourceLocationProperty,
575 sourceFileName);
576 }
577
578 /***
579 * Switch client filtering on/off.
580 *
581 * @param state Whether to filter clients.
582 *
583 * @see #acceptClient(java.lang.String)
584 * @see #denyClient(java.lang.String)
585 */
586 public void setParanoid(boolean state)
587 {
588 webserver.setParanoid(state);
589 }
590
591 /***
592 * Add an IP address to the list of accepted clients. The parameter can
593 * contain '*' as wildcard character, e.g. "192.168.*.*". You must
594 * call setParanoid(true) in order for this to have
595 * any effect.
596 *
597 * @param address The address to add to the list.
598 *
599 * @see #denyClient(java.lang.String)
600 * @see #setParanoid(boolean)
601 */
602 public void acceptClient(String address)
603 {
604 webserver.acceptClient(address);
605 }
606
607 /***
608 * Add an IP address to the list of denied clients. The parameter can
609 * contain '*' as wildcard character, e.g. "192.168.*.*". You must call
610 * setParanoid(true) in order for this to have any effect.
611 *
612 * @param address The address to add to the list.
613 *
614 * @see #acceptClient(java.lang.String)
615 * @see #setParanoid(boolean)
616 */
617 public void denyClient(String address)
618 {
619 webserver.denyClient(address);
620 }
621
622 /***
623 * Shuts down this service, stopping running threads.
624 */
625 public void shutdown()
626 {
627 // Stop the XML RPC server. helma.xmlrpc.WebServer blocks in a call to
628 // ServerSocket.accept() until a socket connection is made.
629 webserver.shutdown();
630 try
631 {
632 Socket interrupt = new Socket(InetAddress.getLocalHost(), port);
633 interrupt.close();
634 }
635 catch (Exception ignored)
636 {
637 // Remotely possible we're leaving an open listener socket around.
638 }
639
640 setInit(false);
641 }
642 }
This page was automatically generated by Maven