1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.security.access;
20
21 import java.io.DataInput;
22 import java.io.DataOutput;
23 import java.io.IOException;
24 import java.util.Arrays;
25 import java.util.Map;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.hbase.classification.InterfaceAudience;
30 import org.apache.hadoop.hbase.classification.InterfaceStability;
31 import org.apache.hadoop.hbase.util.Bytes;
32 import org.apache.hadoop.io.VersionedWritable;
33
34 import com.google.common.collect.Maps;
35
36
37
38
39
40
41
42 @InterfaceAudience.Public
43 @InterfaceStability.Evolving
44 public class Permission extends VersionedWritable {
45 protected static final byte VERSION = 0;
46
47 @InterfaceAudience.Public
48 @InterfaceStability.Evolving
49 public enum Action {
50 READ('R'), WRITE('W'), EXEC('X'), CREATE('C'), ADMIN('A');
51
52 private byte code;
53 Action(char code) {
54 this.code = (byte)code;
55 }
56
57 public byte code() { return code; }
58 }
59
60 private static final Log LOG = LogFactory.getLog(Permission.class);
61 protected static final Map<Byte,Action> ACTION_BY_CODE = Maps.newHashMap();
62
63 protected Action[] actions;
64
65 static {
66 for (Action a : Action.values()) {
67 ACTION_BY_CODE.put(a.code(), a);
68 }
69 }
70
71
72 public Permission() {
73 super();
74 }
75
76 public Permission(Action... assigned) {
77 if (assigned != null && assigned.length > 0) {
78 actions = Arrays.copyOf(assigned, assigned.length);
79 }
80 }
81
82 public Permission(byte[] actionCodes) {
83 if (actionCodes != null) {
84 Action acts[] = new Action[actionCodes.length];
85 int j = 0;
86 for (int i=0; i<actionCodes.length; i++) {
87 byte b = actionCodes[i];
88 Action a = ACTION_BY_CODE.get(b);
89 if (a == null) {
90 LOG.error("Ignoring unknown action code '"+
91 Bytes.toStringBinary(new byte[]{b})+"'");
92 continue;
93 }
94 acts[j++] = a;
95 }
96 this.actions = Arrays.copyOf(acts, j);
97 }
98 }
99
100 public Action[] getActions() {
101 return actions;
102 }
103
104 public boolean implies(Action action) {
105 if (this.actions != null) {
106 for (Action a : this.actions) {
107 if (a == action) {
108 return true;
109 }
110 }
111 }
112
113 return false;
114 }
115
116 @Override
117 public boolean equals(Object obj) {
118 if (!(obj instanceof Permission)) {
119 return false;
120 }
121 Permission other = (Permission)obj;
122
123 if (actions == null && other.getActions() == null) {
124 return true;
125 } else if (actions != null && other.getActions() != null) {
126 Action[] otherActions = other.getActions();
127 if (actions.length != otherActions.length) {
128 return false;
129 }
130
131 outer:
132 for (Action a : actions) {
133 for (Action oa : otherActions) {
134 if (a == oa) continue outer;
135 }
136 return false;
137 }
138 return true;
139 }
140
141 return false;
142 }
143
144 @Override
145 public int hashCode() {
146 final int prime = 37;
147 int result = 23;
148 for (Action a : actions) {
149 result = prime * result + a.code();
150 }
151 return result;
152 }
153
154 @Override
155 public String toString() {
156 StringBuilder str = new StringBuilder("[Permission: ")
157 .append("actions=");
158 if (actions != null) {
159 for (int i=0; i<actions.length; i++) {
160 if (i > 0)
161 str.append(",");
162 if (actions[i] != null)
163 str.append(actions[i].toString());
164 else
165 str.append("NULL");
166 }
167 }
168 str.append("]");
169
170 return str.toString();
171 }
172
173
174 @Override
175 public byte getVersion() {
176 return VERSION;
177 }
178
179 @Override
180 public void readFields(DataInput in) throws IOException {
181 super.readFields(in);
182 int length = (int)in.readByte();
183 if (length > 0) {
184 actions = new Action[length];
185 for (int i = 0; i < length; i++) {
186 byte b = in.readByte();
187 Action a = ACTION_BY_CODE.get(b);
188 if (a == null) {
189 throw new IOException("Unknown action code '"+
190 Bytes.toStringBinary(new byte[]{b})+"' in input");
191 }
192 this.actions[i] = a;
193 }
194 } else {
195 actions = new Action[0];
196 }
197 }
198
199 @Override
200 public void write(DataOutput out) throws IOException {
201 super.write(out);
202 out.writeByte(actions != null ? actions.length : 0);
203 if (actions != null) {
204 for (Action a: actions) {
205 out.writeByte(a.code());
206 }
207 }
208 }
209 }