/******************************************************************************* * ============LICENSE_START==================================================== * * org.onap.aaf * * =========================================================================== * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. * * =========================================================================== * * 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. * * ============LICENSE_END==================================================== * * * * ECOMP is a trademark and service mark of AT&T Intellectual Property. * * ******************************************************************************/ package com.att.cadi; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletInputStream; /** * BufferedServletInputStream * * There are cases in brain-dead middleware (SOAP) where they store routing information in the content. * * In HTTP, this requires reading the content from the InputStream which, of course, cannot be re-read. * * BufferedInputStream exists to implement the "Mark" protocols for Streaming, which will enable being * re-read. Unfortunately, J2EE chose to require a "ServletInputStream" as an abstract class, rather than * an interface, which requires we create a delegating pattern, rather than the preferred inheriting pattern. * * Unfortunately, the standard "BufferedInputStream" cannot be used, because it simply creates a byte array * in the "mark(int)" method of that size. This is not appropriate for this application, because the Header * can be potentially huge, and if a buffer was allocated to accommodate all possibilities, the cost of memory * allocation would be too large for high performance transactions. * * * */ public class BufferedServletInputStream extends ServletInputStream { private static final int NONE = 0; private static final int STORE = 1; private static final int READ = 2; private InputStream is; private int state = NONE; private Capacitor capacitor; public BufferedServletInputStream(InputStream is) { this.is = is; capacitor = null; } // @Override public int read() throws IOException { int value=-1; if(capacitor==null) { value=is.read(); } else { switch(state) { case STORE: value = is.read(); if(value>=0) { capacitor.put((byte)value); } break; case READ: value = capacitor.read(); if(value<0) { capacitor.done(); capacitor=null; // all done with buffer value = is.read(); } } } return value; } // @Override public int read(byte[] b) throws IOException { return read(b,0,b.length); } // @Override public int read(byte[] b, int off, int len) throws IOException { int count = -1; if(capacitor==null) { count = is.read(b,off,len); } else { switch(state) { case STORE: count = is.read(b, off, len); if(count>0) { capacitor.put(b, off, count); } break; case READ: count = capacitor.read(b, off, len); // System.out.println("Capacitor read " + count); if(count<=0) { capacitor.done(); capacitor=null; // all done with buffer } if(count0) { // watch for -1 count+=temp; } else { if(count<=0)count = temp; // must account for Stream coming back -1 } } break; } } // System.out.println("read reports " + count); return count; } // @Override public long skip(long n) throws IOException { long skipped = capacitor.skip(n); if(skipped