001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.util; 019 020import java.io.ByteArrayInputStream; 021import java.io.ByteArrayOutputStream; 022import java.io.DataInputStream; 023import java.io.DataOutputStream; 024import java.io.IOException; 025import java.util.ArrayList; 026import java.util.List; 027import org.apache.hadoop.io.DataInputBuffer; 028import org.apache.hadoop.io.Writable; 029import org.apache.yetus.audience.InterfaceAudience; 030 031/** 032 * Utility class with methods for manipulating Writable objects 033 */ 034@InterfaceAudience.Private 035public class Writables { 036 /** 037 * Get the Writable's contents as a byte array 038 * @param w writable 039 * @return The bytes of <code>w</code> gotten by running its 040 * {@link Writable#write(java.io.DataOutput)} method. 041 * @throws IOException e 042 * @see #getWritable(byte[], Writable) 043 */ 044 public static byte[] getBytes(final Writable w) throws IOException { 045 if (w == null) { 046 throw new IllegalArgumentException("Writable cannot be null"); 047 } 048 ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); 049 DataOutputStream out = new DataOutputStream(byteStream); 050 try { 051 w.write(out); 052 out.close(); 053 out = null; 054 return byteStream.toByteArray(); 055 } finally { 056 if (out != null) { 057 out.close(); 058 } 059 } 060 } 061 062 /** 063 * Put a bunch of Writables as bytes all into the one byte array. 064 * @param ws writable 065 * @return The bytes of <code>w</code> gotten by running its 066 * {@link Writable#write(java.io.DataOutput)} method. 067 * @throws IOException e 068 */ 069 public static byte[] getBytes(final Writable... ws) throws IOException { 070 List<byte[]> bytes = new ArrayList<>(ws.length); 071 int size = 0; 072 for (Writable w : ws) { 073 byte[] b = getBytes(w); 074 size += b.length; 075 bytes.add(b); 076 } 077 byte[] result = new byte[size]; 078 int offset = 0; 079 for (byte[] b : bytes) { 080 System.arraycopy(b, 0, result, offset, b.length); 081 offset += b.length; 082 } 083 return result; 084 } 085 086 /** 087 * Set bytes into the passed Writable by calling its 088 * {@link Writable#readFields(java.io.DataInput)}. 089 * @param bytes serialized bytes 090 * @param w An empty Writable (usually made by calling the null-arg constructor). 091 * @return The passed Writable after its readFields has been called fed by the passed 092 * <code>bytes</code> array or IllegalArgumentException if passed null or an empty 093 * <code>bytes</code> array. 094 * @throws IOException e 095 */ 096 public static Writable getWritable(final byte[] bytes, final Writable w) throws IOException { 097 return getWritable(bytes, 0, bytes.length, w); 098 } 099 100 /** 101 * Set bytes into the passed Writable by calling its 102 * {@link Writable#readFields(java.io.DataInput)}. 103 * @param bytes serialized bytes 104 * @param offset offset into array 105 * @param length length of data 106 * @param w An empty Writable (usually made by calling the null-arg constructor). 107 * @return The passed Writable after its readFields has been called fed by the passed 108 * <code>bytes</code> array or IllegalArgumentException if passed null or an empty 109 * <code>bytes</code> array. 110 * @throws IOException e 111 */ 112 public static Writable getWritable(final byte[] bytes, final int offset, final int length, 113 final Writable w) throws IOException { 114 if (bytes == null || length <= 0) { 115 throw new IllegalArgumentException("Can't build a writable with empty " + "bytes array"); 116 } 117 if (w == null) { 118 throw new IllegalArgumentException("Writable cannot be null"); 119 } 120 DataInputBuffer in = new DataInputBuffer(); 121 try { 122 in.reset(bytes, offset, length); 123 w.readFields(in); 124 return w; 125 } finally { 126 in.close(); 127 } 128 } 129 130 /** 131 * Copy one Writable to another. Copies bytes using data streams. 132 * @param src Source Writable 133 * @param tgt Target Writable 134 * @return The target Writable. 135 * @throws IOException e 136 */ 137 public static Writable copyWritable(final Writable src, final Writable tgt) throws IOException { 138 return copyWritable(getBytes(src), tgt); 139 } 140 141 /** 142 * Copy one Writable to another. Copies bytes using data streams. 143 * @param bytes Source Writable 144 * @param tgt Target Writable 145 * @return The target Writable. 146 * @throws IOException e 147 */ 148 public static Writable copyWritable(final byte[] bytes, final Writable tgt) throws IOException { 149 DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bytes)); 150 try { 151 tgt.readFields(dis); 152 } finally { 153 dis.close(); 154 } 155 return tgt; 156 } 157}