You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2002/03/07 23:43:29 UTC
cvs commit: jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4 CoyoteResponse.java OutputBuffer.java
remm 02/03/07 14:43:29
Modified: coyote/src/java/org/apache/coyote Response.java
coyote/src/java/org/apache/coyote/tomcat4
CoyoteResponse.java OutputBuffer.java
Log:
- Add a new 'message' field in the response.
- Implement the Catalina response object.
Revision Changes Path
1.5 +27 -2 jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/Response.java
Index: Response.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/Response.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- Response.java 31 Jan 2002 18:42:29 -0000 1.4
+++ Response.java 7 Mar 2002 22:43:29 -0000 1.5
@@ -100,6 +100,12 @@
/**
+ * Status message.
+ */
+ protected String message = null;
+
+
+ /**
* Response headers.
*/
protected MimeHeaders headers = new MimeHeaders();
@@ -215,6 +221,22 @@
}
+ /**
+ * Get the status message.
+ */
+ public String getMessage() {
+ return message;
+ }
+
+
+ /**
+ * Set the status message.
+ */
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+
public boolean isCommitted() {
return commited;
}
@@ -279,7 +301,9 @@
locale = Constants.DEFAULT_LOCALE;
characterEncoding = Constants.DEFAULT_CHARACTER_ENCODING;
contentLength = -1;
+
status = 200;
+ message = null;
headers.clear();
// Force the PrintWriter to flush its data to the output
@@ -388,7 +412,7 @@
contentLanguage = locale.getLanguage();
// only one header !
- headers.setValue("Content-Language").setString( contentLanguage);
+ headers.setValue("Content-Language").setString(contentLanguage);
}
public String getCharacterEncoding() {
@@ -401,7 +425,7 @@
if (encoding != null) {
characterEncoding = encoding;
}
- headers.setValue("Content-Type").setString( contentType);
+ headers.setValue("Content-Type").setString(contentType);
}
public String getContentType() {
@@ -437,6 +461,7 @@
characterEncoding = Constants.DEFAULT_CHARACTER_ENCODING;
contentLength = -1;
status = 200;
+ message = null;
commited = false;
errorException = null;
errorURI = null;
1.3 +471 -27 jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteResponse.java
Index: CoyoteResponse.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteResponse.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- CoyoteResponse.java 1 Feb 2002 17:13:48 -0000 1.2
+++ CoyoteResponse.java 7 Mar 2002 22:43:29 -0000 1.3
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteResponse.java,v 1.2 2002/02/01 17:13:48 remm Exp $
- * $Revision: 1.2 $
- * $Date: 2002/02/01 17:13:48 $
+ * $Header: /home/cvs/jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteResponse.java,v 1.3 2002/03/07 22:43:29 remm Exp $
+ * $Revision: 1.3 $
+ * $Date: 2002/03/07 22:43:29 $
*
* ====================================================================
*
@@ -68,6 +68,8 @@
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
@@ -82,7 +84,12 @@
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpUtils;
+
+import org.apache.tomcat.util.http.MimeHeaders;
import org.apache.coyote.Response;
@@ -104,7 +111,7 @@
* Wrapper object for the Coyote response.
*
* @author Remy Maucherat
- * @version $Revision: 1.2 $ $Date: 2002/02/01 17:13:48 $
+ * @version $Revision: 1.3 $ $Date: 2002/03/07 22:43:29 $
*/
public class CoyoteResponse
@@ -170,8 +177,9 @@
*
* @param response The Coyote response
*/
- public void setCoyoteResponse(Response response) {
+ public void setCoyoteResponse(Response coyoteResponse) {
this.coyoteResponse = coyoteResponse;
+ outputBuffer.setResponse(coyoteResponse);
}
/**
@@ -207,6 +215,49 @@
}
+ /**
+ * The associated output buffer.
+ */
+ protected OutputBuffer outputBuffer = new OutputBuffer();
+
+
+ /**
+ * The associated output stream.
+ */
+ protected CoyoteOutputStream outputStream =
+ new CoyoteOutputStream(outputBuffer);
+
+
+ /**
+ * The associated writer.
+ */
+ protected CoyoteWriter writer = new CoyoteWriter(outputBuffer);
+
+
+ /**
+ * The application commit flag.
+ */
+ protected boolean appCommitted = false;
+
+
+ /**
+ * The included flag.
+ */
+ protected boolean included = false;
+
+
+ /**
+ * The error flag.
+ */
+ protected boolean error = false;
+
+
+ /**
+ * The set of Cookies associated with this Response.
+ */
+ protected ArrayList cookies = new ArrayList();
+
+
// --------------------------------------------------------- Public Methods
@@ -215,6 +266,11 @@
* preparation for reuse of this object.
*/
public void recycle() {
+ outputBuffer.recycle();
+ appCommitted = false;
+ included = false;
+ error = false;
+ cookies.clear();
}
@@ -225,7 +281,7 @@
* Return the number of bytes actually written to the output stream.
*/
public int getContentCount() {
- return 0;
+ return outputBuffer.getBytesWritten();
}
@@ -235,6 +291,7 @@
* @param appCommitted The new application committed flag value
*/
public void setAppCommitted(boolean appCommitted) {
+ this.appCommitted = appCommitted;
}
@@ -242,7 +299,7 @@
* Application commit flag accessor.
*/
public boolean isAppCommitted() {
- return false;
+ return (this.appCommitted || isCommitted());
}
@@ -250,7 +307,7 @@
* Return the "processing inside an include" flag.
*/
public boolean getIncluded() {
- return false;
+ return included;
}
@@ -261,6 +318,7 @@
* RequestDispatcher.include(), else <code>false</code>
*/
public void setIncluded(boolean included) {
+ this.included = included;
}
@@ -314,7 +372,7 @@
* Return the output stream associated with this Response.
*/
public OutputStream getStream() {
- return null;
+ return outputStream;
}
@@ -324,6 +382,7 @@
* @param stream The new output stream
*/
public void setStream(OutputStream stream) {
+ // This method is evil
}
@@ -333,6 +392,7 @@
* @param suspended The new suspended flag value
*/
public void setSuspended(boolean suspended) {
+ outputBuffer.setSuspended(suspended);
}
@@ -340,7 +400,7 @@
* Suspended flag accessor.
*/
public boolean isSuspended() {
- return false;
+ return outputBuffer.isSuspended();
}
@@ -348,6 +408,7 @@
* Set the error flag.
*/
public void setError() {
+ error = true;
}
@@ -355,7 +416,7 @@
* Error flag accessor.
*/
public boolean isError() {
- return false;
+ return error;
}
@@ -367,7 +428,8 @@
*/
public ServletOutputStream createOutputStream()
throws IOException {
- return null;
+ // Probably useless
+ return outputStream;
}
@@ -379,6 +441,10 @@
*/
public void finishResponse()
throws IOException {
+ // Writing leftover bytes
+ outputBuffer.close();
+ // Finishing response
+ coyoteResponse.finish();
}
@@ -410,7 +476,11 @@
* has already been used.
*/
public PrintWriter getReporter() {
- return null;
+ if (outputBuffer.isNew()) {
+ return writer;
+ } else {
+ return null;
+ }
}
@@ -424,6 +494,7 @@
*/
public void flushBuffer()
throws IOException {
+ outputBuffer.flush();
}
@@ -431,7 +502,7 @@
* Return the actual buffer size used for this Response.
*/
public int getBufferSize() {
- return 0;
+ return outputBuffer.getBufferSize();
}
@@ -452,7 +523,13 @@
*/
public ServletOutputStream getOutputStream()
throws IOException {
- return null;
+
+ if (writer != null)
+ throw new IllegalStateException
+ (sm.getString("coyoteResponse.getOutputStream.ise"));
+
+ return outputStream;
+
}
@@ -473,7 +550,13 @@
*/
public PrintWriter getWriter()
throws IOException {
- return null;
+
+ if (outputStream != null)
+ throw new IllegalStateException
+ (sm.getString("coyoteResponse.getWriter.ise"));
+
+ return writer;
+
}
@@ -481,7 +564,7 @@
* Has the output of this response already been committed?
*/
public boolean isCommitted() {
- return false;
+ return (coyoteResponse.isCommitted());
}
@@ -492,6 +575,13 @@
* been committed
*/
public void reset() {
+
+ if (included)
+ return; // Ignore any call from an included servlet
+
+ coyoteResponse.reset();
+ outputBuffer.reset();
+
}
@@ -502,6 +592,13 @@
* been committed
*/
public void resetBuffer() {
+
+ if (isCommitted())
+ throw new IllegalStateException
+ (sm.getString("coyoteResponse.resetBuffer.ise"));
+
+ outputBuffer.reset();
+
}
@@ -514,6 +611,13 @@
* output has been committed for this response
*/
public void setBufferSize(int size) {
+
+ if (isCommitted() || !outputBuffer.isNew())
+ throw new IllegalStateException
+ (sm.getString("coyoteResponse.setBufferSize.ise"));
+
+ outputBuffer.setBufferSize(size);
+
}
@@ -523,7 +627,16 @@
* @param length The new content length
*/
public void setContentLength(int length) {
-
+
+ if (isCommitted())
+ return;
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ coyoteResponse.setContentLength(length);
+
}
@@ -533,6 +646,16 @@
* @param type The new content type
*/
public void setContentType(String type) {
+
+ if (isCommitted())
+ return;
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ coyoteResponse.setContentType(type);
+
}
@@ -543,6 +666,16 @@
* @param locale The new locale
*/
public void setLocale(Locale locale) {
+
+ if (isCommitted())
+ return;
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ coyoteResponse.setLocale(locale);
+
}
@@ -554,7 +687,7 @@
* a zero-length array if no cookies have been set.
*/
public Cookie[] getCookies() {
- return null;
+ return ((Cookie[]) cookies.toArray(new Cookie[cookies.size()]));
}
@@ -567,7 +700,7 @@
* @param name Header name to look up
*/
public String getHeader(String name) {
- return null;
+ return coyoteResponse.getMimeHeaders().getHeader(name);
}
@@ -576,7 +709,15 @@
* a zero-length array if no headers have been set.
*/
public String[] getHeaderNames() {
- return null;
+
+ MimeHeaders headers = coyoteResponse.getMimeHeaders();
+ int n = headers.size();
+ String[] result = new String[n];
+ for (int i = 0; i < n; i++) {
+ result[i] = headers.getName(i).toString();
+ }
+ return result;
+
}
@@ -588,7 +729,15 @@
* @param name Header name to look up
*/
public String[] getHeaderValues(String name) {
- return null;
+
+ MimeHeaders headers = coyoteResponse.getMimeHeaders();
+ int n = headers.size();
+ String[] result = new String[n];
+ for (int i = 0; i < n; i++) {
+ result[i] = headers.getValue(i).toString();
+ }
+ return result;
+
}
@@ -597,7 +746,7 @@
* for this Response.
*/
public String getMessage() {
- return null;
+ return coyoteResponse.getMessage();
}
@@ -605,7 +754,7 @@
* Return the HTTP status code associated with this Response.
*/
public int getStatus() {
- return 0;
+ return coyoteResponse.getStatus();
}
@@ -617,6 +766,8 @@
* committed
*/
public void reset(int status, String message) {
+ reset();
+ setStatus(status, message);
}
@@ -630,6 +781,16 @@
* @param cookie Cookie to be added
*/
public void addCookie(Cookie cookie) {
+
+ if (isCommitted())
+ return;
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ cookies.add(cookie);
+
}
@@ -640,6 +801,16 @@
* @param value Date value to be set
*/
public void addDateHeader(String name, long value) {
+
+ if (isCommitted())
+ return;
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ addHeader(name, format.format(new Date(value)));
+
}
@@ -650,6 +821,16 @@
* @param value Value to be set
*/
public void addHeader(String name, String value) {
+
+ if (isCommitted())
+ return;
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ coyoteResponse.addHeader(name, value);
+
}
@@ -660,6 +841,16 @@
* @param value Integer value to be set
*/
public void addIntHeader(String name, int value) {
+
+ if (isCommitted())
+ return;
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ addHeader(name, "" + value);
+
}
@@ -669,7 +860,7 @@
* @param name Name of the header to check
*/
public boolean containsHeader(String name) {
- return false;
+ return coyoteResponse.containsHeader(name);
}
@@ -680,7 +871,15 @@
* @param url URL to be encoded
*/
public String encodeRedirectURL(String url) {
- return null;
+
+ if (isEncodeable(toAbsolute(url))) {
+ HttpServletRequest hreq =
+ (HttpServletRequest) request.getRequest();
+ return (toEncoded(url, hreq.getSession().getId()));
+ } else {
+ return (url);
+ }
+
}
@@ -705,7 +904,15 @@
* @param url URL to be encoded
*/
public String encodeURL(String url) {
- return null;
+
+ if (isEncodeable(toAbsolute(url))) {
+ HttpServletRequest hreq =
+ (HttpServletRequest) request.getRequest();
+ return (toEncoded(url, hreq.getSession().getId()));
+ } else {
+ return (url);
+ }
+
}
@@ -735,6 +942,7 @@
*/
public void sendError(int status)
throws IOException {
+ sendError(status, null);
}
@@ -750,6 +958,26 @@
*/
public void sendError(int status, String message)
throws IOException {
+
+ if (isCommitted())
+ throw new IllegalStateException
+ (sm.getString("coyoteResponse.sendError.ise"));
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ setError();
+
+ coyoteResponse.setStatus(status);
+ coyoteResponse.setMessage(message);
+
+ // Clear any data content that has been buffered
+ resetBuffer();
+
+ // Cause the response to be finished (from the application perspective)
+ setSuspended(true);
+
}
@@ -764,6 +992,30 @@
*/
public void sendRedirect(String location)
throws IOException {
+
+ if (isCommitted())
+ throw new IllegalStateException
+ (sm.getString("coyoteResponse.sendRedirect.ise"));
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ // Clear any data content that has been buffered
+ resetBuffer();
+
+ // Generate a temporary redirect to the specified location
+ try {
+ String absolute = toAbsolute(location);
+ setStatus(SC_MOVED_TEMPORARILY);
+ setHeader("Location", absolute);
+ } catch (IllegalArgumentException e) {
+ setStatus(SC_NOT_FOUND);
+ }
+
+ // Cause the response to be finished (from the application perspective)
+ setSuspended(true);
+
}
@@ -774,6 +1026,16 @@
* @param value Date value to be set
*/
public void setDateHeader(String name, long value) {
+
+ if (isCommitted())
+ return;
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ setHeader(name, format.format(new Date(value)));
+
}
@@ -784,6 +1046,16 @@
* @param value Value to be set
*/
public void setHeader(String name, String value) {
+
+ if (isCommitted())
+ return;
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ coyoteResponse.setHeader(name, value);
+
}
@@ -794,6 +1066,16 @@
* @param value Integer value to be set
*/
public void setIntHeader(String name, int value) {
+
+ if (isCommitted())
+ return;
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ setHeader(name, "" + value);
+
}
@@ -803,6 +1085,7 @@
* @param status The new HTTP status
*/
public void setStatus(int status) {
+ setStatus(status, null);
}
@@ -817,6 +1100,167 @@
* parameter.
*/
public void setStatus(int status, String message) {
+
+ if (isCommitted())
+ return;
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ coyoteResponse.setStatus(status);
+ coyoteResponse.setMessage(message);
+
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * Return <code>true</code> if the specified URL should be encoded with
+ * a session identifier. This will be true if all of the following
+ * conditions are met:
+ * <ul>
+ * <li>The request we are responding to asked for a valid session
+ * <li>The requested session ID was not received via a cookie
+ * <li>The specified URL points back to somewhere within the web
+ * application that is responding to this request
+ * </ul>
+ *
+ * @param location Absolute URL to be validated
+ */
+ protected boolean isEncodeable(String location) {
+
+ if (location == null)
+ return (false);
+
+ // Is this an intra-document reference?
+ if (location.startsWith("#"))
+ return (false);
+
+ // Are we in a valid session that is not using cookies?
+ HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
+ HttpSession session = hreq.getSession(false);
+ if (session == null)
+ return (false);
+ if (!hreq.isRequestedSessionIdFromURL())
+ return (false);
+
+ // Is this a valid absolute URL?
+ URL url = null;
+ try {
+ url = new URL(location);
+ } catch (MalformedURLException e) {
+ return (false);
+ }
+
+ // Does this URL match down to (and including) the context path?
+ if (!hreq.getScheme().equalsIgnoreCase(url.getProtocol()))
+ return (false);
+ if (!hreq.getServerName().equalsIgnoreCase(url.getHost()))
+ return (false);
+ int serverPort = hreq.getServerPort();
+ if (serverPort == -1) {
+ if ("https".equals(hreq.getScheme()))
+ serverPort = 443;
+ else
+ serverPort = 80;
+ }
+ int urlPort = url.getPort();
+ if (urlPort == -1) {
+ if ("https".equals(url.getProtocol()))
+ urlPort = 443;
+ else
+ urlPort = 80;
+ }
+ if (serverPort != urlPort)
+ return (false);
+
+ String contextPath = getContext().getPath();
+ if ((contextPath != null) && (contextPath.length() > 0)) {
+ String file = url.getFile();
+ if ((file == null) || !file.startsWith(contextPath))
+ return (false);
+ if( file.indexOf(";jsessionid=" + session.getId()) >= 0 )
+ return (false);
+ }
+
+ // This URL belongs to our web application, so it is encodeable
+ return (true);
+
+ }
+
+
+ /**
+ * Convert (if necessary) and return the absolute URL that represents the
+ * resource referenced by this possibly relative URL. If this URL is
+ * already absolute, return it unchanged.
+ *
+ * @param location URL to be (possibly) converted and then returned
+ *
+ * @exception IllegalArgumentException if a MalformedURLException is
+ * thrown when converting the relative URL to an absolute one
+ */
+ private String toAbsolute(String location) {
+
+ if (location == null)
+ return (location);
+
+ // Construct a new absolute URL if possible (cribbed from
+ // the DefaultErrorPage servlet)
+ URL url = null;
+ try {
+ url = new URL(location);
+ } catch (MalformedURLException e1) {
+ HttpServletRequest hreq =
+ (HttpServletRequest) request.getRequest();
+ String requrl = HttpUtils.getRequestURL(hreq).toString();
+ try {
+ url = new URL(new URL(requrl), location);
+ } catch (MalformedURLException e2) {
+ throw new IllegalArgumentException(location);
+ }
+ }
+ return (url.toExternalForm());
+
+ }
+
+
+ /**
+ * Return the specified URL with the specified session identifier
+ * suitably encoded.
+ *
+ * @param url URL to be encoded with the session id
+ * @param sessionId Session id to be included in the encoded URL
+ */
+ private String toEncoded(String url, String sessionId) {
+
+ if ((url == null) || (sessionId == null))
+ return (url);
+
+ String path = url;
+ String query = "";
+ String anchor = "";
+ int question = url.indexOf('?');
+ if (question >= 0) {
+ path = url.substring(0, question);
+ query = url.substring(question);
+ }
+ int pound = path.indexOf('#');
+ if (pound >= 0) {
+ anchor = path.substring(pound);
+ path = path.substring(0, pound);
+ }
+ StringBuffer sb = new StringBuffer(path);
+ if( sb.length() > 0 ) { // jsessionid can't be first.
+ sb.append(";jsessionid=");
+ sb.append(sessionId);
+ }
+ sb.append(anchor);
+ sb.append(query);
+ return (sb.toString());
+
}
1.2 +24 -3 jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/OutputBuffer.java
Index: OutputBuffer.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/OutputBuffer.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- OutputBuffer.java 7 Mar 2002 04:27:23 -0000 1.1
+++ OutputBuffer.java 7 Mar 2002 22:43:29 -0000 1.2
@@ -135,6 +135,8 @@
private Response coyoteResponse;
+ private boolean suspended = false;
+
// ----------------------------------------------------------- Constructors
@@ -180,6 +182,22 @@
}
+ /**
+ * Is the response output suspended ?
+ */
+ public boolean isSuspended() {
+ return this.suspended;
+ }
+
+
+ /**
+ * Set the suspended flag.
+ */
+ public void setSuspended(boolean suspended) {
+ this.suspended = suspended;
+ }
+
+
// --------------------------------------------------------- Public Methods
@@ -198,6 +216,7 @@
cb.recycle();
bb.recycle();
closed = false;
+ suspended = false;
if (conv!= null) {
conv.recycle();
@@ -248,6 +267,8 @@
if (debug > 2)
log("realWrite(b, " + off + ", " + cnt + ") " + coyoteResponse);
+ if (suspended)
+ return;
if (closed)
return;
if (coyoteResponse == null)
@@ -452,7 +473,7 @@
conv = (C2BConverter) encoders.get(enc);
if (conv == null) {
try {
- conv = new C2BConverter(bb,enc);
+ conv = new C2BConverter(bb, enc);
encoders.put(enc, conv);
} catch (IOException e) {
conv = (C2BConverter) encoders.get(DEFAULT_ENCODING);
@@ -506,7 +527,7 @@
public void setBufferSize(int size) {
if (size > bb.getLimit()) {// ??????
- bb.setLimit( size );
+ bb.setLimit(size);
}
}
@@ -531,7 +552,7 @@
protected void log( String s ) {
- System.out.println("OutputBuffer: " + s );
+ System.out.println("OutputBuffer: " + s);
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>