You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by vg...@apache.org on 2007/12/19 16:25:04 UTC

svn commit: r605576 - /cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/generation/StreamGenerator.java

Author: vgritsenko
Date: Wed Dec 19 07:25:04 2007
New Revision: 605576

URL: http://svn.apache.org/viewvc?rev=605576&view=rev
Log:
fix javadoc, cleanup implementation

Modified:
    cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/generation/StreamGenerator.java

Modified: cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/generation/StreamGenerator.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/generation/StreamGenerator.java?rev=605576&r1=605575&r2=605576&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/generation/StreamGenerator.java (original)
+++ cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/generation/StreamGenerator.java Wed Dec 19 07:25:04 2007
@@ -35,34 +35,37 @@
 import java.io.StringReader;
 
 /**
+ * The <code>StreamGenerator</code> is a class that reads XML from a request
+ * InputStream and generates SAX Events.
+ *
+ * <p>For the POST requests with a mimetype of <code>application/x-www-form-urlencoded</code>
+ * or <code>multipart/form-data<code> the xml data is expected to be associated
+ * with the sitemap parameter <code>form-name</code>.
+ *
+ * <p>For the POST requests with mimetypes <code>text/plain</code>, <code>text/xml</code>,
+ * <code>application/xhtml+xml</code>, <code>application/xml</code> the xml data
+ * is expected to be in the body of the POST request and its length is specified
+ * by the value returned by {@link Request#getContentLength} method.
+ *
+ * <p>The StreamGenerator uses helper {@link PostInputStream} class for InputStream
+ * reading operations. At the time when Parser is reading the data out of the
+ * 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 - by the means of
+ * PostInputStream - and to return to the requestor '-1' when the
+ * number of bytes read is equal to the content length value.
+ *
  * @cocoon.sitemap.component.documentation
  * The <code>StreamGenerator</code> is a class that reads XML from a
  * request InputStream and generates SAX Events.
- * 
  * @cocoon.sitemap.component.name   stream
  * @cocoon.sitemap.component.label  content
+ * @cocoon.sitemap.component.documentation.caching No
  * @cocoon.sitemap.component.pooling.max  16
  *
- * For the POST requests with a mimetype of application/x-www-form-urlencoded,
- * or multipart/form-data the xml data is expected to be associated with the
- * sitemap parameter 'form-name'.
- *
- * For the POST requests with mimetypes: text/plain, text/xml,
- * application/xhtml+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.
- *
  * @version $Id$
  */
