/* * The contents of this file are subject to the Mozilla Public License Version 1.1 * (the "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at . * * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ package com.silverwrist.venice.ui.rpc; import java.io.*; import java.util.*; import javax.mail.*; import javax.mail.internet.*; import org.apache.log4j.*; import org.w3c.dom.*; import com.silverwrist.util.*; import com.silverwrist.venice.except.*; import com.silverwrist.venice.util.XMLLoader; public class XmlRpcRequest { /*-------------------------------------------------------------------------------- * Static data members *-------------------------------------------------------------------------------- */ private static Category logger = Category.getInstance(XmlRpcRequest.class); private static SimpleTimeZone utc = new SimpleTimeZone(0,"UTC"); /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- */ String method_name; // the method name List method_params; // the method parameters /*-------------------------------------------------------------------------------- * Constructor *-------------------------------------------------------------------------------- */ XmlRpcRequest(Document req_doc) throws XmlRpcFault { if (req_doc==null) throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,"no XML call structure found"); try { // load the initial structure and method name XMLLoader loader = XMLLoader.get(); Element root = loader.postGetRootElement(req_doc,"methodCall"); DOMElementHelper root_h = new DOMElementHelper(root); method_name = loader.postGetSubElementText(root_h,"methodName"); // parse the parameters Element params = root_h.getSubElement("params"); ArrayList tmp_method_params = new ArrayList(); if (params!=null) { // look for children of the node NodeList nl = params.getChildNodes(); for (int i=0; i node if (!(n.getNodeName().equals("param"))) throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST, "non-param element found inside \"params\" element"); tmp_method_params.add(parseValue(loader.postGetSubSection((Element)n,"value"))); } // end if // else ignore this node } // end for } // end if // save the method parameters if (tmp_method_params.isEmpty()) method_params = Collections.EMPTY_LIST; else { // make it read-only before tmp_method_params.trimToSize(); method_params = Collections.unmodifiableList(tmp_method_params); } // end else } // end try catch (ValidationException ve) { // validation exceptions get translated to XML-RPC faults throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,ve); } // end catch } // end constructor /*-------------------------------------------------------------------------------- * Internal static operations *-------------------------------------------------------------------------------- */ private static final Object parseValue(Element val) throws ValidationException, XmlRpcFault { XMLLoader loader = XMLLoader.get(); // see if the value has an embedded type... NodeList nl = val.getChildNodes(); Element type = null; for (int i=0; i element: expected a valid type but got a <" + name + "/>"); throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST, "invalid type element \"" + name + "\" specified inside a \"value\""); } // end else } // end if else { // if there's no type-specific element, treat it as a string DOMElementHelper h = new DOMElementHelper(val); String s = h.getElementText(); if (s==null) s = ""; return s; } // end else } // end parseValue private static final List parseArray(Element val) throws XmlRpcFault, ValidationException { XMLLoader loader = XMLLoader.get(); Element data = loader.postGetSubSection(val,"data"); NodeList nl = data.getChildNodes(); ArrayList rc = new ArrayList(); for (int i=0; i elements within the element Node n = nl.item(i); if (n.getNodeType()==Node.ELEMENT_NODE) { // make sure we've got a value element here! if (!(n.getNodeName().equals("value"))) { // this is a bogus value! logger.error("inside array : expected a but found a <" + n.getNodeName() + "/>"); throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST, "non-value element found inside array \"data\" element"); } // end if rc.add(parseValue((Element)n)); } // end if } // end for if (rc.isEmpty()) return Collections.EMPTY_LIST; else { // trim the result array and return the list rc.trimToSize(); return Collections.unmodifiableList(rc); } // end else } // end parseArray private static final Map parseStruct(Element val) throws XmlRpcFault, ValidationException { XMLLoader loader = XMLLoader.get(); NodeList nl = val.getChildNodes(); HashMap rc = new HashMap(); for (int i=0; i elements within a element Node n = nl.item(i); if (n.getNodeType()==Node.ELEMENT_NODE) { // make sure we've got a value element here! if (!(n.getNodeName().equals("member"))) { // this is a bogus value logger.error("inside : expected a but found a <" + n.getNodeName() + "/>"); throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST, "non-member element found inside \"struct\" element"); } // end if DOMElementHelper h = new DOMElementHelper((Element)n); String my_name = loader.postGetSubElementText(h,"name").trim(); Element my_val = loader.postGetSubSection(h,"value"); rc.put(my_name,parseValue(my_val)); } // end if } // end for if (rc.isEmpty()) return Collections.EMPTY_MAP; else return Collections.unmodifiableMap(rc); } // end parseStruct /*-------------------------------------------------------------------------------- * External operations *-------------------------------------------------------------------------------- */ public final String getMethod() { return method_name; } // end getMethod public final int getParamCount() { return method_params.size(); } // end getParamCount public final List getParams() { return method_params; } // end getParams public final Object getParam(int ndx) { return method_params.get(ndx); } // end getParam public final String getParamType(int ndx) { Object foo = method_params.get(ndx); if (foo instanceof Integer) return "int"; if (foo instanceof Boolean) return "boolean"; if (foo instanceof String) return "string"; if (foo instanceof Double) return "double"; if (foo instanceof Date) return "dateTime"; if (foo instanceof byte[]) return "base64"; if (foo instanceof Map) return "struct"; if (foo instanceof List) return "array"; return "(unknown)"; } // end getParamType public final int getParamInt(int ndx) throws XmlRpcFault { Object foo = method_params.get(ndx); if (foo instanceof Integer) return ((Integer)foo).intValue(); else if (foo instanceof Boolean) return ((Boolean)foo).booleanValue() ? 1 : 0; else throw new XmlRpcFault(XmlRpcFault.INVALID_PARAMS,"parameter type mismatch"); } // end getParamInt public final double getParamDouble(int ndx) throws XmlRpcFault { Object foo = method_params.get(ndx); if ((foo instanceof Integer) || (foo instanceof Double)) return ((Number)foo).doubleValue(); else if (foo instanceof Boolean) return ((Boolean)foo).booleanValue() ? 1 : 0; else throw new XmlRpcFault(XmlRpcFault.INVALID_PARAMS,"parameter type mismatch"); } // end getParamDouble public final String getParamString(int ndx) throws XmlRpcFault { Object foo = method_params.get(ndx); if ((foo instanceof byte[]) || (foo instanceof List) || (foo instanceof Map)) throw new XmlRpcFault(XmlRpcFault.INVALID_PARAMS,"parameter type mismatch"); return foo.toString(); } // end getParamString } // end class XmlRpcRequest