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