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