| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.catalina.ssi; |
| |
| import java.io.IOException; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| |
| import javax.servlet.ServletContext; |
| import javax.servlet.ServletOutputStream; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| import javax.servlet.http.HttpServletResponseWrapper; |
| |
| import org.apache.catalina.util.DateTool; |
| /** |
| * A HttpServletResponseWrapper, used from |
| * <code>SSIServletExternalResolver</code> |
| * |
| * @author Bip Thelin |
| * @author David Becker |
| * @version $Revision$, $Date$ |
| */ |
| public class ResponseIncludeWrapper extends HttpServletResponseWrapper { |
| /** |
| * The names of some headers we want to capture. |
| */ |
| private static final String CONTENT_TYPE = "content-type"; |
| private static final String LAST_MODIFIED = "last-modified"; |
| protected long lastModified = -1; |
| private String contentType = null; |
| |
| /** |
| * Our ServletOutputStream |
| */ |
| protected ServletOutputStream captureServletOutputStream; |
| protected ServletOutputStream servletOutputStream; |
| protected PrintWriter printWriter; |
| |
| private ServletContext context; |
| private HttpServletRequest request; |
| |
| |
| /** |
| * Initialize our wrapper with the current HttpServletResponse and |
| * ServletOutputStream. |
| * |
| * @param context The servlet context |
| * @param request The HttpServletResponse to use |
| * @param response The response to use |
| * @param captureServletOutputStream The ServletOutputStream to use |
| */ |
| public ResponseIncludeWrapper(ServletContext context, |
| HttpServletRequest request, HttpServletResponse response, |
| ServletOutputStream captureServletOutputStream) { |
| super(response); |
| this.context = context; |
| this.request = request; |
| this.captureServletOutputStream = captureServletOutputStream; |
| } |
| |
| |
| /** |
| * Flush the servletOutputStream or printWriter ( only one will be non-null ) |
| * This must be called after a requestDispatcher.include, since we can't |
| * assume that the included servlet flushed its stream. |
| */ |
| public void flushOutputStreamOrWriter() throws IOException { |
| if (servletOutputStream != null) { |
| servletOutputStream.flush(); |
| } |
| if (printWriter != null) { |
| printWriter.flush(); |
| } |
| } |
| |
| |
| /** |
| * Return a printwriter, throws and exception if a OutputStream already |
| * been returned. |
| * |
| * @return a PrintWriter object |
| * @exception java.io.IOException |
| * if the outputstream already been called |
| */ |
| public PrintWriter getWriter() throws java.io.IOException { |
| if (servletOutputStream == null) { |
| if (printWriter == null) { |
| setCharacterEncoding(getCharacterEncoding()); |
| printWriter = new PrintWriter( |
| new OutputStreamWriter(captureServletOutputStream, |
| getCharacterEncoding())); |
| } |
| return printWriter; |
| } |
| throw new IllegalStateException(); |
| } |
| |
| |
| /** |
| * Return a OutputStream, throws and exception if a printwriter already |
| * been returned. |
| * |
| * @return a OutputStream object |
| * @exception java.io.IOException |
| * if the printwriter already been called |
| */ |
| public ServletOutputStream getOutputStream() throws java.io.IOException { |
| if (printWriter == null) { |
| if (servletOutputStream == null) { |
| servletOutputStream = captureServletOutputStream; |
| } |
| return servletOutputStream; |
| } |
| throw new IllegalStateException(); |
| } |
| |
| |
| /** |
| * Returns the value of the <code>last-modified</code> header field. The |
| * result is the number of milliseconds since January 1, 1970 GMT. |
| * |
| * @return the date the resource referenced by this |
| * <code>ResponseIncludeWrapper</code> was last modified, or -1 if not |
| * known. |
| */ |
| public long getLastModified() { |
| if (lastModified == -1) { |
| // javadocs say to return -1 if date not known, if you want another |
| // default, put it here |
| return -1; |
| } |
| return lastModified; |
| } |
| |
| /** |
| * Sets the value of the <code>last-modified</code> header field. |
| * |
| * @param lastModified The number of milliseconds since January 1, 1970 GMT. |
| */ |
| public void setLastModified(long lastModified) { |
| this.lastModified = lastModified; |
| ((HttpServletResponse) getResponse()).setDateHeader(LAST_MODIFIED, |
| lastModified); |
| } |
| |
| /** |
| * Returns the value of the <code>content-type</code> header field. |
| * |
| * @return the content type of the resource referenced by this |
| * <code>ResponseIncludeWrapper</code>, or <code>null</code> if not known. |
| */ |
| public String getContentType() { |
| if (contentType == null) { |
| String url = request.getRequestURI(); |
| String mime = context.getMimeType(url); |
| if (mime != null) |
| { |
| setContentType(mime); |
| } |
| else |
| { |
| // return a safe value |
| setContentType("application/x-octet-stream"); |
| } |
| } |
| return contentType; |
| } |
| |
| /** |
| * Sets the value of the <code>content-type</code> header field. |
| * |
| * @param mime a mime type |
| */ |
| public void setContentType(String mime) { |
| contentType = mime; |
| if (contentType != null) { |
| getResponse().setContentType(contentType); |
| } |
| } |
| |
| |
| public void addDateHeader(String name, long value) { |
| super.addDateHeader(name, value); |
| String lname = name.toLowerCase(); |
| if (lname.equals(LAST_MODIFIED)) { |
| lastModified = value; |
| } |
| } |
| |
| public void addHeader(String name, String value) { |
| super.addHeader(name, value); |
| String lname = name.toLowerCase(); |
| if (lname.equals(LAST_MODIFIED)) { |
| try { |
| lastModified = DateTool.rfc1123Format.parse(value).getTime(); |
| } catch (Throwable ignore) { } |
| } else if (lname.equals(CONTENT_TYPE)) { |
| contentType = value; |
| } |
| } |
| |
| public void setDateHeader(String name, long value) { |
| super.setDateHeader(name, value); |
| String lname = name.toLowerCase(); |
| if (lname.equals(LAST_MODIFIED)) { |
| lastModified = value; |
| } |
| } |
| |
| public void setHeader(String name, String value) { |
| super.setHeader(name, value); |
| String lname = name.toLowerCase(); |
| if (lname.equals(LAST_MODIFIED)) { |
| try { |
| lastModified = DateTool.rfc1123Format.parse(value).getTime(); |
| } catch (Throwable ignore) { } |
| } |
| else if (lname.equals(CONTENT_TYPE)) |
| { |
| contentType = value; |
| } |
| } |
| } |