/* * Hibernate, Relational Persistence for Idiomatic Java * * JBoss, Home of Professional Open Source * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors * as indicated by the @authors tag. All rights reserved. * See the copyright.txt in the distribution for a * full listing of individual contributors. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License, v. 2.1. * This program is distributed in the hope that it will be useful, but WITHOUT A * 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, * v.2.1 along with this distribution; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ package org.hibernate.search.backend.impl.jgroups; import java.nio.charset.Charset; import org.hibernate.search.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 <sanne@hibernate.org> (C) 2012 Red Hat Inc. */ public class MessageSerializationHelper { private static final Charset STRING_ENCODING = Charset.forName( "UTF-8" ); /** * 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 rawBuffer an array of byte. * @return the String, assuming it's encoded by this same class. */ public static String extractIndexName(final byte[] rawBuffer) { int indexNameByteLength = fromByteToInt( rawBuffer[0] ); return new String( rawBuffer, 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 rawBuffer an array of byte. * @return the smaller byte buffer */ public static byte[] extractSerializedQueue(final byte[] rawBuffer) { int indexNameByteLength = rawBuffer[0]; byte[] serializedQueue = new byte[ rawBuffer.length - 1 - indexNameByteLength ]; System.arraycopy( rawBuffer, indexNameByteLength + 1, 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; } }