sunlabs.brazil.servlet.BServletRequest Maven / Gradle / Ivy
Show all versions of sunlabs.brazil Show documentation
/*
* BServletRequest.java
*
* Brazil project web application toolkit,
* export version: 2.3
* Copyright (c) 2001-2004 Sun Microsystems, Inc.
*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License Version
* 1.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is included as the file "license.terms",
* and also available at http://www.sun.com/
*
* The Original Code is from:
* Brazil project web application toolkit release 2.3.
* The Initial Developer of the Original Code is: drach.
* Portions created by drach are Copyright (C) Sun Microsystems, Inc.
* All Rights Reserved.
*
* Contributor(s): drach, suhler.
*
* Version: 2.3
* Created by drach on 01/06/01
* Last modified by suhler on 04/11/30 15:19:41
*
* Version Histories:
*
* 2.3 04/11/30-15:19:41 (suhler)
* fixed sccs version string
*
* 2.2 03/07/23-13:13:47 (suhler)
* - recompute content-length if html output is modified
* - don't emit the Brazil server string
* - remove the servlet context from the request.url (save the original in
* url.servlet)
*
* 2.1 02/10/01-16:39:15 (suhler)
* version change
*
* 1.6 01/08/13-09:10:45 (drach)
* Change server.props back to Properties object.
*
* 1.5 01/08/03-15:44:22 (drach)
* Add PropertiesList
*
* 1.4 01/06/11-17:06:07 (suhler)
* fix javadoc errors
*
* 1.3 01/06/05-22:38:56 (drach)
* package move
*
* 1.2 01/06/04-14:41:37 (suhler)
* package move
*
* 1.2 01/06/01-16:31:01 (Codemgr)
* SunPro Code Manager data about conflicts, renames, etc...
* Name history : 1 0 servlet/BServletRequest.java
*
* 1.1 01/06/01-16:31:00 (drach)
* date and time created 01/06/01 16:31:00 by drach
*
*/
package sunlabs.brazil.servlet;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.UnknownHostException;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sunlabs.brazil.handler.MapPage;
import sunlabs.brazil.properties.PropertiesList;
import sunlabs.brazil.server.Request;
import sunlabs.brazil.server.Server;
/**
*
* This is a subclass of Request
that is used by
* BrazilServlet
to map servlet style requests and responses
* to and from Brazil style requests.
*
* @author Steve Drach
* @version 2.3
*
* @see BServletSocket
* @see BServletServerSocket
* @see BrazilServlet
* @see sunlabs.brazil.server.Request
*/
public class BServletRequest extends Request
{
HttpServletRequest req;
HttpServletResponse res;
/**
* Created a new http request.
*
* @param server the server that owns this request.
* @param req the servlets request object
* @param res the servlets response object
*/
BServletRequest(Server server, HttpServletRequest req, HttpServletResponse res)
throws UnknownHostException, IOException
{
super(server, new BServletSocket(req, res));
this.req = req;
this.res = res;
// Need to do following to assure use of our HttpOutputStream.
try {
out = new HttpOutputStream(new BufferedOutputStream(sock.getOutputStream()));
} catch (IOException e) {}
}
/**
* Converts an HTTP request from the form encapsulated in a servlet
* request object to the form expected by Brazil handlers.
*
* @return true
if the request was successfully read and
* parsed, false
if the request was malformed.
*
* @throws IOException
* if there was an IOException reading from the socket. See
* the socket documentation for a description of socket
* exceptions.
*/
public boolean getRequest() throws IOException
{
if (server.props.get("debugProps") != null) {
PropertiesList.debug = true;
if (props != null) {
props.dump(false, "at beginning of getRequest");
}
}
/*
* Reset state.
*/
requestsLeft--;
connectionHeader = "Connection";
/* I don't think we need to do this
while ((props = server.props.getPrior()) != null) {
props.remove();
}
*/
String origUrl = req.getRequestURI().trim();
int strip = req.getContextPath().length();
url = origUrl.substring(strip);
method = req.getMethod().trim();
query = req.getQueryString();
if (query != null)
query = query.trim();
else
query = "";
protocol = req.getProtocol().trim();
headers.clear();
postData = null;
statusCode = 200;
statusPhrase = "OK";
responseHeaders.clear();
startMillis = System.currentTimeMillis();
out.bytesWritten=0;
log(Server.LOG_LOG, "Request " + requestsLeft + " " + toString());
if (protocol.equals("HTTP/1.0")) {
version = 10;
} else if (protocol.equals("HTTP/1.1")) {
version = 11;
// Should we turn off chunked transfer encoding?
} else {
sendError(505, toString(), null);
return false;
}
Enumeration names = req.getHeaderNames();
while (names.hasMoreElements()) {
String name = (String)names.nextElement();
headers.put(name, req.getHeader(name));
}
/*
* Remember POST data. "Transfer-Encoding: chunked" is not handled
* yet.
*/
String str;
str = getRequestHeader("Content-Length");
if (str != null) {
try {
postData = new byte[Integer.parseInt(str)];
} catch (Exception e) {
sendError(411, str, null);
return false;
} catch (OutOfMemoryError e) {
sendError(411, str, null);
return false;
}
in.readFully(postData);
}
str = getRequestHeader(connectionHeader);
if ("Keep-Alive".equalsIgnoreCase(str)) {
keepAlive = true;
} else if ("close".equalsIgnoreCase(str)) {
keepAlive = false;
} else if (version > 10) {
keepAlive = true;
} else {
keepAlive = false;
}
/*
* Delay initialization until we know we need these things
*/
serverProps = new PropertiesList(server.props);
props = new PropertiesList();
props.addBefore(serverProps);
props.put("url.servlet", origUrl);
return true;
}
/**
*
* Sets response code in the servlet response object.
*/
public void setStatus(int code)
{
if (code < 0)
return;
super.setStatus(code);
res.setStatus(code);
}
/**
*
* Returns the server's fully-qualified base URL. This is "http://"
* followed by the server's hostname and port.
*
* If the HTTP request header "Host" is present, it specifies the
* hostname and port that will be used instead of the server's
* internal name for itself. Due to bugs in certain browsers, when
* using the server's internal name, the port number will be elided
* if it is 80.
*
* @return The string representation of the server's URL.
*/
public String serverUrl()
{
String host = headers.get("Host");
if (host == null) {
host = server.hostName;
}
int port = req.getServerPort();
if ((host.lastIndexOf(":") < 0) && (port != 80)) {
host += ":" + port;
}
return server.protocol + "://" + host;
}
/**
*
* An HttpOutputStream
that is used by the Brazil Servlet
* adaptor to add the web application
* context path to the front of all response URI's so subsequent requests
* will be mapped to the BrazilServlet
's context. See comments
* in BrazilServlet
that describe the assumptions regarding
* the context path.
*
* @author Steve Drach
* @version 2.3, 04/11/30
*
* @see BrazilServlet
*/
public static class HttpOutputStream extends Request.HttpOutputStream {
private ByteArrayOutputStream baos;
private String contextPath;
private BServletRequest req;
public HttpOutputStream(OutputStream out) {
super(out);
}
/**
*
* If the response content type is text/html, this method
* interposes a buffer before the response stream that
* gathers all content for subsequent URI rewriting.
*/
public void sendHeaders(Request request) throws IOException {
this.req = (BServletRequest)request;
Enumeration e = request.responseHeaders.keys();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
if (name.toLowerCase().equals("server")) {
continue; // we're not the server any more
}
req.res.addHeader(name, request.responseHeaders.get(name));
}
// Need to remap URI's in HTML content
String type = request.responseHeaders.get("Content-Type");
if (type != null && type.equals("text/html")) {
baos = new ByteArrayOutputStream(request.server.bufsize);
out = new HttpOutputStream(baos);
contextPath = req.props.getProperty("context_path") + "/";
}
}
/**
*
* Remaps URI's in the buffered HTML content and the writes the
* result to the response stream.
*/
public void close() throws IOException {
if (contextPath == null) {
super.close();
return;
}
MapPage map = new MapPage(contextPath);
String s = map.convertHtml(baos.toString());
// System.err.println("Rewrote: " + map.mapCount());
req.res.setHeader("Content-Length", "" + s.length());
OutputStream out = req.sock.getOutputStream();
out.write(s.getBytes());
out.close();
}
}
public void
redirect(String url, String body)
throws IOException
{
System.out.println("Redirect to " + url);
super.redirect(url, body);
}
}