Package org.apache.niolex.commons.seri

Source Code of org.apache.niolex.commons.seri.ProtoUtil

/**
* ProtoUtil.java
*
* Copyright 2012 Niolex, Inc.
*
* Niolex licenses this file to you 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 org.apache.niolex.commons.seri;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.niolex.commons.reflect.MethodUtil;
import org.apache.niolex.commons.util.Const;

import com.google.protobuf.MessageLite;

/**
* Common Utility to do protocol buffer serialization.
* <p>
* We have a faster access mode, which will need the security rights to set accessible.
* If your system can not grant this, invoke the method {@link #setUseFasterAccess(boolean)}
* with parameter "false" to disable it.
* </p>
*
* @author <a href="mailto:xiejiyun@gmail.com">Xie, Jiyun</a>
* @version 1.0.0
* @since 2012-8-7
*/
public class ProtoUtil {

  /**
   * Store all the classes been parsed with fast method utility, for faster speed.
   */
  private static final ConcurrentHashMap<Type, Method> ONE_MAP = new ConcurrentHashMap<Type, Method>();
  private static final ConcurrentHashMap<Type, Method> MUL_MAP = new ConcurrentHashMap<Type, Method>();
  private static final int BUF_SIZE = 8 * Const.K;

  private static boolean fasterAccess = true;

  /**
   * Set the faster access flag with this new value.
   *
   * @param faster the new faster access flag
   */
  public static final void setUseFasterAccess(boolean faster) {
      fasterAccess = faster;
  }

  /**
   * Clear the internal methods maps.
   */
  public static final void clearMethodsCache() {
      ONE_MAP.clear();
      MUL_MAP.clear();
  }

  /**
   * Parse one object of type <code>type</code> from the byte array.
   *
   * @param data the binary data
   * @param type the object type
   * @return the object
   */
  public static final <T> T parseOne(byte[] data, Class<T> type) {
    try {
      Method method = ONE_MAP.get(type);
      if (method == null) {
        method = MethodUtil.getMethod(type, "parseFrom", byte[].class);
        if (fasterAccess) method.setAccessible(true);
        ONE_MAP.putIfAbsent(type, method);
      }
      @SuppressWarnings("unchecked")
            T r = (T) method.invoke(null, data);
      return r;
    } catch (Exception e) {
      throw new SeriException("Return type is not protobuf type.", e);
    }
  }

  /**
   * Parse delimited one object of type <code>type</code> from the input stream.
   *
   * @param input the input stream used to read data
   * @param type the object type
   * @return the object
   */
  public static final Object parseDelimitedOne(InputStream input, Class<?> type) {
    try {
      Method method = MUL_MAP.get(type);
      if (method == null) {
        method = MethodUtil.getMethod(type, "parseDelimitedFrom", InputStream.class);
        if (fasterAccess) method.setAccessible(true);
        MUL_MAP.putIfAbsent(type, method);
      }
      return method.invoke(null, input);
    } catch (Exception e) {
      throw new SeriException("Return type is not protobuf type.", e);
    }
  }

  /**
   * Parse multiple objects of the specified types from the byte array.
   *
   * @param data the binary data
   * @param types the types array
   * @return the objects array
   */
  public static final Object[] parseMulti(byte[] data, Class<?>[] types) {
    Object[] r = new Object[types.length];
    ByteArrayInputStream binput = new ByteArrayInputStream(data);
    for (int i = 0; i < types.length; ++i) {
      r[i] = parseDelimitedOne(binput, types[i]);
    }
    return r;
  }

  /**
   * Serialize one object using protocol buffer.
   *
   * @param o the object to serialize
   * @return the byte array
   */
  public static final byte[] seriOne(Object o) {
    if (o instanceof MessageLite) {
      MessageLite gen = (MessageLite)o;
      return gen.toByteArray();
    } else {
      throw new SeriException("Message is not protobuf type: " + o.getClass());
    }
  }

  /**
   * Serialize one object delimited using protocol buffer.
   *
   * @param o the object to serialize
   * @param output where to write output
   */
  public static final void seriDelimitedOne(Object o, OutputStream output) {
    if (o instanceof MessageLite) {
      MessageLite gen = (MessageLite)o;
      try {
        gen.writeDelimitedTo(output);
      } catch (IOException e) {
        throw new SeriException("Failed to write data to the output stream.", e);
      }
    } else {
      throw new SeriException("Message is not protobuf type: " + o.getClass());
    }
  }

  /**
   * Serialize multiple protocol buffer objects into byte array.
   *
   * @param params the objects to be serialized
   * @return the byte array
   */
  public static final byte[] seriMulti(Object[] params) {
    ByteArrayOutputStream out = new ByteArrayOutputStream(BUF_SIZE);
    for (int i = 0; i < params.length; ++i) {
      seriDelimitedOne(params[i], out);
    }
    return out.toByteArray();
  }

}
TOP

Related Classes of org.apache.niolex.commons.seri.ProtoUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.