KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > generation > StreamGenerator


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.generation;
17
18 import org.apache.cocoon.ProcessingException;
19 import org.apache.cocoon.ResourceNotFoundException;
20 import org.apache.cocoon.environment.ObjectModelHelper;
21 import org.apache.cocoon.environment.Request;
22 import org.apache.cocoon.environment.http.HttpEnvironment;
23 import org.apache.cocoon.servlet.multipart.Part;
24 import org.apache.cocoon.util.PostInputStream;
25 import org.apache.excalibur.xml.sax.SAXParser;
26 import org.xml.sax.InputSource JavaDoc;
27 import org.xml.sax.SAXException JavaDoc;
28
29 import javax.servlet.http.HttpServletRequest JavaDoc;
30
31 import java.io.IOException JavaDoc;
32 import java.io.InputStreamReader JavaDoc;
33 import java.io.Reader JavaDoc;
34 import java.io.StringReader JavaDoc;
35
36 /**
37  * @cocoon.sitemap.component.documentation
38  * The <code>StreamGenerator</code> is a class that reads XML from a
39  * request InputStream and generates SAX Events.
40  *
41  * @cocoon.sitemap.component.name stream
42  * @cocoon.sitemap.component.label content
43  * @cocoon.sitemap.component.logger sitemap.generator.stream
44  *
45  * @cocoon.sitemap.component.pooling.max 16
46  *
47  * For the POST requests with a mimetype of application/x-www-form-urlencoded,
48  * or multipart/form-data the xml data is expected to be associated with the
49  * sitemap parameter 'form-name'.
50  *
51  * For the POST requests with mimetypes: text/plain, text/xml,
52  * application/xml the xml data is in the body of the POST request and
53  * its length is specified by the value returned by getContentLength()
54  * method. The StreamGenerator uses helper
55  * org.apache.cocoon.util.PostInputStream class for InputStream
56  * reading operations. At the time that Parser is reading the data
57  * out of InputStream - Parser has no knowledge about the length of
58  * data to be read. The only way to signal to the Parser that all
59  * data was read from the InputStream is to control reading operation-
60  * PostInputStream--and to return to the requestor '-1' when the
61  * number of bytes read is equal to the getContentLength() value.
62  *
63  * @author <a HREF="mailto:Kinga_Dziembowski@hp.com">Kinga Dziembowski</a>
64  * @version CVS $Id: StreamGenerator.java 153376 2005-02-11 08:50:21Z cziegeler $
65  */

