Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF 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 com.facebook.hiveio.common; import org.apache.hadoop.hive.metastore.api.FieldSchema; import org.apache.hadoop.io.Writable; import org.apache.hadoop.io.WritableUtils; import com.google.common.base.Preconditions; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInput; import java.io.DataInputStream; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.util.Collection; import java.util.List; import java.util.Map; /** * Helpers for dealing with Writables */ public class Writables { /** Don't construct */ protected Writables() { } /** * Read a class * * @param in DataInput * @param <T> type of class * @return Class for type * @throws IOException I/O errors */ public static <T> Class<T> readClass(DataInput in) throws IOException { String className = WritableUtils.readString(in); try { return (Class<T>) Class.forName(className); } catch (ClassNotFoundException e) { throw new IOException("Could now find class named " + className, e); } } /** * Write class name * * @param out DataOutput * @param klass Class * @throws IOException I/O errors */ public static void writeClassName(DataOutput out, Class<?> klass) throws IOException { WritableUtils.writeString(out, klass.getName()); } /** * Write class name of object * * @param out DataOutput * @param object object * @throws IOException I/O errors */ public static void writeClassName(DataOutput out, Object object) throws IOException { writeClassName(out, object.getClass()); } /** * Read an enum array * * @param in DataInput * @param klass enum class * @param <E> type of enum * @return array of enums * @throws IOException */ public static <E extends Enum<E>> E[] readEnumArray(DataInput in, Class<E> klass) throws IOException { int length = in.readInt(); if (length > 0) { String readClassName = WritableUtils.readString(in); Class<?> readClass = Classes.classForName(readClassName); Preconditions.checkArgument(klass.equals(readClass), "Expected Enum class %s, read %s", klass.getName(), readClassName); } E[] enums = (E[]) Array.newInstance(klass, length); for (int i = 0; i < length; ++i) { enums[i] = WritableUtils.readEnum(in, klass); } return enums; } /** * Write an array of enums * * @param enums Enum array * @param out DataOutput * @param <E> type of enum * @throws IOException */ public static <E extends Enum<E>> void writeEnumArray(DataOutput out, Enum<E>[] enums) throws IOException { out.writeInt(enums.length); if (enums.length > 0) { WritableUtils.writeString(out, enums[0].getDeclaringClass().getName()); } for (Enum<E> val : enums) { WritableUtils.writeEnum(out, val); } } /** * Read a new instance of a class. Reads class name and creates a new * instance using reflection. * * @param in DataInput * @param <T> type of class * @return new instance of type * @throws IOException I/O errors */ public static <T> T readNewInstance(DataInput in) throws IOException { Class<T> klass = readClass(in); try { Constructor<T> constructor = klass.getDeclaredConstructor(); constructor.setAccessible(true); return constructor.newInstance(); // CHECKSTYLE: stop IllegalCatchCheck } catch (Exception e) { // CHECKSTYLE: resume IllegalCatchCheck throw new IOException("Failed to construct class " + klass.getName(), e); } } /** * Read Hive field schemas * * @param in DataInput * @param fieldSchemas list to write to * @throws IOException I/O errors */ public static void readFieldSchemas(DataInput in, List<FieldSchema> fieldSchemas) throws IOException { int numColumns = in.readInt(); fieldSchemas.clear(); for (int i = 0; i < numColumns; ++i) { fieldSchemas.add(readFieldSchema(in)); } } /** * Read a single field schema * * @param in DataInput * @return field schema read * @throws IOException I/O errors */ public static FieldSchema readFieldSchema(DataInput in) throws IOException { FieldSchema fs = new FieldSchema(); fs.setName(WritableUtils.readString(in)); fs.setType(WritableUtils.readString(in)); return fs; } /** * Read an arbitrary Writable * * @param dataInput DataInput * @param <T> Type of writable * @return new writable instance * @throws IOException I/O errors */ public static <T extends Writable> T readUnknownWritable(DataInput dataInput) throws IOException { T writable = (T) readNewInstance(dataInput); writable.readFields(dataInput); return writable; } /** * Write an arbitrary unknown Writable. This first writes the class name of * the writable so we can read it in dynamically later. It is used together * with readUnknownWritable. * * @param out DataOutput * @param object Writable to write * @throws IOException I/O errors */ public static void writeUnknownWritable(DataOutput out, Writable object) throws IOException { writeClassName(out, object); object.write(out); } /** * Read in a Map<String, String> * * @param in DataInput * @param map Map to read into * @throws IOException I/O errors */ public static void readStrStrMap(DataInput in, Map<String, String> map) throws IOException { int size = in.readInt(); map.clear(); for (int i = 0; i < size; ++i) { String key = WritableUtils.readString(in); String value = WritableUtils.readString(in); map.put(key, value); } } /** * Write a Map<String, String> * * @param out DataOutput * @param map Map to write * @throws IOException I/O errors */ public static void writeStrStrMap(DataOutput out, Map<String, String> map) throws IOException { out.writeInt(map.size()); for (Map.Entry<String, String> entry : map.entrySet()) { WritableUtils.writeString(out, entry.getKey()); WritableUtils.writeString(out, entry.getValue()); } } /** * Read data for a Map<String, Integer> * * @param in DataInput * @param data Map to read into * @throws IOException I/O errors */ public static void readStrIntMap(DataInput in, Map<String, Integer> data) throws IOException { int size = in.readInt(); data.clear(); for (int i = 0; i < size; ++i) { String key = WritableUtils.readString(in); int value = in.readInt(); data.put(key, value); } } /** * Write a Map<String, Integer> * * @param out DataOutput * @param map Map to write * @throws IOException I/O errors */ public static void writeStrIntMap(DataOutput out, Map<String, Integer> map) throws IOException { out.writeInt(map.size()); for (Map.Entry<String, Integer> entry : map.entrySet()) { WritableUtils.writeString(out, entry.getKey()); out.writeInt(entry.getValue()); } } /** * Write an array of integers * @param out DataOutput * @param data array of ints * @throws IOException I/O errors */ public static void writeIntArray(DataOutput out, int[] data) throws IOException { out.writeInt(data.length); for (int x : data) { out.writeInt(x); } } /** * Read an array of integers * @param in DataInput * @return array of ints * @throws IOException I/O errors */ public static int[] readIntArray(DataInput in) throws IOException { int size = in.readInt(); int[] result = new int[size]; for (int i = 0; i < size; ++i) { result[i] = in.readInt(); } return result; } /** * Read a List<String> * * @param in DataInput * @param data List to read into * @throws IOException I/O errors */ public static void readStringList(DataInput in, List<String> data) throws IOException { int size = in.readInt(); data.clear(); for (int i = 0; i < size; ++i) { data.add(WritableUtils.readString(in)); } } /** * Write a List<String> * * @param out DataOutput * @param data list of strings * @throws IOException I/O errors */ public static void writeStringList(DataOutput out, List<String> data) throws IOException { out.writeInt(data.size()); for (String s : data) { WritableUtils.writeString(out, s); } } /** * Write a collection of Hive FieldSchemas * * @param out DataOutput * @param fieldSchemas FieldSchema * @throws IOException I/O errors */ public static void writeFieldSchemas(DataOutput out, Collection<FieldSchema> fieldSchemas) throws IOException { out.writeInt(fieldSchemas.size()); for (FieldSchema fs : fieldSchemas) { writeFieldSchema(out, fs); } } /** * Write a Hive FieldSchema to output * * @param out DataOutput * @param fs FieldSchema * @throws IOException I/O errors */ public static void writeFieldSchema(DataOutput out, FieldSchema fs) throws IOException { WritableUtils.writeString(out, fs.getName()); WritableUtils.writeString(out, fs.getType()); } /** * Read fields from byteArray to a Writable object. * * @param bytes Byte array to find the fields in. * @param writableObject Object to fill in the fields. */ public static void readFieldsFromByteArray(byte[] bytes, Writable writableObject) { DataInputStream is = new DataInputStream(new ByteArrayInputStream(bytes)); try { writableObject.readFields(is); } catch (IOException e) { throw new IllegalStateException("readFieldsFromByteArray: IOException", e); } } /** * Write object to a byte array. * * @param writableObject Object to write from. * @return Byte array with serialized object. */ public static byte[] writeToByteArray(Writable writableObject) { ByteArrayOutputStream os = new ByteArrayOutputStream(); DataOutput output = new DataOutputStream(os); try { writableObject.write(output); } catch (IOException e) { throw new IllegalStateException("writeToByteArray: IOStateException", e); } return os.toByteArray(); } /** * Encode bytes to a String * * @param bytes byte[] * @return encoded String */ private static String encodeBytes(byte[] bytes) { StringBuilder strBuf = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ('a'))); strBuf.append((char) (((bytes[i]) & 0xF) + ('a'))); } return strBuf.toString(); } /** * Decode bytes from a String * * @param str String to decode * @return decoded byte[] */ private static byte[] decodeBytes(String str) { byte[] bytes = new byte[str.length() / 2]; for (int i = 0; i < str.length(); i += 2) { char c = str.charAt(i); bytes[i / 2] = (byte) ((c - 'a') << 4); c = str.charAt(i + 1); bytes[i / 2] += c - 'a'; } return bytes; } /** * Write Writable to an encoded string * * @param writable Writable to write * @return encoded string with data */ public static String writeToEncodedStr(Writable writable) { return encodeBytes(writeToByteArray(writable)); } /** * Read fields from an encoded string * * @param str encoded String with data * @param writable Writable to read fields */ public static void readFieldsFromEncodedStr(String str, Writable writable) { readFieldsFromByteArray(decodeBytes(str), writable); } }