All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgroups.BytesMessage Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

The newest version!

package org.jgroups;


import org.jgroups.util.ByteArray;
import org.jgroups.util.Util;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.function.Supplier;

/**
 * A {@link Message} containing a byte array as payload.
 * 
* The byte array can point to a reference, and we can subset it using index and length. When the message is serialized, * only the bytes between index and length are written. * * @since 5.0 * @author Bela Ban */ public class BytesMessage extends BaseMessage { /** The payload */ protected byte[] array; /** The index into the payload */ protected int offset; /** The number of bytes in the array */ protected int length; public BytesMessage() { } /** * Constructs a message given a destination address * @param dest The Address of the receiver. If it is null, then the message is sent to all cluster members. * Otherwise, it is sent to a single member. */ public BytesMessage(Address dest) { super(dest); } /** * Constructs a message given a destination and source address and the payload byte array * @param dest The Address of the receiver. If it is null, then the message is sent to all cluster members. * Otherwise, it is sent to a single member. * @param array The payload. Note that this array must not be modified (e.g. buf[0]='x' is not * allowed) since we don't copy the contents. */ public BytesMessage(Address dest, byte[] array) { this(dest, array, 0, array != null? array.length : 0); } /** * Constructs a message. The index and length parameters provide a reference to a byte array, rather than a copy, * and refer to a subset of the array. This is important when we want to avoid copying. When the message is * serialized, only the subset is serialized.

* * Note that the byte array passed as argument must not be modified. Reason: if we retransmit the * message, it would still have a ref to the original byte array passed in as argument, and so we would * retransmit a changed byte array ! * * * @param dest The Address of the receiver. If it is null, then the message is sent to all cluster members. * Otherwise, it is sent to a single member. * @param array A reference to a byte array * @param offset The index into the byte array * @param length The number of bytes to be used from buf. Both index and length are checked * for array index violations and an ArrayIndexOutOfBoundsException will be thrown if invalid */ public BytesMessage(Address dest, byte[] array, int offset, int length) { super(dest); setArray(array, offset, length); } public BytesMessage(Address dest, ByteArray array) { super(dest); setArray(array); } /** * Constructs a message given a destination and source address and the payload object * @param dest The Address of the receiver. If it is null, then the message is sent to all cluster members. * Otherwise, it is sent to a single member. * @param obj The object that will be marshalled into the byte array. Has to be serializable (e.g. implementing * Serializable, Externalizable or Streamable, or be a basic type (e.g. Integer, Short etc)). */ public BytesMessage(Address dest, Object obj) { super(dest); setObject(obj); } public BytesMessage setFlag(Flag... flags) { super.setFlag(flags); return this; } public Supplier create() {return BytesMessage::new;} public short getType() {return Message.BYTES_MSG;} public boolean hasPayload() {return array != null;} public boolean hasArray() {return true;} public int getOffset() {return offset;} public int getLength() {return length;} /** * Returns a reference to the payload (byte array). Note that this array should not be * modified as we do not copy the array on copy() or clone(): the array of the copied message * is simply a reference to the old array.
* Even if offset and length are used: we return the entire array, not a subset. */ public byte[] getArray() {return array;} /** * Sets the internal array to point to a subset of a given array.

* * Note that the byte array passed as argument must not be modified. Reason: if we retransmit the * message, it would still have a ref to the original byte array passed in as argument, and so we would * retransmit a changed byte array ! * * * @param b The reference to a given array. If null, we'll reset the array to null * @param offset The initial position * @param length The number of bytes */ public BytesMessage setArray(byte[] b, int offset, int length) { array=b; if(array != null) { if(offset < 0 || offset > array.length) throw new ArrayIndexOutOfBoundsException(offset); if((offset + length) > array.length) throw new ArrayIndexOutOfBoundsException((offset+length)); this.offset=offset; this.length=length; } else this.offset=this.length=0; return this; } /** * Sets the array

* Note that the byte array passed as argument must not be modified. Reason: if we retransmit the * message, it would still have a ref to the original byte array passed in as argument, and so we would * retransmit a changed byte array ! */ public BytesMessage setArray(ByteArray buf) { if(buf != null) { this.array=buf.getArray(); this.offset=buf.getOffset(); this.length=buf.getLength(); } return this; } /** * Takes an object and uses Java serialization to generate the byte array which is set in the * message. Parameter 'obj' has to be serializable (e.g. implementing Serializable, * Externalizable or Streamable, or be a basic type (e.g. Integer, Short etc)). */ public BytesMessage setObject(Object obj) { clearFlag(Flag.SERIALIZED); if(obj == null) { array=null; offset=length=0; return this; } if(obj instanceof byte[]) return setArray((byte[])obj, 0, ((byte[])obj).length); if(obj instanceof ByteArray) return setArray((ByteArray)obj); if(obj instanceof ByteBuffer) { ByteBuffer bb=(ByteBuffer)obj; if(bb.hasArray()) return setArray(bb.array(), bb.arrayOffset()+bb.position(), bb.remaining()); else return (BytesMessage)setArray(Util.bufferToArray(bb)); } try { ByteArray tmp=Util.objectToBuffer(obj); setFlag(Flag.SERIALIZED); return setArray(tmp); } catch(Exception ex) { throw new IllegalArgumentException(ex); } } public T getObject() { return getObject(null); } /** * Uses custom serialization to create an object from the array of the message. Note that this is dangerous when * using your own classloader, e.g. inside of an application server ! Most likely, JGroups will use the system * classloader to deserialize the array into an object, whereas (for example) a web application will want to use * the webapp's classloader, resulting in a ClassCastException. The recommended way is for the application to use * their own serialization and only pass byte array to JGroups.

* As of 3.5, a classloader can be passed in. It will be used first to find a class, before contacting * the other classloaders in the list. If null, the default list of classloaders will be used. * @return the object */ public T getObject(ClassLoader loader) { if(array == null) return null; try { return isFlagSet(Flag.SERIALIZED)? Util.objectFromByteBuffer(array, offset, length, loader) : (T)getArray(); } catch(Exception ex) { throw new IllegalArgumentException(ex); } } public int size() { return super.size() +sizeOfPayload(); } /** * Copies the byte array. If offset and length are used (to refer to another array), the copy will contain only * the subset that offset and length point to, copying the subset into the new copy.

* Note that for headers, only the arrays holding references to the headers are copied, not the headers themselves ! * The consequence is that the headers array of the copy hold the *same* references as the original, so do *not* * modify the headers ! If you want to change a header, copy it and call {@link BytesMessage#putHeader(short,Header)} again. */ @Override protected Message copyPayload(Message copy) { if(array != null) copy.setArray(array, offset, length); return copy; } protected int sizeOfPayload() { int retval=Global.INT_SIZE; // length if(array != null) retval+=length; // number of bytes in the array return retval; } public void writePayload(DataOutput out) throws IOException { out.writeInt(array != null? length : -1); if(array != null) out.write(array, offset, length); } public void readPayload(DataInput in) throws IOException { int len=in.readInt(); if(len >= 0) { array=new byte[len]; in.readFully(array, 0, len); length=len; } } protected T createMessage() { return (T)new BytesMessage(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy