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