Package org.springmodules.remoting.xmlrpc.dom

Source Code of org.springmodules.remoting.xmlrpc.dom.AbstractDomXmlRpcParser

/*
* Created on Jun 15, 2005
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* Copyright @2005 the original author or authors.
*/
package org.springmodules.remoting.xmlrpc.dom;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.springframework.util.xml.SimpleSaxErrorHandler;
import org.springmodules.remoting.xmlrpc.XmlRpcInternalException;
import org.springmodules.remoting.xmlrpc.XmlRpcInvalidPayloadException;
import org.springmodules.remoting.xmlrpc.XmlRpcNotWellFormedException;
import org.springmodules.remoting.xmlrpc.XmlRpcParsingException;
import org.springmodules.remoting.xmlrpc.XmlRpcServerException;
import org.springmodules.remoting.xmlrpc.support.XmlRpcArray;
import org.springmodules.remoting.xmlrpc.support.XmlRpcBase64;
import org.springmodules.remoting.xmlrpc.support.XmlRpcBoolean;
import org.springmodules.remoting.xmlrpc.support.XmlRpcDateTime;
import org.springmodules.remoting.xmlrpc.support.XmlRpcDouble;
import org.springmodules.remoting.xmlrpc.support.XmlRpcElement;
import org.springmodules.remoting.xmlrpc.support.XmlRpcElementNames;
import org.springmodules.remoting.xmlrpc.support.XmlRpcInteger;
import org.springmodules.remoting.xmlrpc.support.XmlRpcString;
import org.springmodules.remoting.xmlrpc.support.XmlRpcStruct;
import org.springmodules.remoting.xmlrpc.support.XmlRpcStruct.XmlRpcMember;
import org.springmodules.remoting.xmlrpc.util.XmlRpcParsingUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
* <p>
* Template for XML-RPC request/response parsers that use DOM.
* </p>
*
* @author Alex Ruiz
*
* @version $Revision$ $Date$
*/
public abstract class AbstractDomXmlRpcParser {

  /**
   * SAX entity resolver to be used for parsing. By default,
   * <code>{@link XmlRpcDtdResolver}</code> will be used.
   */
  private EntityResolver entityResolver;

  /**
   * <p>
   * Implementation of <code>org.xml.sax.ErrorHandler</code> for custom
   * handling of XML parsing errors and warnings.
   * </p>
   * <p>
   * If not set, a default <code>{@link SimpleSaxErrorHandler}</code> is used
   * that simply logs warnings using the logger instance of the view class, and
   * rethrows errors to discontinue the XML transformation.
   * </p>
   *
   * @see org.springframework.util.xml.SimpleSaxErrorHandler
   */
  private ErrorHandler errorHandler;

  protected final Log logger = LogFactory.getLog(getClass());

  /**
   * Flag that indicates if the XML parser should validate the XML-RPC request.
   * Default is <code>false</code>.
   */
  private boolean validating;

  public AbstractDomXmlRpcParser() {
    super();
    setEntityResolver(new XmlRpcDtdResolver());
    setErrorHandler(new SimpleSaxErrorHandler(logger));
  }

  /**
   * Creates a new XML document by parsing the given InputStream.
   *
   * @param inputStream
   *          the InputStream to parse.
   * @return the created XML document.
   * @throws XmlRpcServerException
   *           if there are any internal errors.
   * @throws XmlRpcParsingException
   *           if there are any errors during the parsing.
   */
  protected final Document loadXmlDocument(InputStream inputStream) {
    try {
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      if (logger.isDebugEnabled()) {
        logger.debug("Using JAXP implementation [" + factory + "]");
      }
      factory.setValidating(validating);

      DocumentBuilder docBuilder = factory.newDocumentBuilder();
      docBuilder.setErrorHandler(errorHandler);
      if (entityResolver != null) {
        docBuilder.setEntityResolver(entityResolver);
      }

      return docBuilder.parse(inputStream);

    } catch (ParserConfigurationException exception) {
      throw new XmlRpcInternalException("Parser configuration exception",
          exception);

    } catch (SAXParseException exception) {
      throw new XmlRpcNotWellFormedException("Line "
          + exception.getLineNumber() + " in XML-RPC payload is invalid",
          exception);

    } catch (SAXException exception) {
      throw new XmlRpcNotWellFormedException("XML-RPC payload is invalid",
          exception);

    } catch (IOException exception) {
      throw new XmlRpcInternalException(
          "IOException when parsing XML-RPC payload", exception);

    } finally {
      if (inputStream != null) {
        try {
          inputStream.close();
        } catch (IOException exception) {
          logger.warn("Could not close InputStream", exception);
        }
      }
    }
  }

