View Javadoc

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  
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   * Base permissions instance representing the ability to perform a given set
38   * of actions.
39   *
40   * @see TablePermission
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    /** Empty constructor for Writable implementation.  <b>Do not use.</b> */
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     // check actions
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   /** @return the object version number */
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 }