/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.apache.activemq.apollo.openwire.codec;
import org.apache.activemq.apollo.openwire.command.DataStructure;
import org.fusesource.hawtbuf.Buffer;
import org.fusesource.hawtbuf.DataByteArrayInputStream;
import org.fusesource.hawtbuf.DataByteArrayOutputStream;
import org.fusesource.hawtbuf.UTF8Buffer;
import java.io.IOException;
import java.lang.reflect.Constructor;
public abstract class BaseDataStreamMarshaller implements DataStreamMarshaller {
public static final Constructor STACK_TRACE_ELEMENT_CONSTRUCTOR;
static {
Constructor constructor = null;
try {
constructor = StackTraceElement.class.getConstructor(new Class[] {UTF8Buffer.class, UTF8Buffer.class,
UTF8Buffer.class, int.class});
} catch (Throwable e) {
}
STACK_TRACE_ELEMENT_CONSTRUCTOR = constructor;
}
public abstract byte getDataStructureType();
public abstract DataStructure createObject();
public int tightMarshal1(OpenWireFormat wireFormat, Object o, BooleanStream bs) throws IOException {
return 0;
}
public void tightMarshal2(OpenWireFormat wireFormat, Object o, DataByteArrayOutputStream dataOut, BooleanStream bs)
throws IOException {
}
public void tightUnmarshal(OpenWireFormat wireFormat, Object o, DataByteArrayInputStream dataIn, BooleanStream bs)
throws IOException {
}
public int tightMarshalLong1(OpenWireFormat wireFormat, long o, BooleanStream bs) throws IOException {
if (o == 0) {
bs.writeBoolean(false);
bs.writeBoolean(false);
return 0;
} else if ((o & 0xFFFFFFFFFFFF0000L) == 0) {
bs.writeBoolean(false);
bs.writeBoolean(true);
return 2;
} else if ((o & 0xFFFFFFFF00000000L) == 0) {
bs.writeBoolean(true);
bs.writeBoolean(false);
return 4;
} else {
bs.writeBoolean(true);
bs.writeBoolean(true);
return 8;
}
}
public void tightMarshalLong2(OpenWireFormat wireFormat, long o, DataByteArrayOutputStream dataOut, BooleanStream bs)
throws IOException {
if (bs.readBoolean()) {
if (bs.readBoolean()) {
dataOut.writeLong(o);
} else {
dataOut.writeInt((int)o);
}
} else {
if (bs.readBoolean()) {
dataOut.writeShort((int)o);
}
}
}
public long tightUnmarshalLong(OpenWireFormat wireFormat, DataByteArrayInputStream dataIn, BooleanStream bs)
throws IOException {
if (bs.readBoolean()) {
if (bs.readBoolean()) {
return dataIn.readLong();
} else {
return toLong(dataIn.readInt());
}
} else {
if (bs.readBoolean()) {
return toLong(dataIn.readShort());
} else {
return 0;
}
}
}
protected long toLong(short value) {
// lets handle negative values
long answer = value;
return answer & 0xffffL;
}
protected long toLong(int value) {
// lets handle negative values
long answer = value;
return answer & 0xffffffffL;
}
protected DataStructure tightUnmarsalNestedObject(OpenWireFormat wireFormat, DataByteArrayInputStream dataIn,
BooleanStream bs) throws IOException {
return wireFormat.tightUnmarshalNestedObject(dataIn, bs);
}
protected int tightMarshalNestedObject1(OpenWireFormat wireFormat, DataStructure o, BooleanStream bs)
throws IOException {
return wireFormat.tightMarshalNestedObject1(o, bs);
}
protected void tightMarshalNestedObject2(OpenWireFormat wireFormat, DataStructure o, DataByteArrayOutputStream dataOut,
BooleanStream bs) throws IOException {
wireFormat.tightMarshalNestedObject2(o, dataOut, bs);
}
protected DataStructure tightUnmarsalCachedObject(OpenWireFormat wireFormat, DataByteArrayInputStream dataIn,
BooleanStream bs) throws IOException {
if (wireFormat.isCacheEnabled()) {
if (bs.readBoolean()) {
short index = dataIn.readShort();
DataStructure object = wireFormat.tightUnmarshalNestedObject(dataIn, bs);
wireFormat.setInUnmarshallCache(index, object);
return object;
} else {
short index = dataIn.readShort();
return wireFormat.getFromUnmarshallCache(index);
}
} else {
return wireFormat.tightUnmarshalNestedObject(dataIn, bs);
}
}
protected int tightMarshalCachedObject1(OpenWireFormat wireFormat, DataStructure o, BooleanStream bs)
throws IOException {
if (wireFormat.isCacheEnabled()) {
Short index = wireFormat.getMarshallCacheIndex(o);
bs.writeBoolean(index == null);
if (index == null) {
int rc = wireFormat.tightMarshalNestedObject1(o, bs);
wireFormat.addToMarshallCache(o);
return 2 + rc;
} else {
return 2;
}
} else {
return wireFormat.tightMarshalNestedObject1(o, bs);
}
}
protected void tightMarshalCachedObject2(OpenWireFormat wireFormat, DataStructure o, DataByteArrayOutputStream dataOut,
BooleanStream bs) throws IOException {
if (wireFormat.isCacheEnabled()) {
Short index = wireFormat.getMarshallCacheIndex(o);
if (bs.readBoolean()) {
dataOut.writeShort(index.shortValue());
wireFormat.tightMarshalNestedObject2(o, dataOut, bs);
} else {
dataOut.writeShort(index.shortValue());
}
} else {
wireFormat.tightMarshalNestedObject2(o, dataOut, bs);
}
}
protected Throwable tightUnmarsalThrowable(OpenWireFormat wireFormat, DataByteArrayInputStream dataIn, BooleanStream bs)
throws IOException {
if (bs.readBoolean()) {
UTF8Buffer clazz = tightUnmarshalString(dataIn, bs);
UTF8Buffer message = tightUnmarshalString(dataIn, bs);
Throwable o = createThrowable(clazz, message);
if (wireFormat.isStackTraceEnabled()) {
if (STACK_TRACE_ELEMENT_CONSTRUCTOR != null) {
StackTraceElement ss[] = new StackTraceElement[dataIn.readShort()];
for (int i = 0; i < ss.length; i++) {
try {
ss[i] = (StackTraceElement)STACK_TRACE_ELEMENT_CONSTRUCTOR
.newInstance(new Object[] {tightUnmarshalString(dataIn, bs),
tightUnmarshalString(dataIn, bs),
tightUnmarshalString(dataIn, bs),
Integer.valueOf(dataIn.readInt())});
} catch (IOException e) {
throw e;
} catch (Throwable e) {
}
}
o.setStackTrace(ss);
} else {
short size = dataIn.readShort();
for (int i = 0; i < size; i++) {
tightUnmarshalString(dataIn, bs);
tightUnmarshalString(dataIn, bs);
tightUnmarshalString(dataIn, bs);
dataIn.readInt();
}
}
o.initCause(tightUnmarsalThrowable(wireFormat, dataIn, bs));
}
return o;
} else {
return null;
}
}
private Throwable createThrowable(UTF8Buffer className, UTF8Buffer message) {
try {
Class clazz = Class.forName(className.toString(), false, BaseDataStreamMarshaller.class.getClassLoader());
Constructor constructor = clazz.getConstructor(new Class[] {UTF8Buffer.class});
return (Throwable)constructor.newInstance(new Object[] {message.toString()});
} catch (Throwable e) {
return new Throwable(className + ": " + message);
}
}
protected int tightMarshalThrowable1(OpenWireFormat wireFormat, Throwable o, BooleanStream bs)
throws IOException {
if (o == null) {
bs.writeBoolean(false);
return 0;
} else {
int rc = 0;
bs.writeBoolean(true);
rc += tightMarshalString1(new UTF8Buffer(o.getClass().getName()), bs);
rc += tightMarshalString1(new UTF8Buffer(o.getMessage()), bs);
if (wireFormat.isStackTraceEnabled()) {
rc += 2;
StackTraceElement[] stackTrace = o.getStackTrace();
for (int i = 0; i < stackTrace.length; i++) {
StackTraceElement element = stackTrace[i];
rc += tightMarshalString1(new UTF8Buffer(element.getClassName()), bs);
rc += tightMarshalString1(new UTF8Buffer(element.getMethodName()), bs);
rc += tightMarshalString1(new UTF8Buffer(element.getFileName()), bs);
rc += 4;
}
rc += tightMarshalThrowable1(wireFormat, o.getCause(), bs);
}
return rc;
}
}
protected void tightMarshalThrowable2(OpenWireFormat wireFormat, Throwable o, DataByteArrayOutputStream dataOut,
BooleanStream bs) throws IOException {
if (bs.readBoolean()) {
tightMarshalString2(new UTF8Buffer(o.getClass().getName()), dataOut, bs);
tightMarshalString2(new UTF8Buffer(o.getMessage()), dataOut, bs);
if (wireFormat.isStackTraceEnabled()) {
StackTraceElement[] stackTrace = o.getStackTrace();
dataOut.writeShort(stackTrace.length);
for (int i = 0; i < stackTrace.length; i++) {
StackTraceElement element = stackTrace[i];
tightMarshalString2(new UTF8Buffer(element.getClassName()), dataOut, bs);
tightMarshalString2(new UTF8Buffer(element.getMethodName()), dataOut, bs);
tightMarshalString2(new UTF8Buffer(element.getFileName()), dataOut, bs);
dataOut.writeInt(element.getLineNumber());
}
tightMarshalThrowable2(wireFormat, o.getCause(), dataOut, bs);
}
}
}
@SuppressWarnings("deprecation")
protected UTF8Buffer tightUnmarshalString(DataByteArrayInputStream dataIn, BooleanStream bs) throws IOException {
if (bs.readBoolean()) {
boolean ascii = bs.readBoolean(); // ignored for now.
int size = dataIn.readShort();
if( size== 0 ) {
return new UTF8Buffer("");
} else {
Buffer buffer = dataIn.readBuffer(size);
return buffer.utf8();
}
} else {
return null;
}
}
protected int tightMarshalString1(UTF8Buffer value, BooleanStream bs) throws IOException {
bs.writeBoolean(value != null);
if (value != null) {
boolean ascii = false;
// we could check to see if its' really ascii.. for now punt.
// boolean ascii = true;
// int last = value.offset+value.length;
// for (int i = value.offset; i < last; i++) {
// if( (value.data[i] & 0x80) !=0 ) {
// ascii = false;
// }
// }
bs.writeBoolean(ascii);
return value.length() + 2;
} else {
return 0;
}
}
protected void tightMarshalString2(UTF8Buffer value, DataByteArrayOutputStream dataOut, BooleanStream bs) throws IOException {
if (bs.readBoolean()) {
// If we verified it only holds ascii values
bs.readBoolean();
dataOut.writeShort(value.length);
dataOut.write(value);
}
}
protected int tightMarshalObjectArray1(OpenWireFormat wireFormat, DataStructure[] objects,
BooleanStream bs) throws IOException {
if (objects != null) {
int rc = 0;
bs.writeBoolean(true);
rc += 2;
for (int i = 0; i < objects.length; i++) {
rc += tightMarshalNestedObject1(wireFormat, objects[i], bs);
}
return rc;
} else {
bs.writeBoolean(false);
return 0;
}
}
protected void tightMarshalObjectArray2(OpenWireFormat wireFormat, DataStructure[] objects,
DataByteArrayOutputStream dataOut, BooleanStream bs) throws IOException {
if (bs.readBoolean()) {
dataOut.writeShort(objects.length);
for (int i = 0; i < objects.length; i++) {
tightMarshalNestedObject2(wireFormat, objects[i], dataOut, bs);
}
}
}
protected int tightMarshalConstByteArray1(byte[] data, BooleanStream bs, int i) throws IOException {
return i;
}
protected void tightMarshalConstByteArray2(byte[] data, DataByteArrayOutputStream dataOut, BooleanStream bs, int i)
throws IOException {
dataOut.write(data, 0, i);
}
protected byte[] tightUnmarshalConstByteArray(DataByteArrayInputStream dataIn, BooleanStream bs, int i)
throws IOException {
byte data[] = new byte[i];
dataIn.readFully(data);
return data;
}
protected int tightMarshalByteArray1(byte[] data, BooleanStream bs) throws IOException {
bs.writeBoolean(data != null);
if (data != null) {
return data.length + 4;
} else {
return 0;
}
}
protected void tightMarshalByteArray2(byte[] data, DataByteArrayOutputStream dataOut, BooleanStream bs)
throws IOException {
if (bs.readBoolean()) {
dataOut.writeInt(data.length);
dataOut.write(data);
}
}
protected byte[] tightUnmarshalByteArray(DataByteArrayInputStream dataIn, BooleanStream bs) throws IOException {
byte rc[] = null;
if (bs.readBoolean()) {
int size = dataIn.readInt();
rc = new byte[size];
dataIn.readFully(rc);
}
return rc;
}
protected int tightMarshalBuffer1(Buffer data, BooleanStream bs) throws IOException {
bs.writeBoolean(data != null);
if (data != null) {
return data.getLength() + 4;
} else {
return 0;
}
}
protected void tightMarshalBuffer2(Buffer data, DataByteArrayOutputStream dataOut, BooleanStream bs)
throws IOException {
if (bs.readBoolean()) {
dataOut.writeInt(data.getLength());
dataOut.write(data.getData(), data.getOffset(), data.getLength());
}
}
protected Buffer tightUnmarshalBuffer(DataByteArrayInputStream dataIn, BooleanStream bs) throws IOException {
Buffer rc = null;
if (bs.readBoolean()) {
int size = dataIn.readInt();
byte[] t = new byte[size];
dataIn.readFully(t);
return new Buffer(t, 0, size);
}
return rc;
}
//
// The loose marshaling logic
//
public void looseMarshal(OpenWireFormat wireFormat, Object o, DataByteArrayOutputStream dataOut) throws IOException {
}
public void looseUnmarshal(OpenWireFormat wireFormat, Object o, DataByteArrayInputStream dataIn) throws IOException {
}
public void looseMarshalLong(OpenWireFormat wireFormat, long o, DataByteArrayOutputStream dataOut) throws IOException {
dataOut.writeLong(o);
}
public long looseUnmarshalLong(OpenWireFormat wireFormat, DataByteArrayInputStream dataIn) throws IOException {
return dataIn.readLong();
}
protected DataStructure looseUnmarsalNestedObject(OpenWireFormat wireFormat, DataByteArrayInputStream dataIn)
throws IOException {
return wireFormat.looseUnmarshalNestedObject(dataIn);
}
protected void looseMarshalNestedObject(OpenWireFormat wireFormat, DataStructure o, DataByteArrayOutputStream dataOut)
throws IOException {
wireFormat.looseMarshalNestedObject(o, dataOut);
}
protected DataStructure looseUnmarsalCachedObject(OpenWireFormat wireFormat, DataByteArrayInputStream dataIn)
throws IOException {
if (wireFormat.isCacheEnabled()) {
if (dataIn.readBoolean()) {
short index = dataIn.readShort();
DataStructure object = wireFormat.looseUnmarshalNestedObject(dataIn);
wireFormat.setInUnmarshallCache(index, object);
return object;
} else {
short index = dataIn.readShort();
return wireFormat.getFromUnmarshallCache(index);
}
} else {
return wireFormat.looseUnmarshalNestedObject(dataIn);
}
}
protected void looseMarshalCachedObject(OpenWireFormat wireFormat, DataStructure o, DataByteArrayOutputStream dataOut)
throws IOException {
if (wireFormat.isCacheEnabled()) {
Short index = wireFormat.getMarshallCacheIndex(o);
dataOut.writeBoolean(index == null);
if (index == null) {
index = wireFormat.addToMarshallCache(o);
dataOut.writeShort(index.shortValue());
wireFormat.looseMarshalNestedObject(o, dataOut);
} else {
dataOut.writeShort(index.shortValue());
}
} else {
wireFormat.looseMarshalNestedObject(o, dataOut);
}
}
protected Throwable looseUnmarsalThrowable(OpenWireFormat wireFormat, DataByteArrayInputStream dataIn)
throws IOException {
if (dataIn.readBoolean()) {
UTF8Buffer clazz = looseUnmarshalString(dataIn);
UTF8Buffer message = looseUnmarshalString(dataIn);
Throwable o = createThrowable(clazz, message);
if (wireFormat.isStackTraceEnabled()) {
if (STACK_TRACE_ELEMENT_CONSTRUCTOR != null) {
StackTraceElement ss[] = new StackTraceElement[dataIn.readShort()];
for (int i = 0; i < ss.length; i++) {
try {
ss[i] = (StackTraceElement)STACK_TRACE_ELEMENT_CONSTRUCTOR
.newInstance(new Object[] {looseUnmarshalString(dataIn),
looseUnmarshalString(dataIn),
looseUnmarshalString(dataIn),
Integer.valueOf(dataIn.readInt())});
} catch (IOException e) {
throw e;
} catch (Throwable e) {
}
}
o.setStackTrace(ss);
} else {
short size = dataIn.readShort();
for (int i = 0; i < size; i++) {
looseUnmarshalString(dataIn);
looseUnmarshalString(dataIn);
looseUnmarshalString(dataIn);
dataIn.readInt();
}
}
o.initCause(looseUnmarsalThrowable(wireFormat, dataIn));
}
return o;
} else {
return null;
}
}
protected void looseMarshalThrowable(OpenWireFormat wireFormat, Throwable o, DataByteArrayOutputStream dataOut)
throws IOException {
dataOut.writeBoolean(o != null);
if (o != null) {
looseMarshalString(new UTF8Buffer(o.getClass().getName()), dataOut);
looseMarshalString(new UTF8Buffer(o.getMessage()), dataOut);
if (wireFormat.isStackTraceEnabled()) {
StackTraceElement[] stackTrace = o.getStackTrace();
dataOut.writeShort(stackTrace.length);
for (int i = 0; i < stackTrace.length; i++) {
StackTraceElement element = stackTrace[i];
looseMarshalString(new UTF8Buffer(element.getClassName()), dataOut);
looseMarshalString(new UTF8Buffer(element.getMethodName()), dataOut);
looseMarshalString(new UTF8Buffer(element.getFileName()), dataOut);
dataOut.writeInt(element.getLineNumber());
}
looseMarshalThrowable(wireFormat, o.getCause(), dataOut);
}
}
}
protected UTF8Buffer looseUnmarshalString(DataByteArrayInputStream dataIn) throws IOException {
if (dataIn.readBoolean()) {
int size = dataIn.readShort();
return dataIn.readBuffer(size).utf8();
} else {
return null;
}
}
protected void looseMarshalString(UTF8Buffer value, DataByteArrayOutputStream dataOut) throws IOException {
dataOut.writeBoolean(value != null);
if (value != null) {
dataOut.writeShort(value.length);
dataOut.write(value);
}
}
protected void looseMarshalObjectArray(OpenWireFormat wireFormat, DataStructure[] objects,
DataByteArrayOutputStream dataOut) throws IOException {
dataOut.writeBoolean(objects != null);
if (objects != null) {
dataOut.writeShort(objects.length);
for (int i = 0; i < objects.length; i++) {
looseMarshalNestedObject(wireFormat, objects[i], dataOut);
}
}
}
protected void looseMarshalConstByteArray(OpenWireFormat wireFormat, byte[] data, DataByteArrayOutputStream dataOut,
int i) throws IOException {
dataOut.write(data, 0, i);
}
protected byte[] looseUnmarshalConstByteArray(DataByteArrayInputStream dataIn, int i) throws IOException {
byte data[] = new byte[i];
dataIn.readFully(data);
return data;
}
protected void looseMarshalByteArray(OpenWireFormat wireFormat, byte[] data, DataByteArrayOutputStream dataOut)
throws IOException {
dataOut.writeBoolean(data != null);
if (data != null) {
dataOut.writeInt(data.length);
dataOut.write(data);
}
}
protected byte[] looseUnmarshalByteArray(DataByteArrayInputStream dataIn) throws IOException {
byte rc[] = null;
if (dataIn.readBoolean()) {
int size = dataIn.readInt();
rc = new byte[size];
dataIn.readFully(rc);
}
return rc;
}
protected void looseMarshalBuffer(OpenWireFormat wireFormat, Buffer data, DataByteArrayOutputStream dataOut)
throws IOException {
dataOut.writeBoolean(data != null);
if (data != null) {
dataOut.writeInt(data.getLength());
dataOut.write(data.getData(), data.getOffset(), data.getLength());
}
}
protected Buffer looseUnmarshalBuffer(DataByteArrayInputStream dataIn) throws IOException {
Buffer rc = null;
if (dataIn.readBoolean()) {
int size = dataIn.readInt();
byte[] t = new byte[size];
dataIn.readFully(t);
rc = new Buffer(t, 0, size);
}
return rc;
}
}