package edu.washington.cs.oneswarm.f2f.messaging;
import java.io.UnsupportedEncodingException;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.DirectByteBuffer;
import org.gudy.azureus2.core3.util.DirectByteBufferPool;
import com.aelitis.azureus.core.peermanager.messaging.Message;
import com.aelitis.azureus.core.peermanager.messaging.MessageException;
public class OSF2FTextSearch extends OSF2FSearch implements OSF2FMessage {
private final byte type;
private final String searchString;
private byte[] searchStringBytes;
private String description;
private DirectByteBuffer buffer;
private final static int BASE_MESSAGE_LENGTH = 5; // 1 byte type, 4 byte id
private final static int MAX_MESSAGE_LENGTH = 109;
private static final int MAX_SEARCH_STRING_LENGTH = MAX_MESSAGE_LENGTH - BASE_MESSAGE_LENGTH;
private final int messageLength;
public OSF2FTextSearch(byte version, byte type, int searchID, String searchString) {
super(version, searchID);
this.searchString = searchString;
byte[] bytes;
try {
bytes = searchString.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
bytes = searchString.getBytes();
}
if (bytes.length <= MAX_SEARCH_STRING_LENGTH) {
this.searchStringBytes = bytes;
} else {
// Search string too large, crop it.
this.searchStringBytes = new byte[MAX_SEARCH_STRING_LENGTH];
System.arraycopy(bytes, 0, this.searchStringBytes, 0, MAX_SEARCH_STRING_LENGTH);
Debug.out("Search '" + searchString + "' too long, cropping.");
}
this.type = type;
this.messageLength = BASE_MESSAGE_LENGTH + searchStringBytes.length;
}
@Override
public OSF2FTextSearch clone() {
return new OSF2FTextSearch(this.getVersion(), type, this.getSearchID(),
this.getSearchString());
}
public String getSearchString() {
return searchString;
}
@Override
public String getID() {
return OSF2FMessage.ID_OS_TEXT_SEARCH;
}
@Override
public byte[] getIDBytes() {
return OSF2FMessage.ID_OS_TEXT_SEARCH_BYTES;
}
@Override
public String getFeatureID() {
return OSF2FMessage.OS_FEATURE_ID;
}
@Override
public int getFeatureSubID() {
return OSF2FMessage.SUBID_OS_TEXT_SEARCH;
}
@Override
public int getType() {
return Message.TYPE_PROTOCOL_PAYLOAD;
}
@Override
public String getDescription() {
if (description == null) {
description = OSF2FMessage.ID_OS_TEXT_SEARCH + "\tsearchID="
+ Integer.toHexString(getSearchID()) + "\tstring=" + searchString;
}
return description;
}
@Override
public DirectByteBuffer[] getData() {
if (buffer == null) {
buffer = DirectByteBufferPool.getBuffer(DirectByteBuffer.AL_MSG, messageLength);
buffer.put(DirectByteBuffer.SS_MSG, type);
buffer.putInt(DirectByteBuffer.SS_MSG, getSearchID());
buffer.put(DirectByteBuffer.SS_MSG, searchStringBytes);
buffer.flip(DirectByteBuffer.SS_MSG);
}
return new DirectByteBuffer[] { buffer };
}
@Override
public Message deserialize(DirectByteBuffer data, byte version) throws MessageException {
if (data == null) {
throw new MessageException("[" + getID() + "] decode error: data == null");
}
if (data.remaining(DirectByteBuffer.SS_MSG) <= BASE_MESSAGE_LENGTH) {
throw new MessageException("[" + getID() + "] decode error: payload.remaining["
+ data.remaining(DirectByteBuffer.SS_MSG) + "] <= " + BASE_MESSAGE_LENGTH);
}
byte type = data.get(DirectByteBuffer.SS_MSG);
int search = data.getInt(DirectByteBuffer.SS_MSG);
int stringLength = data.remaining(DirectByteBuffer.SS_MSG);
byte[] stringBytes = new byte[stringLength];
data.get(DirectByteBuffer.SS_MSG, stringBytes);
data.returnToPool();
try {
return new OSF2FTextSearch(version, type, search, new String(stringBytes, "UTF-8"));
} catch (UnsupportedEncodingException e) {
Debug.out("unable to decode packet using utf-8, fallback to std encoding", e);
return new OSF2FTextSearch(version, type, search, new String(stringBytes));
}
}
@Override
public void destroy() {
if (buffer != null)
buffer.returnToPool();
}
public byte getRequestType() {
return type;
}
@Override
public int getMessageSize() {
return messageLength;
}
@Override
public int getValueID() {
return searchString.hashCode();
}
}