1    //
2    // SwitchRMI  Framework
3    // Copyright (c) 2000-2002 by Michael J. Henderson & Associates.
4    //
5    // Michael Henderson
6    // http://switchrmi.sf.net
7    // mailto:mikehenderson@dunelm.org.uk
8    //
9    // This library is free software.
10   //
11   // You may redistribute it and/or modify it under the terms of the GNU
12   // Lesser General Public License as published by the Free Software Foundation.
13   //
14   // Version 2.1 of the license should be included with this distribution in
15   // the file LICENSE, as well as License.html. If the license is not
16   // included with this distribution, you may find a copy at the FSF web
17   // site at 'www.gnu.org' or 'www.fsf.org', or you may write to the
18   // Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139 USA.
19   //
20   // This library is distributed in the hope that it will be useful,
21   // but WITHOUT ANY WARRANTY; without even the implied waranty of
22   // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23   // Lesser General Public License for more details.
24   //
25   // $Id: XmlRpcProtocol.java,v 1.1 2002/11/11 22:19:48 mikehenderson Exp $
26   package com.mjh.switchrmi.protocol.xmlrpc;
27   
28   import com.mjh.dom.*;
29   import com.mjh.switchrmi.*;
30   
31   import java.io.*;
32   
33   import java.lang.reflect.Method;
34   
35   import java.text.*;
36   
37   import java.util.*;
38   
39   import javax.xml.parsers.DocumentBuilder;
40   import javax.xml.parsers.DocumentBuilderFactory;
41   import javax.xml.transform.Transformer;
42   import javax.xml.transform.TransformerFactory;
43   import javax.xml.transform.dom.DOMSource;
44   import javax.xml.transform.stream.StreamResult;
45   
46   import org.apache.log4j.Logger;
47   import org.w3c.dom.Document;
48   import org.w3c.dom.Element;
49   import org.w3c.dom.Node;
50   import org.w3c.dom.NodeList;
51   import org.w3c.dom.Text;
52   
53   /*
54       Support Xml rpc spec only.
55       
56       struct params are a Map (not hashtable)
57       array params are a List; (not Vector)
58       
59   
60   */
61   public class XmlRpcProtocol implements RmiProtocol
62   {
63       private static final Logger log = 
64               Logger.getLogger(XmlRpcProtocol.class.getName());
65       private static final String XMLRPC_REQUEST_TEMPLATE_FILE = 
66               "XmlRpcRequestTemplate.xml";
67       private static final String XMLRPC_RESPONSE_TEMPLATE_FILE = 
68               "XmlRpcResponseTemplate.xml";
69       private static final String XMLRPC_FAULTRESPONSE_TEMPLATE_FILE = 
70               "XmlRpcFaultResponseTemplate.xml";
71       private static Document requestTemplate;
72       private static Document responseTemplate;
73       private static Document faultResponseTemplate;
74   
75       static
76       {
77           try
78           {
79               DocumentBuilderFactory factory = 
80                       DocumentBuilderFactory.newInstance();
81               DocumentBuilder builder = factory.newDocumentBuilder();
82   
83               requestTemplate = parse(XMLRPC_REQUEST_TEMPLATE_FILE, builder);
84               responseTemplate = parse(XMLRPC_RESPONSE_TEMPLATE_FILE, builder);
85               faultResponseTemplate = parse(XMLRPC_FAULTRESPONSE_TEMPLATE_FILE, 
86                                             builder);
87           }
88           catch (Exception ex)
89           {
90               ex.printStackTrace();
91           }
92       }
93   
94       private RmiRequest request;
95       private RmiTransport transport;
96       private SimpleDateFormat dateFormatter = 
97               new SimpleDateFormat("yyyyMMdd kk:mm:ss");
98   
99       public XmlRpcProtocol()
100      {
101      }
102  
103      private static Document parse(String resourceName, DocumentBuilder builder)
104                             throws Exception
105      {
106          InputStream in = XmlRpcProtocol.class.getResourceAsStream(resourceName);
107          Document doc = (Document) builder.parse(in);
108  
109          in.close();
110  
111          return doc;
112      }
113  
114      public String getName()
115      {
116          return RmiProtocol.XMLRPC;
117      }
118  
119      public String getMimeType()
120      {
121          return RmiProtocol.XMLRPC_CONTENT_TYPE;
122      }
123  
124      public RmiRequest createRequest(Method method, Object[] args, 
125                                      RmiContext context)
126      {
127          return new RmiRequestImpl(method, args);
128      }
129  
130      public RmiResponse createResponse(RmiRequest request, Object result, 
131                                        RmiContext context)
132      {
133          return new RmiResponseImpl(request, result);
134      }
135  
136      public void writeRequest(RmiRequest req, RmiContext context)
137                        throws Exception
138      {
139          boolean debug = log.isDebugEnabled();
140  
141          log.debug("writeRequest");
142  
143          try
144          {
145              request = req;
146  
147              Document doc = (Document) requestTemplate.cloneNode(true);
148              NodeList nodes = doc.getElementsByTagName("methodName");
149              Node node = nodes.item(0);
150              Text text = (Text) node.getFirstChild();
151              String signature = req.getEncodedMethodSignature();
152              String methodName = 
153                      XmlRpcMethodSignatures.getExternalNameForEncodedSignature(
154                              signature);
155  
156              if (debug)
157              {
158                  log.debug("methodName = " + methodName);
159              }
160  
161              if (methodName == null)
162              {
163                  methodName = signature;
164              }
165  
166              text.setData(methodName);
167  
168              Object[] arguments = request.getArguments();
169              String[] argumentTypes = request.getStringArgumentTypes();
170  
171              nodes = doc.getElementsByTagName("param");
172              node = nodes.item(0);
173  
174              Node params = node.getParentNode();
175  
176              params.removeChild(node);
177  
178              if (argumentTypes != null)
179              {
180                  for (int i = 0; i < argumentTypes.length; i++)
181                  {
182                      String xmlRmiType = 
183                              convertObjectTypeToXmlRpcType(argumentTypes[i]);
184                      Node xmlRmiValue = 
185                              convertObjectToXmlRpcValue(arguments[i], xmlRmiType, 
186                                                         doc);
187                      Node param = doc.createElement("param");
188  
189                      param.appendChild(xmlRmiValue);
190  
191                      params.appendChild(param);
192                  }
193              }
194  
195              TransformerFactory transFactory = TransformerFactory.newInstance();
196              Transformer transformer = transFactory.newTransformer();
197              DOMSource source = new DOMSource(doc);
198              OutputStream out = context.getTransport().getOutputStream(context);
199  
200              if (debug)
201              {
202                  log.debug("doc = " + doc);
203                  log.debug("source = " + source);
204                  log.debug("context.getTransport() = " + context.getTransport());
205                  log.debug("out = " + out);
206              }
207  
208              StreamResult result = new StreamResult(out);
209  
210              transformer.transform(source, result);
211              out.flush();
212  
213              if (debug)
214              {
215                  log.debug("doc = " + doc.getDocumentElement());
216  
217                  ByteArrayOutputStream bo = new ByteArrayOutputStream();
218  
219                  result = new StreamResult(bo);
220                  transformer.transform(source, result);
221                  log.debug("request = " + bo.toString());
222              }
223          }
224          catch (Exception ex)
225          {
226              if (debug)
227              {
228                  log.debug("Exception: " + ex);
229                  ex.printStackTrace();
230              }
231          }
232      }
233  
234      public RmiRequest readRequest(RmiContext context)
235                             throws Exception
236      {
237          boolean debug = log.isDebugEnabled();
238  
239          if (debug)
240          {
241              log.debug("readRequest()");
242          }
243  
244          try
245          {
246              DocumentBuilderFactory factory = 
247                      DocumentBuilderFactory.newInstance();
248              DocumentBuilder builder = factory.newDocumentBuilder();
249              InputStream in = context.getTransport().getInputStream(context);
250              Document doc = (Document) builder.parse(in);
251  
252              if (debug)
253              {
254                  log.debug("doc = " + doc.getDocumentElement());
255              }
256  
257              request = new RmiRequestImpl();
258  
259              Text text = (Text) doc.getElementsByTagName("methodName").item(0)
260                                    .getFirstChild();
261              String externalName = text.getData();
262              String methodName = 
263                      XmlRpcMethodSignatures.getEncodedSignatureForExternalName(
264                              context.getTarget().getClass(), externalName);
265  
266              if (debug)
267              {
268                  log.debug("text = " + text);
269                  log.debug("externalName = " + externalName);
270                  log.debug("context = " + context);
271                  log.debug("context.getTarget = " + context.getTarget());
272                  log.debug("methodName = " + methodName);
273              }
274  
275              if (methodName == null)
276              {
277                  methodName = text.getData();
278              }
279  
280              request.setEncodedMethodSignature(methodName);
281  
282              NodeList nodes = doc.getElementsByTagName("param");
283  
284              if (debug)
285              {
286                  log.debug("nodes = " + nodes);
287                  log.debug("nodes.getLength() = " + nodes.getLength());
288              }
289  
290              if (nodes.getLength() > 0)
291              {
292                  List values = extractValueNodesFromParams(nodes);
293                  Object[] argValues = extractArgumentValuesFromParams(values);
294  
295                  if (debug)
296                  {
297                      log.debug("argValues.length = " + argValues.length);
298                  }
299  
300                  request.setArguments(argValues);
301              }
302          }
303          catch (Exception ex)
304          {
305              if (debug)
306              {
307                  log.debug("Exception: " + ex);
308                  ex.printStackTrace();
309              }
310          }
311  
312          return request;
313      }
314  
315      public void writeResponse(RmiResponse response, RmiContext context)
316                         throws Exception
317      {
318          Object object = response.getObject();
319          Document document = null;
320  
321          if (object instanceof Exception)
322          {
323              document = writeFaultResponse((Exception) object);
324          }
325          else
326          {
327  		log.debug("object = " + object);
328              document = writeResultResponse(object);
329          }
330  
331          TransformerFactory transFactory = TransformerFactory.newInstance();
332          Transformer transformer = transFactory.newTransformer();
333          OutputStream out = context.getTransport().getOutputStream(context);
334  
335          transformer.transform(new DOMSource(document), new StreamResult(out));
336          out.flush();
337  
338          if (log.isDebugEnabled())
339          {
340              log.debug("document = " + document.getDocumentElement());
341          }
342      }
343  
344      private Document writeResultResponse(Object object)
345          throws Exception
346      {
347          Document doc = null;
348  
349          try
350          {
351              doc = (Document) responseTemplate.cloneNode(true);
352  
353              String xmlRmiType = 
354                      convertObjectTypeToXmlRpcType(object.getClass().getName());
355              Node xmlRmiValue = 
356                      convertObjectToXmlRpcValue(object, xmlRmiType, doc);
357              NodeList list = doc.getElementsByTagName("param");
358              Node param = list.item(0);
359  
360              param.appendChild(xmlRmiValue);
361          }
362          catch (Exception ex)
363          {
364              if (log.isDebugEnabled())
365              {
366                  ex.printStackTrace();
367              }
368  
369              throw new XmlRpcUnsupportedTypeException(
370                      "Unsupported Type in response: "
371                      + object.getClass().getName());
372          }
373  
374          return doc;
375      }
376  
377      private Document writeFaultResponse(Exception exception)
378          throws Exception
379      {
380          Document doc = null;
381  
382          try
383          {
384              String faultString = exception.getMessage();
385  
386              if (faultString == null)
387              {
388                  faultString = exception.toString();
389              }
390  
391              HashMap map = new HashMap();
392  
393              map.put("faultCode", new Integer(100));
394              map.put("faultString", faultString);
395              doc = (Document) faultResponseTemplate.cloneNode(true);
396  
397              NodeList list = doc.getElementsByTagName("fault");
398              Node fault = list.item(0);
399              Node xmlRmiValue = convertObjectToXmlRpcValue(map, "struct", doc);
400  
401              fault.appendChild(xmlRmiValue);
402          }
403          catch (Exception ex)
404          {
405              if (log.isDebugEnabled())
406              {
407                  ex.printStackTrace();
408              }
409          }
410  
411          return doc;
412      }
413  
414      public RmiResponse readResponse(RmiContext context)
415                               throws Exception
416      {
417          return (context.getTransport().getType().equals(RmiTransport.SYNCHRONOUS))
418                 ? (RmiResponse) readSynchronousResponse(context)
419                 : new RmiResponseImpl(null);
420      }
421  
422      public RmiResponse readSynchronousResponse(RmiContext context)
423          throws Exception
424      {
425          boolean debug = log.isDebugEnabled();
426  
427          if (debug)
428          {
429              log.debug("readResponse()");
430          }
431  
432          Object result = null;
433  
434          try
435          {
436              if (debug)
437              {
438                  log.debug("transport = " + transport);
439              }
440  
441              InputStream in = context.getTransport().getInputStream(context);
442  
443              if (debug)
444              {
445                  log.debug("in = " + in);
446              }
447  
448              DocumentBuilderFactory factory = 
449                      DocumentBuilderFactory.newInstance();
450              DocumentBuilder builder = factory.newDocumentBuilder();
451              Document doc = (Document) builder.parse(in);
452  
453              if (debug)
454              {
455                  TransformerFactory transFactory = 
456                          TransformerFactory.newInstance();
457                  Transformer transformer = transFactory.newTransformer();
458                  OutputStream out = new java.io.ByteArrayOutputStream();
459  
460                  transformer.transform(new DOMSource(doc), new StreamResult(out));
461                  log.debug("response = " + out.toString());
462                  out.flush();
463                  out.close();
464                  log.debug("doc = " + doc.getDocumentElement());
465              }
466  
467              NodeList list = doc.getElementsByTagName("fault");
468  
469              if (list.getLength() > 0)
470              {
471                  result = readFault(doc);
472              }
473              else
474              {
475                  Node param = doc.getElementsByTagName("param").item(0);
476                  Node value = DomUtil.getChildElements(param).item(0);
477  
478                  result = convertXmlRpcValueToObject(value);
479  
480                  if (log.isDebugEnabled())
481                  {
482                      log.debug("result = " + result);
483                  }
484              }
485          }
486          catch (Exception ex)
487          {
488              result = ex;
489          }
490  
491          RmiResponse response = new RmiResponseImpl(result);
492  
493          return response;
494      }
495  
496      private Object readFault(Document doc)
497                        throws Exception
498      {
499          boolean debug = log.isDebugEnabled();
500          NodeList list = doc.getElementsByTagName("fault");
501          Node node = list.item(0);
502  
503          if (debug)
504          {
505              log.debug("node = [" + node.toString() + "]");
506          }
507  
508          node = DomUtil.getFirstChildElement(node);
509  
510          if (debug)
511          {
512              log.debug("node = [" + node.toString() + "]");
513          }
514  
515          Map map = (Map) convertXmlRpcValueToObject(node);
516          String faultString = (String) map.get("faultString");
517  
518          return new RmiRemoteException(faultString);
519      }
520  
521      private String convertObjectTypeToXmlRpcType(String javaType)
522          throws XmlRpcUnsupportedTypeException
523      {
524          String result = XmlRpcTypes.getXmlRpcTypeForJavaType(javaType);
525  
526          if (result == null)
527          {
528              throw new XmlRpcUnsupportedTypeException(
529                      "Unsupported Type in Method Arguments: " + javaType);
530          }
531  
532          return result;
533      }
534  
535      private Node convertObjectToXmlRpcValue(Object object, String type, 
536                                              Document doc)
537          throws XmlRpcUnsupportedTypeException
538      {
539          Node result = doc.createElement("value");
540          Node value = null;
541  
542          if (type.equals(XmlRpcTypes.STRUCT_TYPE))
543          {
544              value = convertObjectToStruct((Map) object, doc);
545          }
546          else if (type.equals(XmlRpcTypes.ARRAY_TYPE))
547          {
548              value = convertObjectToArray((List) object, doc);
549          }
550          else if (type.equals(XmlRpcTypes.DATETIME_TYPE))
551          {
552              value = convertObjectToDateTimeValue((Date) object, doc);
553          }
554          else if (type.equals(XmlRpcTypes.BASE64_TYPE))
555          {
556              value = convertObjectToBase64Value((byte[]) object, doc);
557          }
558          else if (type.equals(XmlRpcTypes.BOOLEAN_TYPE))
559          {
560              value = doc.createElement(type);
561  
562              Boolean bool = (Boolean) object;
563              String boolString = (bool.booleanValue()) ? "1" : "0";
564  
565              value.appendChild(doc.createTextNode(boolString));
566          }
567          else
568          {
569              value = doc.createElement(type);
570              value.appendChild(doc.createTextNode(object.toString()));
571          }
572  
573          result.appendChild(value);
574  
575          return result;
576      }
577  
578      private Object convertXmlRpcValueToObject(Node node)
579          throws XmlRpcException
580      {
581          boolean debug = log.isDebugEnabled();
582          Object object = null;
583          NodeList list = DomUtil.getChildElements(node);
584  
585          if (list.getLength() > 0)
586          {
587              Element element = (Element) list.item(0);
588              String xmlrpcType = element.getTagName();
589  
590              if (element == null)
591              {
592                  throw new XmlRpcFormatException(
593                          "Missing Value For Request Parameter");
594              }
595  
596              if (debug)
597              {
598                  log.debug("xmlrpcType = " + xmlrpcType);
599                  log.debug("element = " + element);
600              }
601  
602              if (xmlrpcType.equals(XmlRpcTypes.STRUCT_TYPE))
603              {
604                  object = convertStructToObject(element);
605              }
606              else if (xmlrpcType.equals(XmlRpcTypes.ARRAY_TYPE))
607              {
608                  object = convertArrayToObject(element);
609              }
610              else if (xmlrpcType.equals(XmlRpcTypes.DATETIME_TYPE))
611              {
612                  object = convertDateTimeToObject(element);
613              }
614              else if (xmlrpcType.equals(XmlRpcTypes.BASE64_TYPE))
615              {
616                  object = convertBase64ToObject(element);
617              }
618              else
619              {
620                  object = convertSimpleToObject(element);
621              }
622          }
623          else
624          {
625              Text text = (Text) node.getFirstChild();
626  
627              object = text.getData();
628          }
629  
630          return object;
631      }
632  
633      private Object convertSimpleToObject(Element element)
634          throws XmlRpcException
635      {
636          boolean debug = log.isDebugEnabled();
637          Object object = null;
638  
639          if (debug)
640          {
641              log.debug("element = " + element);
642          }
643  
644          try
645          {
646              if (element instanceof Text)
647              {
648                  object = ((Text) element).getData();
649              }
650              else
651              {
652                  String xmlRmiType = element.getTagName();
653                  Text text = (Text) element.getFirstChild();
654  
655                  if (debug)
656                  {
657                      log.debug("text = " + text);
658                  }
659  
660                  if (text != null)
661                  {
662                      String value = text.getData();
663  
664                      if (debug)
665                      {
666                          log.debug("value = " + value);
667                      }
668  
669                      if (xmlRmiType.equals(XmlRpcTypes.INT_TYPE)
670                          || xmlRmiType.equals(XmlRpcTypes.I4_TYPE))
671                      {
672                          object = new Integer(value);
673                      }
674                      else if (xmlRmiType.equals(XmlRpcTypes.BOOLEAN_TYPE))
675                      {
676                          object = new Boolean(!value.equals("0"));
677                      }
678                      else if (xmlRmiType.equals(XmlRpcTypes.DOUBLE_TYPE))
679                      {
680                          object = new Double(value);
681                      }
682                      else
683                      {
684                          object = value;
685                      }
686                  }
687              }
688          }
689          catch (Exception ex)
690          {
691              throw new XmlRpcFormatException("Malformed parameters for  request");
692          }
693  
694          return object;
695      }
696  
697      private Node convertObjectToArray(List list, Document doc)
698          throws XmlRpcUnsupportedTypeException
699      {
700          Element data = doc.createElement("data");
701  
702          Iterator elements = list.iterator();
703  
704          while (elements.hasNext())
705          {
706              Object object = elements.next();
707              String type = convertObjectTypeToXmlRpcType(
708                                    object.getClass().getName());
709              Node node = convertObjectToXmlRpcValue(object, type, doc);
710  
711              data.appendChild(node);
712          }
713  
714          Element array = doc.createElement(XmlRpcTypes.ARRAY_TYPE);
715  
716          array.appendChild(data);
717  
718          return array;
719      }
720  
721      private List convertArrayToObject(Node node)
722          throws XmlRpcException
723      {
724          ArrayList list = null;
725          boolean debug = log.isDebugEnabled();
726  
727          try
728          {
729              node = DomUtil.getChildElementsByTagName(node, "data").item(0);
730  
731              NodeList values = DomUtil.getChildElements(node);
732              int numValues = values.getLength();
733  
734              if (debug)
735              {
736                  log.debug("numValues = " + numValues);
737              }
738  
739              list = new ArrayList(numValues);
740  
741              for (int i = 0; i < numValues; i++)
742              {
743                  String xmlrpcType = "string";
744                  Node value = values.item(i);
745  
746                  /*
747                  Node typeNode = DomUtil.getChildElements(value).item(0);// <int>, <string>, <struct> etc
748                  if (typeNode instanceof Element) {
749                  xmlrpcType = ((Element)typeNode).getTagName();
750                  }
751                  */
752                  if (debug)
753                  {
754                      log.debug("value = " + value);
755                  }
756  
757                  Object object = convertXmlRpcValueToObject(value);
758  
759                  if (debug)
760                  {
761                      log.debug("object = " + object);
762                  }
763  
764                  list.add(object);
765              }
766          }
767          catch (XmlRpcException ex)
768          {
769              throw ex;
770          }
771          catch (Exception ex)
772          {
773              throw new XmlRpcFormatException(
774                      "Failed Converting XML-RPC <array> to List");
775          }
776  
777          return list;
778      }
779  
780      private Node convertObjectToStruct(Map map, Document doc)
781          throws XmlRpcUnsupportedTypeException
782      {
783          Element struct = doc.createElement(XmlRpcTypes.STRUCT_TYPE);
784          Set entrySet = map.entrySet();
785          Iterator entries = entrySet.iterator();
786  
787          while (entries.hasNext())
788          {
789              Map.Entry entry = (Map.Entry) entries.next();
790              String memberName;
791              Object key = entry.getKey();
792  
793              if (key instanceof String)
794              {
795                  memberName = (String) key;
796              }
797              else
798              {
799                  throw new XmlRpcUnsupportedTypeException(
800                          "Unsupported Type For Map Key: "
801                          + key.getClass().getName());
802              }
803  
804              Object object = entry.getValue();
805              Element member = doc.createElement("member");
806              Element name = doc.createElement("name");
807              Text text = doc.createTextNode(memberName);
808  
809              name.appendChild(text);
810              member.appendChild(name);
811  
812              String type = convertObjectTypeToXmlRpcType(
813                                    object.getClass().getName());
814              Node value = convertObjectToXmlRpcValue(object, type, doc);
815  
816              member.appendChild(value);
817  
818              struct.appendChild(member);
819          }
820  
821          return struct;
822      }
823  
824      private Map convertStructToObject(Node node)
825          throws XmlRpcException
826      {
827          HashMap map = null;
828  
829          try
830          {
831              NodeList members = DomUtil.getChildElements(node);
832              int memberCount = members.getLength();
833  
834              map = new HashMap(memberCount);
835  
836              for (int i = 0; i < memberCount; i++)
837              {
838                  Node member = members.item(i);
839                  NodeList nodes = DomUtil.getChildElements(member);
840  
841                  node = nodes.item(0);
842  
843                  Text text = (Text) node.getFirstChild();
844                  String key = text.getData();
845  
846                  node = nodes.item(1);
847  
848                  Object object = convertXmlRpcValueToObject(node);
849  
850                  map.put(key, object);
851              }
852          }
853          catch (XmlRpcException ex)
854          {
855              throw ex;
856          }
857          catch (Exception ex)
858          {
859              throw new XmlRpcFormatException("Failed reading <struct> members");
860          }
861  
862          return map;
863      }
864  
865      private Node convertObjectToDateTimeValue(Date date, Document doc)
866      {
867          Node datetime = doc.createElement(XmlRpcTypes.DATETIME_TYPE);
868          String string = dateFormatter.format(date);
869  
870          string = string.replace(' ', 'T');
871  
872          Text text = doc.createTextNode(string);
873  
874          datetime.appendChild(text);
875  
876          return datetime;
877      }
878  
879      private Date convertDateTimeToObject(Node node)
880          throws XmlRpcException
881      {
882          Date date = null;
883          boolean debug = log.isDebugEnabled();
884  
885          try
886          {
887              if (debug)
888              {
889                  log.debug("node = " + node);
890              }
891  
892              Text text = (Text) node.getFirstChild();
893  
894              if (debug)
895              {
896                  log.debug("text = " + text);
897              }
898  
899              String string = text.getData();
900  
901              string = string.replace('T', ' ');
902  
903              if (debug)
904              {
905                  log.debug("string = " + string);
906              }
907  
908              date = dateFormatter.parse(string);
909  
910              if (debug)
911              {
912                  log.debug("date = " + date);
913              }
914          }
915          catch (Exception ex)
916          {
917              if (debug)
918              {
919                  log.debug("ex = " + ex);
920              }
921  
922              throw new XmlRpcFormatException(
923                      "Failed while parsing a Date from XML-RPC request");
924          }
925  
926          return date;
927      }
928  
929      private Node convertObjectToBase64Value(byte[] bytes, Document doc)
930      {
931          Node node = doc.createElement(XmlRpcTypes.BASE64_TYPE);
932          String string = new String(bytes);
933          Text text = doc.createTextNode(string);
934  
935          node.appendChild(text);
936  
937          return node;
938      }
939  
940      private byte[] convertBase64ToObject(Node node)
941          throws XmlRpcException
942      {
943          byte[] bytes = null;
944          boolean debug = log.isDebugEnabled();
945  
946          try
947          {
948              if (debug)
949              {
950                  log.debug("node = " + node);
951              }
952  
953              Text text = (Text) node.getFirstChild();
954  
955              if (debug)
956              {
957                  log.debug("text = " + text);
958              }
959  
960              String string = text.getData();
961  
962              bytes = string.getBytes();
963          }
964          catch (Exception ex)
965          {
966              if (debug)
967              {
968                  log.debug("ex = " + ex);
969              }
970  
971              throw new XmlRpcFormatException(
972                      "Failed while parsing a Base 64 value from XML-RPC request");
973          }
974  
975          return bytes;
976      }
977  
978      private List extractValueNodesFromParams(NodeList nodes)
979      {
980          int listLength = nodes.getLength();
981          ArrayList list = new ArrayList(listLength);
982  
983          for (int i = 0; i < listLength; i++)
984          {
985              Node node = nodes.item(i); // <param>
986  
987              if (log.isDebugEnabled())
988              {
989                  log.debug("node = " + node);
990              }
991  
992              node = DomUtil.getChildElements(node).item(0); // <value>
993              list.add(node);
994          }
995  
996          return list;
997      }
998  
999      private String[] extractArgumentTypesFromParams(List values)
1000     {
1001         int listLength = values.size();
1002         String[] strings = new String[listLength];
1003         Iterator nodes = values.iterator();
1004         int i = 0;
1005 
1006         while (nodes.hasNext())
1007         {
1008             String xmlrpcType = "string";
1009             Node node = (Node) nodes.next();
1010 
1011             node = node.getFirstChild();
1012 
1013             if (node instanceof Element)
1014             {
1015                 xmlrpcType = ((Element) node).getTagName();
1016             }
1017 
1018 
1019             //String javaType = (String)xmlrpcTypes.get(xmlrpcType);
1020             strings[i++] = xmlrpcType;
1021         }
1022 
1023         return strings;
1024     }
1025 
1026     private Object[] extractArgumentValuesFromParams(List values)
1027         throws XmlRpcException
1028     {
1029         boolean debug = log.isDebugEnabled();
1030         int listLength = values.size();
1031         Object[] objects = new Object[listLength];
1032 
1033         if (debug)
1034         {
1035             log.debug("listLength = " + listLength);
1036         }
1037 
1038         for (int i = 0; i < listLength; i++)
1039         {
1040             Node node = (Node) values.get(i);
1041 
1042             if (debug)
1043             {
1044                 log.debug("node = " + node);
1045             }
1046 
1047             Object object = convertXmlRpcValueToObject(node);
1048 
1049             if (debug)
1050             {
1051                 log.debug("object = " + object);
1052             }
1053 
1054             objects[i] = object;
1055         }
1056 
1057         return objects;
1058     }
1059 }