001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hdfs.server.namenode;
019
020import org.apache.commons.lang.StringUtils;
021import org.apache.hadoop.classification.InterfaceAudience;
022import org.apache.hadoop.classification.InterfaceStability;
023import org.apache.hadoop.fs.Path;
024import org.apache.hadoop.fs.permission.FsAction;
025import org.apache.hadoop.hdfs.DFSUtil;
026import org.apache.hadoop.security.AccessControlException;
027import org.apache.hadoop.security.UserGroupInformation;
028
029@InterfaceAudience.Public
030@InterfaceStability.Unstable
031public abstract class INodeAttributeProvider {
032
033  /**
034   * The AccessControlEnforcer allows implementations to override the
035   * default File System permission checking logic enforced on a file system
036   * object
037   */
038  public interface AccessControlEnforcer {
039
040    /**
041     * Checks permission on a file system object. Has to throw an Exception
042     * if the filesystem object is not accessessible by the calling Ugi.
043     * @param fsOwner Filesystem owner (The Namenode user)
044     * @param supergroup super user geoup
045     * @param callerUgi UserGroupInformation of the caller
046     * @param inodeAttrs Array of INode attributes for each path element in the
047     *                   the path
048     * @param inodes Array of INodes for each path element in the path
049     * @param pathByNameArr Array of byte arrays of the LocalName
050     * @param snapshotId the snapshotId of the requested path
051     * @param path Path String
052     * @param ancestorIndex Index of ancestor
053     * @param doCheckOwner perform ownership check
054     * @param ancestorAccess The access required by the ancestor of the path.
055     * @param parentAccess The access required by the parent of the path.
056     * @param access The access required by the path.
057     * @param subAccess If path is a directory, It is the access required of
058     *                  the path and all the sub-directories. If path is not a
059     *                  directory, there should ideally be no effect.
060     * @param ignoreEmptyDir Ignore permission checking for empty directory?
061     * @throws AccessControlException
062     */
063    public abstract void checkPermission(String fsOwner, String supergroup,
064        UserGroupInformation callerUgi, INodeAttributes[] inodeAttrs,
065        INode[] inodes, byte[][] pathByNameArr, int snapshotId, String path,
066        int ancestorIndex, boolean doCheckOwner, FsAction ancestorAccess,
067        FsAction parentAccess, FsAction access, FsAction subAccess,
068        boolean ignoreEmptyDir)
069            throws AccessControlException;
070
071  }
072  /**
073   * Initialize the provider. This method is called at NameNode startup
074   * time.
075   */
076  public abstract void start();
077
078  /**
079   * Shutdown the provider. This method is called at NameNode shutdown time.
080   */
081  public abstract void stop();
082
083  @Deprecated
084  String[] getPathElements(String path) {
085    path = path.trim();
086    if (path.charAt(0) != Path.SEPARATOR_CHAR) {
087      throw new IllegalArgumentException("It must be an absolute path: " +
088          path);
089    }
090    int numOfElements = StringUtils.countMatches(path, Path.SEPARATOR);
091    if (path.length() > 1 && path.endsWith(Path.SEPARATOR)) {
092      numOfElements--;
093    }
094    String[] pathElements = new String[numOfElements];
095    int elementIdx = 0;
096    int idx = 0;
097    int found = path.indexOf(Path.SEPARATOR_CHAR, idx);
098    while (found > -1) {
099      if (found > idx) {
100        pathElements[elementIdx++] = path.substring(idx, found);
101      }
102      idx = found + 1;
103      found = path.indexOf(Path.SEPARATOR_CHAR, idx);
104    }
105    if (idx < path.length()) {
106      pathElements[elementIdx] = path.substring(idx);
107    }
108    return pathElements;
109  }
110
111  @Deprecated
112  public INodeAttributes getAttributes(String fullPath, INodeAttributes inode) {
113    return getAttributes(getPathElements(fullPath), inode);
114  }
115
116  public abstract INodeAttributes getAttributes(String[] pathElements,
117      INodeAttributes inode);
118
119  public INodeAttributes getAttributes(byte[][] components,
120      INodeAttributes inode) {
121    String[] elements = new String[components.length];
122    for (int i = 0; i < elements.length; i++) {
123      elements[i] = DFSUtil.bytes2String(components[i]);
124    }
125    return getAttributes(elements, inode);
126  }
127
128  /**
129   * Can be over-ridden by implementations to provide a custom Access Control
130   * Enforcer that can provide an alternate implementation of the
131   * default permission checking logic.
132   * @param defaultEnforcer The Default AccessControlEnforcer
133   * @return The AccessControlEnforcer to use
134   */
135  public AccessControlEnforcer getExternalAccessControlEnforcer(
136      AccessControlEnforcer defaultEnforcer) {
137    return defaultEnforcer;
138  }
139}