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   @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   /** @return the object version number */
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 }