  /**
   * Parses the given XML element that contains a XML-RPC array.
   *
   * @param arrayElement
   *          the XML element to parse.
   * @return the created XML-RPC array.
   * @throws XmlRpcInvalidPayloadException
   *           if the element contains an unknown child. Only one "data" element
   *           is allowed inside an "array" element.
   * @see #parseDataElement(Element)
   */
  protected final XmlRpcArray parseArrayElement(Element arrayElement) {
    NodeList children = arrayElement.getChildNodes();
    int childCount = children.getLength();

    for (int i = 0; i < childCount; i++) {
      Node child = children.item(i);

      if (child instanceof Element) {
        String childName = child.getNodeName();

        if (XmlRpcElementNames.DATA.equals(childName)) {
          Element dataElement = (Element) child;
          return parseDataElement(dataElement);
        }
        XmlRpcParsingUtils.handleUnexpectedElementFound(childName);
      }
    }

    // we should not reach this point.
    return null;
  }

  /**
   * Parses the given XML element that contains the data of a XML-RPC array.
   *
   * @param dataElement
   *          the XML element to parse.
   * @return the created XML-RPC array.
   * @see #parseValueElement(Element)
   */
  protected final XmlRpcArray parseDataElement(Element dataElement) {
    XmlRpcArray array = new XmlRpcArray();

    NodeList children = dataElement.getChildNodes();
    int childCount = children.getLength();

    for (int i = 0; i < childCount; i++) {
      Node child = children.item(i);

      if (child instanceof Element) {
        String childName = child.getNodeName();

        if (XmlRpcElementNames.VALUE.equals(childName)) {
          Element valueElement = (Element) child;
          XmlRpcElement element = parseValueElement(valueElement);
          array.add(element);
        }
      }
    }
    return array;
  }

  /**
   * Parses the given XML element that contains a member of a XML-RPC complex
   * structure.
   *
   * @param memberElement
   *          the XML element to parse.
   * @return the created member of a XML-RPC complex structure.
   * @throws XmlRpcInvalidPayloadException
   *           if the element contains a child with an unknown name. Only one
   *           element with name "name" and one element with name "value" are
   *           allowed inside an "member" element.
   * @throws XmlRpcInvalidPayloadException
   *           if the name of the parsed struct member is empty.
   * @see #parseValueElement(Element)
   */
  protected final XmlRpcMember parseMemberElement(Element memberElement) {
    String name = null;
    XmlRpcElement value = null;

    NodeList children = memberElement.getChildNodes();
    int childCount = children.getLength();

    for (int i = 0; i < childCount; i++) {
      Node child = children.item(i);

      if (child instanceof Element) {
        String childName = child.getNodeName();

        if (XmlRpcElementNames.NAME.equals(childName)) {
          Element nameElement = (Element) child;
          name = DomUtils.getTextValue(nameElement);

        } else if (XmlRpcElementNames.VALUE.equals(childName)) {
          Element valueElement = (Element) child;
          value = parseValueElement(valueElement);

        } else {
          XmlRpcParsingUtils.handleUnexpectedElementFound(childName);
        }
      }
    }

    if (!StringUtils.hasText(name)) {
      throw new XmlRpcInvalidPayloadException(
          "The struct member should have a name");
    }

    return new XmlRpcMember(name, value);
  }

  /**
   * Parses the given XML element that contains a single parameter of either a
   * XML-RPC request or a XML-RPC response.
   *
   * @param parameterElement
   *          the XML element to parse.
   * @return the created parameter.
   * @throws XmlRpcInvalidPayloadException
   *           if the element contains a child with name other than a "value".
   * @see #parseValueElement(Element)
   */
  protected final XmlRpcElement parseParameterElement(Element parameterElement) {
    NodeList children = parameterElement.getChildNodes();
    int childCount = children.getLength();

    for (int i = 0; i < childCount; i++) {
      Node child = children.item(i);

      if (child instanceof Element) {
        String nodeName = child.getNodeName();
        if (XmlRpcElementNames.VALUE.equals(nodeName)) {
          Element valueElement = (Element) child;
          return parseValueElement(valueElement);
        }
        XmlRpcParsingUtils.handleUnexpectedElementFound(nodeName);
      }
    }

    // we should not reach this point.
    return null;
  }

