-
Notifications
You must be signed in to change notification settings - Fork 78
/
ServletInputStream.java
237 lines (215 loc) · 8.91 KB
/
ServletInputStream.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/*
* Copyright (c) 1997, 2023 Oracle and/or its affiliates and others.
* All rights reserved.
* Copyright 2004 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 jakarta.servlet;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Objects;
/**
*
* Provides an input stream for reading binary data from a client request, including an efficient <code>readLine</code>
* method for reading data one line at a time. With some protocols, such as HTTP POST and PUT, a
* <code>ServletInputStream</code> object can be used to read data sent from the client.
*
* <p>
* A <code>ServletInputStream</code> object is normally retrieved via the {@link ServletRequest#getInputStream} method.
*
*
* <p>
* This is an abstract class that a servlet container implements. Subclasses of this class must implement the
* <code>java.io.InputStream.read()</code> method.
*
*
* @author Various
*
* @see ServletRequest
*
*/
public abstract class ServletInputStream extends InputStream {
/**
* Does nothing, because this is an abstract class.
*
*/
protected ServletInputStream() {
}
/**
* Reads from the input stream into the given buffer.
* <p>
* If the input stream is in non-blocking mode, before each invocation of this method {@link #isReady()} must be called
* and must return {@code true} or the {@link ReadListener#onDataAvailable()} call back must indicate that data is
* available to read else an {@link IllegalStateException} must be thrown.
* <p>
* Otherwise, if this method is called when {@code buffer} has no space remaining, the method returns {@code 0}
* immediately and {@code buffer} is unchanged.
* <p>
* If the input stream is in blocking mode and {@code buffer} has space remaining, this method blocks until at least one
* byte has been read, end of stream is reached or an exception is thrown.
* <p>
* Returns the number of bytes read or {@code -1} if the end of stream is reached without reading any data.
* <p>
* When the method returns, and if data has been read, the buffer's position will be unchanged from the value when
* passed to this method and the limit will be the position incremented by the number of bytes read.
* <p>
* Subclasses are strongly encouraged to override this method and provide a more efficient implementation.
*
* @param buffer The buffer into which the data is read.
*
* @return The number of bytes read or {@code -1} if the end of the stream has been reached.
*
* @exception IllegalStateException If the input stream is in non-blocking mode and this method is called without first
* calling {@link #isReady()} and that method has returned {@code true} or {@link ReadListener#onDataAvailable()} has
* not signalled that data is available to read.
*
* @exception IOException If data cannot be read for any reason other than the end of stream being reached, the input
* stream has been closed or if some other I/O error occurs.
*
* @exception NullPointerException If buffer is null.
*
* @since Servlet 6.1
*/
public int read(ByteBuffer buffer) throws IOException {
Objects.requireNonNull(buffer);
if (!isReady()) {
throw new IllegalStateException();
}
if (buffer.remaining() == 0) {
return 0;
}
byte[] b = new byte[buffer.remaining()];
int result = read(b);
if (result == -1) {
return -1;
}
int position = buffer.position();
buffer.put(b, 0, result);
buffer.position(position);
buffer.limit(position + result);
return result;
}
/**
* Reads the input stream, one line at a time. Starting at an offset, reads bytes into an array, until it reads a
* certain number of bytes or reaches a newline character, which it reads into the array as well.
* <p>
* This method returns {@code -1} if it reaches the end of the input stream before reading the maximum number of bytes.
* <p>
* This method may only be used when the input stream is in blocking mode.
*
* @param b an array of bytes into which data is read
*
* @param off an integer specifying the character at which this method begins reading
*
* @param len an integer specifying the maximum number of bytes to read
*
* @return an integer specifying the actual number of bytes read, or -1 if the end of the stream is reached
*
* @exception IllegalStateException If this method is called when the input stream is in non-blocking mode.
*
* @exception IOException if an input or output exception has occurred
*/
public int readLine(byte[] b, int off, int len) throws IOException {
if (len <= 0) {
return 0;
}
int count = 0, c;
while ((c = read()) != -1) {
b[off++] = (byte) c;
count++;
if (c == '\n' || count == len) {
break;
}
}
return count > 0 ? count : -1;
}
/**
* Returns true when all the data from the stream has been read else it returns false.
*
* @return <code>true</code> when all data for this particular request has been read, otherwise returns
* <code>false</code>.
*
* @since Servlet 3.1
*/
public abstract boolean isFinished();
/**
* Returns {@code true} if it is allowable to call a {@code read()} method. In blocking mode, this method will always
* return {@code true}, but a subsequent call to a {@code read()} method may block awaiting data. In non-blocking mode
* this method may return {@code false}, in which case it is illegal to call a {@code read()} method and an
* {@link IllegalStateException} MUST be thrown. When {@link ReadListener#onDataAvailable()} is called, a call to this
* method that returned {@code true} is implicit.
* <p>
* If this method returns {@code false} and a {@link ReadListener} has been set via
* {@link #setReadListener(ReadListener)}, then the container will subsequently invoke
* {@link ReadListener#onDataAvailable()} (or {@link ReadListener#onAllDataRead()}) once data (or EOF) has become
* available. Other than the initial call, {@link ReadListener#onDataAvailable()} will only be called if and only if
* this method is called and returns false.
*
* @return {@code true} if data can be obtained without blocking, otherwise returns {@code false}.
* @see ReadListener
* @since Servlet 3.1
*/
public abstract boolean isReady();
/**
* Instructs the <code>ServletInputStream</code> to invoke the provided {@link ReadListener} when it is possible to read
*
* @param readListener the {@link ReadListener} that should be notified when it's possible to read.
*
* @exception IllegalStateException if one of the following conditions is true
* <ul>
* <li>the associated request is neither upgraded nor the async started
* <li>setReadListener is called more than once within the scope of the same request.
* </ul>
*
* @throws NullPointerException if readListener is null
*
* @since Servlet 3.1
*
*/
public abstract void setReadListener(ReadListener readListener);
/**
* {@inheritDoc}
* <p>
* This method may only be used when the input stream is in blocking mode.
*
* @exception IllegalStateException If this method is called when the input stream is in non-blocking mode.
*/
@Override
public byte[] readAllBytes() throws IOException {
return super.readAllBytes();
}
/**
* {@inheritDoc}
* <p>
* This method may only be used when the input stream is in blocking mode.
*
* @exception IllegalStateException If this method is called when the input stream is in non-blocking mode.
*/
@Override
public byte[] readNBytes(int len) throws IOException {
return super.readNBytes(len);
}
/**
* {@inheritDoc}
* <p>
* This method may only be used when the input stream is in blocking mode.
*
* @exception IllegalStateException If this method is called when the input stream is in non-blocking mode.
*/
@Override
public int readNBytes(byte[] b, int off, int len) throws IOException {
return super.readNBytes(b, off, len);
}
}