001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.fs; 019 020import java.io.IOException; 021 022import org.apache.commons.codec.DecoderException; 023import org.apache.commons.codec.binary.Base64; 024import org.apache.commons.codec.binary.Hex; 025import org.apache.hadoop.classification.InterfaceAudience; 026import org.apache.hadoop.classification.InterfaceStability; 027 028import com.google.common.base.Preconditions; 029 030/** 031 * The value of <code>XAttr</code> is byte[], this class is to 032 * covert byte[] to some kind of string representation or convert back. 033 * String representation is convenient for display and input. For example 034 * display in screen as shell response and json response, input as http 035 * or shell parameter. 036 */ 037@InterfaceAudience.Public 038@InterfaceStability.Stable 039public enum XAttrCodec { 040 /** 041 * Value encoded as text 042 * string is enclosed in double quotes (\"). 043 */ 044 TEXT, 045 046 /** 047 * Value encoded as hexadecimal string 048 * is prefixed with 0x. 049 */ 050 HEX, 051 052 /** 053 * Value encoded as base64 string 054 * is prefixed with 0s. 055 */ 056 BASE64; 057 058 private static final String HEX_PREFIX = "0x"; 059 private static final String BASE64_PREFIX = "0s"; 060 private static final Base64 base64 = new Base64(0); 061 062 /** 063 * Decode string representation of a value and check whether it's 064 * encoded. If the given string begins with 0x or 0X, it expresses 065 * a hexadecimal number. If the given string begins with 0s or 0S, 066 * base64 encoding is expected. If the given string is enclosed in 067 * double quotes, the inner string is treated as text. Otherwise 068 * the given string is treated as text. 069 * @param value string representation of the value. 070 * @return byte[] the value 071 * @throws IOException 072 */ 073 public static byte[] decodeValue(String value) throws IOException { 074 byte[] result = null; 075 if (value != null) { 076 if (value.length() >= 2) { 077 String en = value.substring(0, 2); 078 if (value.startsWith("\"") && value.endsWith("\"")) { 079 value = value.substring(1, value.length()-1); 080 result = value.getBytes("utf-8"); 081 } else if (en.equalsIgnoreCase(HEX_PREFIX)) { 082 value = value.substring(2, value.length()); 083 try { 084 result = Hex.decodeHex(value.toCharArray()); 085 } catch (DecoderException e) { 086 throw new IOException(e); 087 } 088 } else if (en.equalsIgnoreCase(BASE64_PREFIX)) { 089 value = value.substring(2, value.length()); 090 result = base64.decode(value); 091 } 092 } 093 if (result == null) { 094 result = value.getBytes("utf-8"); 095 } 096 } 097 return result; 098 } 099 100 /** 101 * Encode byte[] value to string representation with encoding. 102 * Values encoded as text strings are enclosed in double quotes (\"), 103 * while strings encoded as hexadecimal and base64 are prefixed with 104 * 0x and 0s, respectively. 105 * @param value byte[] value 106 * @param encoding 107 * @return String string representation of value 108 * @throws IOException 109 */ 110 public static String encodeValue(byte[] value, XAttrCodec encoding) 111 throws IOException { 112 Preconditions.checkNotNull(value, "Value can not be null."); 113 if (encoding == HEX) { 114 return HEX_PREFIX + Hex.encodeHexString(value); 115 } else if (encoding == BASE64) { 116 return BASE64_PREFIX + base64.encodeToString(value); 117 } else { 118 return "\"" + new String(value, "utf-8") + "\""; 119 } 120 } 121}