  /**
   * Parses the given XML element that contains all the parameters or either a
   * XML-RPC request or a XML-RPC response.
   *
   * @param parametersElement
   *          the XML element to parse.
   * @return the created parameters.
   * @throws XmlRpcInvalidPayloadException
   *           if there are elements other than "param".
   * @see #parseParameterElement(Element)
   */
  protected final XmlRpcElement[] parseParametersElement(
      Element parametersElement) {
    List parameters = new ArrayList();

    NodeList children = parametersElement.getChildNodes();
    int childCount = children.getLength();

    for (int i = 0; i < childCount; i++) {
      Node child = children.item(i);
      if (child instanceof Element) {
        String childName = child.getNodeName();

        if (XmlRpcElementNames.PARAM.equals(childName)) {
          Element parameterElement = (Element) child;
          XmlRpcElement parameter = this
              .parseParameterElement(parameterElement);
          parameters.add(parameter);

        } else {
          XmlRpcParsingUtils.handleUnexpectedElementFound(childName);
        }
      }
    }

    return (XmlRpcElement[]) parameters.toArray(new XmlRpcElement[parameters
        .size()]);
  }

  /**
   * Parses the given XML element that contains a XML-RPC complex structure.
   *
   * @param structElement
   *          the XML element to parse.
   * @return the created XML-RPC complex structure.
   * @see #parseMemberElement(Element)
   */
  protected final XmlRpcStruct parseStructElement(Element structElement) {
    XmlRpcStruct struct = new XmlRpcStruct();

    NodeList children = structElement.getChildNodes();
    int childCount = children.getLength();

    for (int i = 0; i < childCount; i++) {
      Node child = children.item(i);

      if (child instanceof Element) {
        String childName = child.getNodeName();

        if (XmlRpcElementNames.MEMBER.equals(childName)) {
          Element memberElement = (Element) child;
          XmlRpcMember member = parseMemberElement(memberElement);
          struct.add(member);
        }
      }
    }

    return struct;
  }

  /**
   * Parses the given XML element that contains the value of a parameter, a
   * struct member or an element of an array.
   *
   * @param valueElement
   *          the XML element to parse.
   * @return the created value.
   * @throws XmlRpcInvalidPayloadException
   *           if there are invalid XML elements.
   * @see #parseArrayElement(Element)
   * @see #parseStructElement(Element)
   */
  protected final XmlRpcElement parseValueElement(Element valueElement) {
    NodeList children = valueElement.getChildNodes();
    int childCount = children.getLength();

    for (int i = 0; i < childCount; i++) {
      Node child = children.item(i);

      if (child instanceof Element) {
        String childName = child.getNodeName();
        Element xmlElement = (Element) child;

        if (XmlRpcElementNames.ARRAY.equals(childName)) {
          return parseArrayElement(xmlElement);

        } else if (XmlRpcElementNames.BASE_64.equals(childName)) {
          String source = DomUtils.getTextValue(xmlElement);
          return new XmlRpcBase64(source);

        } else if (XmlRpcElementNames.BOOLEAN.equals(childName)) {
          String source = DomUtils.getTextValue(xmlElement);
          return new XmlRpcBoolean(source);

        } else if (XmlRpcElementNames.DATE_TIME.equals(childName)) {
          String source = DomUtils.getTextValue(xmlElement);
          return new XmlRpcDateTime(source);

        } else if (XmlRpcElementNames.DOUBLE.equals(childName)) {
          String source = DomUtils.getTextValue(xmlElement);
          return new XmlRpcDouble(source);

        } else if (XmlRpcElementNames.I4.equals(childName)
            || XmlRpcElementNames.INT.equals(childName)) {
          String source = DomUtils.getTextValue(xmlElement);
          return new XmlRpcInteger(source);

        } else if (XmlRpcElementNames.STRING.equals(childName)) {
          String source = DomUtils.getTextValue(xmlElement);
          return new XmlRpcString(source);

        } else if (XmlRpcElementNames.STRUCT.equals(childName)) {
          return parseStructElement(xmlElement);

        } else {
          XmlRpcParsingUtils.handleUnexpectedElementFound(childName);
        }

      } else if (child instanceof Text) {
        String source = DomUtils.getTextValue(valueElement);
        return new XmlRpcString(source);
      }
    }

    // we should not reach this point.
    return null;
  }

  public final void setEntityResolver(EntityResolver newEntityResolver) {
    entityResolver = newEntityResolver;
  }

  public final void setErrorHandler(ErrorHandler newErrorHandler) {
    errorHandler = newErrorHandler;
  }

  public final void setValidating(boolean newValidating) {
    validating = newValidating;
  }
}
TOP

Related Classes of org.springmodules.remoting.xmlrpc.dom.AbstractDomXmlRpcParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.