You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by ve...@apache.org on 2009/06/04 23:22:55 UTC
svn commit: r781854 - in
/webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter:
./ http/
Author: veithen
Date: Thu Jun 4 21:22:52 2009
New Revision: 781854
URL: http://svn.apache.org/viewvc?rev=781854&view=rev
Log:
* Reverted (my own) change r780724 which would make it more difficult to support keep-alive.
* Some fixes to the chunked decoder/encoder.
Added:
webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/EntityProcessor.java
- copied unchanged from r780723, webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/EntityProcessor.java
webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/ReadOnlyEntityProcessorWrapper.java (with props)
Removed:
webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/EntityCompletionListener.java
Modified:
webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/ChunkedDecoder.java
webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/ChunkedEncoder.java
webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/HttpFilter.java
webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/IdentityDecoder.java
Added: webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/ReadOnlyEntityProcessorWrapper.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/ReadOnlyEntityProcessorWrapper.java?rev=781854&view=auto
==============================================================================
--- webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/ReadOnlyEntityProcessorWrapper.java (added)
+++ webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/ReadOnlyEntityProcessorWrapper.java Thu Jun 4 21:22:52 2009
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2004,2005 The Apache Software Foundation.
+ *
+ * Licensed 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.ws.commons.tcpmon.core.filter;
+
+/**
+ * Wrapper that makes an {@link EntityProcessor} read-only.
+ */
+public class ReadOnlyEntityProcessorWrapper implements EntityProcessor {
+ private final EntityProcessor parent;
+
+ public ReadOnlyEntityProcessorWrapper(EntityProcessor parent) {
+ this.parent = parent;
+ }
+
+ public boolean process(Stream stream) {
+ return parent.process(new ReadOnlyStream(stream));
+ }
+}
Propchange: webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/ReadOnlyEntityProcessorWrapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/ChunkedDecoder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/ChunkedDecoder.java?rev=781854&r1=781853&r2=781854&view=diff
==============================================================================
--- webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/ChunkedDecoder.java (original)
+++ webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/ChunkedDecoder.java Thu Jun 4 21:22:52 2009
@@ -16,51 +16,65 @@
package org.apache.ws.commons.tcpmon.core.filter.http;
+import org.apache.ws.commons.tcpmon.core.filter.EntityProcessor;
import org.apache.ws.commons.tcpmon.core.filter.Stream;
import org.apache.ws.commons.tcpmon.core.filter.StreamException;
-import org.apache.ws.commons.tcpmon.core.filter.StreamFilter;
import org.apache.ws.commons.tcpmon.core.filter.StreamUtil;
/**
* Entity processor that processes HTTP chunked transfer encoding.
*/
-public class ChunkedDecoder implements StreamFilter {
- private final EntityCompletionListener listener;
- private int remaining = -1; // bytes remaining in the current chunk
+public class ChunkedDecoder implements EntityProcessor {
+ private static final int STATE_START_CHUNK = 1;
+ private static final int STATE_CHUNK = 2;
+ private static final int STATE_TRAILER = 3;
+
+ private int state = STATE_START_CHUNK;
+ private int remaining; // bytes remaining in the current chunk
- public ChunkedDecoder(EntityCompletionListener listener) {
- this.listener = listener;
- }
-
- public void invoke(Stream stream) {
+ public boolean process(Stream stream) {
while (stream.available() > 0) {
- if (remaining > 0) {
- int c = Math.min(stream.available(), remaining);
- stream.skip(c);
- remaining -= c;
- } else if (remaining == 0) {
- if (stream.available() < 2) {
- return;
- }
- if (stream.get(0) == '\r' && stream.get(1) == '\n') {
- stream.discard(2);
- remaining = -1;
- } else {
- throw new StreamException("Invalid chunked encoding");
- }
- } else {
- int eolIndex = StreamUtil.searchEndOfLine(stream);
- if (eolIndex == -1) {
- return;
+ switch (state) {
+ case STATE_CHUNK:
+ if (remaining > 0) {
+ int c = Math.min(stream.available(), remaining);
+ stream.skip(c);
+ remaining -= c;
+ } else if (remaining == 0) {
+ if (stream.available() < 2) {
+ return false;
+ }
+ if (stream.get(0) == '\r' && stream.get(1) == '\n') {
+ stream.discard(2);
+ state = STATE_START_CHUNK;
+ } else {
+ throw new StreamException("Invalid chunked encoding");
+ }
+ }
+ break;
+ case STATE_START_CHUNK: {
+ int eolIndex = StreamUtil.searchEndOfLine(stream);
+ if (eolIndex == -1) {
+ return false;
+ }
+ remaining = Integer.parseInt(StreamUtil.getAsciiString(stream, 0, eolIndex), 16);
+ stream.discard(eolIndex+2);
+ state = remaining == 0 ? STATE_TRAILER : STATE_CHUNK;
+ break;
}
- remaining = Integer.parseInt(StreamUtil.getAsciiString(stream, 0, eolIndex), 16);
- stream.discard(eolIndex+2);
- if (remaining == 0) {
- listener.onComplete();
- return;
+ case STATE_TRAILER: {
+ if (stream.available() < 2) {
+ return false;
+ }
+ if (stream.get(0) == '\r' && stream.get(1) == '\n') {
+ stream.discard(2);
+ return true;
+ } else {
+ throw new StreamException("Entity headers in trailer not supported");
+ }
}
}
}
- return;
+ return false;
}
}
Modified: webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/ChunkedEncoder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/ChunkedEncoder.java?rev=781854&r1=781853&r2=781854&view=diff
==============================================================================
--- webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/ChunkedEncoder.java (original)
+++ webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/ChunkedEncoder.java Thu Jun 4 21:22:52 2009
@@ -28,6 +28,9 @@
StreamUtil.insertAsciiString(stream, "\r\n");
StreamUtil.insertAsciiString(stream, Integer.toString(av, 16));
StreamUtil.insertAsciiString(stream, "\r\n");
+ if (av == 0) {
+ StreamUtil.insertAsciiString(stream, "\r\n");
+ }
}
}
}
Modified: webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/HttpFilter.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/HttpFilter.java?rev=781854&r1=781853&r2=781854&view=diff
==============================================================================
--- webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/HttpFilter.java (original)
+++ webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/HttpFilter.java Thu Jun 4 21:22:52 2009
@@ -21,8 +21,10 @@
import javax.activation.MimeType;
import javax.activation.MimeTypeParseException;
+import org.apache.ws.commons.tcpmon.core.filter.EntityProcessor;
import org.apache.ws.commons.tcpmon.core.filter.HeaderParser;
-import org.apache.ws.commons.tcpmon.core.filter.ReadOnlyFilterWrapper;
+import org.apache.ws.commons.tcpmon.core.filter.ReadOnlyEntityProcessorWrapper;
+import org.apache.ws.commons.tcpmon.core.filter.ReadOnlyStream;
import org.apache.ws.commons.tcpmon.core.filter.Stream;
import org.apache.ws.commons.tcpmon.core.filter.StreamException;
import org.apache.ws.commons.tcpmon.core.filter.StreamFilter;
@@ -32,7 +34,7 @@
/**
* Base class for {@link HttpRequestFilter} and {@link HttpResponseFilter}.
*/
-public abstract class HttpFilter implements StreamFilter, EntityCompletionListener {
+public abstract class HttpFilter implements StreamFilter {
private static final int STATE_FIRST_LINE = 0;
private static final int STATE_HEADER = 1;
private static final int STATE_CONTENT = 2;
@@ -42,6 +44,8 @@
private int state = STATE_FIRST_LINE;
private final Headers headers = new Headers();
private ContentFilterFactory contentFilterFactory;
+ private EntityProcessor transferDecoder;
+ private StreamFilter[] contentFilterChain;
public HttpFilter(boolean decodeTransferEncoding) {
this.decodeTransferEncoding = decodeTransferEncoding;
@@ -85,13 +89,29 @@
}
if (headerParser.noMoreHeaders()) {
processHeaders(headerParser, stream);
- state = STATE_CONTENT;
} else {
return;
}
break;
}
- case STATE_CONTENT:
+ case STATE_CONTENT: {
+ if (transferDecoder != null) {
+ Stream decoderStream =
+ decodeTransferEncoding ? stream : new ReadOnlyStream(stream);
+ if (transferDecoder.process(decoderStream)) {
+ state = STATE_COMPLETE;
+ if (contentFilterChain != null) {
+ for (int i=0; i<contentFilterChain.length; i++) {
+ stream.popFilter();
+ }
+ }
+ onComplete();
+ }
+ break;
+ }
+ // Fall through
+ }
+ default:
stream.skipAll();
break;
case STATE_COMPLETE:
@@ -109,22 +129,20 @@
boolean hasEntity = false;
boolean discardHeaders = false;
- StreamFilter transferDecoder = null;
StreamFilter transferEncoder = null;
- StreamFilter[] contentFilterChain = null;
for (Iterator it = headers.iterator(); it.hasNext(); ) {
Header header = (Header)it.next();
String name = header.getName();
String value = header.getValue();
if (name.equalsIgnoreCase("Content-Length")) {
hasEntity = true;
- transferDecoder = new IdentityDecoder(Integer.parseInt(value), this);
+ transferDecoder = new IdentityDecoder(Integer.parseInt(value));
transferEncoder = new IdentityEncoder(headers);
discardHeaders = true;
} else if (name.equalsIgnoreCase("Transfer-Encoding")) {
hasEntity = true;
if (value.equals("chunked")) {
- transferDecoder = new ChunkedDecoder(this);
+ transferDecoder = new ChunkedDecoder();
transferEncoder = new ChunkedEncoder();
discardHeaders = false;
}
@@ -158,19 +176,21 @@
for (int i=contentFilterChain.length-1; i>=0; i--) {
stream.pushFilter(contentFilterChain[i]);
}
+ } else {
+ if (transferDecoder != null && !decodeTransferEncoding) {
+ transferDecoder = new ReadOnlyEntityProcessorWrapper(transferDecoder);
+ }
}
- if (transferDecoder != null) {
- stream.pushFilter(decodeTransferEncoding || contentFilterChain != null
- ? transferDecoder
- : new ReadOnlyFilterWrapper(transferDecoder));
- }
+ state = STATE_CONTENT;
} else {
onComplete();
}
}
-
- public void onComplete() {
+
+ private void onComplete() {
state = STATE_COMPLETE;
+ transferDecoder = null;
+ contentFilterChain = null;
completed();
}
}
Modified: webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/IdentityDecoder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/IdentityDecoder.java?rev=781854&r1=781853&r2=781854&view=diff
==============================================================================
--- webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/IdentityDecoder.java (original)
+++ webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/IdentityDecoder.java Thu Jun 4 21:22:52 2009
@@ -16,27 +16,23 @@
package org.apache.ws.commons.tcpmon.core.filter.http;
+import org.apache.ws.commons.tcpmon.core.filter.EntityProcessor;
import org.apache.ws.commons.tcpmon.core.filter.Stream;
-import org.apache.ws.commons.tcpmon.core.filter.StreamFilter;
/**
* Entity processor that processes HTTP identity transfer encoding.
*/
-public class IdentityDecoder implements StreamFilter {
- private final EntityCompletionListener listener;
+public class IdentityDecoder implements EntityProcessor {
private int remaining;
- public IdentityDecoder(int contentLength, EntityCompletionListener listener) {
+ public IdentityDecoder(int contentLength) {
remaining = contentLength;
- this.listener = listener;
}
- public void invoke(Stream stream) {
+ public boolean process(Stream stream) {
int c = Math.min(stream.available(), remaining);
stream.skip(c);
remaining -= c;
- if (remaining == 0) {
- listener.onComplete();
- }
+ return remaining == 0;
}
}