1 /**
2 * Copyright 2010 The Apache Software Foundation
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 package org.apache.hadoop.hbase.util;
21
22 import org.apache.hadoop.hbase.HRegionInfo;
23 import org.apache.hadoop.hbase.migration.HRegionInfo090x;
24 import org.apache.hadoop.io.DataInputBuffer;
25 import org.apache.hadoop.io.Writable;
26
27 import java.io.ByteArrayInputStream;
28 import java.io.ByteArrayOutputStream;
29 import java.io.DataInputStream;
30 import java.io.DataOutputStream;
31 import java.io.IOException;
32 import java.util.ArrayList;
33 import java.util.List;
34
35 /**
36 * Utility class with methods for manipulating Writable objects
37 */
38 public class Writables {
39 /**
40 * @param w writable
41 * @return The bytes of <code>w</code> gotten by running its
42 * {@link Writable#write(java.io.DataOutput)} method.
43 * @throws IOException e
44 * @see #getWritable(byte[], Writable)
45 */
46 public static byte [] getBytes(final Writable w) throws IOException {
47 if (w == null) {
48 throw new IllegalArgumentException("Writable cannot be null");
49 }
50 ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
51 DataOutputStream out = new DataOutputStream(byteStream);
52 try {
53 w.write(out);
54 out.close();
55 out = null;
56 return byteStream.toByteArray();
57 } finally {
58 if (out != null) {
59 out.close();
60 }
61 }
62 }
63
64 /**
65 * Put a bunch of Writables as bytes all into the one byte array.
66 * @param ws writable
67 * @return The bytes of <code>w</code> gotten by running its
68 * {@link Writable#write(java.io.DataOutput)} method.
69 * @throws IOException e
70 * @see #getHRegionInfos(byte[], int, int)
71 */
72 public static byte [] getBytes(final Writable... ws) throws IOException {
73 List<byte []> bytes = new ArrayList<byte []>();
74 int size = 0;
75 for (Writable w: ws) {
76 byte [] b = getBytes(w);
77 size += b.length;
78 bytes.add(b);
79 }
80 byte [] result = new byte[size];
81 int offset = 0;
82 for (byte [] b: bytes) {
83 System.arraycopy(b, 0, result, offset, b.length);
84 offset += b.length;
85 }
86 return result;
87 }
88
89 /**
90 * Set bytes into the passed Writable by calling its
91 * {@link Writable#readFields(java.io.DataInput)}.
92 * @param bytes serialized bytes
93 * @param w An empty Writable (usually made by calling the null-arg
94 * constructor).
95 * @return The passed Writable after its readFields has been called fed
96 * by the passed <code>bytes</code> array or IllegalArgumentException
97 * if passed null or an empty <code>bytes</code> array.
98 * @throws IOException e
99 * @throws IllegalArgumentException
100 */
101 public static Writable getWritable(final byte [] bytes, final Writable w)
102 throws IOException {
103 return getWritable(bytes, 0, bytes.length, w);
104 }
105
106 /**
107 * Set bytes into the passed Writable by calling its
108 * {@link Writable#readFields(java.io.DataInput)}.
109 * @param bytes serialized bytes
110 * @param offset offset into array
111 * @param length length of data
112 * @param w An empty Writable (usually made by calling the null-arg
113 * constructor).
114 * @return The passed Writable after its readFields has been called fed
115 * by the passed <code>bytes</code> array or IllegalArgumentException
116 * if passed null or an empty <code>bytes</code> array.
117 * @throws IOException e
118 * @throws IllegalArgumentException
119 */
120 public static Writable getWritable(final byte [] bytes, final int offset,
121 final int length, final Writable w)
122 throws IOException {
123 if (bytes == null || length <=0) {
124 throw new IllegalArgumentException("Can't build a writable with empty " +
125 "bytes array");
126 }
127 if (w == null) {
128 throw new IllegalArgumentException("Writable cannot be null");
129 }
130 DataInputBuffer in = new DataInputBuffer();
131 try {
132 in.reset(bytes, offset, length);
133 w.readFields(in);
134 return w;
135 } finally {
136 in.close();
137 }
138 }
139
140 /**
141 * @param bytes serialized bytes
142 * @return A HRegionInfo instance built out of passed <code>bytes</code>.
143 * @throws IOException e
144 */
145 public static HRegionInfo getHRegionInfo(final byte [] bytes)
146 throws IOException {
147 return (HRegionInfo)getWritable(bytes, new HRegionInfo());
148 }
149
150 /**
151 * @param bytes serialized bytes
152 * @return All the hregioninfos that are in the byte array. Keeps reading
153 * till we hit the end.
154 * @throws IOException e
155 */
156 public static List<HRegionInfo> getHRegionInfos(final byte [] bytes,
157 final int offset, final int length)
158 throws IOException {
159 if (bytes == null) {
160 throw new IllegalArgumentException("Can't build a writable with empty " +
161 "bytes array");
162 }
163 DataInputBuffer in = new DataInputBuffer();
164 List<HRegionInfo> hris = new ArrayList<HRegionInfo>();
165 try {
166 in.reset(bytes, offset, length);
167 while (in.available() > 0) {
168 HRegionInfo hri = new HRegionInfo();
169 hri.readFields(in);
170 hris.add(hri);
171 }
172 } finally {
173 in.close();
174 }
175 return hris;
176 }
177
178 /**
179 * @param bytes serialized bytes
180 * @return A HRegionInfo instance built out of passed <code>bytes</code>
181 * or <code>null</code> if passed bytes are null or an empty array.
182 * @throws IOException e
183 */
184 public static HRegionInfo getHRegionInfoOrNull(final byte [] bytes)
185 throws IOException {
186 return (bytes == null || bytes.length <= 0)?
187 null : getHRegionInfo(bytes);
188 }
189
190 /**
191 * Copy one Writable to another. Copies bytes using data streams.
192 * @param src Source Writable
193 * @param tgt Target Writable
194 * @return The target Writable.
195 * @throws IOException e
196 */
197 public static Writable copyWritable(final Writable src, final Writable tgt)
198 throws IOException {
199 return copyWritable(getBytes(src), tgt);
200 }
201
202 /**
203 * Copy one Writable to another. Copies bytes using data streams.
204 * @param bytes Source Writable
205 * @param tgt Target Writable
206 * @return The target Writable.
207 * @throws IOException e
208 */
209 public static Writable copyWritable(final byte [] bytes, final Writable tgt)
210 throws IOException {
211 DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bytes));
212 try {
213 tgt.readFields(dis);
214 } finally {
215 dis.close();
216 }
217 return tgt;
218 }
219 }