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 */
018 package org.apache.hadoop.fs;
019
020 import java.io.IOException;
021
022 import org.apache.commons.codec.DecoderException;
023 import org.apache.commons.codec.binary.Base64;
024 import org.apache.commons.codec.binary.Hex;
025 import org.apache.hadoop.classification.InterfaceAudience;
026 import org.apache.hadoop.classification.InterfaceStability;
027
028 import 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
039 public 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 }