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.hdfs;
19 
20 import java.util.List;
21 import java.util.Map;
22 
23 import org.apache.hadoop.HadoopIllegalArgumentException;
24 import org.apache.hadoop.classification.InterfaceAudience;
25 import org.apache.hadoop.fs.XAttr;
26 import org.apache.hadoop.fs.XAttr.NameSpace;
27 import org.apache.hadoop.util.StringUtils;
28 
29 import com.google.common.base.Preconditions;
30 import com.google.common.collect.Lists;
31 import com.google.common.collect.Maps;
32 
33 @InterfaceAudience.Private
34 public class XAttrHelper {
35 
36   /**
37    * Build <code>XAttr</code> from xattr name with prefix.
38    */
buildXAttr(String name)39   public static XAttr buildXAttr(String name) {
40     return buildXAttr(name, null);
41   }
42 
43   /**
44    * Build <code>XAttr</code> from name with prefix and value.
45    * Name can not be null. Value can be null. The name and prefix
46    * are validated.
47    * Both name and namespace are case sensitive.
48    */
buildXAttr(String name, byte[] value)49   public static XAttr buildXAttr(String name, byte[] value) {
50     Preconditions.checkNotNull(name, "XAttr name cannot be null.");
51 
52     final int prefixIndex = name.indexOf(".");
53     if (prefixIndex < 3) {// Prefix length is at least 3.
54       throw new HadoopIllegalArgumentException("An XAttr name must be " +
55           "prefixed with user/trusted/security/system/raw, followed by a '.'");
56     } else if (prefixIndex == name.length() - 1) {
57       throw new HadoopIllegalArgumentException("XAttr name cannot be empty.");
58     }
59 
60     NameSpace ns;
61     final String prefix = name.substring(0, prefixIndex);
62     if (StringUtils.equalsIgnoreCase(prefix, NameSpace.USER.toString())) {
63       ns = NameSpace.USER;
64     } else if (
65         StringUtils.equalsIgnoreCase(prefix, NameSpace.TRUSTED.toString())) {
66       ns = NameSpace.TRUSTED;
67     } else if (
68         StringUtils.equalsIgnoreCase(prefix, NameSpace.SYSTEM.toString())) {
69       ns = NameSpace.SYSTEM;
70     } else if (
71         StringUtils.equalsIgnoreCase(prefix, NameSpace.SECURITY.toString())) {
72       ns = NameSpace.SECURITY;
73     } else if (
74         StringUtils.equalsIgnoreCase(prefix, NameSpace.RAW.toString())) {
75       ns = NameSpace.RAW;
76     } else {
77       throw new HadoopIllegalArgumentException("An XAttr name must be " +
78           "prefixed with user/trusted/security/system/raw, followed by a '.'");
79     }
80     XAttr xAttr = (new XAttr.Builder()).setNameSpace(ns).setName(name.
81         substring(prefixIndex + 1)).setValue(value).build();
82 
83     return xAttr;
84   }
85 
86   /**
87    * Build xattr name with prefix as <code>XAttr</code> list.
88    */
buildXAttrAsList(String name)89   public static List<XAttr> buildXAttrAsList(String name) {
90     XAttr xAttr = buildXAttr(name);
91     List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1);
92     xAttrs.add(xAttr);
93 
94     return xAttrs;
95   }
96 
97   /**
98    * Get value of first xattr from <code>XAttr</code> list
99    */
getFirstXAttrValue(List<XAttr> xAttrs)100   public static byte[] getFirstXAttrValue(List<XAttr> xAttrs) {
101     byte[] value = null;
102     XAttr xAttr = getFirstXAttr(xAttrs);
103     if (xAttr != null) {
104       value = xAttr.getValue();
105       if (value == null) {
106         value = new byte[0]; // xattr exists, but no value.
107       }
108     }
109     return value;
110   }
111 
112   /**
113    * Get first xattr from <code>XAttr</code> list
114    */
getFirstXAttr(List<XAttr> xAttrs)115   public static XAttr getFirstXAttr(List<XAttr> xAttrs) {
116     if (xAttrs != null && !xAttrs.isEmpty()) {
117       return xAttrs.get(0);
118     }
119 
120     return null;
121   }
122 
123   /**
124    * Build xattr map from <code>XAttr</code> list, the key is
125    * xattr name with prefix, and value is xattr value.
126    */
buildXAttrMap(List<XAttr> xAttrs)127   public static Map<String, byte[]> buildXAttrMap(List<XAttr> xAttrs) {
128     if (xAttrs == null) {
129       return null;
130     }
131     Map<String, byte[]> xAttrMap = Maps.newHashMap();
132     for (XAttr xAttr : xAttrs) {
133       String name = getPrefixName(xAttr);
134       byte[] value = xAttr.getValue();
135       if (value == null) {
136         value = new byte[0];
137       }
138       xAttrMap.put(name, value);
139     }
140 
141     return xAttrMap;
142   }
143 
144   /**
145    * Get name with prefix from <code>XAttr</code>
146    */
getPrefixName(XAttr xAttr)147   public static String getPrefixName(XAttr xAttr) {
148     if (xAttr == null) {
149       return null;
150     }
151 
152     String namespace = xAttr.getNameSpace().toString();
153     return StringUtils.toLowerCase(namespace) + "." + xAttr.getName();
154   }
155 
156   /**
157    * Build <code>XAttr</code> list from xattr name list.
158    */
buildXAttrs(List<String> names)159   public static List<XAttr> buildXAttrs(List<String> names) {
160     if (names == null || names.isEmpty()) {
161       throw new HadoopIllegalArgumentException("XAttr names can not be " +
162           "null or empty.");
163     }
164 
165     List<XAttr> xAttrs = Lists.newArrayListWithCapacity(names.size());
166     for (String name : names) {
167       xAttrs.add(buildXAttr(name, null));
168     }
169     return xAttrs;
170   }
171 }
172