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.nio.ByteBuffer;
25 import java.util.ArrayList;
30 * Storage mechanism for read data, specifically designed for InputStreams.
32 * The Standard BufferedInputStream requires a limit to be set for buffered reading, which is
33 * impractical for reading SOAP headers, which can be quite large.
37 public class Capacitor {
38 private static final int DEFAULT_CHUNK = 256;
39 private ArrayList<ByteBuffer> bbs = new ArrayList<>();
40 private ByteBuffer curr = null;
43 // Maintain a private RingBuffer for Memory, for efficiency
44 private static ByteBuffer[] ring = new ByteBuffer[16];
45 private static int start, end;
48 public void put(byte b) {
49 if (curr == null || curr.remaining()==0) { // ensure we have a "curr" buffer ready for data
58 if (curr.remaining()>0) { // have a buffer, use it!
60 } else if (idx<bbs.size()){ // Buffer not enough, get next one from array
64 } // if no curr buffer, treat as end of stream
69 * read into an array like Streams
76 public int read(byte[] array, int offset, int length) {
77 if (curr==null)return -1;
80 while (length>0) { // loop through while there's data needed
81 if ((len=curr.remaining())>length) { // if enough data in curr buffer, use this code
82 curr.get(array,offset,length);
85 } else { // get data from curr, mark how much is needed to fulfil, and loop for next curr.
86 curr.get(array,offset,len);
93 length=0; // stop, and return the count of how many we were able to load
101 * Put an array of data into Capacitor
107 public void put(byte[] array, int offset, int length) {
108 if (curr == null || curr.remaining()==0) {
115 if ((len=curr.remaining())>length) {
116 curr.put(array,offset,length);
119 // System.out.println(new String(array));
120 curr.put(array,offset,len);
130 * Move state from Storage mode into Read mode, changing all internal buffers to read mode, etc
132 public void setForRead() {
133 for (ByteBuffer bb : bbs) {
146 * reuse all the buffers
149 for (ByteBuffer bb : bbs) {
157 * Declare amount of data available to be read at once.
161 public int available() {
163 for (ByteBuffer bb : bbs) {
164 count+=bb.remaining();
170 * Returns how many are left that were not skipped
174 public long skip(long n) {
181 if (n<(skip=curr.remaining())) {
182 curr.position(curr.position()+(int)n);
186 curr.position(curr.limit());
189 if (idx<bbs.size()) {
197 return skipped > 0 ? skipped : 0;
200 * Be able to re-read data that is stored that has already been re-read. This is not a standard Stream behavior, but can be useful
201 * in a standalone mode.
203 public void reset() {
204 for (ByteBuffer bb : bbs) {
217 * Ring Functions. Reuse allocated memory
219 private ByteBuffer ringGet() {
220 ByteBuffer bb = null;
224 if (bb!=null && ++start>15)start=0;
227 bb=ByteBuffer.allocate(DEFAULT_CHUNK);
229 bb.clear();// refresh reused buffer
234 private void ringPut(ByteBuffer bb) {
236 ring[end]=bb; // if null or not, BB will just be Garbage collected