Author: costin
Date: Sun Nov 20 10:19:56 2005
New Revision: 345767
URL: http://svn.apache.org/viewcvs?rev=345767&view=rev
Log:
Remove even more dups. It seems the apr and non-apr were not actually in
sync, there are at least 2 places where extra SecurityManager magic was
used in non-apr.
Modified:
tomcat/sandbox/java/org/apache/coyote/http11/Http11AprProcessor.java
tomcat/sandbox/java/org/apache/coyote/http11/Http11Processor.java
tomcat/sandbox/java/org/apache/coyote/http11/InternalAprInputBuffer.java
tomcat/sandbox/java/org/apache/coyote/http11/InternalInputBuffer.java
Modified: tomcat/sandbox/java/org/apache/coyote/http11/Http11AprProcessor.java
URL:
http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/coyote/http11/Http11AprProcessor.java?rev=345767&r1=345766&r2=345767&view=diff
==============================================================================
--- tomcat/sandbox/java/org/apache/coyote/http11/Http11AprProcessor.java
(original)
+++ tomcat/sandbox/java/org/apache/coyote/http11/Http11AprProcessor.java Sun
Nov 20 10:19:56 2005
@@ -19,12 +19,11 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
-import java.net.InetAddress;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
import org.apache.coyote.ActionCode;
import org.apache.coyote.ActionHook;
@@ -32,6 +31,7 @@
import org.apache.coyote.Request;
import org.apache.coyote.RequestInfo;
import org.apache.coyote.Response;
+import org.apache.coyote.http11.filters.BufferedInputFilter;
import org.apache.coyote.http11.filters.ChunkedInputFilter;
import org.apache.coyote.http11.filters.ChunkedOutputFilter;
import org.apache.coyote.http11.filters.GzipOutputFilter;
@@ -40,7 +40,6 @@
import org.apache.coyote.http11.filters.SavedRequestInputFilter;
import org.apache.coyote.http11.filters.VoidInputFilter;
import org.apache.coyote.http11.filters.VoidOutputFilter;
-import org.apache.coyote.http11.filters.BufferedInputFilter;
import org.apache.tomcat.jni.Address;
import org.apache.tomcat.jni.SSL;
import org.apache.tomcat.jni.SSLSocket;
@@ -64,20 +63,7 @@
*/
public class Http11AprProcessor extends Http11Processor implements ActionHook {
-
- /**
- * Logger.
- */
- protected static org.apache.commons.logging.Log log
- =
org.apache.commons.logging.LogFactory.getLog(Http11AprProcessor.class);
-
- /**
- * The string manager for this package.
- */
- protected static StringManager sm =
- StringManager.getManager(Constants.Package);
-
-
+
// ----------------------------------------------------------- Constructors
@@ -92,643 +78,52 @@
}
inputBuffer = new InternalAprInputBuffer(request, headerBufferSize,
readTimeout);
- request.setInputBuffer(inputBuffer);
-
- response = new Response();
- response.setHook(this);
- outputBuffer = new InternalAprOutputBuffer(response, headerBufferSize);
- response.setOutputBuffer(outputBuffer);
- request.setResponse(response);
-
- ssl = !"off".equalsIgnoreCase(endpoint.getSSLEngine());
-
- initializeFilters();
-
- // Cause loading of HexUtils
- int foo = HexUtils.DEC[0];
-
- // Cause loading of FastHttpDateFormat
- FastHttpDateFormat.getCurrentDate();
-
- }
-
-
- // ----------------------------------------------------- Instance Variables
-
-
- /**
- * Associated adapter.
- */
- protected Adapter adapter = null;
-
-
- /**
- * Request object.
- */
- protected Request request = null;
-
-
- /**
- * Response object.
- */
- protected Response response = null;
-
-
- /**
- * Input.
- */
- protected InternalAprInputBuffer inputBuffer = null;
-
-
- /**
- * Output.
- */
- protected InternalAprOutputBuffer outputBuffer = null;
-
-
- /**
- * State flag.
- */
- protected boolean started = false;
-
-
- /**
- * Error flag.
- */
- protected boolean error = false;
-
-
- /**
- * Keep-alive.
- */
- protected boolean keepAlive = true;
-
-
- /**
- * HTTP/1.1 flag.
- */
- protected boolean http11 = true;
-
-
- /**
- * HTTP/0.9 flag.
- */
- protected boolean http09 = false;
-
-
- /**
- * Sendfile data.
- */
- protected AprEndpoint.SendfileData sendfileData = null;
-
-
- /**
- * Content delimitator for the request (if false, the connection will
- * be closed at the end of the request).
- */
- protected boolean contentDelimitation = true;
-
-
- /**
- * Is there an expectation ?
- */
- protected boolean expectation = false;
-
-
- /**
- * List of restricted user agents.
- */
- protected Pattern[] restrictedUserAgents = null;
-
-
- /**
- * Maximum number of Keep-Alive requests to honor.
- */
- protected int maxKeepAliveRequests = -1;
-
-
- /**
- * SSL enabled ?
- */
- protected boolean ssl = false;
-
-
- /**
- * Socket associated with the current connection.
- */
- protected long socket;
-
-
- /**
- * Remote Address associated with the current connection.
- */
- protected String remoteAddr = null;
-
-
- /**
- * Remote Host associated with the current connection.
- */
- protected String remoteHost = null;
-
-
- /**
- * Local Host associated with the current connection.
- */
- protected String localName = null;
-
-
-
- /**
- * Local port to which the socket is connected
- */
- protected int localPort = -1;
-
-
- /**
- * Remote port to which the socket is connected
- */
- protected int remotePort = -1;
-
-
- /**
- * The local Host address.
- */
- protected String localAddr = null;
-
-
- /**
- * Maximum timeout on uploads. 5 minutes as in Apache HTTPD server.
- */
- protected int timeout = 300000;
-
-
- /**
- * Flag to disable setting a different time-out on uploads.
- */
- protected boolean disableUploadTimeout = false;
-
-
- /**
- * Allowed compression level.
- */
- protected int compressionLevel = 0;
-
-
- /**
- * Minimum contentsize to make compression.
- */
- protected int compressionMinSize = 2048;
-
-
- /**
- * Socket buffering.
- */
- protected int socketBuffer = -1;
-
-
- /**
- * Max save post size.
- */
- protected int maxSavePostSize = 4 * 1024;
-
-
- /**
- * List of user agents to not use gzip with
- */
- protected Pattern noCompressionUserAgents[] = null;
-
- /**
- * List of MIMES which could be gzipped
- */
- protected String[] compressableMimeTypes =
- { "text/html", "text/xml", "text/plain" };
-
-
- /**
- * Host name (used to avoid useless B2C conversion on the host name).
- */
- protected char[] hostNameC = new char[0];
-
-
- /**
- * Associated endpoint.
- */
- protected AprEndpoint endpoint;
-
-
- /**
- * Allow a customized the server header for the tin-foil hat folks.
- */
- protected String server = null;
-
-
- // ------------------------------------------------------------- Properties
-
-
- /**
- * Return compression level.
- */
- public String getCompression() {
- switch (compressionLevel) {
- case 0:
- return "off";
- case 1:
- return "on";
- case 2:
- return "force";
- }
- return "off";
- }
-
-
- /**
- * Set compression level.
- */
- public void setCompression(String compression) {
- if (compression.equals("on")) {
- this.compressionLevel = 1;
- } else if (compression.equals("force")) {
- this.compressionLevel = 2;
- } else if (compression.equals("off")) {
- this.compressionLevel = 0;
- } else {
- try {
- // Try to parse compression as an int, which would give the
- // minimum compression size
- compressionMinSize = Integer.parseInt(compression);
- this.compressionLevel = 1;
- } catch (Exception e) {
- this.compressionLevel = 0;
- }
- }
- }
-
- /**
- * Set Minimum size to trigger compression.
- */
- public void setCompressionMinSize(int compressionMinSize) {
- this.compressionMinSize = compressionMinSize;
- }
-
-
- /**
- * Add user-agent for which gzip compression didn't works
- * The user agent String given will be exactly matched
- * to the user-agent header submitted by the client.
- *
- * @param userAgent user-agent string
- */
- public void addNoCompressionUserAgent(String userAgent) {
- try {
- Pattern nRule = Pattern.compile(userAgent);
- noCompressionUserAgents =
- addREArray(noCompressionUserAgents, nRule);
- } catch (PatternSyntaxException pse) {
- log.error(sm.getString("http11processor.regexp.error", userAgent),
pse);
- }
- }
-
-
- /**
- * Set no compression user agent list (this method is best when used with
- * a large number of connectors, where it would be better to have all of
- * them referenced a single array).
- */
- public void setNoCompressionUserAgents(Pattern[] noCompressionUserAgents) {
- this.noCompressionUserAgents = noCompressionUserAgents;
- }
-
-
- /**
- * Set no compression user agent list.
- * List contains users agents separated by ',' :
- *
- * ie: "gorilla,desesplorer,tigrus"
- */
- public void setNoCompressionUserAgents(String noCompressionUserAgents) {
- if (noCompressionUserAgents != null) {
- StringTokenizer st = new StringTokenizer(noCompressionUserAgents,
",");
-
- while (st.hasMoreTokens()) {
- addNoCompressionUserAgent(st.nextToken().trim());
- }
- }
- }
-
- /**
- * Add a mime-type which will be compressable
- * The mime-type String will be exactly matched
- * in the response mime-type header .
- *
- * @param mimeType mime-type string
- */
- public void addCompressableMimeType(String mimeType) {
- compressableMimeTypes =
- addStringArray(compressableMimeTypes, mimeType);
- }
-
-
- /**
- * Set compressable mime-type list (this method is best when used with
- * a large number of connectors, where it would be better to have all of
- * them referenced a single array).
- */
- public void setCompressableMimeTypes(String[] compressableMimeTypes) {
- this.compressableMimeTypes = compressableMimeTypes;
- }
-
-
- /**
- * Set compressable mime-type list
- * List contains users agents separated by ',' :
- *
- * ie: "text/html,text/xml,text/plain"
- */
- public void setCompressableMimeTypes(String compressableMimeTypes) {
- if (compressableMimeTypes != null) {
- StringTokenizer st = new StringTokenizer(compressableMimeTypes,
",");
-
- while (st.hasMoreTokens()) {
- addCompressableMimeType(st.nextToken().trim());
- }
- }
- }
-
-
- /**
- * Return the list of restricted user agents.
- */
- public String[] findCompressableMimeTypes() {
- return (compressableMimeTypes);
- }
-
-
-
- // --------------------------------------------------------- Public Methods
-
-
- /**
- * Add input or output filter.
- *
- * @param className class name of the filter
- */
- protected void addFilter(String className) {
- try {
- Class clazz = Class.forName(className);
- Object obj = clazz.newInstance();
- if (obj instanceof InputFilter) {
- inputBuffer.addFilter((InputFilter) obj);
- } else if (obj instanceof OutputFilter) {
- outputBuffer.addFilter((OutputFilter) obj);
- } else {
- log.warn(sm.getString("http11processor.filter.unknown",
className));
- }
- } catch (Exception e) {
- log.error(sm.getString("http11processor.filter.error", className),
e);
- }
- }
-
-
- /**
- * General use method
- *
- * @param sArray the StringArray
- * @param value string
- */
- private String[] addStringArray(String sArray[], String value) {
- String[] result = null;
- if (sArray == null) {
- result = new String[1];
- result[0] = value;
- }
- else {
- result = new String[sArray.length + 1];
- for (int i = 0; i < sArray.length; i++)
- result[i] = sArray[i];
- result[sArray.length] = value;
- }
- return result;
- }
-
-
- /**
- * General use method
- *
- * @param rArray the REArray
- * @param value Obj
- */
- private Pattern[] addREArray(Pattern rArray[], Pattern value) {
- Pattern[] result = null;
- if (rArray == null) {
- result = new Pattern[1];
- result[0] = value;
- }
- else {
- result = new Pattern[rArray.length + 1];
- for (int i = 0; i < rArray.length; i++)
- result[i] = rArray[i];
- result[rArray.length] = value;
- }
- return result;
- }
-
-
- /**
- * General use method
- *
- * @param sArray the StringArray
- * @param value string
- */
- private boolean inStringArray(String sArray[], String value) {
- for (int i = 0; i < sArray.length; i++) {
- if (sArray[i].equals(value)) {
- return true;
- }
- }
- return false;
- }
-
-
- /**
- * Checks if any entry in the string array starts with the specified value
- *
- * @param sArray the StringArray
- * @param value string
- */
- private boolean startsWithStringArray(String sArray[], String value) {
- if (value == null)
- return false;
- for (int i = 0; i < sArray.length; i++) {
- if (value.startsWith(sArray[i])) {
- return true;
- }
- }
- return false;
- }
-
-
- /**
- * Add restricted user-agent (which will downgrade the connector
- * to HTTP/1.0 mode). The user agent String given will be matched
- * via regexp to the user-agent header submitted by the client.
- *
- * @param userAgent user-agent string
- */
- public void addRestrictedUserAgent(String userAgent) {
- try {
- Pattern nRule = Pattern.compile(userAgent);
- restrictedUserAgents = addREArray(restrictedUserAgents, nRule);
- } catch (PatternSyntaxException pse) {
- log.error(sm.getString("http11processor.regexp.error", userAgent),
pse);
- }
- }
-
-
- /**
- * Set restricted user agent list (this method is best when used with
- * a large number of connectors, where it would be better to have all of
- * them referenced a single array).
- */
- public void setRestrictedUserAgents(Pattern[] restrictedUserAgents) {
- this.restrictedUserAgents = restrictedUserAgents;
- }
-
-
- /**
- * Set restricted user agent list (which will downgrade the connector
- * to HTTP/1.0 mode). List contains users agents separated by ',' :
- *
- * ie: "gorilla,desesplorer,tigrus"
- */
- public void setRestrictedUserAgents(String restrictedUserAgents) {
- if (restrictedUserAgents != null) {
- StringTokenizer st =
- new StringTokenizer(restrictedUserAgents, ",");
- while (st.hasMoreTokens()) {
- addRestrictedUserAgent(st.nextToken().trim());
- }
- }
- }
-
-
- /**
- * Return the list of restricted user agents.
- */
- public String[] findRestrictedUserAgents() {
- String[] sarr = new String [restrictedUserAgents.length];
-
- for (int i = 0; i < restrictedUserAgents.length; i++)
- sarr[i] = restrictedUserAgents[i].toString();
-
- return (sarr);
- }
-
-
- /**
- * Set the maximum number of Keep-Alive requests to honor.
- * This is to safeguard from DoS attacks. Setting to a negative
- * value disables the check.
- */
- public void setMaxKeepAliveRequests(int mkar) {
- maxKeepAliveRequests = mkar;
- }
-
-
- /**
- * Return the number of Keep-Alive requests that we will honor.
- */
- public int getMaxKeepAliveRequests() {
- return maxKeepAliveRequests;
- }
-
-
- /**
- * Set the maximum size of a POST which will be buffered in SSL mode.
- */
- public void setMaxSavePostSize(int msps) {
- maxSavePostSize = msps;
- }
-
-
- /**
- * Return the maximum size of a POST which will be buffered in SSL mode.
- */
- public int getMaxSavePostSize() {
- return maxSavePostSize;
- }
+ request.setInputBuffer(inputBuffer);
+ response = new Response();
+ response.setHook(this);
+ outputBuffer = new InternalAprOutputBuffer(response, headerBufferSize);
+ response.setOutputBuffer(outputBuffer);
+ request.setResponse(response);
+
+ ssl = !"off".equalsIgnoreCase(endpoint.getSSLEngine());
- /**
- * Set the flag to control upload time-outs.
- */
- public void setDisableUploadTimeout(boolean isDisabled) {
- disableUploadTimeout = isDisabled;
- }
+ initializeFilters();
- /**
- * Get the flag that controls upload time-outs.
- */
- public boolean getDisableUploadTimeout() {
- return disableUploadTimeout;
- }
+ // Cause loading of HexUtils
+ int foo = HexUtils.DEC[0];
- /**
- * Set the socket buffer flag.
- */
- public void setSocketBuffer(int socketBuffer) {
- this.socketBuffer = socketBuffer;
- outputBuffer.setSocketBuffer(socketBuffer);
- }
+ // Cause loading of FastHttpDateFormat
+ FastHttpDateFormat.getCurrentDate();
- /**
- * Get the socket buffer flag.
- */
- public int getSocketBuffer() {
- return socketBuffer;
}
- /**
- * Set the upload timeout.
- */
- public void setTimeout( int timeouts ) {
- timeout = timeouts ;
- }
+ // ----------------------------------------------------- Instance Variables
/**
- * Get the upload timeout.
+ * Sendfile data.
*/
- public int getTimeout() {
- return timeout;
- }
+ protected AprEndpoint.SendfileData sendfileData = null;
/**
- * Set the server header name.
+ * SSL enabled ?
*/
- public void setServer( String server ) {
- if (server==null || server.equals("")) {
- this.server = null;
- } else {
- this.server = server;
- }
- }
+ protected boolean ssl = false;
+
/**
- * Get the server header name.
+ * Socket associated with the current connection.
*/
- public String getServer() {
- return server;
- }
+ protected long socket;
- /** Get the request associated with this processor.
- *
- * @return The request
+ /**
+ * Associated endpoint.
*/
- public Request getRequest() {
- return request;
- }
+ //protected AprEndpoint endpoint;
+ // ------------------------------------------------------------- Properties
/**
* Process pipelined HTTP requests using the specified input and output
* streams.
@@ -752,8 +147,8 @@
// Setting up the socket
this.socket = socket;
- inputBuffer.setSocket(socket);
- outputBuffer.setSocket(socket);
+ ((InternalAprInputBuffer)inputBuffer).setSocket(socket);
+ ((InternalAprOutputBuffer)outputBuffer).setSocket(socket);
// Error flag
error = false;
@@ -763,7 +158,7 @@
long soTimeout = endpoint.getSoTimeout();
int limit = 0;
- if (endpoint.getFirstReadTimeout() > 0) {
+ if (((AprEndpoint)endpoint).getFirstReadTimeout() > 0) {
limit = endpoint.getMaxThreads() / 2;
}
@@ -784,7 +179,7 @@
// and the method should return true
openSocket = true;
// Add the socket to the poller
- endpoint.getPoller().add(socket);
+ ((AprEndpoint)endpoint).getPoller().add(socket);
break;
}
request.setStartTime(System.currentTimeMillis());
@@ -894,7 +289,7 @@
if (sendfileData != null) {
sendfileData.socket = socket;
sendfileData.keepAlive = keepAlive;
- if (!endpoint.getSendfile().add(sendfileData)) {
+ if (!((AprEndpoint)endpoint).getSendfile().add(sendfileData)) {
openSocket = true;
break;
}
@@ -915,92 +310,10 @@
// ----------------------------------------------------- ActionHook Methods
-
- /**
- * Send an action to the connector.
- *
- * @param actionCode Type of the action
- * @param param Action parameter
- */
- public void action(ActionCode actionCode, Object param) {
-
- if (actionCode == ActionCode.ACTION_COMMIT) {
- // Commit current response
-
- if (response.isCommitted())
- return;
-
- // Validate and write response headers
- prepareResponse();
- try {
- outputBuffer.commit();
- } catch (IOException e) {
- // Set error flag
- error = true;
- }
-
- } else if (actionCode == ActionCode.ACTION_ACK) {
-
- // Acknowlege request
-
- // Send a 100 status back if it makes sense (response not committed
- // yet, and client specified an expectation for 100-continue)
-
- if ((response.isCommitted()) || !expectation)
- return;
-
- inputBuffer.setSwallowInput(true);
- try {
- outputBuffer.sendAck();
- } catch (IOException e) {
- // Set error flag
- error = true;
- }
-
- } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) {
-
- try {
- outputBuffer.flush();
- } catch (IOException e) {
- // Set error flag
- error = true;
- response.setErrorException(e);
- }
-
- } else if (actionCode == ActionCode.ACTION_CLOSE) {
- // Close
-
- // End the processing of the current request, and stop any further
- // transactions with the client
-
- try {
- outputBuffer.endRequest();
- } catch (IOException e) {
- // Set error flag
- error = true;
- }
-
- } else if (actionCode == ActionCode.ACTION_RESET) {
-
- // Reset response
-
- // Note: This must be called before the response is committed
-
- outputBuffer.reset();
-
- } else if (actionCode == ActionCode.ACTION_CUSTOM) {
-
- // Do nothing
-
- } else if (actionCode == ActionCode.ACTION_START) {
-
- started = true;
-
- } else if (actionCode == ActionCode.ACTION_STOP) {
-
- started = false;
-
- } else if (actionCode == ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE) {
+
+ protected void endpointAction(ActionCode actionCode, Object param) {
+ if (actionCode == ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE) {
+
// Get remote host address
if (remoteAddr == null) {
@@ -1167,43 +480,10 @@
}
}
- } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) {
- ByteChunk body = (ByteChunk) param;
-
- InputFilter savedBody = new SavedRequestInputFilter(body);
- savedBody.setRequest(request);
-
- InternalInputBuffer internalBuffer = (InternalInputBuffer)
- request.getInputBuffer();
- internalBuffer.addActiveFilter(savedBody);
}
}
-
- // ------------------------------------------------------ Connector Methods
-
-
- /**
- * Set the associated adapter.
- *
- * @param adapter the new adapter
- */
- public void setAdapter(Adapter adapter) {
- this.adapter = adapter;
- }
-
-
- /**
- * Get the associated adapter.
- *
- * @return the associated adapter
- */
- public Adapter getAdapter() {
- return adapter;
- }
-
-
// ------------------------------------------------------ Protected Methods
@@ -1211,356 +491,28 @@
* After reading the request headers, we have to setup the request filters.
*/
protected void prepareRequest() {
-
- http11 = true;
- http09 = false;
- contentDelimitation = false;
- expectation = false;
+ super.prepareRequest();
+
sendfileData = null;
- if (ssl) {
- request.scheme().setString("https");
- }
- MessageBytes protocolMB = request.protocol();
- if (protocolMB.equals(Constants.HTTP_11)) {
- http11 = true;
- protocolMB.setString(Constants.HTTP_11);
- } else if (protocolMB.equals(Constants.HTTP_10)) {
- http11 = false;
- keepAlive = false;
- protocolMB.setString(Constants.HTTP_10);
- } else if (protocolMB.equals("")) {
- // HTTP/0.9
- http09 = true;
- http11 = false;
- keepAlive = false;
- } else {
- // Unsupported protocol
- http11 = false;
- error = true;
- // Send 505; Unsupported HTTP version
- response.setStatus(505);
- }
-
- MessageBytes methodMB = request.method();
- if (methodMB.equals(Constants.GET)) {
- methodMB.setString(Constants.GET);
- } else if (methodMB.equals(Constants.POST)) {
- methodMB.setString(Constants.POST);
- }
-
- MimeHeaders headers = request.getMimeHeaders();
-
- // Check connection header
- MessageBytes connectionValueMB = headers.getValue("connection");
- if (connectionValueMB != null) {
- ByteChunk connectionValueBC = connectionValueMB.getByteChunk();
- if (findBytes(connectionValueBC, Constants.CLOSE_BYTES) != -1) {
- keepAlive = false;
- } else if (findBytes(connectionValueBC,
- Constants.KEEPALIVE_BYTES) != -1) {
- keepAlive = true;
- }
- }
-
- MessageBytes expectMB = null;
- if (http11)
- expectMB = headers.getValue("expect");
- if ((expectMB != null)
- && (expectMB.indexOfIgnoreCase("100-continue", 0) != -1)) {
- inputBuffer.setSwallowInput(false);
- expectation = true;
- }
-
- // Check user-agent header
- if ((restrictedUserAgents != null) && ((http11) || (keepAlive))) {
- MessageBytes userAgentValueMB = headers.getValue("user-agent");
- // Check in the restricted list, and adjust the http11
- // and keepAlive flags accordingly
- if(userAgentValueMB != null) {
- String userAgentValue = userAgentValueMB.toString();
- for (int i = 0; i < restrictedUserAgents.length; i++) {
- if
(restrictedUserAgents[i].matcher(userAgentValue).matches()) {
- http11 = false;
- keepAlive = false;
- break;
- }
- }
- }
- }
-
- // Check for a full URI (including protocol://host:port/)
- ByteChunk uriBC = request.requestURI().getByteChunk();
- if (uriBC.startsWithIgnoreCase("http", 0)) {
-
- int pos = uriBC.indexOf("://", 0, 3, 4);
- int uriBCStart = uriBC.getStart();
- int slashPos = -1;
- if (pos != -1) {
- byte[] uriB = uriBC.getBytes();
- slashPos = uriBC.indexOf('/', pos + 3);
- if (slashPos == -1) {
- slashPos = uriBC.getLength();
- // Set URI as "/"
- request.requestURI().setBytes
- (uriB, uriBCStart + pos + 1, 1);
- } else {
- request.requestURI().setBytes
- (uriB, uriBCStart + slashPos,
- uriBC.getLength() - slashPos);
- }
- MessageBytes hostMB = headers.setValue("host");
- hostMB.setBytes(uriB, uriBCStart + pos + 3,
- slashPos - pos - 3);
- }
-
- }
-
- // Input filter setup
- InputFilter[] inputFilters = inputBuffer.getFilters();
-
- // Parse transfer-encoding header
- MessageBytes transferEncodingValueMB = null;
- if (http11)
- transferEncodingValueMB = headers.getValue("transfer-encoding");
- if (transferEncodingValueMB != null) {
- String transferEncodingValue = transferEncodingValueMB.toString();
- // Parse the comma separated list. "identity" codings are ignored
- int startPos = 0;
- int commaPos = transferEncodingValue.indexOf(',');
- String encodingName = null;
- while (commaPos != -1) {
- encodingName = transferEncodingValue.substring
- (startPos, commaPos).toLowerCase().trim();
- if (!addInputFilter(inputFilters, encodingName)) {
- // Unsupported transfer encoding
- error = true;
- // 501 - Unimplemented
- response.setStatus(501);
- }
- startPos = commaPos + 1;
- commaPos = transferEncodingValue.indexOf(',', startPos);
- }
- encodingName = transferEncodingValue.substring(startPos)
- .toLowerCase().trim();
- if (!addInputFilter(inputFilters, encodingName)) {
- // Unsupported transfer encoding
- error = true;
- // 501 - Unimplemented
- response.setStatus(501);
- }
- }
-
- // Parse content-length header
- long contentLength = request.getContentLengthLong();
- if (contentLength >= 0 && !contentDelimitation) {
- inputBuffer.addActiveFilter
- (inputFilters[Constants.IDENTITY_FILTER]);
- contentDelimitation = true;
- }
-
- MessageBytes valueMB = headers.getValue("host");
-
- // Check host header
- if (http11 && (valueMB == null)) {
- error = true;
- // 400 - Bad request
- response.setStatus(400);
- }
-
- parseHost(valueMB);
-
- if (!contentDelimitation) {
- // If there's no content length and we're using keep-alive
- // (HTTP/1.0 with keep-alive or HTTP/1.1), assume
- // the client is not broken and didn't send a body
- if (keepAlive) {
- inputBuffer.addActiveFilter
- (inputFilters[Constants.VOID_FILTER]);
- contentDelimitation = true;
- }
- }
-
- if (!contentDelimitation)
- keepAlive = false;
-
// Advertise sendfile support through a request attribute
- if (endpoint.getUseSendfile()) {
+ if (((AprEndpoint)endpoint).getUseSendfile()) {
request.setAttribute("org.apache.tomcat.sendfile.support",
Boolean.TRUE);
}
}
- /**
- * Parse host.
- */
- public void parseHost(MessageBytes valueMB) {
-
- if (valueMB == null || valueMB.isNull()) {
- // HTTP/1.0
- // Default is what the socket tells us. Overriden if a host is
- // found/parsed
- request.setServerPort(endpoint.getPort());
- return;
- }
-
- ByteChunk valueBC = valueMB.getByteChunk();
- byte[] valueB = valueBC.getBytes();
- int valueL = valueBC.getLength();
- int valueS = valueBC.getStart();
- int colonPos = -1;
- if (hostNameC.length < valueL) {
- hostNameC = new char[valueL];
- }
-
- boolean ipv6 = (valueB[valueS] == '[');
- boolean bracketClosed = false;
- for (int i = 0; i < valueL; i++) {
- char b = (char) valueB[i + valueS];
- hostNameC[i] = b;
- if (b == ']') {
- bracketClosed = true;
- } else if (b == ':') {
- if (!ipv6 || bracketClosed) {
- colonPos = i;
- break;
- }
- }
- }
-
- if (colonPos < 0) {
- if (!ssl) {
- // 80 - Default HTTP port
- request.setServerPort(80);
- } else {
- // 443 - Default HTTPS port
- request.setServerPort(443);
- }
- request.serverName().setChars(hostNameC, 0, valueL);
- } else {
-
- request.serverName().setChars(hostNameC, 0, colonPos);
-
- int port = 0;
- int mult = 1;
- for (int i = valueL - 1; i > colonPos; i--) {
- int charValue = HexUtils.DEC[(int) valueB[i + valueS]];
- if (charValue == -1) {
- // Invalid character
- error = true;
- // 400 - Bad request
- response.setStatus(400);
- break;
- }
- port = port + (charValue * mult);
- mult = 10 * mult;
- }
- request.setServerPort(port);
-
- }
-
- }
-
-
- /**
- * Check for compression
- */
- private boolean isCompressable() {
-
- // Nope Compression could works in HTTP 1.0 also
- // cf: mod_deflate
-
- // Compression only since HTTP 1.1
- // if (! http11)
- // return false;
-
- // Check if browser support gzip encoding
- MessageBytes acceptEncodingMB =
- request.getMimeHeaders().getValue("accept-encoding");
-
- if ((acceptEncodingMB == null)
- || (acceptEncodingMB.indexOf("gzip") == -1))
- return false;
-
- // Check if content is not allready gzipped
- MessageBytes contentEncodingMB =
- response.getMimeHeaders().getValue("Content-Encoding");
-
- if ((contentEncodingMB != null)
- && (contentEncodingMB.indexOf("gzip") != -1))
- return false;
-
- // If force mode, allways compress (test purposes only)
- if (compressionLevel == 2)
- return true;
-
- // Check for incompatible Browser
- if (noCompressionUserAgents != null) {
- MessageBytes userAgentValueMB =
- request.getMimeHeaders().getValue("user-agent");
- if(userAgentValueMB != null) {
- String userAgentValue = userAgentValueMB.toString();
-
- // If one Regexp rule match, disable compression
- for (int i = 0; i < noCompressionUserAgents.length; i++)
- if
(noCompressionUserAgents[i].matcher(userAgentValue).matches())
- return false;
- }
- }
-
- // Check if suffisant len to trig the compression
- long contentLength = response.getContentLengthLong();
- if ((contentLength == -1)
- || (contentLength > compressionMinSize)) {
- // Check for compatible MIME-TYPE
- if (compressableMimeTypes != null) {
- return (startsWithStringArray(compressableMimeTypes,
- response.getContentType()));
- }
- }
-
- return false;
+ protected void setDefaultHost() {
+ // HTTP/1.0
+ // Default is what the socket tells us. Overriden if a host is
+ // found/parsed
+ request.setServerPort(endpoint.getPort());
}
+
-
- /**
- * When committing the response, we have to validate the set of headers, as
- * well as setup the response filters.
- */
- protected void prepareResponse() {
-
- boolean entityBody = true;
- contentDelimitation = false;
-
- OutputFilter[] outputFilters = outputBuffer.getFilters();
-
- if (http09 == true) {
- // HTTP/0.9
- outputBuffer.addActiveFilter
- (outputFilters[Constants.IDENTITY_FILTER]);
- return;
- }
-
- int statusCode = response.getStatus();
- if ((statusCode == 204) || (statusCode == 205)
- || (statusCode == 304)) {
- // No entity body
- outputBuffer.addActiveFilter
- (outputFilters[Constants.VOID_FILTER]);
- entityBody = false;
- contentDelimitation = true;
- }
-
- MessageBytes methodMB = request.method();
- if (methodMB.equals("HEAD")) {
- // No entity body
- outputBuffer.addActiveFilter
- (outputFilters[Constants.VOID_FILTER]);
- contentDelimitation = true;
- }
-
+ protected void sendfileSupport(OutputFilter[] outputFilters) {
// Sendfile support
- if (endpoint.getUseSendfile()) {
+ if (((AprEndpoint)endpoint).getUseSendfile()) {
String fileName = (String)
request.getAttribute("org.apache.tomcat.sendfile.filename");
if (fileName != null) {
// No entity body sent here
@@ -1575,192 +527,6 @@
((Long)
request.getAttribute("org.apache.tomcat.sendfile.end")).longValue();
}
}
-
- // Check for compression
- boolean useCompression = false;
- if (entityBody && (compressionLevel > 0) && (sendfileData == null)) {
- useCompression = isCompressable();
- // Change content-length to -1 to force chunking
- if (useCompression) {
- response.setContentLength(-1);
- }
- }
-
- MimeHeaders headers = response.getMimeHeaders();
- if (!entityBody) {
- response.setContentLength(-1);
- } else {
- String contentType = response.getContentType();
- if (contentType != null) {
- headers.setValue("Content-Type").setString(contentType);
- }
- String contentLanguage = response.getContentLanguage();
- if (contentLanguage != null) {
- headers.setValue("Content-Language")
- .setString(contentLanguage);
- }
- }
-
- long contentLength = response.getContentLengthLong();
- if (contentLength != -1) {
- headers.setValue("Content-Length").setLong(contentLength);
- outputBuffer.addActiveFilter
- (outputFilters[Constants.IDENTITY_FILTER]);
- contentDelimitation = true;
- } else {
- if (entityBody && http11 && keepAlive) {
- outputBuffer.addActiveFilter
- (outputFilters[Constants.CHUNKED_FILTER]);
- contentDelimitation = true;
-
headers.addValue(Constants.TRANSFERENCODING).setString(Constants.CHUNKED);
- } else {
- outputBuffer.addActiveFilter
- (outputFilters[Constants.IDENTITY_FILTER]);
- }
- }
-
- if (useCompression) {
- outputBuffer.addActiveFilter(outputFilters[Constants.GZIP_FILTER]);
- headers.setValue("Content-Encoding").setString("gzip");
- // Make Proxies happy via Vary (from mod_deflate)
- headers.setValue("Vary").setString("Accept-Encoding");
- }
-
- // Add date header
-
headers.setValue("Date").setString(FastHttpDateFormat.getCurrentDate());
-
- // FIXME: Add transfer encoding header
-
- if ((entityBody) && (!contentDelimitation)) {
- // Mark as close the connection after the request, and add the
- // connection: close header
- keepAlive = false;
- }
-
- // If we know that the request is bad this early, add the
- // Connection: close header.
- keepAlive = keepAlive && !statusDropsConnection(statusCode);
- if (!keepAlive) {
- headers.addValue(Constants.CONNECTION).setString(Constants.CLOSE);
- } else if (!http11 && !error) {
-
headers.addValue(Constants.CONNECTION).setString(Constants.KEEPALIVE);
- }
-
- // Build the response header
- outputBuffer.sendStatus();
-
- // Add server header
- if (server != null) {
- headers.setValue("Server").setString(server);
- } else {
- outputBuffer.write(Constants.SERVER_BYTES);
- }
-
- int size = headers.size();
- for (int i = 0; i < size; i++) {
- outputBuffer.sendHeader(headers.getName(i), headers.getValue(i));
- }
- outputBuffer.endHeaders();
-
- }
-
-
- /**
- * Initialize standard input and output filters.
- */
- protected void initializeFilters() {
-
- // Create and add the identity filters.
- inputBuffer.addFilter(new IdentityInputFilter());
- outputBuffer.addFilter(new IdentityOutputFilter());
-
- // Create and add the chunked filters.
- inputBuffer.addFilter(new ChunkedInputFilter());
- outputBuffer.addFilter(new ChunkedOutputFilter());
-
- // Create and add the void filters.
- inputBuffer.addFilter(new VoidInputFilter());
- outputBuffer.addFilter(new VoidOutputFilter());
-
- // Create and add buffered input filter
- inputBuffer.addFilter(new BufferedInputFilter());
-
- // Create and add the chunked filters.
- //inputBuffer.addFilter(new GzipInputFilter());
- outputBuffer.addFilter(new GzipOutputFilter());
-
- }
-
-
- /**
- * Add an input filter to the current request.
- *
- * @return false if the encoding was not found (which would mean it is
- * unsupported)
- */
- protected boolean addInputFilter(InputFilter[] inputFilters,
- String encodingName) {
- if (encodingName.equals("identity")) {
- // Skip
- } else if (encodingName.equals("chunked")) {
- inputBuffer.addActiveFilter
- (inputFilters[Constants.CHUNKED_FILTER]);
- contentDelimitation = true;
- } else {
- for (int i = 2; i < inputFilters.length; i++) {
- if (inputFilters[i].getEncodingName()
- .toString().equals(encodingName)) {
- inputBuffer.addActiveFilter(inputFilters[i]);
- return true;
- }
- }
- return false;
- }
- return true;
- }
-
-
- /**
- * Specialized utility method: find a sequence of lower case bytes inside
- * a ByteChunk.
- */
- protected int findBytes(ByteChunk bc, byte[] b) {
-
- byte first = b[0];
- byte[] buff = bc.getBuffer();
- int start = bc.getStart();
- int end = bc.getEnd();
-
- // Look for first char
- int srcEnd = b.length;
-
- for (int i = start; i <= (end - srcEnd); i++) {
- if (Ascii.toLower(buff[i]) != first) continue;
- // found first char, now look for a match
- int myPos = i+1;
- for (int srcPos = 1; srcPos < srcEnd; ) {
- if (Ascii.toLower(buff[myPos++]) != b[srcPos++])
- break;
- if (srcPos == srcEnd) return i - start; // found it
- }
- }
- return -1;
-
- }
-
- /**
- * Determine if we must drop the connection because of the HTTP status
- * code. Use the same list of codes as Apache/httpd.
- */
- protected boolean statusDropsConnection(int status) {
- return status == 400 /* SC_BAD_REQUEST */ ||
- status == 408 /* SC_REQUEST_TIMEOUT */ ||
- status == 411 /* SC_LENGTH_REQUIRED */ ||
- status == 413 /* SC_REQUEST_ENTITY_TOO_LARGE */ ||
- status == 414 /* SC_REQUEST_URI_TOO_LARGE */ ||
- status == 500 /* SC_INTERNAL_SERVER_ERROR */ ||
- status == 503 /* SC_SERVICE_UNAVAILABLE */ ||
- status == 501 /* SC_NOT_IMPLEMENTED */;
}
}
Modified: tomcat/sandbox/java/org/apache/coyote/http11/Http11Processor.java
URL:
http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/coyote/http11/Http11Processor.java?rev=345767&r1=345766&r2=345767&view=diff
==============================================================================
--- tomcat/sandbox/java/org/apache/coyote/http11/Http11Processor.java (original)
+++ tomcat/sandbox/java/org/apache/coyote/http11/Http11Processor.java Sun Nov
20 10:19:56 2005
@@ -561,7 +561,7 @@
* @param sArray the StringArray
* @param value string
*/
- private boolean startsWithStringArray(String sArray[], String value) {
+ protected boolean startsWithStringArray(String sArray[], String value) {
if (value == null)
return false;
for (int i = 0; i < sArray.length; i++) {
@@ -1026,8 +1026,26 @@
} else if (actionCode == ActionCode.ACTION_STOP) {
started = false;
+
+ // ------------------------------------
+ } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) {
+ ByteChunk body = (ByteChunk) param;
+
+ InputFilter savedBody = new SavedRequestInputFilter(body);
+ savedBody.setRequest(request);
+
+ InternalInputBuffer internalBuffer = (InternalInputBuffer)
+ request.getInputBuffer();
+ internalBuffer.addActiveFilter(savedBody);
+ } else {
+ endpointAction(actionCode, param);
+ }
+ }
- } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) {
+ protected void endpointAction(ActionCode actionCode,
+ Object param) {
+
+ if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) {
try {
if (sslSupport != null) {
@@ -1124,15 +1142,6 @@
log.warn(sm.getString("http11processor.socket.ssl"), e);
}
}
- } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) {
- ByteChunk body = (ByteChunk) param;
-
- InputFilter savedBody = new SavedRequestInputFilter(body);
- savedBody.setRequest(request);
-
- InternalInputBuffer internalBuffer = (InternalInputBuffer)
- request.getInputBuffer();
- internalBuffer.addActiveFilter(savedBody);
}
}
@@ -1341,6 +1350,18 @@
}
+ protected void setDefaultHost() {
+ // HTTP/1.0
+ // Default is what the socket tells us. Overriden if a host is
+ // found/parsed
+ // APR: endpoint.getPort(), no serverName.
+ request.setServerPort(socket.getLocalPort());
+
+ InetAddress localAddress = socket.getLocalAddress();
+ // Setting the socket-related fields. The adapter doesn't know
+ // about socket.
+ request.serverName().setString(localAddress.getHostName());
+ }
/**
* Parse host.
@@ -1348,14 +1369,7 @@
public void parseHost(MessageBytes valueMB) {
if (valueMB == null || valueMB.isNull()) {
- // HTTP/1.0
- // Default is what the socket tells us. Overriden if a host is
- // found/parsed
- request.setServerPort(socket.getLocalPort());
- InetAddress localAddress = socket.getLocalAddress();
- // Setting the socket-related fields. The adapter doesn't know
- // about socket.
- request.serverName().setString(localAddress.getHostName());
+ setDefaultHost();
return;
}
@@ -1420,7 +1434,7 @@
/**
* Check for compression
*/
- private boolean isCompressable() {
+ protected boolean isCompressable() {
// Nope Compression could works in HTTP 1.0 also
// cf: mod_deflate
@@ -1514,6 +1528,9 @@
contentDelimitation = true;
}
+ // APR: sendfile
+ sendfileSupport(outputFilters);
+
// Check for compression
boolean useCompression = false;
if (entityBody && (compressionLevel > 0)) {
@@ -1565,7 +1582,7 @@
headers.setValue("Vary").setString("Accept-Encoding");
}
- // Add date header
+ // Add date header. APR didn't have SecurityManager wrapper
String date = null;
if (System.getSecurityManager() != null){
date = (String)AccessController.doPrivileged(
@@ -1615,6 +1632,9 @@
}
+ // Hook for sendfile
+ protected void sendfileSupport(OutputFilter[] outputFilters) {
+ }
/**
* Initialize standard input and output filters.
Modified:
tomcat/sandbox/java/org/apache/coyote/http11/InternalAprInputBuffer.java
URL:
http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/coyote/http11/InternalAprInputBuffer.java?rev=345767&r1=345766&r2=345767&view=diff
==============================================================================
--- tomcat/sandbox/java/org/apache/coyote/http11/InternalAprInputBuffer.java
(original)
+++ tomcat/sandbox/java/org/apache/coyote/http11/InternalAprInputBuffer.java
Sun Nov 20 10:19:56 2005
@@ -21,11 +21,9 @@
import java.io.IOException;
import java.nio.ByteBuffer;
-import org.apache.coyote.InputBuffer;
import org.apache.coyote.Request;
import org.apache.tomcat.jni.Socket;
import org.apache.tomcat.jni.Status;
-import org.apache.tomcat.util.buf.ByteChunk;
/**
* Implementation of InputBuffer which provides HTTP request header parsing as
@@ -51,8 +49,6 @@
bbuf = ByteBuffer.allocateDirect(headerBufferSize);
- inputStreamInputBuffer = new SocketInputBuffer();
-
this.readTimeout = readTimeout * 1000;
}
@@ -110,9 +106,6 @@
public void recycle() {
super.recycle();
- // Recycle Request object
- request.recycle();
-
socket = 0;
}
@@ -364,40 +357,4 @@
return (nRead > 0);
}
-
-
- // ------------------------------------- InputStreamInputBuffer Inner Class
-
-
- /**
- * This class is an input buffer which will read its data from an input
- * stream.
- */
- protected class SocketInputBuffer
- implements InputBuffer {
-
-
- /**
- * Read bytes into the specified chunk.
- */
- public int doRead(ByteChunk chunk, Request req )
- throws IOException {
-
- if (pos >= lastValid) {
- if (!fill())
- return -1;
- }
-
- int length = lastValid - pos;
- chunk.setBytes(buf, pos, length);
- pos = lastValid;
-
- return (length);
-
- }
-
-
- }
-
-
}
Modified: tomcat/sandbox/java/org/apache/coyote/http11/InternalInputBuffer.java
URL:
http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/coyote/http11/InternalInputBuffer.java?rev=345767&r1=345766&r2=345767&view=diff
==============================================================================
--- tomcat/sandbox/java/org/apache/coyote/http11/InternalInputBuffer.java
(original)
+++ tomcat/sandbox/java/org/apache/coyote/http11/InternalInputBuffer.java Sun
Nov 20 10:19:56 2005
@@ -21,6 +21,8 @@
import java.io.InputStream;
import java.io.EOFException;
+import org.apache.tomcat.jni.Socket;
+import org.apache.tomcat.jni.Status;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.http.MimeHeaders;
@@ -385,7 +387,7 @@
* read operations, or if the given buffer is not big enough to accomodate
* the whole line.
*/
- public boolean parseRequestLine(boolean dummy)
+ public boolean parseRequestLine(boolean useAvailableData)
throws IOException {
int start = 0;
@@ -399,6 +401,27 @@
// Read new bytes if needed
if (pos >= lastValid) {
+ /* APR version:
+ if (useAvailableData) {
+ return false;
+ }
+ // Do a simple read with a short timeout
+ bbuf.clear();
+ int nRead = Socket.recvbbt
+ (socket, 0, buf.length - lastValid, readTimeout);
+ if (nRead > 0) {
+ bbuf.limit(nRead);
+ bbuf.get(buf, pos, nRead);
+ lastValid = pos + nRead;
+ } else {
+ if ((-nRead) == Status.ETIMEDOUT || (-nRead) ==
Status.TIMEUP) {
+ return false;
+ } else {
+ throw new IOException(sm.getString("iib.failedread"));
+ }
+ }
+
+ */
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
@@ -417,6 +440,29 @@
// Method name is always US-ASCII
//
+ /* APR: extra code:
+ if (pos >= lastValid) {
+ if (useAvailableData) {
+ return false;
+ }
+ // Do a simple read with a short timeout
+ bbuf.clear();
+ int nRead = Socket.recvbbt
+ (socket, 0, buf.length - lastValid, readTimeout);
+ if (nRead > 0) {
+ bbuf.limit(nRead);
+ bbuf.get(buf, pos, nRead);
+ lastValid = pos + nRead;
+ } else {
+ if ((-nRead) == Status.ETIMEDOUT || (-nRead) == Status.TIMEUP)
{
+ return false;
+ } else {
+ throw new IOException(sm.getString("iib.failedread"));
+ }
+ }
+ }
+ */
+
boolean space = false;
while (!space) {
@@ -740,16 +786,44 @@
(sm.getString("iib.requestheadertoolarge.error"));
}
+ // In APR:
+ /*
+ bbuf.clear();
+ nRead = Socket.recvbb
+ (socket, 0, buf.length - lastValid);
+ if (nRead > 0) {
+ bbuf.limit(nRead);
+ bbuf.get(buf, pos, nRead);
+ lastValid = pos + nRead;
+ } else {
+ if ((-nRead) == Status.EAGAIN) {
+ return false;
+ } else {
+ throw new IOException(sm.getString("iib.failedread"));
+ }
+ }
+ */
nRead = inputStream.read(buf, pos, buf.length - lastValid);
if (nRead > 0) {
lastValid = pos + nRead;
}
} else {
-
buf = bodyBuffer;
pos = 0;
lastValid = 0;
+ /*APR:
+ bbuf.clear();
+ nRead = Socket.recvbb
+ (socket, 0, buf.length);
+ if (nRead > 0) {
+ bbuf.limit(nRead);
+ bbuf.get(buf, 0, nRead);
+ lastValid = nRead;
+ } else {
+ throw new IOException(sm.getString("iib.failedread"));
+ }
+ */
nRead = inputStream.read(buf, 0, buf.length);
if (nRead > 0) {
lastValid = nRead;
@@ -768,6 +842,8 @@
/**
* This class is an input buffer which will read its data from an input
* stream.
+ *
+ * Used as an adapter for the ByteChunk.
*/
protected class InputStreamInputBuffer
implements InputBuffer {
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]