Package org.apache.cocoon.generation

Source Code of org.apache.cocoon.generation.StreamGenerator

/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved.        *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included  with this distribution in *
* the LICENSE file.                                                         *
*****************************************************************************/

package org.apache.cocoon.generation;

import org.apache.avalon.framework.component.Component;
import org.apache.cocoon.Constants;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.ResourceNotFoundException;
import org.apache.cocoon.components.parser.Parser;
import org.apache.avalon.excalibur.pool.Poolable;
import org.apache.cocoon.environment.http.HttpEnvironment;
import javax.servlet.http.HttpServletRequest;
import org.apache.cocoon.util.PostInputStream;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.StringReader;

/**
*
* The <code>StreamGenerator</code> is a class that reads XML from a
* request InputStream and generates SAX Events.
*
* For the POST requests with mimetype of
* application/x-www-form-urlencoded the xml data is expected to be
* associated with the name specified in the sitemap parameter.  For
* the POST requests with mimetypes: text/plain, text/xml,
* application/xml the xml data is in the body of the POST request and
* its length is specified by the value returned by getContentLength()
* method.  The StreamGenerator uses helper
* org.apache.cocoon.util.PostInputStream class for InputStream
* reading operations.  At the time that Parser is reading the data
* out of InputStream - Parser has no knowledge about the length of
* data to be read.  The only way to signal to the Parser that all
* data was read from the InputStream is to control reading operation-
* PostInputStream--and to return to the requestor '-1' when the
* number of bytes read is equal to the getContentLength() value.
*
* @author <a href="mailto:Kinga_Dziembowski@hp.com">Kinga Dziembowski</a>
* @version $Revision: 1.1 $ $Date: 2002/01/03 12:31:16 $
*/
public class StreamGenerator extends ComposerGenerator implements Poolable
{
    public static final String CLASS = StreamGenerator.class.getName();

    /** The parameter holding the name associated with the xml data  **/
    public static final String FORM_NAME = "form-name";

    /** The input source */
    private InputSource inputSource;

    /** The system ID of the input source */
    private String systemID;

    /**
     * Recycle this component.
     * All instance variables are set to <code>null</code>.
     */
    public void recycle() {
        super.recycle();
        this.inputSource = null;
        this.systemID = null;
    }

    /**
     * Generate XML data out of request InputStream.
     */
    public void generate() throws IOException, SAXException, ProcessingException
    {
        Parser parser = null;
        String parameter = parameters.getParameter(StreamGenerator.FORM_NAME, null);
        int len = 0;
    String contentType = null;
        try
        {
            HttpServletRequest request = (HttpServletRequest) objectModel.get(HttpEnvironment.HTTP_REQUEST_OBJECT);
            contentType = request.getContentType();
            if (contentType.startsWith("application/x-www-form-urlencoded")) {
                String sXml = request.getParameter(parameter);
                inputSource = new InputSource(new StringReader(sXml));
            } else if (contentType.startsWith("text/plain") ||
                    contentType.startsWith("text/xml") ||
                    contentType.startsWith("application/xml")) {
                len = request.getContentLength();

                if (len > 0) {
                        PostInputStream anStream = new PostInputStream(request.getInputStream(), len);
                        inputSource = new InputSource(anStream);
                } else {
                    throw new IOException("getContentLen() == 0");
                }
            } else {
                throw new IOException("Unexpected getContentType(): " + request.getContentType());
            }

            if (getLogger().isDebugEnabled()) {
                getLogger().debug("processing stream ContentType= " + request.getContentType() + "ContentLen= " + len);
            }
            String charset =  getCharacterEncoding(request, contentType) ;
      if( charset != null)
      {
        this.inputSource.setEncoding(charset);
            }
            parser = (Parser)this.manager.lookup(Parser.ROLE);
            parser.setContentHandler(super.contentHandler);
            parser.setLexicalHandler(super.lexicalHandler);
            parser.parse(this.inputSource);
        } catch (IOException e) {
            getLogger().error("StreamGenerator.generate()", e);
            throw new ResourceNotFoundException("StreamGenerator could not find resource", e);
        } catch (SAXException e) {
            getLogger().error("StreamGenerator.generate()", e);
            throw(e);
        } catch (Exception e) {
            getLogger().error("Could not get parser", e);
            throw new ProcessingException("Exception in StreamGenerator.generate()", e);
        } finally {
            if (parser != null) {
                this.manager.release((Component)parser);
            }
        }
    }

    /**
  * Content type HTTP header can contains character encodinf info
  * for ex. Content-Type: text/xml; charset=UTF-8
  * If the servlet is following spec 2.3 and higher the servlet API can be used to retrieve character encoding part of
  * Content-Type header. Some containers can choose to not unpack charset info - the spec is not strong about it.
  * in any case this method can be used as a latest resource to retrieve the passed charset value.
  * <code>null</code> is returned.
  * It is very common mistake to send : Content-Type: text/xml; charset="UTF-8".
  * Some containers are not filtering this mistake and the processing results in exception..
    * The getCharacterEncoding() compensates for above mistake.
  *
  * @param contentType value associated with Content-Type HTTP header.
  */
  public String getCharacterEncoding(HttpServletRequest req, String contentType)
  {
    String charencoding = null;
    String charset = "charset=";
    if (contentType == null)
    {
      return (null);
    }
    int idx = contentType.indexOf(charset);
    if (idx == -1)
    {
      return (null);
    }
    try
    {
      charencoding = req.getCharacterEncoding();

      if ( charencoding != null)
      {
        getLogger().debug("charset from container: " + charencoding);
        charencoding = charencoding.trim();
        if ((charencoding.length() > 2) && (charencoding.startsWith("\""))&& (charencoding.endsWith("\"")))
        {
          charencoding = charencoding.substring(1, charencoding.length() - 1);
        }
        getLogger().debug("charset from container clean: " + charencoding);
        return (charencoding);
      }
      else
      {

        return extractCharset( contentType, idx );
      }
    }
    catch(Throwable e)
    {
      // We will be there if the container do not implement getCharacterEncoding() method
       return extractCharset( contentType, idx );
    }
  }


  protected String extractCharset(String contentType, int idx)
  {
    String charencoding = null;
    String charset = "charset=";

    getLogger().debug("charset from extractCharset");
    charencoding = contentType.substring(idx + charset.length());
    int idxEnd = charencoding.indexOf(";");
    if (idxEnd != -1)
    {
      charencoding = charencoding.substring(0, idxEnd);
    }
    charencoding = charencoding.trim();
    if ((charencoding.length() > 2) && (charencoding.startsWith("\""))&& (charencoding.endsWith("\"")))
    {
      charencoding = charencoding.substring(1, charencoding.length() - 1);
    }
    getLogger().debug("charset from extractCharset: " + charencoding);
    return (charencoding.trim());

  }
}
TOP

Related Classes of org.apache.cocoon.generation.StreamGenerator

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.