Package: ResponseInputStream
ResponseInputStream
name | instruction | branch | complexity | line | method | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ResponseInputStream(InputStream) |
|
|
|
|
|
||||||||||||||||||||
available() |
|
|
|
|
|
||||||||||||||||||||
readResponse() |
|
|
|
|
|
||||||||||||||||||||
readResponse(ByteArray) |
|
|
|
|
|
Coverage
1: /*
2: * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Public License v. 2.0, which is available at
6: * http://www.eclipse.org/legal/epl-2.0.
7: *
8: * This Source Code may also be made available under the following Secondary
9: * Licenses when the conditions for such availability set forth in the
10: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11: * version 2 with the GNU Classpath Exception, which is available at
12: * https://www.gnu.org/software/classpath/license.html.
13: *
14: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15: */
16:
17: package org.eclipse.angus.mail.iap;
18:
19: import java.io.*;
20:
21: import org.eclipse.angus.mail.util.ASCIIUtility;
22:
23: /**
24: *
25: * Inputstream that is used to read a Response.
26: *
27: * @author Arun Krishnan
28: * @author Bill Shannon
29: */
30:
31: public class ResponseInputStream {
32:
33: private static final int minIncrement = 256;
34: private static final int maxIncrement = 256 * 1024;
35: private static final int incrementSlop = 16;
36:
37: // where we read from
38: private BufferedInputStream bin;
39:
40: /**
41: * Constructor.
42: *
43: * @param        in        the InputStream to wrap
44: */
45: public ResponseInputStream(InputStream in) {
46:         bin = new BufferedInputStream(in, 2 * 1024);
47: }
48:
49: /**
50: * Read a Response from the InputStream.
51: *
52: * @return                ByteArray that contains the Response
53: * @exception        IOException        for I/O errors
54: */
55: public ByteArray readResponse() throws IOException {
56:         return readResponse(null);
57: }
58:
59: /**
60: * Read a Response from the InputStream.
61: *
62: * @param        ba        the ByteArray in which to store the response, or null
63: * @return                ByteArray that contains the Response
64: * @exception        IOException        for I/O errors
65: */
66: public ByteArray readResponse(ByteArray ba) throws IOException {
67:•        if (ba == null)
68:          ba = new ByteArray(new byte[128], 0, 128);
69:
70:         byte[] buffer = ba.getBytes();
71:         int idx = 0;
72:         for (;;) {        // read until CRLF with no preceeding literal
73:          // XXX - b needs to be an int, to handle bytes with value 0xff
74:          int b = 0;
75:          boolean gotCRLF=false;
76:
77:          // Read a CRLF terminated line from the InputStream
78:•         while (!gotCRLF &&
79:•                 ((b = bin.read()) != -1)) {
80:•                if (b == '\n') {
81:•                 if ((idx > 0) && buffer[idx-1] == '\r')
82:                         gotCRLF = true;
83:                 }
84:•                if (idx >= buffer.length) {
85:                  int incr = buffer.length;
86:•                 if (incr > maxIncrement)
87:                         incr = maxIncrement;
88:                  ba.grow(incr);
89:                  buffer = ba.getBytes();
90:                 }
91:                 buffer[idx++] = (byte)b;
92:          }
93:
94:•         if (b == -1)
95:                 throw new IOException("Connection dropped by server?");
96:
97:          // Now lets check for literals : {<digits>}CRLF
98:          // Note: index needs to >= 5 for the above sequence to occur
99:•         if (idx < 5 || buffer[idx-3] != '}')
100:                 break;
101:
102:          int i;
103:          // look for left curly
104:•         for (i = idx - 4; i >= 0; i--)
105:•                if (buffer[i] == '{')
106:                  break;
107:
108:•         if (i < 0) // Nope, not a literal ?
109:                 break;
110:
111:          int count = 0;
112:          // OK, handle the literal ..
113:          try {
114:                 count = ASCIIUtility.parseInt(buffer, i+1, idx-3);
115:          } catch (NumberFormatException e) {
116:                 break;
117:          }
118:
119:          // Now read 'count' bytes. (Note: count could be 0)
120:•         if (count > 0) {
121:                 int avail = buffer.length - idx; // available space in buffer
122:•                if (count + incrementSlop > avail) {
123:                  // need count-avail more bytes
124:•                 ba.grow(minIncrement > count + incrementSlop - avail ?
125:                          minIncrement : count + incrementSlop - avail);
126:                  buffer = ba.getBytes();
127:                 }
128:
129:                 /*
130:                  * read() might not return all the bytes in one shot,
131:                  * so call repeatedly till we are done
132:                  */
133:                 int actual;
134:•                while (count > 0) {
135:                  actual = bin.read(buffer, idx, count);
136:•                 if (actual == -1)
137:                         throw new IOException("Connection dropped by server?");
138:                  count -= actual;
139:                  idx += actual;
140:                 }
141:          }
142:          // back to top of loop to read until CRLF
143:         }
144:         ba.setCount(idx);
145:         return ba;
146: }
147:
148: /**
149: * How much buffered data do we have?
150: *
151: * @return        number of bytes available
152: * @exception        IOException        if the stream has been closed
153: * @since        JavaMail 1.5.4
154: */
155: public int available() throws IOException {
156:         return bin.available();
157: }
158: }