/* * Hibernate Search, full-text search for your domain model * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.search.backend.jgroups.impl; import java.nio.charset.Charset; import org.hibernate.search.exception.SearchException; /** * While we use the configured LuceneWorkSerializer to serialize the Work queue, * the JGroups backend needs to prefix the stream with the index name. * * @author Sanne Grinovero (C) 2012 Red Hat Inc. */ public final class MessageSerializationHelper { private static final Charset STRING_ENCODING = Charset.forName( "UTF-8" ); private MessageSerializationHelper() { //not allowed } /** * Byte encodes a String as a prefix for an existing byte buffer * * @param name the string to encode * @param data the existing buffer * @return a new buffer containing the length of the string buffer, the string buffer and then the data. */ public static byte[] prependString(final String name, final byte[] data) { byte[] string = name.getBytes( STRING_ENCODING ); if ( string.length > 255 ) { throw new SearchException( "Index name is too long to be encoded" ); } byte[] result = new byte[ data.length + string.length + 1 ]; result[0] = fromIntToByte( string.length ); System.arraycopy( string, 0, result, 1, string.length ); System.arraycopy( data, 0, result, 1 + string.length, data.length ); return result; } /** * Extracts the string only from the header of a byte array. * Is the reverse operation of {@link #prependString(String, byte[])} * The buffer is not altered. * * @param startingOffset the starting offset of our message in the larger network buffer * @param rawBuffer an array of byte. * @return the String, assuming it's encoded by this same class. */ public static String extractIndexName(final int startingOffset, final byte[] rawBuffer) { int indexNameByteLength = fromByteToInt( rawBuffer[startingOffset] ); return new String( rawBuffer, startingOffset + 1, indexNameByteLength, STRING_ENCODING ); } /** * Inverse operation of {@link #prependString(String, byte[])}: extracts * the original buffer discarding the prefixed string. * The buffer is not altered. * * @param startingOffset the starting offset of our message in the larger network buffer * @param bufferLength we won't attempt to access the buffer beyond this index * @param rawBuffer an array of byte. * @return the smaller byte buffer */ public static byte[] extractSerializedQueue(final int startingOffset, final int bufferLength, final byte[] rawBuffer) { final int indexNameByteLength = fromByteToInt( rawBuffer[startingOffset] ); final int relevantStartingOffset = startingOffset + 1 + indexNameByteLength; byte[] serializedQueue = new byte[ bufferLength - 1 - indexNameByteLength ]; System.arraycopy( rawBuffer, relevantStartingOffset, serializedQueue, 0, serializedQueue.length ); return serializedQueue; } public static int fromByteToInt(byte b) { return b & 0xFF; } public static byte fromIntToByte(int i) { if ( i > 255 ) { throw new SearchException( "Int is too long to be encoded" ); } return (byte) i; } }