Package org.apache.xmlrpc.server

Source Code of org.apache.xmlrpc.server.XmlRpcStreamServer

/*
* Copyright 1999,2005 The Apache Software Foundation.
*
* 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.
*/
package org.apache.xmlrpc.server;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.XmlRpcRequest;
import org.apache.xmlrpc.XmlRpcRequestConfig;
import org.apache.xmlrpc.common.ServerStreamConnection;
import org.apache.xmlrpc.common.XmlRpcStreamRequestConfig;
import org.apache.xmlrpc.common.XmlRpcStreamRequestProcessor;
import org.apache.xmlrpc.parser.XmlRpcRequestParser;
import org.apache.xmlrpc.serializer.DefaultXMLWriterFactory;
import org.apache.xmlrpc.serializer.XmlRpcWriter;
import org.apache.xmlrpc.serializer.XmlWriterFactory;
import org.apache.xmlrpc.util.SAXParsers;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;


/** Extension of {@link XmlRpcServer} with support for reading
* requests from a stream and writing the response to another
* stream.
*/
public abstract class XmlRpcStreamServer extends XmlRpcServer
    implements XmlRpcStreamRequestProcessor {
  private static final Log log = LogFactory.getLog(XmlRpcStreamServer.class);
  private XmlWriterFactory writerFactory = new DefaultXMLWriterFactory();

  protected XmlRpcRequest getRequest(final XmlRpcStreamRequestConfig pConfig,
                     InputStream pStream) throws XmlRpcException {
    final XmlRpcRequestParser parser = new XmlRpcRequestParser(pConfig, getTypeFactory());
    final XMLReader xr = SAXParsers.newXMLReader();
    xr.setContentHandler(parser);
    try {
      xr.parse(new InputSource(pStream));
    } catch (SAXException e) {
      Exception ex = e.getException();
      if (ex != null  &&  ex instanceof XmlRpcException) {
        throw (XmlRpcException) ex;
      }
      throw new XmlRpcException("Failed to parse XML-RPC request: " + e.getMessage(), e);
    } catch (IOException e) {
      throw new XmlRpcException("Failed to read XML-RPC request: " + e.getMessage(), e);
    }
    final List params = parser.getParams();
    return new XmlRpcRequest(){
      public XmlRpcRequestConfig getConfig() { return pConfig; }
      public String getMethodName() { return parser.getMethodName(); }
      public int getParameterCount() { return params.size(); }
      public Object getParameter(int pIndex) { return params.get(pIndex); }
    };
  }

  protected XmlRpcWriter getXmlRpcWriter(XmlRpcStreamRequestConfig pConfig,
                       OutputStream pStream)
      throws XmlRpcException {
    ContentHandler w = getXMLWriterFactory().getXmlWriter(pConfig, pStream);
    return new XmlRpcWriter(pConfig, w, getTypeFactory());
  }

  protected void writeResponse(XmlRpcStreamRequestConfig pConfig, OutputStream pStream,
                 Object pResult) throws XmlRpcException {
    try {
      getXmlRpcWriter(pConfig, pStream).write(pConfig, pResult);
    } catch (SAXException e) {
      throw new XmlRpcException("Failed to write XML-RPC response: " + e.getMessage(), e);
    }
  }

  protected void writeError(XmlRpcStreamRequestConfig pConfig, OutputStream pStream,
                Throwable pError)
      throws XmlRpcException {
    final int code;
    final String message;
    if (pError instanceof XmlRpcException) {
      XmlRpcException ex = (XmlRpcException) pError;
      code = ex.code;
    } else {
      code = 0;
    }
    message = pError.getMessage();
    try {
      getXmlRpcWriter(pConfig, pStream).write(pConfig, code, message);
    } catch (SAXException e) {
      throw new XmlRpcException("Failed to write XML-RPC response: " + e.getMessage(), e);
    }
  }

  /** Sets the XML Writer factory.
   * @param pFactory The XML Writer factory.
   */
  public void setXMLWriterFactory(XmlWriterFactory pFactory) {
    writerFactory = pFactory;
  }

  /** Returns the XML Writer factory.
   * @return The XML Writer factory.
   */
  public XmlWriterFactory getXMLWriterFactory() {
    return writerFactory;
  }

  protected InputStream getInputStream(XmlRpcStreamRequestConfig pConfig,
                     ServerStreamConnection pConnection) throws IOException {
    InputStream istream = pConnection.newInputStream();
    if (pConfig.isEnabledForExtensions()  &&  pConfig.isGzipCompressing()) {
      istream = new GZIPInputStream(istream);
    }
    return istream;
  }

  /** Called to prepare the output stream. Typically used for enabling
   * compression, or similar filters.
   */
  protected OutputStream getOutputStream(ServerStreamConnection pConnection,
                       XmlRpcStreamRequestConfig pConfig, OutputStream pStream) throws IOException {
    if (pConfig.isEnabledForExtensions()  &&  pConfig.isGzipRequesting()) {
      return new GZIPOutputStream(pStream);
    } else {
      return pStream;
    }
  }

  /** Called to prepare the output stream, if content length is
   * required.
   */
  protected OutputStream getOutputStream(XmlRpcStreamRequestConfig pConfig,
                       ServerStreamConnection pConnection,
                       int pSize) throws IOException {
      return pConnection.newOutputStream();
  }

  /** Returns, whether the requests content length is required.
   */
  protected boolean isContentLengthRequired(XmlRpcStreamRequestConfig pConfig) {
    return false;
  }

  /** Returns, whether the
  /** Processes a "connection". The "connection" is an opaque object, which is
   * being handled by the subclasses.
   * @param pConfig The request configuration.
   * @param pConnection The "connection" being processed.
   * @throws XmlRpcException Processing the request failed.
   */
  public void execute(XmlRpcStreamRequestConfig pConfig,
            ServerStreamConnection pConnection)
      throws XmlRpcException {
    log.debug("execute: ->");
    try {
      Object result;
      Throwable error;
      InputStream istream = null;
      try {
        istream = getInputStream(pConfig, pConnection);
        XmlRpcRequest request = getRequest(pConfig, istream);
        result = execute(request);
        istream.close();
        istream = null;
        error = null;
        log.debug("execute: Request performed successfully");
      } catch (Throwable t) {
        log.error("execute: Error while performing request", t);
        result = null;
        error = t;
      } finally {
        if (istream != null) { try { istream.close(); } catch (Throwable ignore) {} }
      }
      boolean contentLengthRequired = isContentLengthRequired(pConfig);
      ByteArrayOutputStream baos;
      OutputStream ostream;
      if (contentLengthRequired) {
        baos = new ByteArrayOutputStream();
        ostream = baos;
      } else {
        baos = null;
        ostream = pConnection.newOutputStream();
      }
      ostream = getOutputStream(pConnection, pConfig, ostream);
      try {
        if (error == null) {
          writeResponse(pConfig, ostream, result);
        } else {
          writeError(pConfig, ostream, error);
        }
        ostream.close();
        ostream = null;
      } finally {
        if (ostream != null) { try { ostream.close(); } catch (Throwable ignore) {} }
      }
      if (baos != null) {
        OutputStream dest = getOutputStream(pConfig, pConnection, baos.size());
        try {
          baos.writeTo(dest);
          dest.close();
          dest = null;
        } finally {
          if (dest != null) { try { dest.close(); } catch (Throwable ignore) {} }
        }
      }
            pConnection.close();
      pConnection = null;
    } catch (IOException e) {
      throw new XmlRpcException("I/O error while processing request: "
          + e.getMessage(), e);
    } finally {
      if (pConnection != null) { try { pConnection.close(); } catch (Throwable ignore) {} }
    }
    log.debug("execute: <-");
  }
}
TOP

Related Classes of org.apache.xmlrpc.server.XmlRpcStreamServer

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.