-public class StreamGenerator extends ServiceableGenerator
-{
+public class StreamGenerator extends ServiceableGenerator {
 
     /** The parameter holding the name associated with the xml data  **/
     public static final String FORM_NAME = "form-name";
@@ -75,8 +78,8 @@
      * All instance variables are set to <code>null</code>.
      */
     public void recycle() {
-        super.recycle();
         this.inputSource = null;
+        super.recycle();
     }
 
     /**
@@ -86,7 +89,7 @@
     throws IOException, SAXException, ProcessingException {
         SAXParser parser = null;
         int len = 0;
-        String contentType = null;
+        String contentType;
 
         Request request = ObjectModelHelper.getRequest(this.objectModel);
         try {
@@ -97,57 +100,59 @@
                     getLogger().debug("no Content-Type header - using contentType parameter: " + contentType);
                 }
                 if (contentType == null) {
-                    throw new IOException("both Content-Type header and defaultContentType parameter are not set");
+                    throw new IOException("Both Content-Type header and defaultContentType parameter are not set");
                 }
             }
+
             if (contentType.startsWith("application/x-www-form-urlencoded") ||
                     contentType.startsWith("multipart/form-data")) {
                 String parameter = parameters.getParameter(FORM_NAME, null);
                 if (parameter == null) {
-                    throw new ProcessingException(
-                        "StreamGenerator expects a sitemap parameter called '" +
-                        FORM_NAME + "' for handling form data"
-                    );
+                    throw new ProcessingException("StreamGenerator expects a sitemap parameter called '" +
+                                                  FORM_NAME + "' for handling form data");
                 }
+
                 Object xmlObject = request.get(parameter);
-                Reader xmlReader = null;
+                Reader xmlReader;
                 if (xmlObject instanceof String) {
-                    xmlReader  = new StringReader((String)xmlObject);
+                    xmlReader = new StringReader((String) xmlObject);
                 } else if (xmlObject instanceof Part) {
-                    xmlReader = new InputStreamReader(((Part)xmlObject).getInputStream());
+                    xmlReader = new InputStreamReader(((Part) xmlObject).getInputStream());
                 } else {
                     throw new ProcessingException("Unknown request object encountered named " + 
                                                   parameter + " : " + xmlObject);
-                }                
-                inputSource = new InputSource(xmlReader);
+                }
+
+                this.inputSource = new InputSource(xmlReader);
             } else if (contentType.startsWith("text/plain") ||
                     contentType.startsWith("text/xml") ||
                     contentType.startsWith("application/xhtml+xml") ||
                     contentType.startsWith("application/xml")) {
 
                 HttpServletRequest httpRequest = (HttpServletRequest) objectModel.get(HttpEnvironment.HTTP_REQUEST_OBJECT);
-                if ( httpRequest == null ) {
+                if (httpRequest == null) {
                     throw new ProcessingException("This feature is only available in an http environment.");
                 }
                 len = request.getContentLength();
-                if (len > 0) {
-                        PostInputStream anStream = new PostInputStream(httpRequest.getInputStream(), len);
-                        inputSource = new InputSource(anStream);
-                } else {
+                if (len <= 0) {
                     throw new IOException("getContentLen() == 0");
                 }
+
+                PostInputStream anStream = new PostInputStream(httpRequest.getInputStream(), len);
+                this.inputSource = new InputSource(anStream);
             } else {
                 throw new IOException("Unexpected getContentType(): " + request.getContentType());
             }
 
             if (getLogger().isDebugEnabled()) {
-                getLogger().debug("processing stream ContentType=" + contentType + " ContentLen=" + len);
+                getLogger().debug("Processing stream ContentType=" + contentType + " ContentLength=" + len);
             }
-            String charset =  getCharacterEncoding(request, contentType) ;
-            if( charset != null) {
+            String charset = getCharacterEncoding(request, contentType);
+            if (charset != null) {
                 this.inputSource.setEncoding(charset);
             }
-            parser = (SAXParser)this.manager.lookup(SAXParser.ROLE);
+
+            parser = (SAXParser) this.manager.lookup(SAXParser.ROLE);
             parser.parse(this.inputSource, super.xmlConsumer);
         } catch (IOException e) {
             getLogger().error("StreamGenerator.generate()", e);
@@ -159,71 +164,73 @@
             getLogger().error("Could not get parser", e);
             throw new ProcessingException("Exception in StreamGenerator.generate()", e);
         } finally {
-            this.manager.release( parser);
+            this.manager.release(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.
-    */
+     * Content type HTTP header can contain character encoding information,
+     * for example: <code>Content-Type: text/xml; charset=UTF-8</code>.
+     *
+     * <p>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 last resort to
+     * retrieve the passed charset value.
+     *
+     * <p>It is very common mistake to send : <code>Content-Type: text/xml; charset="UTF-8"</code>.
+     * Some containers are not filtering this mistake and the processing results in exception.
+     * This method compensates for the above mistake.
+     *
+     * <p>If contentType is null or has no charset part, <code>null</code> is returned.
+     *
+     * @param contentType value associated with Content-Type HTTP header.
+     */
     public String getCharacterEncoding(Request req, String contentType) {
-        String charencoding = null;
-        String charset = "charset=";
         if (contentType == null) {
             return null;
         }
-        int idx = contentType.indexOf(charset);
+
+        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);
+        String encoding;
+        try {
+            encoding = req.getCharacterEncoding();
+            if (encoding != null) {
+                encoding = cleanup(encoding);
+                if (getLogger().isDebugEnabled()) {
+                    getLogger().debug("Using charset from container: " + encoding);
                 }
-                getLogger().debug("charset from container clean: " + charencoding);
-                return charencoding;
-            } else {
-                return extractCharset( contentType, idx );
+
+                return encoding;
             }
-        } catch(Throwable e) {
-            // We will be there if the container do not implement getCharacterEncoding() method
-             return extractCharset( contentType, idx );
+        } catch (Throwable e) {
+            // We will be there if the container did not implement getCharacterEncoding() method
         }
-    }
 
-
-    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(";");
+        encoding = contentType.substring(idx + "charset=".length());
+        int idxEnd = encoding.indexOf(";");
         if (idxEnd != -1) {
-            charencoding = charencoding.substring(0, idxEnd);
+            encoding = encoding.substring(0, idxEnd);
         }
-        charencoding = charencoding.trim();
-        if ((charencoding.length() > 2) && (charencoding.startsWith("\""))&& (charencoding.endsWith("\""))) {
-            charencoding = charencoding.substring(1, charencoding.length() - 1);
+
+        encoding = cleanup(encoding);
+        if (getLogger().isDebugEnabled()) {
+            getLogger().debug("Using charset from header: " + encoding);
         }
-        getLogger().debug("charset from extractCharset: " + charencoding);
-        return charencoding.trim();
 
+        return encoding;
     }
-}
 
+    private String cleanup(String encoding) {
+        encoding = encoding.trim();
+        if (encoding.length() > 2 && encoding.startsWith("\"") && encoding.endsWith("\"")) {
+            encoding = encoding.substring(1, encoding.length() - 1);
+        }
+
+        return encoding;
+    }
+}