1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.coyote.http11.filters;
19
20 import java.io.IOException;
21
22 import org.apache.tomcat.util.buf.ByteChunk;
23
24 import org.apache.coyote.InputBuffer;
25 import org.apache.coyote.Request;
26 import org.apache.coyote.http11.InputFilter;
27
28 /**
29 * Identity input filter.
30 *
31 * @author Remy Maucherat
32 */
33 public class IdentityInputFilter implements InputFilter {
34
35
36 // -------------------------------------------------------------- Constants
37
38
39 protected static final String ENCODING_NAME = "identity";
40 protected static final ByteChunk ENCODING = new ByteChunk();
41
42
43 // ----------------------------------------------------- Static Initializer
44
45
46 static {
47 ENCODING.setBytes(ENCODING_NAME.getBytes(), 0, ENCODING_NAME.length());
48 }
49
50
51 // ----------------------------------------------------- Instance Variables
52
53
54 /**
55 * Content length.
56 */
57 protected long contentLength = -1;
58
59
60 /**
61 * Remaining bytes.
62 */
63 protected long remaining = 0;
64
65
66 /**
67 * Next buffer in the pipeline.
68 */
69 protected InputBuffer buffer;
70
71
72 /**
73 * Chunk used to read leftover bytes.
74 */
75 protected ByteChunk endChunk = new ByteChunk();
76
77
78 // ------------------------------------------------------------- Properties
79
80
81 /**
82 * Get content length.
83 */
84 public long getContentLength() {
85 return contentLength;
86 }
87
88
89 /**
90 * Get remaining bytes.
91 */
92 public long getRemaining() {
93 return remaining;
94 }
95
96
97 // ---------------------------------------------------- InputBuffer Methods
98
99
100 /**
101 * Read bytes.
102 *
103 * @return If the filter does request length control, this value is
104 * significant; it should be the number of bytes consumed from the buffer,
105 * up until the end of the current request body, or the buffer length,
106 * whichever is greater. If the filter does not do request body length
107 * control, the returned value should be -1.
108 */
109 public int doRead(ByteChunk chunk, Request req)
110 throws IOException {
111
112 int result = -1;
113
114 if (contentLength >= 0) {
115 if (remaining > 0) {
116 int nRead = buffer.doRead(chunk, req);
117 if (nRead > remaining) {
118 // The chunk is longer than the number of bytes remaining
119 // in the body; changing the chunk length to the number
120 // of bytes remaining
121 chunk.setBytes(chunk.getBytes(), chunk.getStart(),
122 (int) remaining);
123 result = (int) remaining;
124 } else {
125 result = nRead;
126 }
127 remaining = remaining - nRead;
128 } else {
129 // No more bytes left to be read : return -1 and clear the
130 // buffer
131 chunk.recycle();
132 result = -1;
133 }
134 }
135
136 return result;
137
138 }
139
140
141 // ---------------------------------------------------- InputFilter Methods
142
143
144 /**
145 * Read the content length from the request.
146 */
147 public void setRequest(Request request) {
148 contentLength = request.getContentLengthLong();
149 remaining = contentLength;
150 }
151
152
153 /**
154 * End the current request.
155 */
156 public long end()
157 throws IOException {
158
159 // Consume extra bytes.
160 while (remaining > 0) {
161 int nread = buffer.doRead(endChunk, null);
162 if (nread > 0 ) {
163 remaining = remaining - nread;
164 } else { // errors are handled higher up.
165 remaining = 0;
166 }
167 }
168
169 // If too many bytes were read, return the amount.
170 return -remaining;
171
172 }
173
174
175 /**
176 * Amount of bytes still available in a buffer.
177 */
178 public int available() {
179 return 0;
180 }
181
182
183 /**
184 * Set the next buffer in the filter pipeline.
185 */
186 public void setBuffer(InputBuffer buffer) {
187 this.buffer = buffer;
188 }
189
190
191 /**
192 * Make the filter ready to process the next request.
193 */
194 public void recycle() {
195 contentLength = -1;
196 remaining = 0;
197 endChunk.recycle();
198 }
199
200
201 /**
202 * Return the name of the associated encoding; Here, the value is
203 * "identity".
204 */
205 public ByteChunk getEncodingName() {
206 return ENCODING;
207 }
208
209
210 }