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.environment.commandline;
018:
019: import org.apache.avalon.framework.logger.Logger;
020: import org.apache.cocoon.CascadingIOException;
021: import org.apache.cocoon.Constants;
022: import org.apache.cocoon.ProcessingException;
023: import org.apache.cocoon.components.source.SourceUtil;
024: import org.apache.cocoon.environment.AbstractEnvironment;
025: import org.apache.cocoon.environment.Redirector;
026: import org.apache.excalibur.source.Source;
027: import org.apache.excalibur.source.SourceException;
028: import org.xml.sax.SAXException;
029:
030: import java.io.File;
031: import java.io.IOException;
032: import java.io.InputStream;
033: import java.io.OutputStream;
034: import java.net.MalformedURLException;
035:
036: /**
037: * This environment is used to save the requested file to disk.
038: *
039: * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
040: * @version $Id: AbstractCommandLineEnvironment.java 433543 2006-08-22 06:22:54Z crossley $
041: */
042:
043: public abstract class AbstractCommandLineEnvironment extends
044: AbstractEnvironment implements Redirector {
045:
046: protected String contentType;
047: protected int contentLength;
048: protected boolean hasRedirected = false;
049: protected int statusCode;
050:
051: public AbstractCommandLineEnvironment(String uri, String view,
052: File context, OutputStream stream, Logger log)
053: throws MalformedURLException {
054: super (uri, view, context);
055: this .enableLogging(log);
056: this .outputStream = stream;
057: this .statusCode = 0;
058: }
059:
060: /**
061: * Redirect the client to a new URL
062: */
063: public void redirect(boolean sessionmode, String newURL)
064: throws IOException {
065:
066: this .hasRedirected = true;
067:
068: if (sessionmode) {
069: CommandLineSession.getSession(true);
070: }
071:
072: // fix all urls created with request.getScheme()+... etc.
073: if (newURL.startsWith("cli:/")) {
074: int pos = newURL.indexOf('/', 6);
075: newURL = newURL.substring(pos + 1);
076: }
077:
078: // fix all relative urls to use to cocoon: protocol
079: if (newURL.indexOf(":") == -1) {
080: newURL = "cocoon:/" + newURL;
081: }
082:
083: // FIXME: this is a hack for the links view
084: if (newURL.startsWith("cocoon:") && this .getView() != null
085: && this .getView().equals(Constants.LINK_VIEW)) {
086:
087: // as the internal cocoon protocol is used the last
088: // serializer is removed from it! And therefore
089: // the LinkSerializer is not used.
090: // so we create one without Avalon...
091: org.apache.cocoon.serialization.LinkSerializer ls = new org.apache.cocoon.serialization.LinkSerializer();
092: ls.setOutputStream(this .outputStream);
093:
094: Source redirectSource = null;
095: try {
096: redirectSource = this .resolveURI(newURL);
097: SourceUtil.parse(this .manager, redirectSource, ls);
098: } catch (SourceException se) {
099: throw new CascadingIOException(
100: "SourceException: " + se, se);
101: } catch (SAXException se) {
102: throw new CascadingIOException("SAXException: " + se,
103: se);
104: } catch (ProcessingException pe) {
105: throw new CascadingIOException("ProcessingException: "
106: + pe, pe);
107: } finally {
108: this .release(redirectSource);
109: }
110: } else {
111: Source redirectSource = null;
112: try {
113: redirectSource = this .resolveURI(newURL);
114: InputStream is = redirectSource.getInputStream();
115: byte[] buffer = new byte[8192];
116: int length = -1;
117:
118: while ((length = is.read(buffer)) > -1) {
119: this .outputStream.write(buffer, 0, length);
120: }
121: } catch (SourceException se) {
122: throw new CascadingIOException(
123: "SourceException: " + se, se);
124: } finally {
125: this .release(redirectSource);
126: }
127: }
128: }
129:
130: public void sendStatus(int sc) {
131: setStatus(sc);
132: this .hasRedirected = true;
133: }
134:
135: public boolean hasRedirected() {
136: return this .hasRedirected;
137: }
138:
139: /**
140: * Set the StatusCode
141: */
142: public void setStatus(int statusCode) {
143: this .statusCode = statusCode;
144: }
145:
146: /**
147: * Get the StatusCode
148: */
149: public int getStatus() {
150: return statusCode;
151: }
152:
153: /**
154: * Set the ContentType
155: */
156: public void setContentType(String contentType) {
157: this .contentType = contentType;
158: }
159:
160: /**
161: * Set the ContentLength
162: */
163: public void setContentLength(int contentLength) {
164: this .contentLength = contentLength;
165: }
166:
167: /**
168: * Get the ContentType
169: */
170: public String getContentType() {
171: return this .contentType;
172: }
173:
174: /**
175: * Always return <code>true</code>.
176: */
177: public boolean isExternal() {
178: return true;
179: }
180:
181: /**
182: * Return an OutputStream, but allow it to be null for when
183: * the pipeline is being streamed to the provided SAX
184: * content handler (using CocoonBean)
185: */
186: public OutputStream getOutputStream(int bufferSize)
187: throws IOException {
188: if (this.outputStream == null) {
189: return null;
190: } else {
191: return super.getOutputStream(bufferSize);
192: }
193: }
194: }
|