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 final 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   public void setActions(Action[] assigned) {
116     if (assigned != null && assigned.length > 0) {
117       actions = Arrays.copyOf(assigned, assigned.length);
118     }
119   }
120 
121   @Override
122   public boolean equals(Object obj) {
123     if (!(obj instanceof Permission)) {
124       return false;
125     }
126     Permission other = (Permission)obj;
127     // check actions
128     if (actions == null && other.getActions() == null) {
129       return true;
130     } else if (actions != null && other.getActions() != null) {
131       Action[] otherActions = other.getActions();
132       if (actions.length != otherActions.length) {
133         return false;
134       }
135 
136       outer:
137       for (Action a : actions) {
138         for (Action oa : otherActions) {
139           if (a == oa) continue outer;
140         }
141         return false;
142       }
143       return true;
144     }
145 
146     return false;
147   }
148 
149   @Override
150   public int hashCode() {
151     final int prime = 37;
152     int result = 23;
153     for (Action a : actions) {
154       result = prime * result + a.code();
155     }
156     return result;
157   }
158 
159   @Override
160   public String toString() {
161     StringBuilder str = new StringBuilder("[Permission: ")
162         .append("actions=");
163     if (actions != null) {
164       for (int i=0; i<actions.length; i++) {
165         if (i > 0)
166           str.append(",");
167         if (actions[i] != null)
168           str.append(actions[i].toString());
169         else
170           str.append("NULL");
171       }
172     }
173     str.append("]");
174 
175     return str.toString();
176   }
177 
178   /** @return the object version number */
179   @Override
180   public byte getVersion() {
181     return VERSION;
182   }
183 
184   @Override
185   public void readFields(DataInput in) throws IOException {
186     super.readFields(in);
187     int length = (int)in.readByte();
188     if (length > 0) {
189       actions = new Action[length];
190       for (int i = 0; i < length; i++) {
191         byte b = in.readByte();
192         Action a = ACTION_BY_CODE.get(b);
193         if (a == null) {
194           throw new IOException("Unknown action code '"+
195               Bytes.toStringBinary(new byte[]{b})+"' in input");
196         }
197         this.actions[i] = a;
198       }
199     } else {
200       actions = new Action[0];
201     }
202   }
203 
204   @Override
205   public void write(DataOutput out) throws IOException {
206     super.write(out);
207     out.writeByte(actions != null ? actions.length : 0);
208     if (actions != null) {
209       for (Action a: actions) {
210         out.writeByte(a.code());
211       }
212     }
213   }
214 }