001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.reading;
018:
019: import java.io.ByteArrayInputStream;
020: import java.io.IOException;
021: import java.io.InputStreamReader;
022: import java.io.OutputStreamWriter;
023: import java.io.Reader;
024: import java.io.Writer;
025:
026: import javax.servlet.ServletContext;
027: import javax.servlet.ServletException;
028: import javax.servlet.http.HttpServletRequest;
029: import javax.servlet.http.HttpServletResponse;
030:
031: import org.apache.avalon.framework.configuration.Configurable;
032: import org.apache.avalon.framework.configuration.Configuration;
033: import org.apache.avalon.framework.configuration.ConfigurationException;
034: import org.apache.cocoon.ProcessingException;
035: import org.apache.cocoon.components.jsp.JSPEngine;
036: import org.apache.cocoon.environment.http.HttpEnvironment;
037: import org.apache.excalibur.source.Source;
038:
039: /**
040: * The <code>JSPReader</code> component is used to serve Servlet and JSP page
041: * output data in a sitemap pipeline.
042: *
043: * @author <a href="mailto:kpiroumian@flagship.ru">Konstantin Piroumian</a>
044: * @version CVS $Id: JSPReader.java 433543 2006-08-22 06:22:54Z crossley $
045: */
046: public class JSPReader extends ServiceableReader implements
047: Configurable {
048:
049: private static final int DEFAULT_BUFFER_SIZE = 8192;
050:
051: // buffer size for IO
052: private int bufferSize;
053:
054: // output encoding
055: private String outputEncoding;
056:
057: public void configure(Configuration conf)
058: throws ConfigurationException {
059: bufferSize = conf.getChild("buffer-size").getValueAsInteger(
060: DEFAULT_BUFFER_SIZE);
061: outputEncoding = conf.getChild("output-encoding")
062: .getValue(null);
063: }
064:
065: /**
066: * Generates the output from JSPEngine.
067: */
068: public void generate() throws IOException, ProcessingException {
069: if (this .source == null) {
070: throw new ProcessingException(
071: "JSPReader: source JSP is not specified");
072: }
073:
074: HttpServletResponse servletResponse = (HttpServletResponse) super .objectModel
075: .get(HttpEnvironment.HTTP_RESPONSE_OBJECT);
076: HttpServletRequest servletRequest = (HttpServletRequest) super .objectModel
077: .get(HttpEnvironment.HTTP_REQUEST_OBJECT);
078: ServletContext servletContext = (ServletContext) super .objectModel
079: .get(HttpEnvironment.HTTP_SERVLET_CONTEXT);
080:
081: // ensure that we are running in a servlet environment
082: if (servletResponse == null || servletRequest == null
083: || servletContext == null) {
084: throw new ProcessingException(
085: "JSPReader can only be used from within a Servlet environment.");
086: }
087:
088: JSPEngine engine = null;
089: Source inputSource = null;
090: Source contextSource = null;
091: try {
092: inputSource = this .resolver.resolveURI(this .source);
093: contextSource = this .resolver.resolveURI("context:/");
094:
095: String inputSourceURI = inputSource.getURI();
096: String contextSourceURI = contextSource.getURI();
097:
098: if (!inputSourceURI.startsWith(contextSourceURI)) {
099: throw new ProcessingException(
100: "You must not reference a file "
101: + "outside of the servlet context at "
102: + contextSourceURI + ".");
103: }
104:
105: String url = inputSourceURI.substring(contextSourceURI
106: .length());
107: if (url.charAt(0) != '/') {
108: url = "/" + url;
109: }
110:
111: if (getLogger().isDebugEnabled()) {
112: getLogger().debug("JSPReader executing:" + url);
113: }
114:
115: engine = (JSPEngine) super .manager.lookup(JSPEngine.ROLE);
116: byte[] bytes = engine.executeJSP(url, servletRequest,
117: servletResponse, servletContext);
118:
119: if (this .outputEncoding != null) {
120: recodeResult(bytes, this .outputEncoding);
121: } else {
122: out.write(bytes);
123: out.flush();
124: }
125:
126: bytes = null;
127: } catch (ServletException e) {
128: throw new ProcessingException(
129: "ServletException while executing JSPEngine", e);
130: } catch (IOException e) {
131: throw new ProcessingException(
132: "IOException JSPReader.generate()", e);
133: } catch (ProcessingException e) {
134: throw e;
135: } catch (Exception e) {
136: throw new ProcessingException(
137: "Exception JSPReader.generate()", e);
138: } finally {
139: super .manager.release(engine);
140: this .resolver.release(inputSource);
141: this .resolver.release(contextSource);
142: }
143: }
144:
145: private void recodeResult(byte[] bytes, String encoding)
146: throws IOException {
147: char[] buffer = new char[this .bufferSize];
148:
149: ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
150: // UTF-8 is the default encoding/contract of the JSPEngine
151: Reader reader = new InputStreamReader(bais, "UTF-8");
152: Writer writer = new OutputStreamWriter(out, encoding);
153:
154: int length = -1;
155: while ((length = reader.read(buffer)) > -1) {
156: writer.write(buffer, 0, length);
157: }
158: writer.flush();
159: }
160: }
|