io.airlift.jmx.http.rpc.HttpMBeanServerRpc Maven / Gradle / Ivy
/*
* Copyright 2010 Proofpoint, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.airlift.jmx.http.rpc;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.charset.Charset;
final class HttpMBeanServerRpc
{
public static final Charset UTF_8 = Charset.forName("UTF-8");
private HttpMBeanServerRpc() {}
public static byte[] createSuccessResponse(Object result)
throws IOException
{
return serialize(result);
}
public static byte[] createExceptionResponse(Exception exception)
throws IOException
{
return serialize(exception);
}
public static byte[] serialize(Object object)
throws IOException
{
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(bytes);
objectOutputStream.writeObject(object);
objectOutputStream.flush();
objectOutputStream.close();
return bytes.toByteArray();
}
public static Object deserialize(InputStream inputStream)
throws IOException
{
try {
return new ObjectInputStream(inputStream).readObject();
}
catch (ClassNotFoundException e) {
throw new IOException(e);
}
}
//
// This code was swiped from Guava
//
public static void propagateIfInstanceOf(Throwable throwable, Class declaredType)
throws X
{
if (throwable != null && declaredType.isInstance(throwable)) {
throw declaredType.cast(throwable);
}
}
public static void propagateIfPossible(Throwable throwable)
{
propagateIfInstanceOf(throwable, Error.class);
propagateIfInstanceOf(throwable, RuntimeException.class);
}
/**
* Implements the "base64" binary encoding scheme as defined by
* RFC 2045.
*
* Portions of code here are taken from Apache Pivot
*/
private static final char[] lookup = new char[64];
private static final byte[] reverseLookup = new byte[256];
static {
// Populate the lookup array
for (int i = 0; i < 26; i++) {
lookup[i] = (char) ('A' + i);
}
for (int i = 26, j = 0; i < 52; i++, j++) {
lookup[i] = (char) ('a' + j);
}
for (int i = 52, j = 0; i < 62; i++, j++) {
lookup[i] = (char) ('0' + j);
}
lookup[62] = '+';
lookup[63] = '/';
// Populate the reverse lookup array
for (int i = 0; i < 256; i++) {
reverseLookup[i] = -1;
}
for (int i = 'Z'; i >= 'A'; i--) {
reverseLookup[i] = (byte) (i - 'A');
}
for (int i = 'z'; i >= 'a'; i--) {
reverseLookup[i] = (byte) (i - 'a' + 26);
}
for (int i = '9'; i >= '0'; i--) {
reverseLookup[i] = (byte) (i - '0' + 52);
}
reverseLookup['+'] = 62;
reverseLookup['/'] = 63;
reverseLookup['='] = 0;
}
public static String base64Encode(String data)
{
return base64Encode(data.getBytes(UTF_8));
}
/**
* Encodes the specified data into a base64 string.
*
* @param bytes The unencoded raw data.
*/
public static String base64Encode(byte[] bytes)
{
// always sequence of 4 characters for each 3 bytes; padded with '='s as necessary:
StringBuilder buf = new StringBuilder(((bytes.length + 2) / 3) * 4);
// first, handle complete chunks (fast loop)
int i = 0;
for (int end = bytes.length - 2; i < end; ) {
int chunk = ((bytes[i++] & 0xFF) << 16)
| ((bytes[i++] & 0xFF) << 8)
| (bytes[i++] & 0xFF);
buf.append(lookup[chunk >> 18]);
buf.append(lookup[(chunk >> 12) & 0x3F]);
buf.append(lookup[(chunk >> 6) & 0x3F]);
buf.append(lookup[chunk & 0x3F]);
}
// then leftovers, if any
int len = bytes.length;
if (i < len) { // 1 or 2 extra bytes?
int chunk = ((bytes[i++] & 0xFF) << 16);
buf.append(lookup[chunk >> 18]);
if (i < len) { // 2 bytes
chunk |= ((bytes[i] & 0xFF) << 8);
buf.append(lookup[(chunk >> 12) & 0x3F]);
buf.append(lookup[(chunk >> 6) & 0x3F]);
}
else { // 1 byte
buf.append(lookup[(chunk >> 12) & 0x3F]);
buf.append('=');
}
buf.append('=');
}
return buf.toString();
}
/**
* Decodes the specified base64 string back into its raw data.
*
* @param encoded The base64 encoded string.
*/
public static byte[] base64Decode(String encoded)
{
int padding = 0;
for (int i = encoded.length() - 1; encoded.charAt(i) == '='; i--) {
padding++;
}
int length = encoded.length() * 6 / 8 - padding;
byte[] bytes = new byte[length];
for (int i = 0, index = 0, n = encoded.length(); i < n; i += 4) {
int word = reverseLookup[encoded.charAt(i)] << 18;
word += reverseLookup[encoded.charAt(i + 1)] << 12;
word += reverseLookup[encoded.charAt(i + 2)] << 6;
word += reverseLookup[encoded.charAt(i + 3)];
for (int j = 0; j < 3 && index + j < length; j++) {
bytes[index + j] = (byte) (word >> (8 * (2 - j)));
}
index += 3;
}
return bytes;
}
}