View Javadoc

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 }