1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.accumulo.core.security;
18
19 import java.io.Serializable;
20 import java.io.UnsupportedEncodingException;
21 import java.nio.ByteBuffer;
22 import java.nio.charset.Charset;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Set;
30 import java.util.TreeSet;
31
32 import org.apache.accumulo.core.data.ArrayByteSequence;
33 import org.apache.accumulo.core.data.ByteSequence;
34 import org.apache.accumulo.core.util.ArgumentChecker;
35 import org.apache.accumulo.core.util.ByteBufferUtil;
36 import org.apache.commons.codec.binary.Base64;
37
38 public class Authorizations implements Iterable<byte[]>, Serializable {
39
40 private static final long serialVersionUID = 1L;
41
42 private Set<ByteSequence> auths = new HashSet<ByteSequence>();
43 private List<byte[]> authsList = new ArrayList<byte[]>();
44 private List<byte[]> immutableList = Collections.unmodifiableList(authsList);
45
46 private static final boolean[] validAuthChars = new boolean[256];
47
48 public static final String HEADER = "!AUTH1:";
49
50 static {
51 for (int i = 0; i < 256; i++) {
52 validAuthChars[i] = false;
53 }
54
55 for (int i = 'a'; i <= 'z'; i++) {
56 validAuthChars[i] = true;
57 }
58
59 for (int i = 'A'; i <= 'Z'; i++) {
60 validAuthChars[i] = true;
61 }
62
63 for (int i = '0'; i <= '9'; i++) {
64 validAuthChars[i] = true;
65 }
66
67 validAuthChars['_'] = true;
68 validAuthChars['-'] = true;
69 validAuthChars[':'] = true;
70 validAuthChars['.'] = true;
71 validAuthChars['/'] = true;
72 }
73
74 static final boolean isValidAuthChar(byte b) {
75 return validAuthChars[0xff & b];
76 }
77
78 private void checkAuths() {
79 Set<ByteSequence> sortedAuths = new TreeSet<ByteSequence>(auths);
80
81 for (ByteSequence bs : sortedAuths) {
82 if (bs.length() == 0) {
83 throw new IllegalArgumentException("Empty authorization");
84 }
85
86 authsList.add(bs.toArray());
87 }
88 }
89
90 public Authorizations(Collection<byte[]> authorizations) {
91 ArgumentChecker.notNull(authorizations);
92 for (byte[] auth : authorizations)
93 auths.add(new ArrayByteSequence(auth));
94 checkAuths();
95 }
96
97 public Authorizations(List<ByteBuffer> authorizations) {
98 ArgumentChecker.notNull(authorizations);
99 for (ByteBuffer buffer : authorizations) {
100 auths.add(new ArrayByteSequence(ByteBufferUtil.toBytes(buffer)));
101 }
102 checkAuths();
103 }
104
105 /**
106 * @param authorizations
107 * a serialized authorizations string produced by {@link #getAuthorizationsArray()} or {@link #serialize()}
108 */
109
110 public Authorizations(byte[] authorizations) {
111
112 ArgumentChecker.notNull(authorizations);
113
114 String authsString = new String(authorizations);
115 if (authsString.startsWith(HEADER)) {
116
117 authsString = authsString.substring(HEADER.length());
118 if (authsString.length() > 0) {
119 for (String encAuth : authsString.split(",")) {
120 byte[] auth = Base64.decodeBase64(encAuth.getBytes());
121 auths.add(new ArrayByteSequence(auth));
122 }
123 checkAuths();
124 }
125 } else {
126
127 ArgumentChecker.notNull(authorizations);
128 if (authorizations.length > 0)
129 setAuthorizations(authsString.split(","));
130 }
131 }
132
133 public Authorizations() {}
134
135 /**
136 *
137 * @param charset
138 * used to convert each authorization to a byte array
139 * @param authorizations
140 * array of authorizations
141 */
142
143 public Authorizations(Charset charset, String... authorizations) {
144 setAuthorizations(charset, authorizations);
145 }
146
147 public Authorizations(String... authorizations) {
148 setAuthorizations(authorizations);
149 }
150
151 private void setAuthorizations(String... authorizations) {
152 setAuthorizations(Charset.defaultCharset(), authorizations);
153 }
154
155 private void setAuthorizations(Charset charset, String... authorizations) {
156 ArgumentChecker.notNull(authorizations);
157 auths.clear();
158 for (String str : authorizations) {
159 str = str.trim();
160 try {
161 auths.add(new ArrayByteSequence(str.getBytes(charset.name())));
162 } catch (UnsupportedEncodingException e) {
163 throw new RuntimeException(e);
164 }
165 }
166
167 checkAuths();
168 }
169
170 public byte[] getAuthorizationsArray() {
171 return serialize().getBytes();
172 }
173
174 public List<byte[]> getAuthorizations() {
175 return immutableList;
176 }
177
178 public List<ByteBuffer> getAuthorizationsBB() {
179 return ByteBufferUtil.toByteBuffers(immutableList);
180 }
181
182 public String toString() {
183 StringBuilder sb = new StringBuilder();
184 String sep = "";
185 for (ByteSequence auth : auths) {
186 sb.append(sep);
187 sep = ",";
188 sb.append(new String(auth.toArray()));
189 }
190
191 return sb.toString();
192 }
193
194 public boolean contains(byte[] auth) {
195 return auths.contains(new ArrayByteSequence(auth));
196 }
197
198 public boolean contains(ByteSequence auth) {
199 return auths.contains(auth);
200 }
201
202 public boolean equals(Object o) {
203 if (o == null) {
204 return false;
205 }
206
207 if (o instanceof Authorizations) {
208 Authorizations ao = (Authorizations) o;
209
210 return auths.equals(ao.auths);
211 }
212
213 return false;
214 }
215
216 public int hashCode() {
217 int result = 0;
218 for (ByteSequence b : auths)
219 result += b.hashCode();
220 return result;
221 }
222
223 public int size() {
224 return auths.size();
225 }
226
227 public boolean isEmpty() {
228 return auths.isEmpty();
229 }
230
231 @Override
232 public Iterator<byte[]> iterator() {
233 return immutableList.iterator();
234 }
235
236 public String serialize() {
237 StringBuilder sb = new StringBuilder(HEADER);
238 String sep = "";
239 for (byte[] auth : immutableList) {
240 sb.append(sep);
241 sep = ",";
242 sb.append(new String(Base64.encodeBase64(auth)));
243 }
244
245 return sb.toString();
246 }
247 }