/******************************************************************************* * gMix open source project - https://svs.informatik.uni-hamburg.de/gmix/ * Copyright (C) 2014 SVS * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ /** */ package userGeneratedContent.testbedPlugIns.layerPlugIns.layer5application.httpPush_v0_001.dataObjects; import java.util.Arrays; import java.util.LinkedList; /** * @author bash * SynchronizedBuffer.java * * This class represents a buffer for message handling. * * Incoming messages are added as byte[] to this buffer. The processing * objects are able to remove messages from this buffer. * * The buffer contains a linked list of byte[]. * * byte[] could be added to the buffer and removed if necessary. * * * This buffer is threadsafe. * */ public class SynchronizedBuffer { private LinkedList<byte[]> buffer; private int byteSize; /** * Constructor */ public SynchronizedBuffer() { this.buffer = new LinkedList<byte[]>(); this.byteSize = 0; } /** * Method to add a new element at the end of the List * * @param message */ public void addArrayToBuffer(byte[] message) { synchronized (buffer) { buffer.add(message); byteSize += message.length; } } /** * Method to get the first element of the queue without removing the element * from queue * * @return byte[] from top of the list */ public byte[] peekBuffer() { synchronized (buffer) { return buffer.peek(); } } /** * This method allows to remove a designated amount of bytes from this * buffer * * @param amount * @return `amount' bytes as byte[] */ public byte[] removeBytes(int amount) { synchronized (buffer) { if (byteSize < amount) { return null; } byte[] result = new byte[amount]; int pos = 0; byte[] buf = null; while (pos < amount) { buf = buffer.poll(); System.arraycopy(buf, 0, result, pos, Math.min(amount - pos, buf.length)); pos += buf.length; } if (pos > amount) { buffer.addFirst(Arrays.copyOfRange(buf, buf.length - (pos - amount), buf.length)); } byteSize -= amount; return result; } } /** * This method allows to inspect, but not remove, a designated amount of * bytes from this buffer * * @param amount * @return `amount' bytes as byte[] */ public byte[] peekBytes(int amount) { synchronized (buffer) { if (byteSize < amount) { return null; } byte[] result = new byte[amount]; int pos = 0; byte[] buf = null; int bufferPos = 0; while (pos < amount) { buf = buffer.get(bufferPos); System.arraycopy(buf, 0, result, pos, Math.min(amount - pos, buf.length)); pos += buf.length; bufferPos += 1; } return result; } } /** * Removes the top of the list * * @return byte[] from top of the list */ public byte[] removeTopOfBuffer() { synchronized (buffer) { byteSize -= buffer.peek().length; return buffer.poll(); } } /** * Return size of list * * @return amount of byte[] contained in the buffer */ public int getLength() { return buffer.size(); } /** * Return the byte amount contained by the buffer * * @return the byteSize */ public int getByteSize() { return byteSize; } /** * Remove a header from top of the buffer * * @return a header as string, null if there is no header on top of the * buffer */ public String getHeaderString() { synchronized (buffer) { int pos = 0; byte pre = 0; for (byte[] array : buffer) { for (int pos2 = 0; pos2 < array.length; pos2++) { pos += 1; if (pre == 13 && array[pos2] == 10) { byte[] message = removeBytes(pos); return new String(message, 0, pos); } pre = array[pos2]; } } if (getByteSize() > 0) { int length = getByteSize(); byte[] message = removeBytes(getByteSize()); return new String(message, 0, length); } return null; } } /** * Method to return the length of a chunk from the first line of a chunk * * @return chunk length in hex */ public String getChunkHeaderLine() { byte pre = 0; int i = 0; for (byte[] array : buffer) { for (int pos2 = 0; pos2 < array.length; pos2++) { i += 1; if (pre == 13 && array[pos2] == 10) { byte[] message = peekBytes(i); return new String(message, 0, i); } pre = array[pos2]; } } return null; } /** * Method for debugging purpose * * @return complete buffer as String */ public String getAllDataAsString() { String string = "readBytesSize: " + byteSize + "\r\n" + "queueSize: " + buffer.size() + "\r\n" + "DeterSize: " + getLength() + "\r\n"; synchronized (buffer) { for (int i = 0; i < buffer.size(); i++) { string += "bufferpartlength: "; string += buffer.get(i).length; string += "\r\n"; } for (int i = 0; i < buffer.size(); i++) { string += new String(buffer.get(i)); string += "------------------"; } } return string; } }