66 public class StreamGenerator extends ServiceableGenerator
67 {
68
69     /** The parameter holding the name associated with the xml data **/
70     public static final String JavaDoc FORM_NAME = "form-name";
71
72     /** The input source */
73     private InputSource JavaDoc inputSource;
74
75     /**
76      * Recycle this component.
77      * All instance variables are set to <code>null</code>.
78      */

79     public void recycle() {
80         super.recycle();
81         this.inputSource = null;
82     }
83
84     /**
85      * Generate XML data out of request InputStream.
86      */

87     public void generate()
88     throws IOException JavaDoc, SAXException JavaDoc, ProcessingException {
89         SAXParser parser = null;
90         int len = 0;
91         String JavaDoc contentType = null;
92
93         Request request = ObjectModelHelper.getRequest(this.objectModel);
94         try {
95             contentType = request.getContentType();
96             if (contentType == null) {
97                 contentType = parameters.getParameter("defaultContentType", null);
98                 if (getLogger().isDebugEnabled()) {
99                     getLogger().debug("no Content-Type header - using contentType parameter: " + contentType);
100                 }
101                 if (contentType == null) {
102                     throw new IOException JavaDoc("both Content-Type header and defaultContentType parameter are not set");
103                 }
104             }
105             if (contentType.startsWith("application/x-www-form-urlencoded") ||
106                     contentType.startsWith("multipart/form-data")) {
107                 String JavaDoc parameter = parameters.getParameter(FORM_NAME, null);
108                 if (parameter == null) {
109                     throw new ProcessingException(
110                         "StreamGenerator expects a sitemap parameter called '" +
111                         FORM_NAME + "' for handling form data"
112                     );
113                 }
114                 Object JavaDoc xmlObject = request.get(parameter);
115                 Reader JavaDoc xmlReader = null;
116                 if (xmlObject instanceof String JavaDoc) {
117                     xmlReader = new StringReader JavaDoc((String JavaDoc)xmlObject);
118                 } else if (xmlObject instanceof Part) {
119                     xmlReader = new InputStreamReader JavaDoc(((Part)xmlObject).getInputStream());
120                 } else {
121                     throw new ProcessingException("Unknown request object encountered named " +
122                                                   parameter + " : " + xmlObject);
123                 }
124                 inputSource = new InputSource JavaDoc(xmlReader);
125             } else if (contentType.startsWith("text/plain") ||
126                     contentType.startsWith("text/xml") ||
127                     contentType.startsWith("application/xml")) {
128
129                 HttpServletRequest JavaDoc httpRequest = (HttpServletRequest JavaDoc) objectModel.get(HttpEnvironment.HTTP_REQUEST_OBJECT);
130                 if ( httpRequest == null ) {
131                     throw new ProcessingException("This feature is only available in an http environment.");
132                 }
133                 len = request.getContentLength();
134                 if (len > 0) {
135                         PostInputStream anStream = new PostInputStream(httpRequest.getInputStream(), len);
136                         inputSource = new InputSource JavaDoc(anStream);
137                 } else {
138                     throw new IOException JavaDoc("getContentLen() == 0");
139                 }
140             } else {
141                 throw new IOException JavaDoc("Unexpected getContentType(): " + request.getContentType());
142             }
143
144             if (getLogger().isDebugEnabled()) {
145                 getLogger().debug("processing stream ContentType=" + contentType + " ContentLen=" + len);
146             }
147             String JavaDoc charset = getCharacterEncoding(request, contentType) ;
148             if( charset != null) {
149                 this.inputSource.setEncoding(charset);
150             }
151             parser = (SAXParser)this.manager.lookup(SAXParser.ROLE);
152             parser.parse(this.inputSource, super.xmlConsumer);
153         } catch (IOException JavaDoc e) {
154             getLogger().error("StreamGenerator.generate()", e);
155             throw new ResourceNotFoundException("StreamGenerator could not find resource", e);
156         } catch (SAXException JavaDoc e) {
157             getLogger().error("StreamGenerator.generate()", e);
158             throw(e);
159         } catch (Exception JavaDoc e) {
160             getLogger().error("Could not get parser", e);
161             throw new ProcessingException("Exception in StreamGenerator.generate()", e);
162         } finally {
163             this.manager.release( parser);
164         }
165     }
166
167     /**
168     * Content type HTTP header can contains character encodinf info
169     * for ex. Content-Type: text/xml; charset=UTF-8
170     * If the servlet is following spec 2.3 and higher the servlet API can be used to retrieve character encoding part of
171     * Content-Type header. Some containers can choose to not unpack charset info - the spec is not strong about it.
172     * in any case this method can be used as a latest resource to retrieve the passed charset value.
173     * <code>null</code> is returned.
174     * It is very common mistake to send : Content-Type: text/xml; charset="UTF-8".
175     * Some containers are not filtering this mistake and the processing results in exception..
176     * The getCharacterEncoding() compensates for above mistake.
177     *
178     * @param contentType value associated with Content-Type HTTP header.
179     */

180     public String JavaDoc getCharacterEncoding(Request req, String JavaDoc contentType) {
181         String JavaDoc charencoding = null;
182         String JavaDoc charset = "charset=";
183         if (contentType == null) {
184             return null;
185         }
186         int idx = contentType.indexOf(charset);
187         if (idx == -1) {
188             return null;
189         }
190         try {
191             charencoding = req.getCharacterEncoding();
192
193             if ( charencoding != null) {
194                 getLogger().debug("charset from container: " + charencoding);
195                 charencoding = charencoding.trim();
196                 if ((charencoding.length() > 2) && (charencoding.startsWith("\""))&& (charencoding.endsWith("\""))) {
197                     charencoding = charencoding.substring(1, charencoding.length() - 1);
198                 }
199                 getLogger().debug("charset from container clean: " + charencoding);
200                 return charencoding;
201             } else {
202                 return extractCharset( contentType, idx );
203             }
204         } catch(Throwable JavaDoc e) {
205             // We will be there if the container do not implement getCharacterEncoding() method
206
return extractCharset( contentType, idx );
207         }
208     }
209
210
211     protected String JavaDoc extractCharset(String JavaDoc contentType, int idx) {
212         String JavaDoc charencoding = null;
213         String JavaDoc charset = "charset=";
214
215         getLogger().debug("charset from extractCharset");
216         charencoding = contentType.substring(idx + charset.length());
217         int idxEnd = charencoding.indexOf(";");
218         if (idxEnd != -1) {
219             charencoding = charencoding.substring(0, idxEnd);
220         }
221         charencoding = charencoding.trim();
222         if ((charencoding.length() > 2) && (charencoding.startsWith("\""))&& (charencoding.endsWith("\""))) {
223             charencoding = charencoding.substring(1, charencoding.length() - 1);
224         }
225         getLogger().debug("charset from extractCharset: " + charencoding);
226         return charencoding.trim();
227
228     }
229 }
230
231
Popular Tags