001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.coyote.http11.filters;
019:
020: import java.io.IOException;
021:
022: import org.apache.tomcat.util.buf.ByteChunk;
023:
024: import org.apache.coyote.InputBuffer;
025: import org.apache.coyote.Request;
026: import org.apache.coyote.http11.InputFilter;
027:
028: /**
029: * Identity input filter.
030: *
031: * @author Remy Maucherat
032: */
033: public class IdentityInputFilter implements InputFilter {
034:
035: // -------------------------------------------------------------- Constants
036:
037: protected static final String ENCODING_NAME = "identity";
038: protected static final ByteChunk ENCODING = new ByteChunk();
039:
040: // ----------------------------------------------------- Static Initializer
041:
042: static {
043: ENCODING.setBytes(ENCODING_NAME.getBytes(), 0, ENCODING_NAME
044: .length());
045: }
046:
047: // ----------------------------------------------------- Instance Variables
048:
049: /**
050: * Content length.
051: */
052: protected long contentLength = -1;
053:
054: /**
055: * Remaining bytes.
056: */
057: protected long remaining = 0;
058:
059: /**
060: * Next buffer in the pipeline.
061: */
062: protected InputBuffer buffer;
063:
064: /**
065: * Chunk used to read leftover bytes.
066: */
067: protected ByteChunk endChunk = new ByteChunk();
068:
069: // ------------------------------------------------------------- Properties
070:
071: /**
072: * Get content length.
073: */
074: public long getContentLength() {
075: return contentLength;
076: }
077:
078: /**
079: * Get remaining bytes.
080: */
081: public long getRemaining() {
082: return remaining;
083: }
084:
085: // ---------------------------------------------------- InputBuffer Methods
086:
087: /**
088: * Read bytes.
089: *
090: * @return If the filter does request length control, this value is
091: * significant; it should be the number of bytes consumed from the buffer,
092: * up until the end of the current request body, or the buffer length,
093: * whichever is greater. If the filter does not do request body length
094: * control, the returned value should be -1.
095: */
096: public int doRead(ByteChunk chunk, Request req) throws IOException {
097:
098: int result = -1;
099:
100: if (contentLength >= 0) {
101: if (remaining > 0) {
102: int nRead = buffer.doRead(chunk, req);
103: if (nRead > remaining) {
104: // The chunk is longer than the number of bytes remaining
105: // in the body; changing the chunk length to the number
106: // of bytes remaining
107: chunk.setBytes(chunk.getBytes(), chunk.getStart(),
108: (int) remaining);
109: result = (int) remaining;
110: } else {
111: result = nRead;
112: }
113: remaining = remaining - nRead;
114: } else {
115: // No more bytes left to be read : return -1 and clear the
116: // buffer
117: chunk.recycle();
118: result = -1;
119: }
120: }
121:
122: return result;
123:
124: }
125:
126: // ---------------------------------------------------- InputFilter Methods
127:
128: /**
129: * Read the content length from the request.
130: */
131: public void setRequest(Request request) {
132: contentLength = request.getContentLengthLong();
133: remaining = contentLength;
134: }
135:
136: /**
137: * End the current request.
138: */
139: public long end() throws IOException {
140:
141: // Consume extra bytes.
142: while (remaining > 0) {
143: int nread = buffer.doRead(endChunk, null);
144: if (nread > 0) {
145: remaining = remaining - nread;
146: } else { // errors are handled higher up.
147: remaining = 0;
148: }
149: }
150:
151: // If too many bytes were read, return the amount.
152: return -remaining;
153:
154: }
155:
156: /**
157: * Amount of bytes still available in a buffer.
158: */
159: public int available() {
160: return 0;
161: }
162:
163: /**
164: * Set the next buffer in the filter pipeline.
165: */
166: public void setBuffer(InputBuffer buffer) {
167: this .buffer = buffer;
168: }
169:
170: /**
171: * Make the filter ready to process the next request.
172: */
173: public void recycle() {
174: contentLength = -1;
175: remaining = 0;
176: endChunk.recycle();
177: }
178:
179: /**
180: * Return the name of the associated encoding; Here, the value is
181: * "identity".
182: */
183: public ByteChunk getEncodingName() {
184: return ENCODING;
185: }
186:
187: }
|