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 package org.apache.catalina.connector;
18
19 import java.io.IOException;
20 import java.nio.ByteBuffer;
21 import java.security.AccessController;
22 import java.security.PrivilegedActionException;
23 import java.security.PrivilegedExceptionAction;
24
25 import javax.servlet.ReadListener;
26 import javax.servlet.ServletInputStream;
27
28 import org.apache.catalina.security.SecurityUtil;
29 import org.apache.tomcat.util.res.StringManager;
30
31 /**
32  * This class handles reading bytes.
33  *
34  * @author Remy Maucherat
35  */

36 public class CoyoteInputStream extends ServletInputStream {
37
38     protected static final StringManager sm = StringManager.getManager(CoyoteInputStream.class);
39
40
41     protected InputBuffer ib;
42
43
44     protected CoyoteInputStream(InputBuffer ib) {
45         this.ib = ib;
46     }
47
48
49     /**
50      * Clear facade.
51      */

52     void clear() {
53         ib = null;
54     }
55
56
57     /**
58      * Prevent cloning the facade.
59      */

60     @Override
61     protected Object clone() throws CloneNotSupportedException {
62         throw new CloneNotSupportedException();
63     }
64
65
66     @Override
67     public int read() throws IOException {
68         checkNonBlockingRead();
69
70         if (SecurityUtil.isPackageProtectionEnabled()) {
71
72             try {
73                 Integer result = AccessController.doPrivileged(new PrivilegedRead(ib));
74                 return result.intValue();
75             } catch (PrivilegedActionException pae) {
76                 Exception e = pae.getException();
77                 if (e instanceof IOException) {
78                     throw (IOException) e;
79                 } else {
80                     throw new RuntimeException(e.getMessage(), e);
81                 }
82             }
83         } else {
84             return ib.readByte();
85         }
86     }
87
88     @Override
89     public int available() throws IOException {
90
91         if (SecurityUtil.isPackageProtectionEnabled()) {
92             try {
93                 Integer result = AccessController.doPrivileged(new PrivilegedAvailable(ib));
94                 return result.intValue();
95             } catch (PrivilegedActionException pae) {
96                 Exception e = pae.getException();
97                 if (e instanceof IOException) {
98                     throw (IOException) e;
99                 } else {
100                     throw new RuntimeException(e.getMessage(), e);
101                 }
102             }
103         } else {
104             return ib.available();
105         }
106     }
107
108     @Override
109     public int read(final byte[] b) throws IOException {
110         return read(b, 0, b.length);
111     }
112
113
114     @Override
115     public int read(final byte[] b, final int off, final int len) throws IOException {
116         checkNonBlockingRead();
117
118         if (SecurityUtil.isPackageProtectionEnabled()) {
119             try {
120                 Integer result = AccessController.doPrivileged(
121                         new PrivilegedReadArray(ib, b, off, len));
122                 return result.intValue();
123             } catch (PrivilegedActionException pae) {
124                 Exception e = pae.getException();
125                 if (e instanceof IOException) {
126                     throw (IOException) e;
127                 } else {
128                     throw new RuntimeException(e.getMessage(), e);
129                 }
130             }
131         } else {
132             return ib.read(b, off, len);
133         }
134     }
135
136
137     /**
138      * Transfers bytes from the buffer to the specified ByteBuffer. After the
139      * operation the position of the ByteBuffer will be returned to the one
140      * before the operation, the limit will be the position incremented by
141      * the number of the transferred bytes.
142      *
143      * @param b the ByteBuffer into which bytes are to be written.
144      * @return an integer specifying the actual number of bytes read, or -1 if
145      *         the end of the stream is reached
146      * @throws IOException if an input or output exception has occurred
147      */

148     public int read(final ByteBuffer b) throws IOException {
149         checkNonBlockingRead();
150
151         if (SecurityUtil.isPackageProtectionEnabled()) {
152             try {
153                 Integer result = AccessController.doPrivileged(new PrivilegedReadBuffer(ib, b));
154                 return result.intValue();
155             } catch (PrivilegedActionException pae) {
156                 Exception e = pae.getException();
157                 if (e instanceof IOException) {
158                     throw (IOException) e;
159                 } else {
160                     throw new RuntimeException(e.getMessage(), e);
161                 }
162             }
163         } else {
164             return ib.read(b);
165         }
166     }
167
168
169     /**
170      * Close the stream
171      * Since we re-cycle, we can't allow the call to super.close()
172      * which would permanently disable us.
173      */

174     @Override
175     public void close() throws IOException {
176
177         if (SecurityUtil.isPackageProtectionEnabled()) {
178             try {
179                 AccessController.doPrivileged(new PrivilegedClose(ib));
180             } catch (PrivilegedActionException pae) {
181                 Exception e = pae.getException();
182                 if (e instanceof IOException) {
183                     throw (IOException) e;
184                 } else {
185                     throw new RuntimeException(e.getMessage(), e);
186                 }
187             }
188         } else {
189             ib.close();
190         }
191     }
192
193     @Override
194     public boolean isFinished() {
195         return ib.isFinished();
196     }
197
198
199     @Override
200     public boolean isReady() {
201         return ib.isReady();
202     }
203
204
205     @Override
206     public void setReadListener(ReadListener listener) {
207         ib.setReadListener(listener);
208     }
209
210
211     private void checkNonBlockingRead() {
212         if (!ib.isBlocking() && !ib.isReady()) {
213             throw new IllegalStateException(sm.getString("coyoteInputStream.nbNotready"));
214         }
215     }
216
217
218     private static class PrivilegedAvailable implements PrivilegedExceptionAction<Integer> {
219
220         private final InputBuffer inputBuffer;
221
222         public PrivilegedAvailable(InputBuffer inputBuffer) {
223             this.inputBuffer = inputBuffer;
224         }
225
226         @Override
227         public Integer run() throws IOException {
228             return Integer.valueOf(inputBuffer.available());
229         }
230     }
231
232
233     private static class PrivilegedClose implements PrivilegedExceptionAction<Void> {
234
235         private final InputBuffer inputBuffer;
236
237         public PrivilegedClose(InputBuffer inputBuffer) {
238             this.inputBuffer = inputBuffer;
239         }
240
241         @Override
242         public Void run() throws IOException {
243             inputBuffer.close();
244             return null;
245         }
246     }
247
248
249     private static class PrivilegedRead implements PrivilegedExceptionAction<Integer> {
250
251         private final InputBuffer inputBuffer;
252
253         public PrivilegedRead(InputBuffer inputBuffer) {
254             this.inputBuffer = inputBuffer;
255         }
256
257         @Override
258         public Integer run() throws IOException {
259             Integer integer = Integer.valueOf(inputBuffer.readByte());
260             return integer;
261         }
262     }
263
264
265     private static class PrivilegedReadArray implements PrivilegedExceptionAction<Integer> {
266
267         private final InputBuffer inputBuffer;
268         private final byte[] buf;
269         private final int off;
270         private final int len;
271
272         public PrivilegedReadArray(InputBuffer inputBuffer, byte[] buf, int off, int len) {
273             this.inputBuffer = inputBuffer;
274             this.buf = buf;
275             this.off = off;
276             this.len = len;
277         }
278
279         @Override
280         public Integer run() throws IOException {
281             Integer integer = Integer.valueOf(inputBuffer.read(buf, off, len));
282             return integer;
283         }
284     }
285
286
287     private static class PrivilegedReadBuffer implements PrivilegedExceptionAction<Integer> {
288
289         private final InputBuffer inputBuffer;
290         private final ByteBuffer bb;
291
292         public PrivilegedReadBuffer(InputBuffer inputBuffer, ByteBuffer bb) {
293             this.inputBuffer = inputBuffer;
294             this.bb = bb;
295         }
296
297         @Override
298         public Integer run() throws IOException {
299             Integer integer = Integer.valueOf(inputBuffer.read(bb));
300             return integer;
301         }
302     }
303 }
304