View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.util;
20  
21  import org.apache.hadoop.hbase.classification.InterfaceAudience;
22  import org.apache.hadoop.io.DataInputBuffer;
23  import org.apache.hadoop.io.Writable;
24  
25  import java.io.ByteArrayInputStream;
26  import java.io.ByteArrayOutputStream;
27  import java.io.DataInputStream;
28  import java.io.DataOutputStream;
29  import java.io.IOException;
30  import java.util.ArrayList;
31  import java.util.List;
32  
33  /**
34   * Utility class with methods for manipulating Writable objects
35   */
36  @InterfaceAudience.Private
37  public class Writables {
38    /**
39     * @param w writable
40     * @return The bytes of <code>w</code> gotten by running its
41     * {@link Writable#write(java.io.DataOutput)} method.
42     * @throws IOException e
43     * @see #getWritable(byte[], Writable)
44     */
45    public static byte [] getBytes(final Writable w) throws IOException {
46      if (w == null) {
47        throw new IllegalArgumentException("Writable cannot be null");
48      }
49      ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
50      DataOutputStream out = new DataOutputStream(byteStream);
51      try {
52        w.write(out);
53        out.close();
54        out = null;
55        return byteStream.toByteArray();
56      } finally {
57        if (out != null) {
58          out.close();
59        }
60      }
61    }
62  
63    /**
64     * Put a bunch of Writables as bytes all into the one byte array.
65     * @param ws writable
66     * @return The bytes of <code>w</code> gotten by running its
67     * {@link Writable#write(java.io.DataOutput)} method.
68     * @throws IOException e
69     */
70    public static byte [] getBytes(final Writable... ws) throws IOException {
71      List<byte []> bytes = new ArrayList<byte []>();
72      int size = 0;
73      for (Writable w: ws) {
74        byte [] b = getBytes(w);
75        size += b.length;
76        bytes.add(b);
77      }
78      byte [] result = new byte[size];
79      int offset = 0;
80      for (byte [] b: bytes) {
81        System.arraycopy(b, 0, result, offset, b.length);
82        offset += b.length;
83      }
84      return result;
85    }
86  
87    /**
88     * Set bytes into the passed Writable by calling its
89     * {@link Writable#readFields(java.io.DataInput)}.
90     * @param bytes serialized bytes
91     * @param w An empty Writable (usually made by calling the null-arg
92     * constructor).
93     * @return The passed Writable after its readFields has been called fed
94     * by the passed <code>bytes</code> array or IllegalArgumentException
95     * if passed null or an empty <code>bytes</code> array.
96     * @throws IOException e
97     * @throws IllegalArgumentException
98     */
99    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 }