/* * Copyright (c) 2007, 2011-2013 Eike Stepper (Berlin, Germany) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eike Stepper - initial API and implementation */ package org.eclipse.internal.net4j.buffer; import org.eclipse.net4j.util.WrappedException; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; /** * @author Eike Stepper */ public final class BufferUtil { public static final String UTF8_CHAR_SET_NAME = "UTF-8"; //$NON-NLS-1$ private static final Charset CHARSET = Charset.forName(UTF8_CHAR_SET_NAME); private static final byte FALSE = (byte)0; private static final byte TRUE = (byte)1; private BufferUtil() { } /** * @deprecated Use {@link #putString(ByteBuffer, String, boolean)} */ @Deprecated public static byte[] toUTF8(String str) { if (str == null) { return new byte[0]; } byte[] bytes; String test; try { bytes = str.getBytes(UTF8_CHAR_SET_NAME); test = new String(bytes, UTF8_CHAR_SET_NAME); } catch (UnsupportedEncodingException ex) { // This should really not happen throw WrappedException.wrap(ex); } if (!test.equals(str)) { throw new IllegalArgumentException("String not encodable: " + str); //$NON-NLS-1$ } return bytes; } /** * @deprecated Use {@link #getString(ByteBuffer)} */ @Deprecated public static String fromUTF8(byte[] bytes) { try { return new String(bytes, UTF8_CHAR_SET_NAME); } catch (UnsupportedEncodingException ex) { // This should really not happen throw WrappedException.wrap(ex); } } /** * @deprecated Use {@link #putString(ByteBuffer, String, boolean)} */ @Deprecated public static void putUTF8(ByteBuffer byteBuffer, String str) { putString(byteBuffer, str, false); } public static void putObject(ByteBuffer byteBuffer, Object object) throws IOException { if (object != null) { byteBuffer.put(TRUE); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream stream = new ObjectOutputStream(baos); stream.writeObject(object); byte[] array = baos.toByteArray(); putByteArray(byteBuffer, array); } else { byteBuffer.put(FALSE); } } public static Object getObject(ByteBuffer byteBuffer) throws IOException, ClassNotFoundException { boolean nonNull = byteBuffer.get() == TRUE; if (nonNull) { byte[] array = getByteArray(byteBuffer); ByteArrayInputStream bais = new ByteArrayInputStream(array); ObjectInputStream stream = new ObjectInputStream(bais); return stream.readObject(); } return null; } public static void putByteArray(ByteBuffer byteBuffer, byte[] array) { short length = array == null ? 0 : (short)array.length; byteBuffer.putShort(length); // BYTE_ARRAY_PREFIX if (length != 0) { byteBuffer.put(array); } } public static byte[] getByteArray(ByteBuffer byteBuffer) { short length = byteBuffer.getShort(); byte[] array = new byte[length]; if (length != 0) { byteBuffer.get(array); } return array; } public static void putString(ByteBuffer byteBuffer, String str, boolean bestEffort) { int sizePosition = byteBuffer.position(); byteBuffer.putShort((short)-1); // Placeholder for size if (str != null) { CharsetEncoder encoder = CHARSET.newEncoder(); CharBuffer input = CharBuffer.wrap(str); int start = byteBuffer.position(); int max = -1; for (;;) { CoderResult result = encoder.encode(input, byteBuffer, true); if (result.isError()) { if (result.isOverflow() && bestEffort) { if (max == -1) { max = (int)(byteBuffer.remaining() / encoder.maxBytesPerChar()); } else { --max; } if (max > 0) { str = str.substring(0, max); byteBuffer.position(start); continue; } } try { result.throwException(); } catch (Exception ex) { throw WrappedException.wrap(ex); } } break; } int end = byteBuffer.position(); short size = (short)Math.abs(end - start); byteBuffer.position(sizePosition); byteBuffer.putShort(size); byteBuffer.position(end); } } public static String getString(ByteBuffer byteBuffer) { short size = byteBuffer.getShort(); if (size == -1) { return null; } if (size == 0) { return ""; } byte[] bytes = new byte[size]; byteBuffer.get(bytes); try { return new String(bytes, UTF8_CHAR_SET_NAME); } catch (UnsupportedEncodingException ex) { // This should really not happen throw WrappedException.wrap(ex); } } }