/*
* JBoss, Home of Professional Open Source
* Copyright 2011, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.mobicents.ss7.management.transceiver;
import java.nio.ByteBuffer;
/**
* <p>
* Construct the Shell Command Message
* </p>
*
* <p>
* A given invocation of the Java virtual machine maintains a single system-wide default message factory instance, which is
* returned by the {@link ChannelProvider#getMessageFactory() getMessageFactory} method.
* </p>
*
* @author amit bhayani
*
*/
public class MessageFactory {
public static final int MESSAGE_HEADER_SIZE = 4;
private byte[] header = new byte[MESSAGE_HEADER_SIZE];
private boolean isHeaderReady = false;
private int pos = 0;
private int length;
private byte[] params;
private Message message;
protected MessageFactory() {
}
/**
* Crate new instance of message object
*
* @param message
* @return
*/
public Message createMessage(String message) {
return new Message(message.getBytes());
}
/**
* The received buffer may not have necessary bytes to decode a message. Instance of this factory keeps data locally till
* next set of data is received and a message can be successfully decoded
*
* @param buffer
* @return
*/
public Message createMessage(ByteBuffer buffer) {
if (!isHeaderReady) {
int len = Math.min(MESSAGE_HEADER_SIZE - pos, buffer.remaining());
buffer.get(header, pos, len);
// update cursor postion in the header's buffer
pos += len;
// header completed?
isHeaderReady = pos == header.length;
if (!isHeaderReady) {
// no more data available
return null;
}
// obtain remaining length of the message and prepare buffer
length = ((header[0] & 0xff) << 24);
length += ((header[1] & 0xff) << 16);
length += ((header[2] & 0xff) << 8);
length += (header[3] & 0xff);
length -= MESSAGE_HEADER_SIZE;
params = new byte[length];
// finally switch cursor position
pos = 0;
message = new Message();
}
// at this point we must recheck remainder of the input buffer
// because possible case when input buffer fits exactly to the header
if (length > 0 && !buffer.hasRemaining()) {
return null;
}
// again, reading all parameters before parsing
// compute available or required data
int len = Math.min((params.length - pos), buffer.remaining());
buffer.get(params, pos, len);
// update cursor position
pos += len;
// end of message not reached
if (pos < params.length) {
return null;
}
// end of message reached and most probably some data remains in buffer
// do not touch remainder of the input buffer, next call to this method
// will proceed remainder
// parsing params of this message
message.decode(params);
// switch factory for receiving new message
this.isHeaderReady = false;
this.pos = 0;
// return
return message;
}
}