View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.protobuf;
19  
20  
21  import static org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME;
22  
23  import java.io.ByteArrayOutputStream;
24  import java.io.FilterInputStream;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.lang.reflect.Constructor;
28  import java.lang.reflect.InvocationTargetException;
29  import java.lang.reflect.Method;
30  import java.lang.reflect.ParameterizedType;
31  import java.lang.reflect.Type;
32  import java.nio.ByteBuffer;
33  import java.util.ArrayList;
34  import java.util.Collection;
35  import java.util.HashMap;
36  import java.util.List;
37  import java.util.Map;
38  import java.util.Map.Entry;
39  import java.util.NavigableSet;
40  import java.util.concurrent.TimeUnit;
41  import org.apache.hadoop.hbase.classification.InterfaceAudience;
42  import org.apache.hadoop.conf.Configuration;
43  import org.apache.hadoop.fs.Path;
44  import org.apache.hadoop.hbase.Cell;
45  import org.apache.hadoop.hbase.CellScanner;
46  import org.apache.hadoop.hbase.CellUtil;
47  import org.apache.hadoop.hbase.DoNotRetryIOException;
48  import org.apache.hadoop.hbase.HBaseConfiguration;
49  import org.apache.hadoop.hbase.HConstants;
50  import org.apache.hadoop.hbase.HRegionInfo;
51  import org.apache.hadoop.hbase.HTableDescriptor;
52  import org.apache.hadoop.hbase.KeyValue;
53  import org.apache.hadoop.hbase.NamespaceDescriptor;
54  import org.apache.hadoop.hbase.ServerName;
55  import org.apache.hadoop.hbase.TableName;
56  import org.apache.hadoop.hbase.Tag;
57  import org.apache.hadoop.hbase.client.Append;
58  import org.apache.hadoop.hbase.client.Consistency;
59  import org.apache.hadoop.hbase.client.Delete;
60  import org.apache.hadoop.hbase.client.Durability;
61  import org.apache.hadoop.hbase.client.Get;
62  import org.apache.hadoop.hbase.client.Increment;
63  import org.apache.hadoop.hbase.client.Mutation;
64  import org.apache.hadoop.hbase.client.Put;
65  import org.apache.hadoop.hbase.client.Result;
66  import org.apache.hadoop.hbase.client.Scan;
67  import org.apache.hadoop.hbase.client.metrics.ScanMetrics;
68  import org.apache.hadoop.hbase.client.security.SecurityCapability;
69  import org.apache.hadoop.hbase.exceptions.DeserializationException;
70  import org.apache.hadoop.hbase.filter.ByteArrayComparable;
71  import org.apache.hadoop.hbase.filter.Filter;
72  import org.apache.hadoop.hbase.io.TimeRange;
73  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
74  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
75  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService;
76  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionRequest;
77  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionResponse;
78  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetOnlineRegionRequest;
79  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetOnlineRegionResponse;
80  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoRequest;
81  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse;
82  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetServerInfoRequest;
83  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetServerInfoResponse;
84  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetStoreFileRequest;
85  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetStoreFileResponse;
86  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.MergeRegionsRequest;
87  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionRequest;
88  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.ServerInfo;
89  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.SplitRegionRequest;
90  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.WarmupRegionRequest;
91  import org.apache.hadoop.hbase.protobuf.generated.AuthenticationProtos;
92  import org.apache.hadoop.hbase.protobuf.generated.CellProtos;
93  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
94  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileRequest;
95  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileResponse;
96  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ClientService;
97  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Column;
98  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.CoprocessorServiceCall;
99  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.CoprocessorServiceRequest;
100 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.CoprocessorServiceResponse;
101 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.GetRequest;
102 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.GetResponse;
103 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto;
104 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.ColumnValue;
105 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.ColumnValue.QualifierValue;
106 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.DeleteType;
107 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.MutationType;
108 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanRequest;
109 import org.apache.hadoop.hbase.protobuf.generated.ClusterStatusProtos;
110 import org.apache.hadoop.hbase.protobuf.generated.ClusterStatusProtos.RegionLoad;
111 import org.apache.hadoop.hbase.protobuf.generated.ComparatorProtos;
112 import org.apache.hadoop.hbase.protobuf.generated.FilterProtos;
113 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
114 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameBytesPair;
115 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionInfo;
116 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier;
117 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
118 import org.apache.hadoop.hbase.protobuf.generated.MapReduceProtos;
119 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos;
120 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableRequest;
121 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsResponse;
122 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MasterService;
123 import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos;
124 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionServerReportRequest;
125 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest;
126 import org.apache.hadoop.hbase.protobuf.generated.WALProtos;
127 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.CompactionDescriptor;
128 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.FlushDescriptor;
129 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.FlushDescriptor.FlushAction;
130 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.RegionEventDescriptor;
131 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.RegionEventDescriptor.EventType;
132 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.BulkLoadDescriptor;
133 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.StoreDescriptor;
134 import org.apache.hadoop.hbase.quotas.QuotaScope;
135 import org.apache.hadoop.hbase.quotas.QuotaType;
136 import org.apache.hadoop.hbase.quotas.ThrottleType;
137 import org.apache.hadoop.hbase.replication.ReplicationLoadSink;
138 import org.apache.hadoop.hbase.replication.ReplicationLoadSource;
139 import org.apache.hadoop.hbase.security.access.Permission;
140 import org.apache.hadoop.hbase.security.access.TablePermission;
141 import org.apache.hadoop.hbase.security.access.UserPermission;
142 import org.apache.hadoop.hbase.security.token.AuthenticationTokenIdentifier;
143 import org.apache.hadoop.hbase.security.visibility.Authorizations;
144 import org.apache.hadoop.hbase.security.visibility.CellVisibility;
145 import org.apache.hadoop.hbase.util.ByteStringer;
146 import org.apache.hadoop.hbase.util.Bytes;
147 import org.apache.hadoop.hbase.util.DynamicClassLoader;
148 import org.apache.hadoop.hbase.util.ExceptionUtil;
149 import org.apache.hadoop.hbase.util.Methods;
150 import org.apache.hadoop.hbase.util.Pair;
151 import org.apache.hadoop.hbase.util.VersionInfo;
152 import org.apache.hadoop.io.Text;
153 import org.apache.hadoop.ipc.RemoteException;
154 import org.apache.hadoop.security.token.Token;
155 
156 import com.google.common.collect.ArrayListMultimap;
157 import com.google.common.collect.ListMultimap;
158 import com.google.common.collect.Lists;
159 import com.google.protobuf.ByteString;
160 import com.google.protobuf.CodedInputStream;
161 import com.google.protobuf.InvalidProtocolBufferException;
162 import com.google.protobuf.Message;
163 import com.google.protobuf.Parser;
164 import com.google.protobuf.RpcChannel;
165 import com.google.protobuf.Service;
166 import com.google.protobuf.ServiceException;
167 import com.google.protobuf.TextFormat;
168 
169 /**
170  * Protobufs utility.
171  */
172 @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED",
173   justification="None. Address sometime.")
174 @InterfaceAudience.Private // TODO: some clients (Hive, etc) use this class
175 public final class ProtobufUtil {
176 
177   private ProtobufUtil() {
178   }
179 
180   /**
181    * Primitive type to class mapping.
182    */
183   private final static Map<String, Class<?>>
184     PRIMITIVES = new HashMap<String, Class<?>>();
185 
186 
187   /**
188    * Many results are simple: no cell, exists true or false. To save on object creations,
189    *  we reuse them across calls.
190    */
191   private final static Cell[] EMPTY_CELL_ARRAY = new Cell[]{};
192   private final static Result EMPTY_RESULT = Result.create(EMPTY_CELL_ARRAY);
193   private final static Result EMPTY_RESULT_EXISTS_TRUE = Result.create(null, true);
194   private final static Result EMPTY_RESULT_EXISTS_FALSE = Result.create(null, false);
195   private final static Result EMPTY_RESULT_STALE = Result.create(EMPTY_CELL_ARRAY, null, true);
196   private final static Result EMPTY_RESULT_EXISTS_TRUE_STALE
197     = Result.create((Cell[])null, true, true);
198   private final static Result EMPTY_RESULT_EXISTS_FALSE_STALE
199     = Result.create((Cell[])null, false, true);
200 
201   private final static ClientProtos.Result EMPTY_RESULT_PB;
202   private final static ClientProtos.Result EMPTY_RESULT_PB_EXISTS_TRUE;
203   private final static ClientProtos.Result EMPTY_RESULT_PB_EXISTS_FALSE;
204   private final static ClientProtos.Result EMPTY_RESULT_PB_STALE;
205   private final static ClientProtos.Result EMPTY_RESULT_PB_EXISTS_TRUE_STALE;
206   private final static ClientProtos.Result EMPTY_RESULT_PB_EXISTS_FALSE_STALE;
207 
208 
209   static {
210     ClientProtos.Result.Builder builder = ClientProtos.Result.newBuilder();
211 
212     builder.setExists(true);
213     builder.setAssociatedCellCount(0);
214     EMPTY_RESULT_PB_EXISTS_TRUE =  builder.build();
215 
216     builder.setStale(true);
217     EMPTY_RESULT_PB_EXISTS_TRUE_STALE = builder.build();
218     builder.clear();
219 
220     builder.setExists(false);
221     builder.setAssociatedCellCount(0);
222     EMPTY_RESULT_PB_EXISTS_FALSE =  builder.build();
223     builder.setStale(true);
224     EMPTY_RESULT_PB_EXISTS_FALSE_STALE = builder.build();
225 
226     builder.clear();
227     builder.setAssociatedCellCount(0);
228     EMPTY_RESULT_PB =  builder.build();
229     builder.setStale(true);
230     EMPTY_RESULT_PB_STALE = builder.build();
231   }
232 
233   /**
234    * Dynamic class loader to load filter/comparators
235    */
236   private final static ClassLoader CLASS_LOADER;
237 
238   static {
239     ClassLoader parent = ProtobufUtil.class.getClassLoader();
240     Configuration conf = HBaseConfiguration.create();
241     CLASS_LOADER = new DynamicClassLoader(conf, parent);
242 
243     PRIMITIVES.put(Boolean.TYPE.getName(), Boolean.TYPE);
244     PRIMITIVES.put(Byte.TYPE.getName(), Byte.TYPE);
245     PRIMITIVES.put(Character.TYPE.getName(), Character.TYPE);
246     PRIMITIVES.put(Short.TYPE.getName(), Short.TYPE);
247     PRIMITIVES.put(Integer.TYPE.getName(), Integer.TYPE);
248     PRIMITIVES.put(Long.TYPE.getName(), Long.TYPE);
249     PRIMITIVES.put(Float.TYPE.getName(), Float.TYPE);
250     PRIMITIVES.put(Double.TYPE.getName(), Double.TYPE);
251     PRIMITIVES.put(Void.TYPE.getName(), Void.TYPE);
252   }
253 
254   /**
255    * Magic we put ahead of a serialized protobuf message.
256    * For example, all znode content is protobuf messages with the below magic
257    * for preamble.
258    */
259   public static final byte [] PB_MAGIC = new byte [] {'P', 'B', 'U', 'F'};
260   private static final String PB_MAGIC_STR = Bytes.toString(PB_MAGIC);
261 
262   /**
263    * Prepend the passed bytes with four bytes of magic, {@link #PB_MAGIC}, to flag what
264    * follows as a protobuf in hbase.  Prepend these bytes to all content written to znodes, etc.
265    * @param bytes Bytes to decorate
266    * @return The passed <code>bytes</code> with magic prepended (Creates a new
267    * byte array that is <code>bytes.length</code> plus {@link #PB_MAGIC}.length.
268    */
269   public static byte [] prependPBMagic(final byte [] bytes) {
270     return Bytes.add(PB_MAGIC, bytes);
271   }
272 
273   /**
274    * @param bytes Bytes to check.
275    * @return True if passed <code>bytes</code> has {@link #PB_MAGIC} for a prefix.
276    */
277   public static boolean isPBMagicPrefix(final byte [] bytes) {
278     if (bytes == null) return false;
279     return isPBMagicPrefix(bytes, 0, bytes.length);
280   }
281 
282   /**
283    * @param bytes Bytes to check.
284    * @param offset offset to start at
285    * @param len length to use
286    * @return True if passed <code>bytes</code> has {@link #PB_MAGIC} for a prefix.
287    */
288   public static boolean isPBMagicPrefix(final byte [] bytes, int offset, int len) {
289     if (bytes == null || len < PB_MAGIC.length) return false;
290     return Bytes.compareTo(PB_MAGIC, 0, PB_MAGIC.length, bytes, offset, PB_MAGIC.length) == 0;
291   }
292 
293   /**
294    * @param bytes bytes to check
295    * @throws DeserializationException if we are missing the pb magic prefix
296    */
297   public static void expectPBMagicPrefix(final byte [] bytes) throws DeserializationException {
298     if (!isPBMagicPrefix(bytes)) {
299       throw new DeserializationException("Missing pb magic " + PB_MAGIC_STR + " prefix");
300     }
301   }
302 
303   /**
304    * @return Length of {@link #PB_MAGIC}
305    */
306   public static int lengthOfPBMagic() {
307     return PB_MAGIC.length;
308   }
309 
310   /**
311    * Return the IOException thrown by the remote server wrapped in
312    * ServiceException as cause.
313    *
314    * @param se ServiceException that wraps IO exception thrown by the server
315    * @return Exception wrapped in ServiceException or
316    *   a new IOException that wraps the unexpected ServiceException.
317    */
318   public static IOException getRemoteException(ServiceException se) {
319     Throwable e = se.getCause();
320     if (e == null) {
321       return new IOException(se);
322     }
323     if (ExceptionUtil.isInterrupt(e)) {
324       return ExceptionUtil.asInterrupt(e);
325     }
326     if (e instanceof RemoteException) {
327       e = ((RemoteException) e).unwrapRemoteException();
328     }
329     return e instanceof IOException ? (IOException) e : new IOException(se);
330   }
331 
332   /**
333    * Convert a ServerName to a protocol buffer ServerName
334    *
335    * @param serverName the ServerName to convert
336    * @return the converted protocol buffer ServerName
337    * @see #toServerName(org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.ServerName)
338    */
339   public static HBaseProtos.ServerName
340       toServerName(final ServerName serverName) {
341     if (serverName == null) return null;
342     HBaseProtos.ServerName.Builder builder =
343       HBaseProtos.ServerName.newBuilder();
344     builder.setHostName(serverName.getHostname());
345     if (serverName.getPort() >= 0) {
346       builder.setPort(serverName.getPort());
347     }
348     if (serverName.getStartcode() >= 0) {
349       builder.setStartCode(serverName.getStartcode());
350     }
351     return builder.build();
352   }
353 
354   /**
355    * Convert a protocol buffer ServerName to a ServerName
356    *
357    * @param proto the protocol buffer ServerName to convert
358    * @return the converted ServerName
359    */
360   public static ServerName toServerName(final HBaseProtos.ServerName proto) {
361     if (proto == null) return null;
362     String hostName = proto.getHostName();
363     long startCode = -1;
364     int port = -1;
365     if (proto.hasPort()) {
366       port = proto.getPort();
367     }
368     if (proto.hasStartCode()) {
369       startCode = proto.getStartCode();
370     }
371     return ServerName.valueOf(hostName, port, startCode);
372   }
373 
374   /**
375    * Get HTableDescriptor[] from GetTableDescriptorsResponse protobuf
376    *
377    * @param proto the GetTableDescriptorsResponse
378    * @return HTableDescriptor[]
379    */
380   public static HTableDescriptor[] getHTableDescriptorArray(GetTableDescriptorsResponse proto) {
381     if (proto == null) return null;
382 
383     HTableDescriptor[] ret = new HTableDescriptor[proto.getTableSchemaCount()];
384     for (int i = 0; i < proto.getTableSchemaCount(); ++i) {
385       ret[i] = HTableDescriptor.convert(proto.getTableSchema(i));
386     }
387     return ret;
388   }
389 
390   /**
391    * get the split keys in form "byte [][]" from a CreateTableRequest proto
392    *
393    * @param proto the CreateTableRequest
394    * @return the split keys
395    */
396   public static byte [][] getSplitKeysArray(final CreateTableRequest proto) {
397     byte [][] splitKeys = new byte[proto.getSplitKeysCount()][];
398     for (int i = 0; i < proto.getSplitKeysCount(); ++i) {
399       splitKeys[i] = proto.getSplitKeys(i).toByteArray();
400     }
401     return splitKeys;
402   }
403 
404   /**
405    * Convert a protobuf Durability into a client Durability
406    */
407   public static Durability toDurability(
408       final ClientProtos.MutationProto.Durability proto) {
409     switch(proto) {
410     case USE_DEFAULT:
411       return Durability.USE_DEFAULT;
412     case SKIP_WAL:
413       return Durability.SKIP_WAL;
414     case ASYNC_WAL:
415       return Durability.ASYNC_WAL;
416     case SYNC_WAL:
417       return Durability.SYNC_WAL;
418     case FSYNC_WAL:
419       return Durability.FSYNC_WAL;
420     default:
421       return Durability.USE_DEFAULT;
422     }
423   }
424 
425   /**
426    * Convert a client Durability into a protbuf Durability
427    */
428   public static ClientProtos.MutationProto.Durability toDurability(
429       final Durability d) {
430     switch(d) {
431     case USE_DEFAULT:
432       return ClientProtos.MutationProto.Durability.USE_DEFAULT;
433     case SKIP_WAL:
434       return ClientProtos.MutationProto.Durability.SKIP_WAL;
435     case ASYNC_WAL:
436       return ClientProtos.MutationProto.Durability.ASYNC_WAL;
437     case SYNC_WAL:
438       return ClientProtos.MutationProto.Durability.SYNC_WAL;
439     case FSYNC_WAL:
440       return ClientProtos.MutationProto.Durability.FSYNC_WAL;
441     default:
442       return ClientProtos.MutationProto.Durability.USE_DEFAULT;
443     }
444   }
445 
446   /**
447    * Convert a protocol buffer Get to a client Get
448    *
449    * @param proto the protocol buffer Get to convert
450    * @return the converted client Get
451    * @throws IOException
452    */
453   public static Get toGet(
454       final ClientProtos.Get proto) throws IOException {
455     if (proto == null) return null;
456     byte[] row = proto.getRow().toByteArray();
457     Get get = new Get(row);
458     if (proto.hasCacheBlocks()) {
459       get.setCacheBlocks(proto.getCacheBlocks());
460     }
461     if (proto.hasMaxVersions()) {
462       get.setMaxVersions(proto.getMaxVersions());
463     }
464     if (proto.hasStoreLimit()) {
465       get.setMaxResultsPerColumnFamily(proto.getStoreLimit());
466     }
467     if (proto.hasStoreOffset()) {
468       get.setRowOffsetPerColumnFamily(proto.getStoreOffset());
469     }
470     if (proto.getCfTimeRangeCount() > 0) {
471       for (HBaseProtos.ColumnFamilyTimeRange cftr : proto.getCfTimeRangeList()) {
472         TimeRange timeRange = protoToTimeRange(cftr.getTimeRange());
473         get.setColumnFamilyTimeRange(cftr.getColumnFamily().toByteArray(),
474             timeRange.getMin(), timeRange.getMax());
475       }
476     }
477     if (proto.hasTimeRange()) {
478       TimeRange timeRange = protoToTimeRange(proto.getTimeRange());
479       get.setTimeRange(timeRange.getMin(), timeRange.getMax());
480     }
481     if (proto.hasFilter()) {
482       FilterProtos.Filter filter = proto.getFilter();
483       get.setFilter(ProtobufUtil.toFilter(filter));
484     }
485     for (NameBytesPair attribute: proto.getAttributeList()) {
486       get.setAttribute(attribute.getName(), attribute.getValue().toByteArray());
487     }
488     if (proto.getColumnCount() > 0) {
489       for (Column column: proto.getColumnList()) {
490         byte[] family = column.getFamily().toByteArray();
491         if (column.getQualifierCount() > 0) {
492           for (ByteString qualifier: column.getQualifierList()) {
493             get.addColumn(family, qualifier.toByteArray());
494           }
495         } else {
496           get.addFamily(family);
497         }
498       }
499     }
500     if (proto.hasExistenceOnly() && proto.getExistenceOnly()){
501       get.setCheckExistenceOnly(true);
502     }
503     if (proto.hasClosestRowBefore() && proto.getClosestRowBefore()){
504       get.setClosestRowBefore(true);
505     }
506     if (proto.hasConsistency()) {
507       get.setConsistency(toConsistency(proto.getConsistency()));
508     }
509     return get;
510   }
511 
512   public static Consistency toConsistency(ClientProtos.Consistency consistency) {
513     switch (consistency) {
514       case STRONG : return Consistency.STRONG;
515       case TIMELINE : return Consistency.TIMELINE;
516       default : return Consistency.STRONG;
517     }
518   }
519 
520   public static ClientProtos.Consistency toConsistency(Consistency consistency) {
521     switch (consistency) {
522       case STRONG : return ClientProtos.Consistency.STRONG;
523       case TIMELINE : return ClientProtos.Consistency.TIMELINE;
524       default : return ClientProtos.Consistency.STRONG;
525     }
526   }
527 
528   /**
529    * Convert a protocol buffer Mutate to a Put.
530    *
531    * @param proto The protocol buffer MutationProto to convert
532    * @return A client Put.
533    * @throws IOException
534    */
535   public static Put toPut(final MutationProto proto)
536   throws IOException {
537     return toPut(proto, null);
538   }
539 
540   /**
541    * Convert a protocol buffer Mutate to a Put.
542    *
543    * @param proto The protocol buffer MutationProto to convert
544    * @param cellScanner If non-null, the Cell data that goes with this proto.
545    * @return A client Put.
546    * @throws IOException
547    */
548   public static Put toPut(final MutationProto proto, final CellScanner cellScanner)
549   throws IOException {
550     // TODO: Server-side at least why do we convert back to the Client types?  Why not just pb it?
551     MutationType type = proto.getMutateType();
552     assert type == MutationType.PUT: type.name();
553     long timestamp = proto.hasTimestamp()? proto.getTimestamp(): HConstants.LATEST_TIMESTAMP;
554     Put put = proto.hasRow() ? new Put(proto.getRow().toByteArray(), timestamp) : null;
555     int cellCount = proto.hasAssociatedCellCount()? proto.getAssociatedCellCount(): 0;
556     if (cellCount > 0) {
557       // The proto has metadata only and the data is separate to be found in the cellScanner.
558       if (cellScanner == null) {
559         throw new DoNotRetryIOException("Cell count of " + cellCount + " but no cellScanner: " +
560             toShortString(proto));
561       }
562       for (int i = 0; i < cellCount; i++) {
563         if (!cellScanner.advance()) {
564           throw new DoNotRetryIOException("Cell count of " + cellCount + " but at index " + i +
565             " no cell returned: " + toShortString(proto));
566         }
567         Cell cell = cellScanner.current();
568         if (put == null) {
569           put = new Put(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(), timestamp);
570         }
571         put.add(cell);
572       }
573     } else {
574       if (put == null) {
575         throw new IllegalArgumentException("row cannot be null");
576       }
577       // The proto has the metadata and the data itself
578       for (ColumnValue column: proto.getColumnValueList()) {
579         byte[] family = column.getFamily().toByteArray();
580         for (QualifierValue qv: column.getQualifierValueList()) {
581           if (!qv.hasValue()) {
582             throw new DoNotRetryIOException(
583                 "Missing required field: qualifier value");
584           }
585           ByteBuffer qualifier =
586               qv.hasQualifier() ? qv.getQualifier().asReadOnlyByteBuffer() : null;
587           ByteBuffer value =
588               qv.hasValue() ? qv.getValue().asReadOnlyByteBuffer() : null;
589           long ts = timestamp;
590           if (qv.hasTimestamp()) {
591             ts = qv.getTimestamp();
592           }
593           byte[] tags;
594           if (qv.hasTags()) {
595             tags = qv.getTags().toByteArray();
596             Object[] array = Tag.asList(tags, 0, (short)tags.length).toArray();
597             Tag[] tagArray = new Tag[array.length];
598             for(int i = 0; i< array.length; i++) {
599               tagArray[i] = (Tag)array[i];
600             }
601             if(qv.hasDeleteType()) {
602               byte[] qual = qv.hasQualifier() ? qv.getQualifier().toByteArray() : null;
603               put.add(new KeyValue(proto.getRow().toByteArray(), family, qual, ts,
604                   fromDeleteType(qv.getDeleteType()), null, tags));
605             } else {
606               put.addImmutable(family, qualifier, ts, value, tagArray);
607             }
608           } else {
609             if(qv.hasDeleteType()) {
610               byte[] qual = qv.hasQualifier() ? qv.getQualifier().toByteArray() : null;
611               put.add(new KeyValue(proto.getRow().toByteArray(), family, qual, ts,
612                   fromDeleteType(qv.getDeleteType())));
613             } else{
614               put.addImmutable(family, qualifier, ts, value);
615             }
616           }
617         }
618       }
619     }
620     put.setDurability(toDurability(proto.getDurability()));
621     for (NameBytesPair attribute: proto.getAttributeList()) {
622       put.setAttribute(attribute.getName(), attribute.getValue().toByteArray());
623     }
624     return put;
625   }
626 
627   /**
628    * Convert a protocol buffer Mutate to a Delete
629    *
630    * @param proto the protocol buffer Mutate to convert
631    * @return the converted client Delete
632    * @throws IOException
633    */
634   public static Delete toDelete(final MutationProto proto)
635   throws IOException {
636     return toDelete(proto, null);
637   }
638 
639   /**
640    * Convert a protocol buffer Mutate to a Delete
641    *
642    * @param proto the protocol buffer Mutate to convert
643    * @param cellScanner if non-null, the data that goes with this delete.
644    * @return the converted client Delete
645    * @throws IOException
646    */
647   public static Delete toDelete(final MutationProto proto, final CellScanner cellScanner)
648   throws IOException {
649     MutationType type = proto.getMutateType();
650     assert type == MutationType.DELETE : type.name();
651     long timestamp = proto.hasTimestamp() ? proto.getTimestamp() : HConstants.LATEST_TIMESTAMP;
652     Delete delete = proto.hasRow() ? new Delete(proto.getRow().toByteArray(), timestamp) : null;
653     int cellCount = proto.hasAssociatedCellCount()? proto.getAssociatedCellCount(): 0;
654     if (cellCount > 0) {
655       // The proto has metadata only and the data is separate to be found in the cellScanner.
656       if (cellScanner == null) {
657         // TextFormat should be fine for a Delete since it carries no data, just coordinates.
658         throw new DoNotRetryIOException("Cell count of " + cellCount + " but no cellScanner: " +
659           TextFormat.shortDebugString(proto));
660       }
661       for (int i = 0; i < cellCount; i++) {
662         if (!cellScanner.advance()) {
663           // TextFormat should be fine for a Delete since it carries no data, just coordinates.
664           throw new DoNotRetryIOException("Cell count of " + cellCount + " but at index " + i +
665             " no cell returned: " + TextFormat.shortDebugString(proto));
666         }
667         Cell cell = cellScanner.current();
668         if (delete == null) {
669           delete =
670             new Delete(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(), timestamp);
671         }
672         delete.addDeleteMarker(cell);
673       }
674     } else {
675       if (delete == null) {
676         throw new IllegalArgumentException("row cannot be null");
677       }
678       for (ColumnValue column: proto.getColumnValueList()) {
679         byte[] family = column.getFamily().toByteArray();
680         for (QualifierValue qv: column.getQualifierValueList()) {
681           DeleteType deleteType = qv.getDeleteType();
682           byte[] qualifier = null;
683           if (qv.hasQualifier()) {
684             qualifier = qv.getQualifier().toByteArray();
685           }
686           long ts = HConstants.LATEST_TIMESTAMP;
687           if (qv.hasTimestamp()) {
688             ts = qv.getTimestamp();
689           }
690           if (deleteType == DeleteType.DELETE_ONE_VERSION) {
691             delete.deleteColumn(family, qualifier, ts);
692           } else if (deleteType == DeleteType.DELETE_MULTIPLE_VERSIONS) {
693             delete.deleteColumns(family, qualifier, ts);
694           } else if (deleteType == DeleteType.DELETE_FAMILY_VERSION) {
695             delete.deleteFamilyVersion(family, ts);
696           } else {
697             delete.deleteFamily(family, ts);
698           }
699         }
700       }
701     }
702     delete.setDurability(toDurability(proto.getDurability()));
703     for (NameBytesPair attribute: proto.getAttributeList()) {
704       delete.setAttribute(attribute.getName(), attribute.getValue().toByteArray());
705     }
706     return delete;
707   }
708 
709   /**
710    * Convert a protocol buffer Mutate to an Append
711    * @param cellScanner
712    * @param proto the protocol buffer Mutate to convert
713    * @return the converted client Append
714    * @throws IOException
715    */
716   public static Append toAppend(final MutationProto proto, final CellScanner cellScanner)
717   throws IOException {
718     MutationType type = proto.getMutateType();
719     assert type == MutationType.APPEND : type.name();
720     byte [] row = proto.hasRow()? proto.getRow().toByteArray(): null;
721     Append append = null;
722     int cellCount = proto.hasAssociatedCellCount()? proto.getAssociatedCellCount(): 0;
723     if (cellCount > 0) {
724       // The proto has metadata only and the data is separate to be found in the cellScanner.
725       if (cellScanner == null) {
726         throw new DoNotRetryIOException("Cell count of " + cellCount + " but no cellScanner: " +
727           toShortString(proto));
728       }
729       for (int i = 0; i < cellCount; i++) {
730         if (!cellScanner.advance()) {
731           throw new DoNotRetryIOException("Cell count of " + cellCount + " but at index " + i +
732             " no cell returned: " + toShortString(proto));
733         }
734         Cell cell = cellScanner.current();
735         if (append == null) {
736           append = new Append(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
737         }
738         append.add(cell);
739       }
740     } else {
741       append = new Append(row);
742       for (ColumnValue column: proto.getColumnValueList()) {
743         byte[] family = column.getFamily().toByteArray();
744         for (QualifierValue qv: column.getQualifierValueList()) {
745           byte[] qualifier = qv.getQualifier().toByteArray();
746           if (!qv.hasValue()) {
747             throw new DoNotRetryIOException(
748               "Missing required field: qualifier value");
749           }
750           byte[] value = qv.getValue().toByteArray();
751           byte[] tags = null;
752           if (qv.hasTags()) {
753             tags = qv.getTags().toByteArray();
754           }
755           append.add(CellUtil.createCell(row, family, qualifier, qv.getTimestamp(),
756               KeyValue.Type.Put, value, tags));
757         }
758       }
759     }
760     append.setDurability(toDurability(proto.getDurability()));
761     for (NameBytesPair attribute: proto.getAttributeList()) {
762       append.setAttribute(attribute.getName(), attribute.getValue().toByteArray());
763     }
764     return append;
765   }
766 
767   /**
768    * Convert a MutateRequest to Mutation
769    *
770    * @param proto the protocol buffer Mutate to convert
771    * @return the converted Mutation
772    * @throws IOException
773    */
774   public static Mutation toMutation(final MutationProto proto) throws IOException {
775     MutationType type = proto.getMutateType();
776     if (type == MutationType.APPEND) {
777       return toAppend(proto, null);
778     }
779     if (type == MutationType.DELETE) {
780       return toDelete(proto, null);
781     }
782     if (type == MutationType.PUT) {
783       return toPut(proto, null);
784     }
785     throw new IOException("Unknown mutation type " + type);
786   }
787 
788   /**
789    * Convert a protocol buffer Mutate to an Increment
790    *
791    * @param proto the protocol buffer Mutate to convert
792    * @return the converted client Increment
793    * @throws IOException
794    */
795   public static Increment toIncrement(final MutationProto proto, final CellScanner cellScanner)
796   throws IOException {
797     MutationType type = proto.getMutateType();
798     assert type == MutationType.INCREMENT : type.name();
799     byte [] row = proto.hasRow()? proto.getRow().toByteArray(): null;
800     Increment increment = null;
801     int cellCount = proto.hasAssociatedCellCount()? proto.getAssociatedCellCount(): 0;
802     if (cellCount > 0) {
803       // The proto has metadata only and the data is separate to be found in the cellScanner.
804       if (cellScanner == null) {
805         throw new DoNotRetryIOException("Cell count of " + cellCount + " but no cellScanner: " +
806           TextFormat.shortDebugString(proto));
807       }
808       for (int i = 0; i < cellCount; i++) {
809         if (!cellScanner.advance()) {
810           throw new DoNotRetryIOException("Cell count of " + cellCount + " but at index " + i +
811             " no cell returned: " + TextFormat.shortDebugString(proto));
812         }
813         Cell cell = cellScanner.current();
814         if (increment == null) {
815           increment = new Increment(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
816         }
817         increment.add(cell);
818       }
819     } else {
820       increment = new Increment(row);
821       for (ColumnValue column: proto.getColumnValueList()) {
822         byte[] family = column.getFamily().toByteArray();
823         for (QualifierValue qv: column.getQualifierValueList()) {
824           byte[] qualifier = qv.getQualifier().toByteArray();
825           if (!qv.hasValue()) {
826             throw new DoNotRetryIOException("Missing required field: qualifier value");
827           }
828           byte[] value = qv.getValue().toByteArray();
829           byte[] tags = null;
830           if (qv.hasTags()) {
831             tags = qv.getTags().toByteArray();
832           }
833           increment.add(CellUtil.createCell(row, family, qualifier, qv.getTimestamp(),
834               KeyValue.Type.Put, value, tags));
835         }
836       }
837     }
838     if (proto.hasTimeRange()) {
839       TimeRange timeRange = protoToTimeRange(proto.getTimeRange());
840       increment.setTimeRange(timeRange.getMin(), timeRange.getMax());
841     }
842     increment.setDurability(toDurability(proto.getDurability()));
843     for (NameBytesPair attribute : proto.getAttributeList()) {
844       increment.setAttribute(attribute.getName(), attribute.getValue().toByteArray());
845     }
846     return increment;
847   }
848 
849   /**
850    * Convert a client Scan to a protocol buffer Scan
851    *
852    * @param scan the client Scan to convert
853    * @return the converted protocol buffer Scan
854    * @throws IOException
855    */
856   public static ClientProtos.Scan toScan(
857       final Scan scan) throws IOException {
858     ClientProtos.Scan.Builder scanBuilder =
859       ClientProtos.Scan.newBuilder();
860     scanBuilder.setCacheBlocks(scan.getCacheBlocks());
861     if (scan.getBatch() > 0) {
862       scanBuilder.setBatchSize(scan.getBatch());
863     }
864     if (scan.getMaxResultSize() > 0) {
865       scanBuilder.setMaxResultSize(scan.getMaxResultSize());
866     }
867     if (scan.isSmall()) {
868       scanBuilder.setSmall(scan.isSmall());
869     }
870     if (scan.getAllowPartialResults()) {
871       scanBuilder.setAllowPartialResults(scan.getAllowPartialResults());
872     }
873     Boolean loadColumnFamiliesOnDemand = scan.getLoadColumnFamiliesOnDemandValue();
874     if (loadColumnFamiliesOnDemand != null) {
875       scanBuilder.setLoadColumnFamiliesOnDemand(loadColumnFamiliesOnDemand.booleanValue());
876     }
877     scanBuilder.setMaxVersions(scan.getMaxVersions());
878     for (Entry<byte[], TimeRange> cftr : scan.getColumnFamilyTimeRange().entrySet()) {
879       HBaseProtos.ColumnFamilyTimeRange.Builder b = HBaseProtos.ColumnFamilyTimeRange.newBuilder();
880       b.setColumnFamily(ByteString.copyFrom(cftr.getKey()));
881       b.setTimeRange(timeRangeToProto(cftr.getValue()));
882       scanBuilder.addCfTimeRange(b);
883     }
884     TimeRange timeRange = scan.getTimeRange();
885     if (!timeRange.isAllTime()) {
886       HBaseProtos.TimeRange.Builder timeRangeBuilder =
887         HBaseProtos.TimeRange.newBuilder();
888       timeRangeBuilder.setFrom(timeRange.getMin());
889       timeRangeBuilder.setTo(timeRange.getMax());
890       scanBuilder.setTimeRange(timeRangeBuilder.build());
891     }
892     Map<String, byte[]> attributes = scan.getAttributesMap();
893     if (!attributes.isEmpty()) {
894       NameBytesPair.Builder attributeBuilder = NameBytesPair.newBuilder();
895       for (Map.Entry<String, byte[]> attribute: attributes.entrySet()) {
896         attributeBuilder.setName(attribute.getKey());
897         attributeBuilder.setValue(ByteStringer.wrap(attribute.getValue()));
898         scanBuilder.addAttribute(attributeBuilder.build());
899       }
900     }
901     byte[] startRow = scan.getStartRow();
902     if (startRow != null && startRow.length > 0) {
903       scanBuilder.setStartRow(ByteStringer.wrap(startRow));
904     }
905     byte[] stopRow = scan.getStopRow();
906     if (stopRow != null && stopRow.length > 0) {
907       scanBuilder.setStopRow(ByteStringer.wrap(stopRow));
908     }
909     if (scan.hasFilter()) {
910       scanBuilder.setFilter(ProtobufUtil.toFilter(scan.getFilter()));
911     }
912     if (scan.hasFamilies()) {
913       Column.Builder columnBuilder = Column.newBuilder();
914       for (Map.Entry<byte[],NavigableSet<byte []>>
915           family: scan.getFamilyMap().entrySet()) {
916         columnBuilder.setFamily(ByteStringer.wrap(family.getKey()));
917         NavigableSet<byte []> qualifiers = family.getValue();
918         columnBuilder.clearQualifier();
919         if (qualifiers != null && qualifiers.size() > 0) {
920           for (byte [] qualifier: qualifiers) {
921             columnBuilder.addQualifier(ByteStringer.wrap(qualifier));
922           }
923         }
924         scanBuilder.addColumn(columnBuilder.build());
925       }
926     }
927     if (scan.getMaxResultsPerColumnFamily() >= 0) {
928       scanBuilder.setStoreLimit(scan.getMaxResultsPerColumnFamily());
929     }
930     if (scan.getRowOffsetPerColumnFamily() > 0) {
931       scanBuilder.setStoreOffset(scan.getRowOffsetPerColumnFamily());
932     }
933     if (scan.isReversed()) {
934       scanBuilder.setReversed(scan.isReversed());
935     }
936     if (scan.getConsistency() == Consistency.TIMELINE) {
937       scanBuilder.setConsistency(toConsistency(scan.getConsistency()));
938     }
939     if (scan.getCaching() > 0) {
940       scanBuilder.setCaching(scan.getCaching());
941     }
942     return scanBuilder.build();
943   }
944 
945   /**
946    * Convert a protocol buffer Scan to a client Scan
947    *
948    * @param proto the protocol buffer Scan to convert
949    * @return the converted client Scan
950    * @throws IOException
951    */
952   public static Scan toScan(
953       final ClientProtos.Scan proto) throws IOException {
954     byte [] startRow = HConstants.EMPTY_START_ROW;
955     byte [] stopRow  = HConstants.EMPTY_END_ROW;
956     if (proto.hasStartRow()) {
957       startRow = proto.getStartRow().toByteArray();
958     }
959     if (proto.hasStopRow()) {
960       stopRow = proto.getStopRow().toByteArray();
961     }
962     Scan scan = new Scan(startRow, stopRow);
963     if (proto.hasCacheBlocks()) {
964       scan.setCacheBlocks(proto.getCacheBlocks());
965     }
966     if (proto.hasMaxVersions()) {
967       scan.setMaxVersions(proto.getMaxVersions());
968     }
969     if (proto.hasStoreLimit()) {
970       scan.setMaxResultsPerColumnFamily(proto.getStoreLimit());
971     }
972     if (proto.hasStoreOffset()) {
973       scan.setRowOffsetPerColumnFamily(proto.getStoreOffset());
974     }
975     if (proto.hasLoadColumnFamiliesOnDemand()) {
976       scan.setLoadColumnFamiliesOnDemand(proto.getLoadColumnFamiliesOnDemand());
977     }
978     if (proto.getCfTimeRangeCount() > 0) {
979       for (HBaseProtos.ColumnFamilyTimeRange cftr : proto.getCfTimeRangeList()) {
980         TimeRange timeRange = protoToTimeRange(cftr.getTimeRange());
981         scan.setColumnFamilyTimeRange(cftr.getColumnFamily().toByteArray(),
982             timeRange.getMin(), timeRange.getMax());
983       }
984     }
985     if (proto.hasTimeRange()) {
986       TimeRange timeRange = protoToTimeRange(proto.getTimeRange());
987       scan.setTimeRange(timeRange.getMin(), timeRange.getMax());
988     }
989     if (proto.hasFilter()) {
990       FilterProtos.Filter filter = proto.getFilter();
991       scan.setFilter(ProtobufUtil.toFilter(filter));
992     }
993     if (proto.hasBatchSize()) {
994       scan.setBatch(proto.getBatchSize());
995     }
996     if (proto.hasMaxResultSize()) {
997       scan.setMaxResultSize(proto.getMaxResultSize());
998     }
999     if (proto.hasSmall()) {
1000       scan.setSmall(proto.getSmall());
1001     }
1002     if (proto.hasAllowPartialResults()) {
1003       scan.setAllowPartialResults(proto.getAllowPartialResults());
1004     }
1005     for (NameBytesPair attribute: proto.getAttributeList()) {
1006       scan.setAttribute(attribute.getName(), attribute.getValue().toByteArray());
1007     }
1008     if (proto.getColumnCount() > 0) {
1009       for (Column column: proto.getColumnList()) {
1010         byte[] family = column.getFamily().toByteArray();
1011         if (column.getQualifierCount() > 0) {
1012           for (ByteString qualifier: column.getQualifierList()) {
1013             scan.addColumn(family, qualifier.toByteArray());
1014           }
1015         } else {
1016           scan.addFamily(family);
1017         }
1018       }
1019     }
1020     if (proto.hasReversed()) {
1021       scan.setReversed(proto.getReversed());
1022     }
1023     if (proto.hasConsistency()) {
1024       scan.setConsistency(toConsistency(proto.getConsistency()));
1025     }
1026     if (proto.hasCaching()) {
1027       scan.setCaching(proto.getCaching());
1028     }
1029     return scan;
1030   }
1031 
1032   /**
1033    * Create a protocol buffer Get based on a client Get.
1034    *
1035    * @param get the client Get
1036    * @return a protocol buffer Get
1037    * @throws IOException
1038    */
1039   public static ClientProtos.Get toGet(
1040       final Get get) throws IOException {
1041     ClientProtos.Get.Builder builder =
1042       ClientProtos.Get.newBuilder();
1043     builder.setRow(ByteStringer.wrap(get.getRow()));
1044     builder.setCacheBlocks(get.getCacheBlocks());
1045     builder.setMaxVersions(get.getMaxVersions());
1046     if (get.getFilter() != null) {
1047       builder.setFilter(ProtobufUtil.toFilter(get.getFilter()));
1048     }
1049     for (Entry<byte[], TimeRange> cftr : get.getColumnFamilyTimeRange().entrySet()) {
1050       HBaseProtos.ColumnFamilyTimeRange.Builder b = HBaseProtos.ColumnFamilyTimeRange.newBuilder();
1051       b.setColumnFamily(ByteString.copyFrom(cftr.getKey()));
1052       b.setTimeRange(timeRangeToProto(cftr.getValue()));
1053       builder.addCfTimeRange(b);
1054     }
1055     TimeRange timeRange = get.getTimeRange();
1056     if (!timeRange.isAllTime()) {
1057       HBaseProtos.TimeRange.Builder timeRangeBuilder =
1058         HBaseProtos.TimeRange.newBuilder();
1059       timeRangeBuilder.setFrom(timeRange.getMin());
1060       timeRangeBuilder.setTo(timeRange.getMax());
1061       builder.setTimeRange(timeRangeBuilder.build());
1062     }
1063     Map<String, byte[]> attributes = get.getAttributesMap();
1064     if (!attributes.isEmpty()) {
1065       NameBytesPair.Builder attributeBuilder = NameBytesPair.newBuilder();
1066       for (Map.Entry<String, byte[]> attribute: attributes.entrySet()) {
1067         attributeBuilder.setName(attribute.getKey());
1068         attributeBuilder.setValue(ByteStringer.wrap(attribute.getValue()));
1069         builder.addAttribute(attributeBuilder.build());
1070       }
1071     }
1072     if (get.hasFamilies()) {
1073       Column.Builder columnBuilder = Column.newBuilder();
1074       Map<byte[], NavigableSet<byte[]>> families = get.getFamilyMap();
1075       for (Map.Entry<byte[], NavigableSet<byte[]>> family: families.entrySet()) {
1076         NavigableSet<byte[]> qualifiers = family.getValue();
1077         columnBuilder.setFamily(ByteStringer.wrap(family.getKey()));
1078         columnBuilder.clearQualifier();
1079         if (qualifiers != null && qualifiers.size() > 0) {
1080           for (byte[] qualifier: qualifiers) {
1081             columnBuilder.addQualifier(ByteStringer.wrap(qualifier));
1082           }
1083         }
1084         builder.addColumn(columnBuilder.build());
1085       }
1086     }
1087     if (get.getMaxResultsPerColumnFamily() >= 0) {
1088       builder.setStoreLimit(get.getMaxResultsPerColumnFamily());
1089     }
1090     if (get.getRowOffsetPerColumnFamily() > 0) {
1091       builder.setStoreOffset(get.getRowOffsetPerColumnFamily());
1092     }
1093     if (get.isCheckExistenceOnly()){
1094       builder.setExistenceOnly(true);
1095     }
1096     if (get.isClosestRowBefore()){
1097       builder.setClosestRowBefore(true);
1098     }
1099     if (get.getConsistency() != null && get.getConsistency() != Consistency.STRONG) {
1100       builder.setConsistency(toConsistency(get.getConsistency()));
1101     }
1102 
1103     return builder.build();
1104   }
1105 
1106   /**
1107    * Convert a client Increment to a protobuf Mutate.
1108    *
1109    * @param increment
1110    * @return the converted mutate
1111    */
1112   public static MutationProto toMutation(
1113     final Increment increment, final MutationProto.Builder builder, long nonce) {
1114     builder.setRow(ByteStringer.wrap(increment.getRow()));
1115     builder.setMutateType(MutationType.INCREMENT);
1116     builder.setDurability(toDurability(increment.getDurability()));
1117     if (nonce != HConstants.NO_NONCE) {
1118       builder.setNonce(nonce);
1119     }
1120     TimeRange timeRange = increment.getTimeRange();
1121     if (!timeRange.isAllTime()) {
1122       HBaseProtos.TimeRange.Builder timeRangeBuilder =
1123         HBaseProtos.TimeRange.newBuilder();
1124       timeRangeBuilder.setFrom(timeRange.getMin());
1125       timeRangeBuilder.setTo(timeRange.getMax());
1126       builder.setTimeRange(timeRangeBuilder.build());
1127     }
1128     ColumnValue.Builder columnBuilder = ColumnValue.newBuilder();
1129     QualifierValue.Builder valueBuilder = QualifierValue.newBuilder();
1130     for (Map.Entry<byte[], List<Cell>> family: increment.getFamilyCellMap().entrySet()) {
1131       columnBuilder.setFamily(ByteStringer.wrap(family.getKey()));
1132       columnBuilder.clearQualifierValue();
1133       List<Cell> values = family.getValue();
1134       if (values != null && values.size() > 0) {
1135         for (Cell cell: values) {
1136           valueBuilder.clear();
1137           valueBuilder.setQualifier(ByteStringer.wrap(
1138               cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()));
1139           valueBuilder.setValue(ByteStringer.wrap(
1140               cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));
1141           if (cell.getTagsLength() > 0) {
1142             valueBuilder.setTags(ByteStringer.wrap(cell.getTagsArray(),
1143                 cell.getTagsOffset(), cell.getTagsLength()));
1144           }
1145           columnBuilder.addQualifierValue(valueBuilder.build());
1146         }
1147       }
1148       builder.addColumnValue(columnBuilder.build());
1149     }
1150     Map<String, byte[]> attributes = increment.getAttributesMap();
1151     if (!attributes.isEmpty()) {
1152       NameBytesPair.Builder attributeBuilder = NameBytesPair.newBuilder();
1153       for (Map.Entry<String, byte[]> attribute : attributes.entrySet()) {
1154         attributeBuilder.setName(attribute.getKey());
1155         attributeBuilder.setValue(ByteStringer.wrap(attribute.getValue()));
1156         builder.addAttribute(attributeBuilder.build());
1157       }
1158     }
1159     return builder.build();
1160   }
1161 
1162   public static MutationProto toMutation(final MutationType type, final Mutation mutation)
1163     throws IOException {
1164     return toMutation(type, mutation, HConstants.NO_NONCE);
1165   }
1166 
1167   /**
1168    * Create a protocol buffer Mutate based on a client Mutation
1169    *
1170    * @param type
1171    * @param mutation
1172    * @return a protobuf'd Mutation
1173    * @throws IOException
1174    */
1175   public static MutationProto toMutation(final MutationType type, final Mutation mutation,
1176     final long nonce) throws IOException {
1177     return toMutation(type, mutation, MutationProto.newBuilder(), nonce);
1178   }
1179 
1180   public static MutationProto toMutation(final MutationType type, final Mutation mutation,
1181       MutationProto.Builder builder) throws IOException {
1182     return toMutation(type, mutation, builder, HConstants.NO_NONCE);
1183   }
1184 
1185   public static MutationProto toMutation(final MutationType type, final Mutation mutation,
1186       MutationProto.Builder builder, long nonce)
1187   throws IOException {
1188     builder = getMutationBuilderAndSetCommonFields(type, mutation, builder);
1189     if (nonce != HConstants.NO_NONCE) {
1190       builder.setNonce(nonce);
1191     }
1192     ColumnValue.Builder columnBuilder = ColumnValue.newBuilder();
1193     QualifierValue.Builder valueBuilder = QualifierValue.newBuilder();
1194     for (Map.Entry<byte[],List<Cell>> family: mutation.getFamilyCellMap().entrySet()) {
1195       columnBuilder.clear();
1196       columnBuilder.setFamily(ByteStringer.wrap(family.getKey()));
1197       for (Cell cell: family.getValue()) {
1198         valueBuilder.clear();
1199         valueBuilder.setQualifier(ByteStringer.wrap(
1200             cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()));
1201         valueBuilder.setValue(ByteStringer.wrap(
1202             cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));
1203         valueBuilder.setTimestamp(cell.getTimestamp());
1204         if (type == MutationType.DELETE || (type == MutationType.PUT && CellUtil.isDelete(cell))) {
1205           KeyValue.Type keyValueType = KeyValue.Type.codeToType(cell.getTypeByte());
1206           valueBuilder.setDeleteType(toDeleteType(keyValueType));
1207         }
1208         columnBuilder.addQualifierValue(valueBuilder.build());
1209       }
1210       builder.addColumnValue(columnBuilder.build());
1211     }
1212     return builder.build();
1213   }
1214 
1215   /**
1216    * Create a protocol buffer MutationProto based on a client Mutation. Does NOT include data.
1217    * Understanding is that the Cell will be transported other than via protobuf.
1218    * @param type
1219    * @param mutation
1220    * @param builder
1221    * @return a protobuf'd Mutation
1222    * @throws IOException
1223    */
1224   public static MutationProto toMutationNoData(final MutationType type, final Mutation mutation,
1225       final MutationProto.Builder builder)  throws IOException {
1226     return toMutationNoData(type, mutation, builder, HConstants.NO_NONCE);
1227   }
1228 
1229   /**
1230    * Create a protocol buffer MutationProto based on a client Mutation.  Does NOT include data.
1231    * Understanding is that the Cell will be transported other than via protobuf.
1232    * @param type
1233    * @param mutation
1234    * @return a protobuf'd Mutation
1235    * @throws IOException
1236    */
1237   public static MutationProto toMutationNoData(final MutationType type, final Mutation mutation)
1238   throws IOException {
1239     MutationProto.Builder builder =  MutationProto.newBuilder();
1240     return toMutationNoData(type, mutation, builder);
1241   }
1242 
1243   public static MutationProto toMutationNoData(final MutationType type, final Mutation mutation,
1244       final MutationProto.Builder builder, long nonce) throws IOException {
1245     getMutationBuilderAndSetCommonFields(type, mutation, builder);
1246     builder.setAssociatedCellCount(mutation.size());
1247     if (nonce != HConstants.NO_NONCE) {
1248       builder.setNonce(nonce);
1249     }
1250     return builder.build();
1251   }
1252 
1253   /**
1254    * Code shared by {@link #toMutation(MutationType, Mutation)} and
1255    * {@link #toMutationNoData(MutationType, Mutation)}
1256    * @param type
1257    * @param mutation
1258    * @return A partly-filled out protobuf'd Mutation.
1259    */
1260   private static MutationProto.Builder getMutationBuilderAndSetCommonFields(final MutationType type,
1261       final Mutation mutation, MutationProto.Builder builder) {
1262     builder.setRow(ByteStringer.wrap(mutation.getRow()));
1263     builder.setMutateType(type);
1264     builder.setDurability(toDurability(mutation.getDurability()));
1265     builder.setTimestamp(mutation.getTimeStamp());
1266     Map<String, byte[]> attributes = mutation.getAttributesMap();
1267     if (!attributes.isEmpty()) {
1268       NameBytesPair.Builder attributeBuilder = NameBytesPair.newBuilder();
1269       for (Map.Entry<String, byte[]> attribute: attributes.entrySet()) {
1270         attributeBuilder.setName(attribute.getKey());
1271         attributeBuilder.setValue(ByteStringer.wrap(attribute.getValue()));
1272         builder.addAttribute(attributeBuilder.build());
1273       }
1274     }
1275     return builder;
1276   }
1277 
1278   /**
1279    * Convert a client Result to a protocol buffer Result
1280    *
1281    * @param result the client Result to convert
1282    * @return the converted protocol buffer Result
1283    */
1284   public static ClientProtos.Result toResult(final Result result) {
1285     if (result.getExists() != null) {
1286       return toResult(result.getExists(), result.isStale());
1287     }
1288 
1289     Cell[] cells = result.rawCells();
1290     if (cells == null || cells.length == 0) {
1291       return result.isStale() ? EMPTY_RESULT_PB_STALE : EMPTY_RESULT_PB;
1292     }
1293 
1294     ClientProtos.Result.Builder builder = ClientProtos.Result.newBuilder();
1295     for (Cell c : cells) {
1296       builder.addCell(toCell(c));
1297     }
1298 
1299     builder.setStale(result.isStale());
1300     builder.setPartial(result.isPartial());
1301 
1302     return builder.build();
1303   }
1304 
1305   /**
1306    * Convert a client Result to a protocol buffer Result
1307    *
1308    * @param existence the client existence to send
1309    * @return the converted protocol buffer Result
1310    */
1311   public static ClientProtos.Result toResult(final boolean existence, boolean stale) {
1312     if (stale){
1313       return existence ? EMPTY_RESULT_PB_EXISTS_TRUE_STALE : EMPTY_RESULT_PB_EXISTS_FALSE_STALE;
1314     } else {
1315       return existence ? EMPTY_RESULT_PB_EXISTS_TRUE : EMPTY_RESULT_PB_EXISTS_FALSE;
1316     }
1317   }
1318 
1319   /**
1320    * Convert a client Result to a protocol buffer Result.
1321    * The pb Result does not include the Cell data.  That is for transport otherwise.
1322    *
1323    * @param result the client Result to convert
1324    * @return the converted protocol buffer Result
1325    */
1326   public static ClientProtos.Result toResultNoData(final Result result) {
1327     if (result.getExists() != null) return toResult(result.getExists(), result.isStale());
1328     int size = result.size();
1329     if (size == 0) return result.isStale() ? EMPTY_RESULT_PB_STALE : EMPTY_RESULT_PB;
1330     ClientProtos.Result.Builder builder = ClientProtos.Result.newBuilder();
1331     builder.setAssociatedCellCount(size);
1332     builder.setStale(result.isStale());
1333     return builder.build();
1334   }
1335 
1336   /**
1337    * Convert a protocol buffer Result to a client Result
1338    *
1339    * @param proto the protocol buffer Result to convert
1340    * @return the converted client Result
1341    */
1342   public static Result toResult(final ClientProtos.Result proto) {
1343     if (proto.hasExists()) {
1344       if (proto.getStale()) {
1345         return proto.getExists() ? EMPTY_RESULT_EXISTS_TRUE_STALE :EMPTY_RESULT_EXISTS_FALSE_STALE;
1346       }
1347       return proto.getExists() ? EMPTY_RESULT_EXISTS_TRUE : EMPTY_RESULT_EXISTS_FALSE;
1348     }
1349 
1350     List<CellProtos.Cell> values = proto.getCellList();
1351     if (values.isEmpty()){
1352       return proto.getStale() ? EMPTY_RESULT_STALE : EMPTY_RESULT;
1353     }
1354 
1355     List<Cell> cells = new ArrayList<Cell>(values.size());
1356     for (CellProtos.Cell c : values) {
1357       cells.add(toCell(c));
1358     }
1359     return Result.create(cells, null, proto.getStale(), proto.getPartial());
1360   }
1361 
1362   /**
1363    * Convert a protocol buffer Result to a client Result
1364    *
1365    * @param proto the protocol buffer Result to convert
1366    * @param scanner Optional cell scanner.
1367    * @return the converted client Result
1368    * @throws IOException
1369    */
1370   public static Result toResult(final ClientProtos.Result proto, final CellScanner scanner)
1371   throws IOException {
1372     List<CellProtos.Cell> values = proto.getCellList();
1373 
1374     if (proto.hasExists()) {
1375       if ((values != null && !values.isEmpty()) ||
1376           (proto.hasAssociatedCellCount() && proto.getAssociatedCellCount() > 0)) {
1377         throw new IllegalArgumentException("bad proto: exists with cells is no allowed " + proto);
1378       }
1379       if (proto.getStale()) {
1380         return proto.getExists() ? EMPTY_RESULT_EXISTS_TRUE_STALE :EMPTY_RESULT_EXISTS_FALSE_STALE;
1381       }
1382       return proto.getExists() ? EMPTY_RESULT_EXISTS_TRUE : EMPTY_RESULT_EXISTS_FALSE;
1383     }
1384 
1385     // TODO: Unit test that has some Cells in scanner and some in the proto.
1386     List<Cell> cells = null;
1387     if (proto.hasAssociatedCellCount()) {
1388       int count = proto.getAssociatedCellCount();
1389       cells = new ArrayList<Cell>(count + values.size());
1390       for (int i = 0; i < count; i++) {
1391         if (!scanner.advance()) throw new IOException("Failed get " + i + " of " + count);
1392         cells.add(scanner.current());
1393       }
1394     }
1395 
1396     if (!values.isEmpty()){
1397       if (cells == null) cells = new ArrayList<Cell>(values.size());
1398       for (CellProtos.Cell c: values) {
1399         cells.add(toCell(c));
1400       }
1401     }
1402 
1403     return (cells == null || cells.isEmpty())
1404         ? (proto.getStale() ? EMPTY_RESULT_STALE : EMPTY_RESULT)
1405         : Result.create(cells, null, proto.getStale());
1406   }
1407 
1408 
1409   /**
1410    * Convert a ByteArrayComparable to a protocol buffer Comparator
1411    *
1412    * @param comparator the ByteArrayComparable to convert
1413    * @return the converted protocol buffer Comparator
1414    */
1415   public static ComparatorProtos.Comparator toComparator(ByteArrayComparable comparator) {
1416     ComparatorProtos.Comparator.Builder builder = ComparatorProtos.Comparator.newBuilder();
1417     builder.setName(comparator.getClass().getName());
1418     builder.setSerializedComparator(ByteStringer.wrap(comparator.toByteArray()));
1419     return builder.build();
1420   }
1421 
1422   /**
1423    * Convert a protocol buffer Comparator to a ByteArrayComparable
1424    *
1425    * @param proto the protocol buffer Comparator to convert
1426    * @return the converted ByteArrayComparable
1427    */
1428   @SuppressWarnings("unchecked")
1429   public static ByteArrayComparable toComparator(ComparatorProtos.Comparator proto)
1430   throws IOException {
1431     String type = proto.getName();
1432     String funcName = "parseFrom";
1433     byte [] value = proto.getSerializedComparator().toByteArray();
1434     try {
1435       Class<? extends ByteArrayComparable> c =
1436         (Class<? extends ByteArrayComparable>)Class.forName(type, true, CLASS_LOADER);
1437       Method parseFrom = c.getMethod(funcName, byte[].class);
1438       if (parseFrom == null) {
1439         throw new IOException("Unable to locate function: " + funcName + " in type: " + type);
1440       }
1441       return (ByteArrayComparable)parseFrom.invoke(null, value);
1442     } catch (Exception e) {
1443       throw new IOException(e);
1444     }
1445   }
1446 
1447   /**
1448    * Convert a protocol buffer Filter to a client Filter
1449    *
1450    * @param proto the protocol buffer Filter to convert
1451    * @return the converted Filter
1452    */
1453   @SuppressWarnings("unchecked")
1454   public static Filter toFilter(FilterProtos.Filter proto) throws IOException {
1455     String type = proto.getName();
1456     final byte [] value = proto.getSerializedFilter().toByteArray();
1457     String funcName = "parseFrom";
1458     try {
1459       Class<? extends Filter> c =
1460         (Class<? extends Filter>)Class.forName(type, true, CLASS_LOADER);
1461       Method parseFrom = c.getMethod(funcName, byte[].class);
1462       if (parseFrom == null) {
1463         throw new IOException("Unable to locate function: " + funcName + " in type: " + type);
1464       }
1465       return (Filter)parseFrom.invoke(c, value);
1466     } catch (Exception e) {
1467       // Either we couldn't instantiate the method object, or "parseFrom" failed.
1468       // In either case, let's not retry.
1469       throw new DoNotRetryIOException(e);
1470     }
1471   }
1472 
1473   /**
1474    * Convert a client Filter to a protocol buffer Filter
1475    *
1476    * @param filter the Filter to convert
1477    * @return the converted protocol buffer Filter
1478    */
1479   public static FilterProtos.Filter toFilter(Filter filter) throws IOException {
1480     FilterProtos.Filter.Builder builder = FilterProtos.Filter.newBuilder();
1481     builder.setName(filter.getClass().getName());
1482     builder.setSerializedFilter(ByteStringer.wrap(filter.toByteArray()));
1483     return builder.build();
1484   }
1485 
1486   /**
1487    * Convert a delete KeyValue type to protocol buffer DeleteType.
1488    *
1489    * @param type
1490    * @return protocol buffer DeleteType
1491    * @throws IOException
1492    */
1493   public static DeleteType toDeleteType(
1494       KeyValue.Type type) throws IOException {
1495     switch (type) {
1496     case Delete:
1497       return DeleteType.DELETE_ONE_VERSION;
1498     case DeleteColumn:
1499       return DeleteType.DELETE_MULTIPLE_VERSIONS;
1500     case DeleteFamily:
1501       return DeleteType.DELETE_FAMILY;
1502     case DeleteFamilyVersion:
1503       return DeleteType.DELETE_FAMILY_VERSION;
1504     default:
1505         throw new IOException("Unknown delete type: " + type);
1506     }
1507   }
1508 
1509   /**
1510    * Convert a protocol buffer DeleteType to delete KeyValue type.
1511    *
1512    * @param type The DeleteType
1513    * @return The type.
1514    * @throws IOException
1515    */
1516   public static KeyValue.Type fromDeleteType(
1517       DeleteType type) throws IOException {
1518     switch (type) {
1519     case DELETE_ONE_VERSION:
1520       return KeyValue.Type.Delete;
1521     case DELETE_MULTIPLE_VERSIONS:
1522       return KeyValue.Type.DeleteColumn;
1523     case DELETE_FAMILY:
1524       return KeyValue.Type.DeleteFamily;
1525     case DELETE_FAMILY_VERSION:
1526       return KeyValue.Type.DeleteFamilyVersion;
1527     default:
1528       throw new IOException("Unknown delete type: " + type);
1529     }
1530   }
1531 
1532   /**
1533    * Convert a stringified protocol buffer exception Parameter to a Java Exception
1534    *
1535    * @param parameter the protocol buffer Parameter to convert
1536    * @return the converted Exception
1537    * @throws IOException if failed to deserialize the parameter
1538    */
1539   @SuppressWarnings("unchecked")
1540   public static Throwable toException(final NameBytesPair parameter) throws IOException {
1541     if (parameter == null || !parameter.hasValue()) return null;
1542     String desc = parameter.getValue().toStringUtf8();
1543     String type = parameter.getName();
1544     try {
1545       Class<? extends Throwable> c =
1546         (Class<? extends Throwable>)Class.forName(type, true, CLASS_LOADER);
1547       Constructor<? extends Throwable> cn = null;
1548       try {
1549         cn = c.getDeclaredConstructor(String.class);
1550         return cn.newInstance(desc);
1551       } catch (NoSuchMethodException e) {
1552         // Could be a raw RemoteException. See HBASE-8987.
1553         cn = c.getDeclaredConstructor(String.class, String.class);
1554         return cn.newInstance(type, desc);
1555       }
1556     } catch (Exception e) {
1557       throw new IOException(e);
1558     }
1559   }
1560 
1561 // Start helpers for Client
1562 
1563   /**
1564    * A helper to get a row of the closet one before using client protocol.
1565    *
1566    * @param client
1567    * @param regionName
1568    * @param row
1569    * @param family
1570    * @return the row or the closestRowBefore if it doesn't exist
1571    * @throws IOException
1572    * @deprecated since 0.99 - use reversed scanner instead.
1573    */
1574   @Deprecated
1575   public static Result getRowOrBefore(final ClientService.BlockingInterface client,
1576       final byte[] regionName, final byte[] row,
1577       final byte[] family) throws IOException {
1578     GetRequest request =
1579       RequestConverter.buildGetRowOrBeforeRequest(
1580         regionName, row, family);
1581     try {
1582       GetResponse response = client.get(null, request);
1583       if (!response.hasResult()) return null;
1584       return toResult(response.getResult());
1585     } catch (ServiceException se) {
1586       throw getRemoteException(se);
1587     }
1588   }
1589 
1590   /**
1591    * A helper to bulk load a list of HFiles using client protocol.
1592    *
1593    * @param client
1594    * @param familyPaths
1595    * @param regionName
1596    * @param assignSeqNum
1597    * @return true if all are loaded
1598    * @throws IOException
1599    */
1600   public static boolean bulkLoadHFile(final ClientService.BlockingInterface client,
1601       final List<Pair<byte[], String>> familyPaths,
1602       final byte[] regionName, boolean assignSeqNum) throws IOException {
1603     BulkLoadHFileRequest request =
1604       RequestConverter.buildBulkLoadHFileRequest(familyPaths, regionName, assignSeqNum);
1605     try {
1606       BulkLoadHFileResponse response =
1607         client.bulkLoadHFile(null, request);
1608       return response.getLoaded();
1609     } catch (ServiceException se) {
1610       throw getRemoteException(se);
1611     }
1612   }
1613 
1614   public static CoprocessorServiceResponse execService(final ClientService.BlockingInterface client,
1615       final CoprocessorServiceCall call, final byte[] regionName) throws IOException {
1616     CoprocessorServiceRequest request = CoprocessorServiceRequest.newBuilder()
1617         .setCall(call).setRegion(
1618             RequestConverter.buildRegionSpecifier(REGION_NAME, regionName)).build();
1619     try {
1620       CoprocessorServiceResponse response =
1621           client.execService(null, request);
1622       return response;
1623     } catch (ServiceException se) {
1624       throw getRemoteException(se);
1625     }
1626   }
1627 
1628   public static CoprocessorServiceResponse execService(
1629     final MasterService.BlockingInterface client, final CoprocessorServiceCall call)
1630   throws IOException {
1631     CoprocessorServiceRequest request = CoprocessorServiceRequest.newBuilder()
1632         .setCall(call).setRegion(
1633             RequestConverter.buildRegionSpecifier(REGION_NAME, HConstants.EMPTY_BYTE_ARRAY)).build();
1634     try {
1635       CoprocessorServiceResponse response =
1636           client.execMasterService(null, request);
1637       return response;
1638     } catch (ServiceException se) {
1639       throw getRemoteException(se);
1640     }
1641   }
1642 
1643   /**
1644    * Make a region server endpoint call
1645    * @param client
1646    * @param call
1647    * @return CoprocessorServiceResponse
1648    * @throws IOException
1649    */
1650   public static CoprocessorServiceResponse execRegionServerService(
1651       final ClientService.BlockingInterface client, final CoprocessorServiceCall call)
1652       throws IOException {
1653     CoprocessorServiceRequest request =
1654         CoprocessorServiceRequest
1655             .newBuilder()
1656             .setCall(call)
1657             .setRegion(
1658               RequestConverter.buildRegionSpecifier(REGION_NAME, HConstants.EMPTY_BYTE_ARRAY))
1659             .build();
1660     try {
1661       CoprocessorServiceResponse response = client.execRegionServerService(null, request);
1662       return response;
1663     } catch (ServiceException se) {
1664       throw getRemoteException(se);
1665     }
1666   }
1667 
1668   @SuppressWarnings("unchecked")
1669   public static <T extends Service> T newServiceStub(Class<T> service, RpcChannel channel)
1670       throws Exception {
1671     return (T)Methods.call(service, null, "newStub",
1672         new Class[]{ RpcChannel.class }, new Object[]{ channel });
1673   }
1674 
1675 // End helpers for Client
1676 // Start helpers for Admin
1677 
1678   /**
1679    * A helper to retrieve region info given a region name
1680    * using admin protocol.
1681    *
1682    * @param admin
1683    * @param regionName
1684    * @return the retrieved region info
1685    * @throws IOException
1686    */
1687   public static HRegionInfo getRegionInfo(final AdminService.BlockingInterface admin,
1688       final byte[] regionName) throws IOException {
1689     try {
1690       GetRegionInfoRequest request =
1691         RequestConverter.buildGetRegionInfoRequest(regionName);
1692       GetRegionInfoResponse response =
1693         admin.getRegionInfo(null, request);
1694       return HRegionInfo.convert(response.getRegionInfo());
1695     } catch (ServiceException se) {
1696       throw getRemoteException(se);
1697     }
1698   }
1699 
1700   /**
1701    * A helper to close a region given a region name
1702    * using admin protocol.
1703    *
1704    * @param admin
1705    * @param regionName
1706    * @param transitionInZK
1707    * @throws IOException
1708    */
1709   public static void closeRegion(final AdminService.BlockingInterface admin,
1710       final ServerName server, final byte[] regionName, final boolean transitionInZK) throws IOException {
1711     CloseRegionRequest closeRegionRequest =
1712       RequestConverter.buildCloseRegionRequest(server, regionName, transitionInZK);
1713     try {
1714       admin.closeRegion(null, closeRegionRequest);
1715     } catch (ServiceException se) {
1716       throw getRemoteException(se);
1717     }
1718   }
1719 
1720   /**
1721    * A helper to close a region given a region name
1722    * using admin protocol.
1723    *
1724    * @param admin
1725    * @param regionName
1726    * @param versionOfClosingNode
1727    * @return true if the region is closed
1728    * @throws IOException
1729    */
1730   public static boolean closeRegion(final AdminService.BlockingInterface admin,
1731       final ServerName server,
1732       final byte[] regionName,
1733       final int versionOfClosingNode, final ServerName destinationServer,
1734       final boolean transitionInZK) throws IOException {
1735     CloseRegionRequest closeRegionRequest =
1736       RequestConverter.buildCloseRegionRequest(server,
1737         regionName, versionOfClosingNode, destinationServer, transitionInZK);
1738     try {
1739       CloseRegionResponse response = admin.closeRegion(null, closeRegionRequest);
1740       return ResponseConverter.isClosed(response);
1741     } catch (ServiceException se) {
1742       throw getRemoteException(se);
1743     }
1744   }
1745 
1746   /**
1747    * A helper to warmup a region given a region name
1748    * using admin protocol
1749    *
1750    * @param admin
1751    * @param regionInfo
1752    *
1753    */
1754   public static void warmupRegion(final AdminService.BlockingInterface admin,
1755       final HRegionInfo regionInfo) throws IOException  {
1756 
1757     try {
1758       WarmupRegionRequest warmupRegionRequest =
1759            RequestConverter.buildWarmupRegionRequest(regionInfo);
1760 
1761       admin.warmupRegion(null, warmupRegionRequest);
1762     } catch (ServiceException e) {
1763       throw getRemoteException(e);
1764     }
1765   }
1766 
1767   /**
1768    * A helper to open a region using admin protocol.
1769    * @param admin
1770    * @param region
1771    * @throws IOException
1772    */
1773   public static void openRegion(final AdminService.BlockingInterface admin,
1774       ServerName server, final HRegionInfo region) throws IOException {
1775     OpenRegionRequest request =
1776       RequestConverter.buildOpenRegionRequest(server, region, -1, null, null);
1777     try {
1778       admin.openRegion(null, request);
1779     } catch (ServiceException se) {
1780       throw ProtobufUtil.getRemoteException(se);
1781     }
1782   }
1783 
1784 
1785   /**
1786    * A helper to get the all the online regions on a region
1787    * server using admin protocol.
1788    *
1789    * @param admin
1790    * @return a list of online region info
1791    * @throws IOException
1792    */
1793   public static List<HRegionInfo> getOnlineRegions(final AdminService.BlockingInterface admin)
1794   throws IOException {
1795     GetOnlineRegionRequest request = RequestConverter.buildGetOnlineRegionRequest();
1796     GetOnlineRegionResponse response = null;
1797     try {
1798       response = admin.getOnlineRegion(null, request);
1799     } catch (ServiceException se) {
1800       throw getRemoteException(se);
1801     }
1802     return getRegionInfos(response);
1803   }
1804 
1805   /**
1806    * Get the list of region info from a GetOnlineRegionResponse
1807    *
1808    * @param proto the GetOnlineRegionResponse
1809    * @return the list of region info or null if <code>proto</code> is null
1810    */
1811   static List<HRegionInfo> getRegionInfos(final GetOnlineRegionResponse proto) {
1812     if (proto == null) return null;
1813     List<HRegionInfo> regionInfos = new ArrayList<HRegionInfo>();
1814     for (RegionInfo regionInfo: proto.getRegionInfoList()) {
1815       regionInfos.add(HRegionInfo.convert(regionInfo));
1816     }
1817     return regionInfos;
1818   }
1819 
1820   /**
1821    * A helper to get the info of a region server using admin protocol.
1822    *
1823    * @param admin
1824    * @return the server name
1825    * @throws IOException
1826    */
1827   public static ServerInfo getServerInfo(final AdminService.BlockingInterface admin)
1828   throws IOException {
1829     GetServerInfoRequest request = RequestConverter.buildGetServerInfoRequest();
1830     try {
1831       GetServerInfoResponse response = admin.getServerInfo(null, request);
1832       return response.getServerInfo();
1833     } catch (ServiceException se) {
1834       throw getRemoteException(se);
1835     }
1836   }
1837 
1838   /**
1839    * A helper to get the list of files of a column family
1840    * on a given region using admin protocol.
1841    *
1842    * @param admin
1843    * @param regionName
1844    * @param family
1845    * @return the list of store files
1846    * @throws IOException
1847    */
1848   public static List<String> getStoreFiles(final AdminService.BlockingInterface admin,
1849       final byte[] regionName, final byte[] family)
1850   throws IOException {
1851     GetStoreFileRequest request =
1852       RequestConverter.buildGetStoreFileRequest(regionName, family);
1853     try {
1854       GetStoreFileResponse response = admin.getStoreFile(null, request);
1855       return response.getStoreFileList();
1856     } catch (ServiceException se) {
1857       throw ProtobufUtil.getRemoteException(se);
1858     }
1859   }
1860 
1861   /**
1862    * A helper to split a region using admin protocol.
1863    *
1864    * @param admin
1865    * @param hri
1866    * @param splitPoint
1867    * @throws IOException
1868    */
1869   public static void split(final AdminService.BlockingInterface admin,
1870       final HRegionInfo hri, byte[] splitPoint) throws IOException {
1871     SplitRegionRequest request =
1872       RequestConverter.buildSplitRegionRequest(hri.getRegionName(), splitPoint);
1873     try {
1874       admin.splitRegion(null, request);
1875     } catch (ServiceException se) {
1876       throw ProtobufUtil.getRemoteException(se);
1877     }
1878   }
1879 
1880   /**
1881    * A helper to merge regions using admin protocol. Send request to
1882    * regionserver.
1883    * @param admin
1884    * @param region_a
1885    * @param region_b
1886    * @param forcible true if do a compulsory merge, otherwise we will only merge
1887    *          two adjacent regions
1888    * @throws IOException
1889    */
1890   public static void mergeRegions(final AdminService.BlockingInterface admin,
1891       final HRegionInfo region_a, final HRegionInfo region_b,
1892       final boolean forcible) throws IOException {
1893     MergeRegionsRequest request = RequestConverter.buildMergeRegionsRequest(
1894         region_a.getRegionName(), region_b.getRegionName(),forcible);
1895     try {
1896       admin.mergeRegions(null, request);
1897     } catch (ServiceException se) {
1898       throw ProtobufUtil.getRemoteException(se);
1899     }
1900   }
1901 
1902 // End helpers for Admin
1903 
1904   /*
1905    * Get the total (read + write) requests from a RegionLoad pb
1906    * @param rl - RegionLoad pb
1907    * @return total (read + write) requests
1908    */
1909   public static long getTotalRequestsCount(RegionLoad rl) {
1910     if (rl == null) {
1911       return 0;
1912     }
1913 
1914     return rl.getReadRequestsCount() + rl.getWriteRequestsCount();
1915   }
1916 
1917 
1918   /**
1919    * @param m Message to get delimited pb serialization of (with pb magic prefix)
1920    */
1921   public static byte [] toDelimitedByteArray(final Message m) throws IOException {
1922     // Allocate arbitrary big size so we avoid resizing.
1923     ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
1924     baos.write(PB_MAGIC);
1925     m.writeDelimitedTo(baos);
1926     return baos.toByteArray();
1927   }
1928 
1929   /**
1930    * Converts a Permission proto to a client Permission object.
1931    *
1932    * @param proto the protobuf Permission
1933    * @return the converted Permission
1934    */
1935   public static Permission toPermission(AccessControlProtos.Permission proto) {
1936     if (proto.getType() != AccessControlProtos.Permission.Type.Global) {
1937       return toTablePermission(proto);
1938     } else {
1939       List<Permission.Action> actions = toPermissionActions(proto.getGlobalPermission().getActionList());
1940       return new Permission(actions.toArray(new Permission.Action[actions.size()]));
1941     }
1942   }
1943 
1944   /**
1945    * Converts a Permission proto to a client TablePermission object.
1946    *
1947    * @param proto the protobuf Permission
1948    * @return the converted TablePermission
1949    */
1950   public static TablePermission toTablePermission(AccessControlProtos.Permission proto) {
1951     if(proto.getType() == AccessControlProtos.Permission.Type.Global) {
1952       AccessControlProtos.GlobalPermission perm = proto.getGlobalPermission();
1953       List<Permission.Action> actions = toPermissionActions(perm.getActionList());
1954 
1955       return new TablePermission(null, null, null,
1956           actions.toArray(new Permission.Action[actions.size()]));
1957     }
1958     if(proto.getType() == AccessControlProtos.Permission.Type.Namespace) {
1959       AccessControlProtos.NamespacePermission perm = proto.getNamespacePermission();
1960       List<Permission.Action> actions = toPermissionActions(perm.getActionList());
1961 
1962       if(!proto.hasNamespacePermission()) {
1963         throw new IllegalStateException("Namespace must not be empty in NamespacePermission");
1964       }
1965       String namespace = perm.getNamespaceName().toStringUtf8();
1966       return new TablePermission(namespace, actions.toArray(new Permission.Action[actions.size()]));
1967     }
1968     if(proto.getType() == AccessControlProtos.Permission.Type.Table) {
1969       AccessControlProtos.TablePermission perm = proto.getTablePermission();
1970       List<Permission.Action> actions = toPermissionActions(perm.getActionList());
1971 
1972       byte[] qualifier = null;
1973       byte[] family = null;
1974       TableName table = null;
1975 
1976       if (!perm.hasTableName()) {
1977         throw new IllegalStateException("TableName cannot be empty");
1978       }
1979       table = ProtobufUtil.toTableName(perm.getTableName());
1980 
1981       if (perm.hasFamily()) family = perm.getFamily().toByteArray();
1982       if (perm.hasQualifier()) qualifier = perm.getQualifier().toByteArray();
1983 
1984       return new TablePermission(table, family, qualifier,
1985           actions.toArray(new Permission.Action[actions.size()]));
1986     }
1987     throw new IllegalStateException("Unrecognize Perm Type: "+proto.getType());
1988   }
1989 
1990   /**
1991    * Convert a client Permission to a Permission proto
1992    *
1993    * @param perm the client Permission
1994    * @return the protobuf Permission
1995    */
1996   public static AccessControlProtos.Permission toPermission(Permission perm) {
1997     AccessControlProtos.Permission.Builder ret = AccessControlProtos.Permission.newBuilder();
1998     if (perm instanceof TablePermission) {
1999       TablePermission tablePerm = (TablePermission)perm;
2000       if(tablePerm.hasNamespace()) {
2001         ret.setType(AccessControlProtos.Permission.Type.Namespace);
2002 
2003         AccessControlProtos.NamespacePermission.Builder builder =
2004             AccessControlProtos.NamespacePermission.newBuilder();
2005         builder.setNamespaceName(ByteString.copyFromUtf8(tablePerm.getNamespace()));
2006         Permission.Action actions[] = perm.getActions();
2007         if (actions != null) {
2008           for (Permission.Action a : actions) {
2009             builder.addAction(toPermissionAction(a));
2010           }
2011         }
2012         ret.setNamespacePermission(builder);
2013         return ret.build();
2014       } else if (tablePerm.hasTable()) {
2015         ret.setType(AccessControlProtos.Permission.Type.Table);
2016 
2017         AccessControlProtos.TablePermission.Builder builder =
2018             AccessControlProtos.TablePermission.newBuilder();
2019         builder.setTableName(ProtobufUtil.toProtoTableName(tablePerm.getTableName()));
2020         if (tablePerm.hasFamily()) {
2021           builder.setFamily(ByteStringer.wrap(tablePerm.getFamily()));
2022         }
2023         if (tablePerm.hasQualifier()) {
2024           builder.setQualifier(ByteStringer.wrap(tablePerm.getQualifier()));
2025         }
2026         Permission.Action actions[] = perm.getActions();
2027         if (actions != null) {
2028           for (Permission.Action a : actions) {
2029             builder.addAction(toPermissionAction(a));
2030           }
2031         }
2032         ret.setTablePermission(builder);
2033         return ret.build();
2034       }
2035     }
2036 
2037     ret.setType(AccessControlProtos.Permission.Type.Global);
2038 
2039     AccessControlProtos.GlobalPermission.Builder builder =
2040         AccessControlProtos.GlobalPermission.newBuilder();
2041     Permission.Action actions[] = perm.getActions();
2042     if (actions != null) {
2043       for (Permission.Action a: actions) {
2044         builder.addAction(toPermissionAction(a));
2045       }
2046     }
2047     ret.setGlobalPermission(builder);
2048     return ret.build();
2049   }
2050 
2051   /**
2052    * Converts a list of Permission.Action proto to a list of client Permission.Action objects.
2053    *
2054    * @param protoActions the list of protobuf Actions
2055    * @return the converted list of Actions
2056    */
2057   public static List<Permission.Action> toPermissionActions(
2058       List<AccessControlProtos.Permission.Action> protoActions) {
2059     List<Permission.Action> actions = new ArrayList<Permission.Action>(protoActions.size());
2060     for (AccessControlProtos.Permission.Action a : protoActions) {
2061       actions.add(toPermissionAction(a));
2062     }
2063     return actions;
2064   }
2065 
2066   /**
2067    * Converts a Permission.Action proto to a client Permission.Action object.
2068    *
2069    * @param action the protobuf Action
2070    * @return the converted Action
2071    */
2072   public static Permission.Action toPermissionAction(
2073       AccessControlProtos.Permission.Action action) {
2074     switch (action) {
2075       case READ:
2076         return Permission.Action.READ;
2077       case WRITE:
2078         return Permission.Action.WRITE;
2079       case EXEC:
2080         return Permission.Action.EXEC;
2081       case CREATE:
2082         return Permission.Action.CREATE;
2083       case ADMIN:
2084         return Permission.Action.ADMIN;
2085     }
2086     throw new IllegalArgumentException("Unknown action value "+action.name());
2087   }
2088 
2089   /**
2090    * Convert a client Permission.Action to a Permission.Action proto
2091    *
2092    * @param action the client Action
2093    * @return the protobuf Action
2094    */
2095   public static AccessControlProtos.Permission.Action toPermissionAction(
2096       Permission.Action action) {
2097     switch (action) {
2098       case READ:
2099         return AccessControlProtos.Permission.Action.READ;
2100       case WRITE:
2101         return AccessControlProtos.Permission.Action.WRITE;
2102       case EXEC:
2103         return AccessControlProtos.Permission.Action.EXEC;
2104       case CREATE:
2105         return AccessControlProtos.Permission.Action.CREATE;
2106       case ADMIN:
2107         return AccessControlProtos.Permission.Action.ADMIN;
2108     }
2109     throw new IllegalArgumentException("Unknown action value "+action.name());
2110   }
2111 
2112   /**
2113    * Convert a client user permission to a user permission proto
2114    *
2115    * @param perm the client UserPermission
2116    * @return the protobuf UserPermission
2117    */
2118   public static AccessControlProtos.UserPermission toUserPermission(UserPermission perm) {
2119     return AccessControlProtos.UserPermission.newBuilder()
2120         .setUser(ByteStringer.wrap(perm.getUser()))
2121         .setPermission(toPermission(perm))
2122         .build();
2123   }
2124 
2125   /**
2126    * Converts a user permission proto to a client user permission object.
2127    *
2128    * @param proto the protobuf UserPermission
2129    * @return the converted UserPermission
2130    */
2131   public static UserPermission toUserPermission(AccessControlProtos.UserPermission proto) {
2132     return new UserPermission(proto.getUser().toByteArray(),
2133         toTablePermission(proto.getPermission()));
2134   }
2135 
2136   /**
2137    * Convert a ListMultimap&lt;String, TablePermission&gt; where key is username
2138    * to a protobuf UserPermission
2139    *
2140    * @param perm the list of user and table permissions
2141    * @return the protobuf UserTablePermissions
2142    */
2143   public static AccessControlProtos.UsersAndPermissions toUserTablePermissions(
2144       ListMultimap<String, TablePermission> perm) {
2145     AccessControlProtos.UsersAndPermissions.Builder builder =
2146                   AccessControlProtos.UsersAndPermissions.newBuilder();
2147     for (Map.Entry<String, Collection<TablePermission>> entry : perm.asMap().entrySet()) {
2148       AccessControlProtos.UsersAndPermissions.UserPermissions.Builder userPermBuilder =
2149                   AccessControlProtos.UsersAndPermissions.UserPermissions.newBuilder();
2150       userPermBuilder.setUser(ByteString.copyFromUtf8(entry.getKey()));
2151       for (TablePermission tablePerm: entry.getValue()) {
2152         userPermBuilder.addPermissions(toPermission(tablePerm));
2153       }
2154       builder.addUserPermissions(userPermBuilder.build());
2155     }
2156     return builder.build();
2157   }
2158 
2159   /**
2160    * A utility used to grant a user global permissions.
2161    * <p>
2162    * It's also called by the shell, in case you want to find references.
2163    *
2164    * @param protocol the AccessControlService protocol proxy
2165    * @param userShortName the short name of the user to grant permissions
2166    * @param actions the permissions to be granted
2167    * @throws ServiceException
2168    */
2169   public static void grant(AccessControlService.BlockingInterface protocol,
2170       String userShortName, Permission.Action... actions) throws ServiceException {
2171     List<AccessControlProtos.Permission.Action> permActions =
2172         Lists.newArrayListWithCapacity(actions.length);
2173     for (Permission.Action a : actions) {
2174       permActions.add(ProtobufUtil.toPermissionAction(a));
2175     }
2176     AccessControlProtos.GrantRequest request = RequestConverter.
2177       buildGrantRequest(userShortName, permActions.toArray(
2178         new AccessControlProtos.Permission.Action[actions.length]));
2179     protocol.grant(null, request);
2180   }
2181 
2182   /**
2183    * A utility used to grant a user table permissions. The permissions will
2184    * be for a table table/column family/qualifier.
2185    * <p>
2186    * It's also called by the shell, in case you want to find references.
2187    *
2188    * @param protocol the AccessControlService protocol proxy
2189    * @param userShortName the short name of the user to grant permissions
2190    * @param tableName optional table name
2191    * @param f optional column family
2192    * @param q optional qualifier
2193    * @param actions the permissions to be granted
2194    * @throws ServiceException
2195    */
2196   public static void grant(AccessControlService.BlockingInterface protocol,
2197       String userShortName, TableName tableName, byte[] f, byte[] q,
2198       Permission.Action... actions) throws ServiceException {
2199     List<AccessControlProtos.Permission.Action> permActions =
2200         Lists.newArrayListWithCapacity(actions.length);
2201     for (Permission.Action a : actions) {
2202       permActions.add(ProtobufUtil.toPermissionAction(a));
2203     }
2204     AccessControlProtos.GrantRequest request = RequestConverter.
2205       buildGrantRequest(userShortName, tableName, f, q, permActions.toArray(
2206         new AccessControlProtos.Permission.Action[actions.length]));
2207     protocol.grant(null, request);
2208   }
2209 
2210   /**
2211    * A utility used to grant a user namespace permissions.
2212    * <p>
2213    * It's also called by the shell, in case you want to find references.
2214    *
2215    * @param protocol the AccessControlService protocol proxy
2216    * @param namespace the short name of the user to grant permissions
2217    * @param actions the permissions to be granted
2218    * @throws ServiceException
2219    */
2220   public static void grant(AccessControlService.BlockingInterface protocol,
2221       String userShortName, String namespace,
2222       Permission.Action... actions) throws ServiceException {
2223     List<AccessControlProtos.Permission.Action> permActions =
2224         Lists.newArrayListWithCapacity(actions.length);
2225     for (Permission.Action a : actions) {
2226       permActions.add(ProtobufUtil.toPermissionAction(a));
2227     }
2228     AccessControlProtos.GrantRequest request = RequestConverter.
2229       buildGrantRequest(userShortName, namespace, permActions.toArray(
2230         new AccessControlProtos.Permission.Action[actions.length]));
2231     protocol.grant(null, request);
2232   }
2233 
2234   /**
2235    * A utility used to revoke a user's global permissions.
2236    * <p>
2237    * It's also called by the shell, in case you want to find references.
2238    *
2239    * @param protocol the AccessControlService protocol proxy
2240    * @param userShortName the short name of the user to revoke permissions
2241    * @param actions the permissions to be revoked
2242    * @throws ServiceException
2243    */
2244   public static void revoke(AccessControlService.BlockingInterface protocol,
2245       String userShortName, Permission.Action... actions) throws ServiceException {
2246     List<AccessControlProtos.Permission.Action> permActions =
2247         Lists.newArrayListWithCapacity(actions.length);
2248     for (Permission.Action a : actions) {
2249       permActions.add(ProtobufUtil.toPermissionAction(a));
2250     }
2251     AccessControlProtos.RevokeRequest request = RequestConverter.
2252       buildRevokeRequest(userShortName, permActions.toArray(
2253         new AccessControlProtos.Permission.Action[actions.length]));
2254     protocol.revoke(null, request);
2255   }
2256 
2257   /**
2258    * A utility used to revoke a user's table permissions. The permissions will
2259    * be for a table/column family/qualifier.
2260    * <p>
2261    * It's also called by the shell, in case you want to find references.
2262    *
2263    * @param protocol the AccessControlService protocol proxy
2264    * @param userShortName the short name of the user to revoke permissions
2265    * @param tableName optional table name
2266    * @param f optional column family
2267    * @param q optional qualifier
2268    * @param actions the permissions to be revoked
2269    * @throws ServiceException
2270    */
2271   public static void revoke(AccessControlService.BlockingInterface protocol,
2272       String userShortName, TableName tableName, byte[] f, byte[] q,
2273       Permission.Action... actions) throws ServiceException {
2274     List<AccessControlProtos.Permission.Action> permActions =
2275         Lists.newArrayListWithCapacity(actions.length);
2276     for (Permission.Action a : actions) {
2277       permActions.add(ProtobufUtil.toPermissionAction(a));
2278     }
2279     AccessControlProtos.RevokeRequest request = RequestConverter.
2280       buildRevokeRequest(userShortName, tableName, f, q, permActions.toArray(
2281         new AccessControlProtos.Permission.Action[actions.length]));
2282     protocol.revoke(null, request);
2283   }
2284 
2285   /**
2286    * A utility used to revoke a user's namespace permissions.
2287    * <p>
2288    * It's also called by the shell, in case you want to find references.
2289    *
2290    * @param protocol the AccessControlService protocol proxy
2291    * @param userShortName the short name of the user to revoke permissions
2292    * @param namespace optional table name
2293    * @param actions the permissions to be revoked
2294    * @throws ServiceException
2295    */
2296   public static void revoke(AccessControlService.BlockingInterface protocol,
2297       String userShortName, String namespace,
2298       Permission.Action... actions) throws ServiceException {
2299     List<AccessControlProtos.Permission.Action> permActions =
2300         Lists.newArrayListWithCapacity(actions.length);
2301     for (Permission.Action a : actions) {
2302       permActions.add(ProtobufUtil.toPermissionAction(a));
2303     }
2304     AccessControlProtos.RevokeRequest request = RequestConverter.
2305       buildRevokeRequest(userShortName, namespace, permActions.toArray(
2306         new AccessControlProtos.Permission.Action[actions.length]));
2307     protocol.revoke(null, request);
2308   }
2309 
2310   /**
2311    * A utility used to get user's global permissions.
2312    * <p>
2313    * It's also called by the shell, in case you want to find references.
2314    *
2315    * @param protocol the AccessControlService protocol proxy
2316    * @throws ServiceException
2317    */
2318   public static List<UserPermission> getUserPermissions(
2319       AccessControlService.BlockingInterface protocol) throws ServiceException {
2320     AccessControlProtos.GetUserPermissionsRequest.Builder builder =
2321       AccessControlProtos.GetUserPermissionsRequest.newBuilder();
2322     builder.setType(AccessControlProtos.Permission.Type.Global);
2323     AccessControlProtos.GetUserPermissionsRequest request = builder.build();
2324     AccessControlProtos.GetUserPermissionsResponse response =
2325       protocol.getUserPermissions(null, request);
2326     List<UserPermission> perms = new ArrayList<UserPermission>(response.getUserPermissionCount());
2327     for (AccessControlProtos.UserPermission perm: response.getUserPermissionList()) {
2328       perms.add(ProtobufUtil.toUserPermission(perm));
2329     }
2330     return perms;
2331   }
2332 
2333   /**
2334    * A utility used to get user table permissions.
2335    * <p>
2336    * It's also called by the shell, in case you want to find references.
2337    *
2338    * @param protocol the AccessControlService protocol proxy
2339    * @param t optional table name
2340    * @throws ServiceException
2341    */
2342   public static List<UserPermission> getUserPermissions(
2343       AccessControlService.BlockingInterface protocol,
2344       TableName t) throws ServiceException {
2345     AccessControlProtos.GetUserPermissionsRequest.Builder builder =
2346       AccessControlProtos.GetUserPermissionsRequest.newBuilder();
2347     if (t != null) {
2348       builder.setTableName(ProtobufUtil.toProtoTableName(t));
2349     }
2350     builder.setType(AccessControlProtos.Permission.Type.Table);
2351     AccessControlProtos.GetUserPermissionsRequest request = builder.build();
2352     AccessControlProtos.GetUserPermissionsResponse response =
2353       protocol.getUserPermissions(null, request);
2354     List<UserPermission> perms = new ArrayList<UserPermission>(response.getUserPermissionCount());
2355     for (AccessControlProtos.UserPermission perm: response.getUserPermissionList()) {
2356       perms.add(ProtobufUtil.toUserPermission(perm));
2357     }
2358     return perms;
2359   }
2360 
2361   /**
2362    * A utility used to get permissions for selected namespace.
2363    * <p>
2364    * It's also called by the shell, in case you want to find references.
2365    *
2366    * @param protocol the AccessControlService protocol proxy
2367    * @param namespace name of the namespace
2368    * @throws ServiceException
2369    */
2370   public static List<UserPermission> getUserPermissions(
2371       AccessControlService.BlockingInterface protocol,
2372       byte[] namespace) throws ServiceException {
2373     AccessControlProtos.GetUserPermissionsRequest.Builder builder =
2374       AccessControlProtos.GetUserPermissionsRequest.newBuilder();
2375     if (namespace != null) {
2376       builder.setNamespaceName(ByteStringer.wrap(namespace));
2377     }
2378     builder.setType(AccessControlProtos.Permission.Type.Namespace);
2379     AccessControlProtos.GetUserPermissionsRequest request = builder.build();
2380     AccessControlProtos.GetUserPermissionsResponse response =
2381       protocol.getUserPermissions(null, request);
2382     List<UserPermission> perms = new ArrayList<UserPermission>(response.getUserPermissionCount());
2383     for (AccessControlProtos.UserPermission perm: response.getUserPermissionList()) {
2384       perms.add(ProtobufUtil.toUserPermission(perm));
2385     }
2386     return perms;
2387   }
2388 
2389   /**
2390    * Convert a protobuf UserTablePermissions to a
2391    * ListMultimap&lt;String, TablePermission&gt; where key is username.
2392    *
2393    * @param proto the protobuf UserPermission
2394    * @return the converted UserPermission
2395    */
2396   public static ListMultimap<String, TablePermission> toUserTablePermissions(
2397       AccessControlProtos.UsersAndPermissions proto) {
2398     ListMultimap<String, TablePermission> perms = ArrayListMultimap.create();
2399     AccessControlProtos.UsersAndPermissions.UserPermissions userPerm;
2400 
2401     for (int i = 0; i < proto.getUserPermissionsCount(); i++) {
2402       userPerm = proto.getUserPermissions(i);
2403       for (int j = 0; j < userPerm.getPermissionsCount(); j++) {
2404         TablePermission tablePerm = toTablePermission(userPerm.getPermissions(j));
2405         perms.put(userPerm.getUser().toStringUtf8(), tablePerm);
2406       }
2407     }
2408 
2409     return perms;
2410   }
2411 
2412   /**
2413    * Converts a Token instance (with embedded identifier) to the protobuf representation.
2414    *
2415    * @param token the Token instance to copy
2416    * @return the protobuf Token message
2417    */
2418   public static AuthenticationProtos.Token toToken(Token<AuthenticationTokenIdentifier> token) {
2419     AuthenticationProtos.Token.Builder builder = AuthenticationProtos.Token.newBuilder();
2420     builder.setIdentifier(ByteStringer.wrap(token.getIdentifier()));
2421     builder.setPassword(ByteStringer.wrap(token.getPassword()));
2422     if (token.getService() != null) {
2423       builder.setService(ByteString.copyFromUtf8(token.getService().toString()));
2424     }
2425     return builder.build();
2426   }
2427 
2428   /**
2429    * Converts a protobuf Token message back into a Token instance.
2430    *
2431    * @param proto the protobuf Token message
2432    * @return the Token instance
2433    */
2434   public static Token<AuthenticationTokenIdentifier> toToken(AuthenticationProtos.Token proto) {
2435     return new Token<AuthenticationTokenIdentifier>(
2436         proto.hasIdentifier() ? proto.getIdentifier().toByteArray() : null,
2437         proto.hasPassword() ? proto.getPassword().toByteArray() : null,
2438         AuthenticationTokenIdentifier.AUTH_TOKEN_TYPE,
2439         proto.hasService() ? new Text(proto.getService().toStringUtf8()) : null);
2440   }
2441 
2442   /**
2443    * Find the HRegion encoded name based on a region specifier
2444    *
2445    * @param regionSpecifier the region specifier
2446    * @return the corresponding region's encoded name
2447    * @throws DoNotRetryIOException if the specifier type is unsupported
2448    */
2449   public static String getRegionEncodedName(
2450       final RegionSpecifier regionSpecifier) throws DoNotRetryIOException {
2451     byte[] value = regionSpecifier.getValue().toByteArray();
2452     RegionSpecifierType type = regionSpecifier.getType();
2453     switch (type) {
2454       case REGION_NAME:
2455         return HRegionInfo.encodeRegionName(value);
2456       case ENCODED_REGION_NAME:
2457         return Bytes.toString(value);
2458       default:
2459         throw new DoNotRetryIOException(
2460           "Unsupported region specifier type: " + type);
2461     }
2462   }
2463 
2464   public static ScanMetrics toScanMetrics(final byte[] bytes) {
2465     Parser<MapReduceProtos.ScanMetrics> parser = MapReduceProtos.ScanMetrics.PARSER;
2466     MapReduceProtos.ScanMetrics pScanMetrics = null;
2467     try {
2468       pScanMetrics = parser.parseFrom(bytes);
2469     } catch (InvalidProtocolBufferException e) {
2470       //Ignored there are just no key values to add.
2471     }
2472     ScanMetrics scanMetrics = new ScanMetrics();
2473     if (pScanMetrics != null) {
2474       for (HBaseProtos.NameInt64Pair pair : pScanMetrics.getMetricsList()) {
2475         if (pair.hasName() && pair.hasValue()) {
2476           scanMetrics.setCounter(pair.getName(), pair.getValue());
2477         }
2478       }
2479     }
2480     return scanMetrics;
2481   }
2482 
2483   public static MapReduceProtos.ScanMetrics toScanMetrics(ScanMetrics scanMetrics) {
2484     MapReduceProtos.ScanMetrics.Builder builder = MapReduceProtos.ScanMetrics.newBuilder();
2485     Map<String, Long> metrics = scanMetrics.getMetricsMap();
2486     for (Entry<String, Long> e : metrics.entrySet()) {
2487       HBaseProtos.NameInt64Pair nameInt64Pair =
2488           HBaseProtos.NameInt64Pair.newBuilder()
2489               .setName(e.getKey())
2490               .setValue(e.getValue())
2491               .build();
2492       builder.addMetrics(nameInt64Pair);
2493     }
2494     return builder.build();
2495   }
2496 
2497   /**
2498    * Unwraps an exception from a protobuf service into the underlying (expected) IOException.
2499    * This method will <strong>always</strong> throw an exception.
2500    * @param se the {@code ServiceException} instance to convert into an {@code IOException}
2501    */
2502   public static void toIOException(ServiceException se) throws IOException {
2503     if (se == null) {
2504       throw new NullPointerException("Null service exception passed!");
2505     }
2506 
2507     Throwable cause = se.getCause();
2508     if (cause != null && cause instanceof IOException) {
2509       throw (IOException)cause;
2510     }
2511     throw new IOException(se);
2512   }
2513 
2514   public static CellProtos.Cell toCell(final Cell kv) {
2515     // Doing this is going to kill us if we do it for all data passed.
2516     // St.Ack 20121205
2517     CellProtos.Cell.Builder kvbuilder = CellProtos.Cell.newBuilder();
2518     kvbuilder.setRow(ByteStringer.wrap(kv.getRowArray(), kv.getRowOffset(),
2519         kv.getRowLength()));
2520     kvbuilder.setFamily(ByteStringer.wrap(kv.getFamilyArray(),
2521         kv.getFamilyOffset(), kv.getFamilyLength()));
2522     kvbuilder.setQualifier(ByteStringer.wrap(kv.getQualifierArray(),
2523         kv.getQualifierOffset(), kv.getQualifierLength()));
2524     kvbuilder.setCellType(CellProtos.CellType.valueOf(kv.getTypeByte()));
2525     kvbuilder.setTimestamp(kv.getTimestamp());
2526     kvbuilder.setValue(ByteStringer.wrap(kv.getValueArray(), kv.getValueOffset(),
2527         kv.getValueLength()));
2528     return kvbuilder.build();
2529   }
2530 
2531   public static Cell toCell(final CellProtos.Cell cell) {
2532     // Doing this is going to kill us if we do it for all data passed.
2533     // St.Ack 20121205
2534     return CellUtil.createCell(cell.getRow().toByteArray(),
2535       cell.getFamily().toByteArray(),
2536       cell.getQualifier().toByteArray(),
2537       cell.getTimestamp(),
2538       (byte)cell.getCellType().getNumber(),
2539       cell.getValue().toByteArray());
2540   }
2541 
2542   public static HBaseProtos.NamespaceDescriptor toProtoNamespaceDescriptor(NamespaceDescriptor ns) {
2543     HBaseProtos.NamespaceDescriptor.Builder b =
2544         HBaseProtos.NamespaceDescriptor.newBuilder()
2545             .setName(ByteString.copyFromUtf8(ns.getName()));
2546     for(Map.Entry<String, String> entry: ns.getConfiguration().entrySet()) {
2547       b.addConfiguration(HBaseProtos.NameStringPair.newBuilder()
2548           .setName(entry.getKey())
2549           .setValue(entry.getValue()));
2550     }
2551     return b.build();
2552   }
2553 
2554   public static NamespaceDescriptor toNamespaceDescriptor(
2555       HBaseProtos.NamespaceDescriptor desc) throws IOException {
2556     NamespaceDescriptor.Builder b =
2557       NamespaceDescriptor.create(desc.getName().toStringUtf8());
2558     for(HBaseProtos.NameStringPair prop : desc.getConfigurationList()) {
2559       b.addConfiguration(prop.getName(), prop.getValue());
2560     }
2561     return b.build();
2562   }
2563 
2564   /**
2565    * Get an instance of the argument type declared in a class's signature. The
2566    * argument type is assumed to be a PB Message subclass, and the instance is
2567    * created using parseFrom method on the passed ByteString.
2568    * @param runtimeClass the runtime type of the class
2569    * @param position the position of the argument in the class declaration
2570    * @param b the ByteString which should be parsed to get the instance created
2571    * @return the instance
2572    * @throws IOException
2573    */
2574   @SuppressWarnings("unchecked")
2575   public static <T extends Message>
2576   T getParsedGenericInstance(Class<?> runtimeClass, int position, ByteString b)
2577       throws IOException {
2578     Type type = runtimeClass.getGenericSuperclass();
2579     Type argType = ((ParameterizedType)type).getActualTypeArguments()[position];
2580     Class<T> classType = (Class<T>)argType;
2581     T inst;
2582     try {
2583       Method m = classType.getMethod("parseFrom", ByteString.class);
2584       inst = (T)m.invoke(null, b);
2585       return inst;
2586     } catch (SecurityException e) {
2587       throw new IOException(e);
2588     } catch (NoSuchMethodException e) {
2589       throw new IOException(e);
2590     } catch (IllegalArgumentException e) {
2591       throw new IOException(e);
2592     } catch (InvocationTargetException e) {
2593       throw new IOException(e);
2594     } catch (IllegalAccessException e) {
2595       throw new IOException(e);
2596     }
2597   }
2598 
2599   public static CompactionDescriptor toCompactionDescriptor(HRegionInfo info, byte[] family,
2600       List<Path> inputPaths, List<Path> outputPaths, Path storeDir) {
2601     return toCompactionDescriptor(info, null, family, inputPaths, outputPaths, storeDir);
2602   }
2603 
2604   @SuppressWarnings("deprecation")
2605   public static CompactionDescriptor toCompactionDescriptor(HRegionInfo info, byte[] regionName,
2606       byte[] family, List<Path> inputPaths, List<Path> outputPaths, Path storeDir) {
2607     // compaction descriptor contains relative paths.
2608     // input / output paths are relative to the store dir
2609     // store dir is relative to region dir
2610     CompactionDescriptor.Builder builder = CompactionDescriptor.newBuilder()
2611         .setTableName(ByteStringer.wrap(info.getTableName()))
2612         .setEncodedRegionName(ByteStringer.wrap(
2613           regionName == null ? info.getEncodedNameAsBytes() : regionName))
2614         .setFamilyName(ByteStringer.wrap(family))
2615         .setStoreHomeDir(storeDir.getName()); //make relative
2616     for (Path inputPath : inputPaths) {
2617       builder.addCompactionInput(inputPath.getName()); //relative path
2618     }
2619     for (Path outputPath : outputPaths) {
2620       builder.addCompactionOutput(outputPath.getName());
2621     }
2622     builder.setRegionName(ByteStringer.wrap(info.getRegionName()));
2623     return builder.build();
2624   }
2625 
2626   public static FlushDescriptor toFlushDescriptor(FlushAction action, HRegionInfo hri,
2627       long flushSeqId, Map<byte[], List<Path>> committedFiles) {
2628     FlushDescriptor.Builder desc = FlushDescriptor.newBuilder()
2629         .setAction(action)
2630         .setEncodedRegionName(ByteStringer.wrap(hri.getEncodedNameAsBytes()))
2631         .setRegionName(ByteStringer.wrap(hri.getRegionName()))
2632         .setFlushSequenceNumber(flushSeqId)
2633         .setTableName(ByteStringer.wrap(hri.getTable().getName()));
2634 
2635     for (Map.Entry<byte[], List<Path>> entry : committedFiles.entrySet()) {
2636       WALProtos.FlushDescriptor.StoreFlushDescriptor.Builder builder =
2637           WALProtos.FlushDescriptor.StoreFlushDescriptor.newBuilder()
2638           .setFamilyName(ByteStringer.wrap(entry.getKey()))
2639           .setStoreHomeDir(Bytes.toString(entry.getKey())); //relative to region
2640       if (entry.getValue() != null) {
2641         for (Path path : entry.getValue()) {
2642           builder.addFlushOutput(path.getName());
2643         }
2644       }
2645       desc.addStoreFlushes(builder);
2646     }
2647     return desc.build();
2648   }
2649 
2650   public static RegionEventDescriptor toRegionEventDescriptor(
2651       EventType eventType, HRegionInfo hri, long seqId, ServerName server,
2652       Map<byte[], List<Path>> storeFiles) {
2653     RegionEventDescriptor.Builder desc = RegionEventDescriptor.newBuilder()
2654         .setEventType(eventType)
2655         .setTableName(ByteStringer.wrap(hri.getTable().getName()))
2656         .setEncodedRegionName(ByteStringer.wrap(hri.getEncodedNameAsBytes()))
2657         .setRegionName(ByteStringer.wrap(hri.getRegionName()))
2658         .setLogSequenceNumber(seqId)
2659         .setServer(toServerName(server));
2660 
2661     for (Map.Entry<byte[], List<Path>> entry : storeFiles.entrySet()) {
2662       StoreDescriptor.Builder builder = StoreDescriptor.newBuilder()
2663           .setFamilyName(ByteStringer.wrap(entry.getKey()))
2664           .setStoreHomeDir(Bytes.toString(entry.getKey()));
2665       for (Path path : entry.getValue()) {
2666         builder.addStoreFile(path.getName());
2667       }
2668 
2669       desc.addStores(builder);
2670     }
2671     return desc.build();
2672   }
2673 
2674   /**
2675    * Return short version of Message toString'd, shorter than TextFormat#shortDebugString.
2676    * Tries to NOT print out data both because it can be big but also so we do not have data in our
2677    * logs. Use judiciously.
2678    * @param m
2679    * @return toString of passed <code>m</code>
2680    */
2681   public static String getShortTextFormat(Message m) {
2682     if (m == null) return "null";
2683     if (m instanceof ScanRequest) {
2684       // This should be small and safe to output.  No data.
2685       return TextFormat.shortDebugString(m);
2686     } else if (m instanceof RegionServerReportRequest) {
2687       // Print a short message only, just the servername and the requests, not the full load.
2688       RegionServerReportRequest r = (RegionServerReportRequest)m;
2689       return "server " + TextFormat.shortDebugString(r.getServer()) +
2690         " load { numberOfRequests: " + r.getLoad().getNumberOfRequests() + " }";
2691     } else if (m instanceof RegionServerStartupRequest) {
2692       // Should be small enough.
2693       return TextFormat.shortDebugString(m);
2694     } else if (m instanceof MutationProto) {
2695       return toShortString((MutationProto)m);
2696     } else if (m instanceof GetRequest) {
2697       GetRequest r = (GetRequest) m;
2698       return "region= " + getStringForByteString(r.getRegion().getValue()) +
2699           ", row=" + getStringForByteString(r.getGet().getRow());
2700     } else if (m instanceof ClientProtos.MultiRequest) {
2701       ClientProtos.MultiRequest r = (ClientProtos.MultiRequest) m;
2702       // Get first set of Actions.
2703       ClientProtos.RegionAction actions = r.getRegionActionList().get(0);
2704       String row = actions.getActionCount() <= 0? "":
2705         getStringForByteString(actions.getAction(0).hasGet()?
2706           actions.getAction(0).getGet().getRow():
2707           actions.getAction(0).getMutation().getRow());
2708       return "region= " + getStringForByteString(actions.getRegion().getValue()) +
2709           ", for " + r.getRegionActionCount() +
2710           " actions and 1st row key=" + row;
2711     } else if (m instanceof ClientProtos.MutateRequest) {
2712       ClientProtos.MutateRequest r = (ClientProtos.MutateRequest) m;
2713       return "region= " + getStringForByteString(r.getRegion().getValue()) +
2714           ", row=" + getStringForByteString(r.getMutation().getRow());
2715     }
2716     return "TODO: " + m.getClass().toString();
2717   }
2718 
2719   private static String getStringForByteString(ByteString bs) {
2720     return Bytes.toStringBinary(bs.toByteArray());
2721   }
2722 
2723   /**
2724    * Print out some subset of a MutationProto rather than all of it and its data
2725    * @param proto Protobuf to print out
2726    * @return Short String of mutation proto
2727    */
2728   static String toShortString(final MutationProto proto) {
2729     return "row=" + Bytes.toString(proto.getRow().toByteArray()) +
2730         ", type=" + proto.getMutateType().toString();
2731   }
2732 
2733   public static TableName toTableName(HBaseProtos.TableName tableNamePB) {
2734     return TableName.valueOf(tableNamePB.getNamespace().asReadOnlyByteBuffer(),
2735         tableNamePB.getQualifier().asReadOnlyByteBuffer());
2736   }
2737 
2738   public static HBaseProtos.TableName toProtoTableName(TableName tableName) {
2739     return HBaseProtos.TableName.newBuilder()
2740         .setNamespace(ByteStringer.wrap(tableName.getNamespace()))
2741         .setQualifier(ByteStringer.wrap(tableName.getQualifier())).build();
2742   }
2743 
2744   public static TableName[] getTableNameArray(List<HBaseProtos.TableName> tableNamesList) {
2745     if (tableNamesList == null) {
2746       return new TableName[0];
2747     }
2748     TableName[] tableNames = new TableName[tableNamesList.size()];
2749     for (int i = 0; i < tableNamesList.size(); i++) {
2750       tableNames[i] = toTableName(tableNamesList.get(i));
2751     }
2752     return tableNames;
2753   }
2754 
2755   /**
2756    * Convert a protocol buffer CellVisibility to a client CellVisibility
2757    *
2758    * @param proto
2759    * @return the converted client CellVisibility
2760    */
2761   public static CellVisibility toCellVisibility(ClientProtos.CellVisibility proto) {
2762     if (proto == null) return null;
2763     return new CellVisibility(proto.getExpression());
2764   }
2765 
2766   /**
2767    * Convert a protocol buffer CellVisibility bytes to a client CellVisibility
2768    *
2769    * @param protoBytes
2770    * @return the converted client CellVisibility
2771    * @throws DeserializationException
2772    */
2773   public static CellVisibility toCellVisibility(byte[] protoBytes) throws DeserializationException {
2774     if (protoBytes == null) return null;
2775     ClientProtos.CellVisibility.Builder builder = ClientProtos.CellVisibility.newBuilder();
2776     ClientProtos.CellVisibility proto = null;
2777     try {
2778       ProtobufUtil.mergeFrom(builder, protoBytes);
2779       proto = builder.build();
2780     } catch (IOException e) {
2781       throw new DeserializationException(e);
2782     }
2783     return toCellVisibility(proto);
2784   }
2785 
2786   /**
2787    * Create a protocol buffer CellVisibility based on a client CellVisibility.
2788    *
2789    * @param cellVisibility
2790    * @return a protocol buffer CellVisibility
2791    */
2792   public static ClientProtos.CellVisibility toCellVisibility(CellVisibility cellVisibility) {
2793     ClientProtos.CellVisibility.Builder builder = ClientProtos.CellVisibility.newBuilder();
2794     builder.setExpression(cellVisibility.getExpression());
2795     return builder.build();
2796   }
2797 
2798   /**
2799    * Convert a protocol buffer Authorizations to a client Authorizations
2800    *
2801    * @param proto
2802    * @return the converted client Authorizations
2803    */
2804   public static Authorizations toAuthorizations(ClientProtos.Authorizations proto) {
2805     if (proto == null) return null;
2806     return new Authorizations(proto.getLabelList());
2807   }
2808 
2809   /**
2810    * Convert a protocol buffer Authorizations bytes to a client Authorizations
2811    *
2812    * @param protoBytes
2813    * @return the converted client Authorizations
2814    * @throws DeserializationException
2815    */
2816   public static Authorizations toAuthorizations(byte[] protoBytes) throws DeserializationException {
2817     if (protoBytes == null) return null;
2818     ClientProtos.Authorizations.Builder builder = ClientProtos.Authorizations.newBuilder();
2819     ClientProtos.Authorizations proto = null;
2820     try {
2821       ProtobufUtil.mergeFrom(builder, protoBytes);
2822       proto = builder.build();
2823     } catch (IOException e) {
2824       throw new DeserializationException(e);
2825     }
2826     return toAuthorizations(proto);
2827   }
2828 
2829   /**
2830    * Create a protocol buffer Authorizations based on a client Authorizations.
2831    *
2832    * @param authorizations
2833    * @return a protocol buffer Authorizations
2834    */
2835   public static ClientProtos.Authorizations toAuthorizations(Authorizations authorizations) {
2836     ClientProtos.Authorizations.Builder builder = ClientProtos.Authorizations.newBuilder();
2837     for (String label : authorizations.getLabels()) {
2838       builder.addLabel(label);
2839     }
2840     return builder.build();
2841   }
2842 
2843   public static AccessControlProtos.UsersAndPermissions toUsersAndPermissions(String user,
2844       Permission perms) {
2845     return AccessControlProtos.UsersAndPermissions.newBuilder()
2846       .addUserPermissions(AccessControlProtos.UsersAndPermissions.UserPermissions.newBuilder()
2847         .setUser(ByteString.copyFromUtf8(user))
2848         .addPermissions(toPermission(perms))
2849         .build())
2850       .build();
2851   }
2852 
2853   public static AccessControlProtos.UsersAndPermissions toUsersAndPermissions(
2854       ListMultimap<String, Permission> perms) {
2855     AccessControlProtos.UsersAndPermissions.Builder builder =
2856         AccessControlProtos.UsersAndPermissions.newBuilder();
2857     for (Map.Entry<String, Collection<Permission>> entry : perms.asMap().entrySet()) {
2858       AccessControlProtos.UsersAndPermissions.UserPermissions.Builder userPermBuilder =
2859         AccessControlProtos.UsersAndPermissions.UserPermissions.newBuilder();
2860       userPermBuilder.setUser(ByteString.copyFromUtf8(entry.getKey()));
2861       for (Permission perm: entry.getValue()) {
2862         userPermBuilder.addPermissions(toPermission(perm));
2863       }
2864       builder.addUserPermissions(userPermBuilder.build());
2865     }
2866     return builder.build();
2867   }
2868 
2869   public static ListMultimap<String, Permission> toUsersAndPermissions(
2870       AccessControlProtos.UsersAndPermissions proto) {
2871     ListMultimap<String, Permission> result = ArrayListMultimap.create();
2872     for (AccessControlProtos.UsersAndPermissions.UserPermissions userPerms:
2873         proto.getUserPermissionsList()) {
2874       String user = userPerms.getUser().toStringUtf8();
2875       for (AccessControlProtos.Permission perm: userPerms.getPermissionsList()) {
2876         result.put(user, toPermission(perm));
2877       }
2878     }
2879     return result;
2880   }
2881   
2882   /**
2883    * Convert a protocol buffer TimeUnit to a client TimeUnit
2884    * @param proto
2885    * @return the converted client TimeUnit
2886    */
2887   public static TimeUnit toTimeUnit(final HBaseProtos.TimeUnit proto) {
2888     switch (proto) {
2889     case NANOSECONDS:
2890       return TimeUnit.NANOSECONDS;
2891     case MICROSECONDS:
2892       return TimeUnit.MICROSECONDS;
2893     case MILLISECONDS:
2894       return TimeUnit.MILLISECONDS;
2895     case SECONDS:
2896       return TimeUnit.SECONDS;
2897     case MINUTES:
2898       return TimeUnit.MINUTES;
2899     case HOURS:
2900       return TimeUnit.HOURS;
2901     case DAYS:
2902       return TimeUnit.DAYS;
2903     default:
2904       throw new RuntimeException("Invalid TimeUnit " + proto);
2905     }
2906   }
2907 
2908   /**
2909    * Convert a client TimeUnit to a protocol buffer TimeUnit
2910    * @param timeUnit
2911    * @return the converted protocol buffer TimeUnit
2912    */
2913   public static HBaseProtos.TimeUnit toProtoTimeUnit(final TimeUnit timeUnit) {
2914     switch (timeUnit) {
2915     case NANOSECONDS:
2916       return HBaseProtos.TimeUnit.NANOSECONDS;
2917     case MICROSECONDS:
2918       return HBaseProtos.TimeUnit.MICROSECONDS;
2919     case MILLISECONDS:
2920       return HBaseProtos.TimeUnit.MILLISECONDS;
2921     case SECONDS:
2922       return HBaseProtos.TimeUnit.SECONDS;
2923     case MINUTES:
2924       return HBaseProtos.TimeUnit.MINUTES;
2925     case HOURS:
2926       return HBaseProtos.TimeUnit.HOURS;
2927     case DAYS:
2928       return HBaseProtos.TimeUnit.DAYS;
2929     default:
2930       throw new RuntimeException("Invalid TimeUnit " + timeUnit);
2931     }
2932   }
2933 
2934   /**
2935    * Convert a protocol buffer ThrottleType to a client ThrottleType
2936    * @param proto
2937    * @return the converted client ThrottleType
2938    */
2939   public static ThrottleType toThrottleType(final QuotaProtos.ThrottleType proto) {
2940     switch (proto) {
2941     case REQUEST_NUMBER:
2942       return ThrottleType.REQUEST_NUMBER;
2943     case REQUEST_SIZE:
2944       return ThrottleType.REQUEST_SIZE;
2945     case WRITE_NUMBER:
2946       return ThrottleType.WRITE_NUMBER;
2947     case WRITE_SIZE:
2948       return ThrottleType.WRITE_SIZE;
2949     case READ_NUMBER:
2950       return ThrottleType.READ_NUMBER;
2951     case READ_SIZE:
2952       return ThrottleType.READ_SIZE;
2953     default:
2954       throw new RuntimeException("Invalid ThrottleType " + proto);
2955     }
2956   }
2957 
2958   /**
2959    * Convert a client ThrottleType to a protocol buffer ThrottleType
2960    * @param type
2961    * @return the converted protocol buffer ThrottleType
2962    */
2963   public static QuotaProtos.ThrottleType toProtoThrottleType(final ThrottleType type) {
2964     switch (type) {
2965     case REQUEST_NUMBER:
2966       return QuotaProtos.ThrottleType.REQUEST_NUMBER;
2967     case REQUEST_SIZE:
2968       return QuotaProtos.ThrottleType.REQUEST_SIZE;
2969     case WRITE_NUMBER:
2970       return QuotaProtos.ThrottleType.WRITE_NUMBER;
2971     case WRITE_SIZE:
2972       return QuotaProtos.ThrottleType.WRITE_SIZE;
2973     case READ_NUMBER:
2974       return QuotaProtos.ThrottleType.READ_NUMBER;
2975     case READ_SIZE:
2976       return QuotaProtos.ThrottleType.READ_SIZE;
2977     default:
2978       throw new RuntimeException("Invalid ThrottleType " + type);
2979     }
2980   }
2981 
2982   /**
2983    * Convert a protocol buffer QuotaScope to a client QuotaScope
2984    * @param proto
2985    * @return the converted client QuotaScope
2986    */
2987   public static QuotaScope toQuotaScope(final QuotaProtos.QuotaScope proto) {
2988     switch (proto) {
2989     case CLUSTER:
2990       return QuotaScope.CLUSTER;
2991     case MACHINE:
2992       return QuotaScope.MACHINE;
2993     default:
2994       throw new RuntimeException("Invalid QuotaScope " + proto);
2995     }
2996   }
2997 
2998   /**
2999    * Convert a client QuotaScope to a protocol buffer QuotaScope
3000    * @param scope
3001    * @return the converted protocol buffer QuotaScope
3002    */
3003   public static QuotaProtos.QuotaScope toProtoQuotaScope(final QuotaScope scope) {
3004     switch (scope) {
3005     case CLUSTER:
3006       return QuotaProtos.QuotaScope.CLUSTER;
3007     case MACHINE:
3008       return QuotaProtos.QuotaScope.MACHINE;
3009     default:
3010       throw new RuntimeException("Invalid QuotaScope " + scope);
3011     }
3012   }
3013 
3014   /**
3015    * Convert a protocol buffer QuotaType to a client QuotaType
3016    * @param proto
3017    * @return the converted client QuotaType
3018    */
3019   public static QuotaType toQuotaScope(final QuotaProtos.QuotaType proto) {
3020     switch (proto) {
3021     case THROTTLE:
3022       return QuotaType.THROTTLE;
3023     default:
3024       throw new RuntimeException("Invalid QuotaType " + proto);
3025     }
3026   }
3027 
3028   /**
3029    * Convert a client QuotaType to a protocol buffer QuotaType
3030    * @param type
3031    * @return the converted protocol buffer QuotaType
3032    */
3033   public static QuotaProtos.QuotaType toProtoQuotaScope(final QuotaType type) {
3034     switch (type) {
3035     case THROTTLE:
3036       return QuotaProtos.QuotaType.THROTTLE;
3037     default:
3038       throw new RuntimeException("Invalid QuotaType " + type);
3039     }
3040   }
3041 
3042   /**
3043    * Build a protocol buffer TimedQuota
3044    * @param limit the allowed number of request/data per timeUnit
3045    * @param timeUnit the limit time unit
3046    * @param scope the quota scope
3047    * @return the protocol buffer TimedQuota
3048    */
3049   public static QuotaProtos.TimedQuota toTimedQuota(final long limit, final TimeUnit timeUnit,
3050       final QuotaScope scope) {
3051     return QuotaProtos.TimedQuota.newBuilder().setSoftLimit(limit)
3052         .setTimeUnit(toProtoTimeUnit(timeUnit)).setScope(toProtoQuotaScope(scope)).build();
3053   }
3054 
3055   /**
3056    * Generates a marker for the WAL so that we propagate the notion of a bulk region load
3057    * throughout the WAL.
3058    *
3059    * @param tableName         The tableName into which the bulk load is being imported into.
3060    * @param encodedRegionName Encoded region name of the region which is being bulk loaded.
3061    * @param storeFiles        A set of store files of a column family are bulk loaded.
3062    * @param bulkloadSeqId     sequence ID (by a force flush) used to create bulk load hfile
3063    *                          name
3064    * @return The WAL log marker for bulk loads.
3065    */
3066   public static WALProtos.BulkLoadDescriptor toBulkLoadDescriptor(TableName tableName,
3067       ByteString encodedRegionName, Map<byte[], List<Path>> storeFiles, long bulkloadSeqId) {
3068     BulkLoadDescriptor.Builder desc = BulkLoadDescriptor.newBuilder()
3069         .setTableName(ProtobufUtil.toProtoTableName(tableName))
3070         .setEncodedRegionName(encodedRegionName).setBulkloadSeqNum(bulkloadSeqId);
3071 
3072     for (Map.Entry<byte[], List<Path>> entry : storeFiles.entrySet()) {
3073       WALProtos.StoreDescriptor.Builder builder = StoreDescriptor.newBuilder()
3074           .setFamilyName(ByteStringer.wrap(entry.getKey()))
3075           .setStoreHomeDir(Bytes.toString(entry.getKey())); // relative to region
3076       for (Path path : entry.getValue()) {
3077         builder.addStoreFile(path.getName());
3078       }
3079       desc.addStores(builder);
3080     }
3081 
3082     return desc.build();
3083   }
3084 
3085   /**
3086    * This version of protobuf's mergeDelimitedFrom avoids the hard-coded 64MB limit for decoding
3087    * buffers
3088    * @param builder current message builder
3089    * @param in Inputsream with delimited protobuf data
3090    * @throws IOException
3091    */
3092   public static void mergeDelimitedFrom(Message.Builder builder, InputStream in)
3093     throws IOException {
3094     // This used to be builder.mergeDelimitedFrom(in);
3095     // but is replaced to allow us to bump the protobuf size limit.
3096     final int firstByte = in.read();
3097     if (firstByte != -1) {
3098       final int size = CodedInputStream.readRawVarint32(firstByte, in);
3099       final InputStream limitedInput = new LimitedInputStream(in, size);
3100       final CodedInputStream codedInput = CodedInputStream.newInstance(limitedInput);
3101       codedInput.setSizeLimit(size);
3102       builder.mergeFrom(codedInput);
3103       codedInput.checkLastTagWas(0);
3104     }
3105   }
3106 
3107   /**
3108    * This version of protobuf's mergeFrom avoids the hard-coded 64MB limit for decoding
3109    * buffers where the message size is known
3110    * @param builder current message builder
3111    * @param in InputStream containing protobuf data
3112    * @param size known size of protobuf data
3113    * @throws IOException 
3114    */
3115   public static void mergeFrom(Message.Builder builder, InputStream in, int size)
3116       throws IOException {
3117     final CodedInputStream codedInput = CodedInputStream.newInstance(in);
3118     codedInput.setSizeLimit(size);
3119     builder.mergeFrom(codedInput);
3120     codedInput.checkLastTagWas(0);
3121   }
3122 
3123   /**
3124    * This version of protobuf's mergeFrom avoids the hard-coded 64MB limit for decoding
3125    * buffers where the message size is not known
3126    * @param builder current message builder
3127    * @param in InputStream containing protobuf data
3128    * @throws IOException 
3129    */
3130   public static void mergeFrom(Message.Builder builder, InputStream in)
3131       throws IOException {
3132     final CodedInputStream codedInput = CodedInputStream.newInstance(in);
3133     codedInput.setSizeLimit(Integer.MAX_VALUE);
3134     builder.mergeFrom(codedInput);
3135     codedInput.checkLastTagWas(0);
3136   }
3137 
3138   /**
3139    * This version of protobuf's mergeFrom avoids the hard-coded 64MB limit for decoding
3140    * buffers when working with ByteStrings
3141    * @param builder current message builder
3142    * @param bs ByteString containing the 
3143    * @throws IOException 
3144    */
3145   public static void mergeFrom(Message.Builder builder, ByteString bs) throws IOException {
3146     final CodedInputStream codedInput = bs.newCodedInput();
3147     codedInput.setSizeLimit(bs.size());
3148     builder.mergeFrom(codedInput);
3149     codedInput.checkLastTagWas(0);
3150   }
3151 
3152   /**
3153    * This version of protobuf's mergeFrom avoids the hard-coded 64MB limit for decoding
3154    * buffers when working with byte arrays
3155    * @param builder current message builder
3156    * @param b byte array
3157    * @throws IOException 
3158    */
3159   public static void mergeFrom(Message.Builder builder, byte[] b) throws IOException {
3160     final CodedInputStream codedInput = CodedInputStream.newInstance(b);
3161     codedInput.setSizeLimit(b.length);
3162     builder.mergeFrom(codedInput);
3163     codedInput.checkLastTagWas(0);
3164   }
3165 
3166   /**
3167    * This version of protobuf's mergeFrom avoids the hard-coded 64MB limit for decoding
3168    * buffers when working with byte arrays
3169    * @param builder current message builder
3170    * @param b byte array
3171    * @param offset
3172    * @param length
3173    * @throws IOException
3174    */
3175   public static void mergeFrom(Message.Builder builder, byte[] b, int offset, int length)
3176       throws IOException {
3177     final CodedInputStream codedInput = CodedInputStream.newInstance(b, offset, length);
3178     codedInput.setSizeLimit(length);
3179     builder.mergeFrom(codedInput);
3180     codedInput.checkLastTagWas(0);
3181   }
3182 
3183   public static ReplicationLoadSink toReplicationLoadSink(
3184       ClusterStatusProtos.ReplicationLoadSink cls) {
3185     return new ReplicationLoadSink(cls.getAgeOfLastAppliedOp(), cls.getTimeStampsOfLastAppliedOp());
3186   }
3187 
3188   public static ReplicationLoadSource toReplicationLoadSource(
3189       ClusterStatusProtos.ReplicationLoadSource cls) {
3190     return new ReplicationLoadSource(cls.getPeerID(), cls.getAgeOfLastShippedOp(),
3191         cls.getSizeOfLogQueue(), cls.getTimeStampOfLastShippedOp(), cls.getReplicationLag());
3192   }
3193 
3194   public static List<ReplicationLoadSource> toReplicationLoadSourceList(
3195       List<ClusterStatusProtos.ReplicationLoadSource> clsList) {
3196     ArrayList<ReplicationLoadSource> rlsList = new ArrayList<ReplicationLoadSource>();
3197     for (ClusterStatusProtos.ReplicationLoadSource cls : clsList) {
3198       rlsList.add(toReplicationLoadSource(cls));
3199     }
3200     return rlsList;
3201   }
3202 
3203   /**
3204    * Get a protocol buffer VersionInfo
3205    *
3206    * @return the converted protocol buffer VersionInfo
3207    */
3208   public static HBaseProtos.VersionInfo getVersionInfo() {
3209     HBaseProtos.VersionInfo.Builder builder = HBaseProtos.VersionInfo.newBuilder();
3210     builder.setVersion(VersionInfo.getVersion());
3211     builder.setUrl(VersionInfo.getUrl());
3212     builder.setRevision(VersionInfo.getRevision());
3213     builder.setUser(VersionInfo.getUser());
3214     builder.setDate(VersionInfo.getDate());
3215     builder.setSrcChecksum(VersionInfo.getSrcChecksum());
3216     return builder.build();
3217   }
3218 
3219   /**
3220    * Convert SecurityCapabilitiesResponse.Capability to SecurityCapability
3221    * @param capabilities capabilities returned in the SecurityCapabilitiesResponse message
3222    * @return the converted list of SecurityCapability elements
3223    */
3224   public static List<SecurityCapability> toSecurityCapabilityList(
3225       List<MasterProtos.SecurityCapabilitiesResponse.Capability> capabilities) {
3226     List<SecurityCapability> scList = new ArrayList<>(capabilities.size());
3227     for (MasterProtos.SecurityCapabilitiesResponse.Capability c: capabilities) {
3228       try {
3229         scList.add(SecurityCapability.valueOf(c.getNumber()));
3230       } catch (IllegalArgumentException e) {
3231         // Unknown capability, just ignore it. We don't understand the new capability
3232         // but don't care since by definition we cannot take advantage of it.
3233       }
3234     }
3235     return scList;
3236   }
3237 
3238   private static HBaseProtos.TimeRange.Builder timeRangeToProto(TimeRange timeRange) {
3239     HBaseProtos.TimeRange.Builder timeRangeBuilder =
3240         HBaseProtos.TimeRange.newBuilder();
3241     timeRangeBuilder.setFrom(timeRange.getMin());
3242     timeRangeBuilder.setTo(timeRange.getMax());
3243     return timeRangeBuilder;
3244   }
3245 
3246   private static TimeRange protoToTimeRange(HBaseProtos.TimeRange timeRange) throws IOException {
3247       long minStamp = 0;
3248       long maxStamp = Long.MAX_VALUE;
3249       if (timeRange.hasFrom()) {
3250         minStamp = timeRange.getFrom();
3251       }
3252       if (timeRange.hasTo()) {
3253         maxStamp = timeRange.getTo();
3254       }
3255     return new TimeRange(minStamp, maxStamp);
3256   }
3257 
3258   /**
3259    * This is cut and paste from protobuf's package private AbstractMessageLite.
3260    *
3261    * An InputStream implementations which reads from some other InputStream
3262    * but is limited to a particular number of bytes.  Used by
3263    * mergeDelimitedFrom().  This is intentionally package-private so that
3264    * UnknownFieldSet can share it.
3265    */
3266   static final class LimitedInputStream extends FilterInputStream {
3267     private int limit;
3268 
3269     LimitedInputStream(InputStream in, int limit) {
3270       super(in);
3271       this.limit = limit;
3272     }
3273 
3274     @Override
3275     public int available() throws IOException {
3276       return Math.min(super.available(), limit);
3277     }
3278 
3279     @Override
3280     public int read() throws IOException {
3281       if (limit <= 0) {
3282         return -1;
3283       }
3284       final int result = super.read();
3285       if (result >= 0) {
3286         --limit;
3287       }
3288       return result;
3289     }
3290 
3291     @Override
3292     public int read(final byte[] b, final int off, int len)
3293             throws IOException {
3294       if (limit <= 0) {
3295         return -1;
3296       }
3297       len = Math.min(len, limit);
3298       final int result = super.read(b, off, len);
3299       if (result >= 0) {
3300         limit -= result;
3301       }
3302       return result;
3303     }
3304 
3305     @Override
3306     public long skip(final long n) throws IOException {
3307       final long result = super.skip(Math.min(n, limit));
3308       if (result >= 0) {
3309         limit -= result;
3310       }
3311       return result;
3312     }
3313   }
3314 }