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  
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    /** Empty constructor for Writable implementation.  <b>Do not use.</b> */
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     // check actions
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   public String toString() {
154     StringBuilder str = new StringBuilder("[Permission: ")
155         .append("actions=");
156     if (actions != null) {
157       for (int i=0; i<actions.length; i++) {
158         if (i > 0)
159           str.append(",");
160         if (actions[i] != null)
161           str.append(actions[i].toString());
162         else
163           str.append("NULL");
164       }
165     }
166     str.append("]");
167 
168     return str.toString();
169   }
170 
171   /** @return the object version number */
172   public byte getVersion() {
173     return VERSION;
174   }
175 
176   @Override
177   public void readFields(DataInput in) throws IOException {
178     super.readFields(in);
179     int length = (int)in.readByte();
180     if (length > 0) {
181       actions = new Action[length];
182       for (int i = 0; i < length; i++) {
183         byte b = in.readByte();
184         Action a = ACTION_BY_CODE.get(b);
185         if (a == null) {
186           throw new IOException("Unknown action code '"+
187               Bytes.toStringBinary(new byte[]{b})+"' in input");
188         }
189         this.actions[i] = a;
190       }
191     } else {
192       actions = new Action[0];
193     }
194   }
195 
196   @Override
197   public void write(DataOutput out) throws IOException {
198     super.write(out);
199     out.writeByte(actions != null ? actions.length : 0);
200     if (actions != null) {
201       for (Action a: actions) {
202         out.writeByte(a.code());
203       }
204     }
205   }
206 }