2 * ============LICENSE_START====================================================
4 * ===========================================================================
5 * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6 * ===========================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END====================================================
22 package org.onap.aaf.cadi;
24 import java.io.IOException;
25 import java.io.InputStream;
27 import javax.servlet.ServletInputStream;
30 * BufferedServletInputStream
32 * There are cases in brain-dead middleware (SOAP) where they store routing information in the content.
34 * In HTTP, this requires reading the content from the InputStream which, of course, cannot be re-read.
36 * BufferedInputStream exists to implement the "Mark" protocols for Streaming, which will enable being
37 * re-read. Unfortunately, J2EE chose to require a "ServletInputStream" as an abstract class, rather than
38 * an interface, which requires we create a delegating pattern, rather than the preferred inheriting pattern.
40 * Unfortunately, the standard "BufferedInputStream" cannot be used, because it simply creates a byte array
41 * in the "mark(int)" method of that size. This is not appropriate for this application, because the Header
42 * can be potentially huge, and if a buffer was allocated to accommodate all possibilities, the cost of memory
43 * allocation would be too large for high performance transactions.
49 public class BufferedServletInputStream extends ServletInputStream {
50 private static final int NONE = 0;
51 private static final int STORE = 1;
52 private static final int READ = 2;
54 private InputStream is;
55 private int state = NONE;
56 private Capacitor capacitor;
58 public BufferedServletInputStream(InputStream is) {
64 public int read() throws IOException {
66 if (capacitor==null) {
73 capacitor.put((byte)value);
77 value = capacitor.read();
80 capacitor=null; // all done with buffer
88 public int read(byte[] b) throws IOException {
89 return read(b,0,b.length);
93 public int read(byte[] b, int off, int len) throws IOException {
95 if (capacitor==null) {
96 count = is.read(b,off,len);
100 count = is.read(b, off, len);
102 capacitor.put(b, off, count);
106 count = capacitor.read(b, off, len);
109 capacitor=null; // all done with buffer
112 int temp = is.read(b, count, len-count);
113 if (temp>0) { // watch for -1
115 } else if (count<=0) {
116 count = temp; // must account for Stream coming back -1
125 public long skip(long n) throws IOException {
126 long skipped = capacitor.skip(n);
128 skipped += is.skip(n-skipped);
134 public int available() throws IOException {
135 int count = is.available();
136 if (capacitor!=null)count+=capacitor.available();
141 * Return just amount buffered (for debugging purposes, mostly)
144 public int buffered() {
145 return capacitor.available();
149 public void close() throws IOException {
150 if (capacitor!=null) {
159 * Note: Readlimit is ignored in this implementation, because the need was for unknown buffer size which wouldn't
160 * require allocating and dumping huge chunks of memory every use, or risk overflow.
162 public synchronized void mark(int readlimit) {
165 capacitor = new Capacitor();
178 * Calling this twice is not supported in typical Stream situations, but it is allowed in this service. The caveat is that it can only reset
179 * the data read in since Mark has been called. The data integrity is only valid if you have not continued to read past what is stored.
182 public synchronized void reset() throws IOException {
185 capacitor.setForRead();
192 throw new IOException("InputStream has not been marked");
197 public boolean markSupported() {