org.apache.hadoop.fs.FileStatus.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.fs.FileStatus.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.fs;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputValidation;
import java.io.Serializable;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;

import org.apache.hadoop.fs.FSProtos.FileStatusProto;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.fs.protocolPB.PBHelper;
import org.apache.hadoop.io.Writable;

/** Interface that represents the client side information for a file.
 */
@InterfaceAudience.Public
@InterfaceStability.Stable
public class FileStatus implements Writable, Comparable<Object>, Serializable, ObjectInputValidation {

    private static final long serialVersionUID = 0x13caeae8;

    private Path path;
    private long length;
    private Boolean isdir;
    private short block_replication;
    private long blocksize;
    private long modification_time;
    private long access_time;
    private FsPermission permission;
    private String owner;
    private String group;
    private Path symlink;
    private Set<AttrFlags> attr;

    /**
     * Flags for entity attributes.
     */
    public enum AttrFlags {
        /** ACL information available for this entity. */
        HAS_ACL,
        /** Entity is encrypted. */
        HAS_CRYPT,
        /** Entity is stored erasure-coded. */
        HAS_EC,
        /** Snapshot capability enabled. */
        SNAPSHOT_ENABLED,
    }

    /**
     * Shared, empty set of attributes (a common case for FileStatus).
     */
    public static final Set<AttrFlags> NONE = Collections.<AttrFlags>emptySet();

    /**
     * Convert boolean attributes to a set of flags.
     * @param acl   See {@link AttrFlags#HAS_ACL}.
     * @param crypt See {@link AttrFlags#HAS_CRYPT}.
     * @param ec    See {@link AttrFlags#HAS_EC}.
     * @param sn    See {@link AttrFlags#SNAPSHOT_ENABLED}.
     * @return converted set of flags.
     */
    public static Set<AttrFlags> attributes(boolean acl, boolean crypt, boolean ec, boolean sn) {
        if (!(acl || crypt || ec || sn)) {
            return NONE;
        }
        EnumSet<AttrFlags> ret = EnumSet.noneOf(AttrFlags.class);
        if (acl) {
            ret.add(AttrFlags.HAS_ACL);
        }
        if (crypt) {
            ret.add(AttrFlags.HAS_CRYPT);
        }
        if (ec) {
            ret.add(AttrFlags.HAS_EC);
        }
        if (sn) {
            ret.add(AttrFlags.SNAPSHOT_ENABLED);
        }
        return ret;
    }

    public FileStatus() {
        this(0, false, 0, 0, 0, 0, null, null, null, null);
    }

    //We should deprecate this soon?
    public FileStatus(long length, boolean isdir, int block_replication, long blocksize, long modification_time,
            Path path) {

        this(length, isdir, block_replication, blocksize, modification_time, 0, null, null, null, path);
    }

    /**
     * Constructor for file systems on which symbolic links are not supported
     */
    public FileStatus(long length, boolean isdir, int block_replication, long blocksize, long modification_time,
            long access_time, FsPermission permission, String owner, String group, Path path) {
        this(length, isdir, block_replication, blocksize, modification_time, access_time, permission, owner, group,
                null, path);
    }

    public FileStatus(long length, boolean isdir, int block_replication, long blocksize, long modification_time,
            long access_time, FsPermission permission, String owner, String group, Path symlink, Path path) {
        this(length, isdir, block_replication, blocksize, modification_time, access_time, permission, owner, group,
                symlink, path, false, false, false);
    }

    public FileStatus(long length, boolean isdir, int block_replication, long blocksize, long modification_time,
            long access_time, FsPermission permission, String owner, String group, Path symlink, Path path,
            boolean hasAcl, boolean isEncrypted, boolean isErasureCoded) {
        this(length, isdir, block_replication, blocksize, modification_time, access_time, permission, owner, group,
                symlink, path, attributes(hasAcl, isEncrypted, isErasureCoded, false));
    }

    public FileStatus(long length, boolean isdir, int block_replication, long blocksize, long modification_time,
            long access_time, FsPermission permission, String owner, String group, Path symlink, Path path,
            Set<AttrFlags> attr) {
        this.length = length;
        this.isdir = isdir;
        this.block_replication = (short) block_replication;
        this.blocksize = blocksize;
        this.modification_time = modification_time;
        this.access_time = access_time;
        if (permission != null) {
            this.permission = permission;
        } else if (isdir) {
            this.permission = FsPermission.getDirDefault();
        } else if (symlink != null) {
            this.permission = FsPermission.getDefault();
        } else {
            this.permission = FsPermission.getFileDefault();
        }
        this.owner = (owner == null) ? "" : owner;
        this.group = (group == null) ? "" : group;
        this.symlink = symlink;
        this.path = path;
        this.attr = attr;

        // The variables isdir and symlink indicate the type:
        // 1. isdir implies directory, in which case symlink must be null.
        // 2. !isdir implies a file or symlink, symlink != null implies a
        //    symlink, otherwise it's a file.
        assert (isdir && symlink == null) || !isdir;
    }

    /**
     * Copy constructor.
     *
     * @param other FileStatus to copy
     */
    public FileStatus(FileStatus other) throws IOException {
        // It's important to call the getters here instead of directly accessing the
        // members.  Subclasses like ViewFsFileStatus can override the getters.
        this(other.getLen(), other.isDirectory(), other.getReplication(), other.getBlockSize(),
                other.getModificationTime(), other.getAccessTime(), other.getPermission(), other.getOwner(),
                other.getGroup(), (other.isSymlink() ? other.getSymlink() : null), other.getPath());
    }

    /**
     * Get the length of this file, in bytes.
     * @return the length of this file, in bytes.
     */
    public long getLen() {
        return length;
    }

    /**
     * Is this a file?
     * @return true if this is a file
     */
    public boolean isFile() {
        return !isDirectory() && !isSymlink();
    }

    /**
     * Is this a directory?
     * @return true if this is a directory
     */
    public boolean isDirectory() {
        return isdir;
    }

    /**
     * Old interface, instead use the explicit {@link FileStatus#isFile()},
     * {@link FileStatus#isDirectory()}, and {@link FileStatus#isSymlink()}
     * @return true if this is a directory.
     * @deprecated Use {@link FileStatus#isFile()},
     * {@link FileStatus#isDirectory()}, and {@link FileStatus#isSymlink()}
     * instead.
     */
    @Deprecated
    public final boolean isDir() {
        return isDirectory();
    }

    /**
     * Is this a symbolic link?
     * @return true if this is a symbolic link
     */
    public boolean isSymlink() {
        return symlink != null;
    }

    /**
     * Get the block size of the file.
     * @return the number of bytes
     */
    public long getBlockSize() {
        return blocksize;
    }

    /**
     * Get the replication factor of a file.
     * @return the replication factor of a file.
     */
    public short getReplication() {
        return block_replication;
    }

    /**
     * Get the modification time of the file.
     * @return the modification time of file in milliseconds since January 1, 1970 UTC.
     */
    public long getModificationTime() {
        return modification_time;
    }

    /**
     * Get the access time of the file.
     * @return the access time of file in milliseconds since January 1, 1970 UTC.
     */
    public long getAccessTime() {
        return access_time;
    }

    /**
     * Get FsPermission associated with the file.
     * @return permission. If a filesystem does not have a notion of permissions
     *         or if permissions could not be determined, then default 
     *         permissions equivalent of "rwxrwxrwx" is returned.
     */
    public FsPermission getPermission() {
        return permission;
    }

    /**
     * Tell whether the underlying file or directory has ACLs set.
     *
     * @return true if the underlying file or directory has ACLs set.
     */
    public boolean hasAcl() {
        return attr.contains(AttrFlags.HAS_ACL);
    }

    /**
     * Tell whether the underlying file or directory is encrypted or not.
     *
     * @return true if the underlying file is encrypted.
     */
    public boolean isEncrypted() {
        return attr.contains(AttrFlags.HAS_CRYPT);
    }

    /**
     * Tell whether the underlying file or directory is erasure coded or not.
     *
     * @return true if the underlying file or directory is erasure coded.
     */
    public boolean isErasureCoded() {
        return attr.contains(AttrFlags.HAS_EC);
    }

    /**
     * Check if directory is Snapshot enabled or not.
     *
     * @return true if directory is snapshot enabled
     */
    public boolean isSnapshotEnabled() {
        return attr.contains(AttrFlags.SNAPSHOT_ENABLED);
    }

    /**
     * Get the owner of the file.
     * @return owner of the file. The string could be empty if there is no
     *         notion of owner of a file in a filesystem or if it could not 
     *         be determined (rare).
     */
    public String getOwner() {
        return owner;
    }

    /**
     * Get the group associated with the file.
     * @return group for the file. The string could be empty if there is no
     *         notion of group of a file in a filesystem or if it could not 
     *         be determined (rare).
     */
    public String getGroup() {
        return group;
    }

    public Path getPath() {
        return path;
    }

    public void setPath(final Path p) {
        path = p;
    }

    /* These are provided so that these values could be loaded lazily 
     * by a filesystem (e.g. local file system).
     */

    /**
     * Sets permission.
     * @param permission if permission is null, default value is set
     */
    protected void setPermission(FsPermission permission) {
        this.permission = (permission == null) ? FsPermission.getFileDefault() : permission;
    }

    /**
     * Sets owner.
     * @param owner if it is null, default value is set
     */
    protected void setOwner(String owner) {
        this.owner = (owner == null) ? "" : owner;
    }

    /**
     * Sets group.
     * @param group if it is null, default value is set
     */
    protected void setGroup(String group) {
        this.group = (group == null) ? "" : group;
    }

    /**
     * @return The contents of the symbolic link.
     */
    public Path getSymlink() throws IOException {
        if (!isSymlink()) {
            throw new IOException("Path " + path + " is not a symbolic link");
        }
        return symlink;
    }

    public void setSymlink(final Path p) {
        symlink = p;
    }

    /**
     * Compare this FileStatus to another FileStatus
     * @param   o the FileStatus to be compared.
     * @return  a negative integer, zero, or a positive integer as this object
     *   is less than, equal to, or greater than the specified object.
     */
    public int compareTo(FileStatus o) {
        return this.getPath().compareTo(o.getPath());
    }

    /**
     * Compare this FileStatus to another FileStatus.
     * This method was added back by HADOOP-14683 to keep binary compatibility.
     *
     * @param   o the FileStatus to be compared.
     * @return  a negative integer, zero, or a positive integer as this object
     *   is less than, equal to, or greater than the specified object.
     * @throws ClassCastException if the specified object is not FileStatus
     */
    @Override
    public int compareTo(Object o) {
        FileStatus other = (FileStatus) o;
        return compareTo(other);
    }

    /** Compare if this object is equal to another object
     * @param   o the object to be compared.
     * @return  true if two file status has the same path name; false if not.
     */
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof FileStatus)) {
            return false;
        }
        if (this == o) {
            return true;
        }
        FileStatus other = (FileStatus) o;
        return this.getPath().equals(other.getPath());
    }

    /**
     * Returns a hash code value for the object, which is defined as
     * the hash code of the path name.
     *
     * @return  a hash code value for the path name.
     */
    @Override
    public int hashCode() {
        return getPath().hashCode();
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append("{");
        sb.append("path=" + path);
        sb.append("; isDirectory=" + isdir);
        if (!isDirectory()) {
            sb.append("; length=" + length);
            sb.append("; replication=" + block_replication);
            sb.append("; blocksize=" + blocksize);
        }
        sb.append("; modification_time=" + modification_time);
        sb.append("; access_time=" + access_time);
        sb.append("; owner=" + owner);
        sb.append("; group=" + group);
        sb.append("; permission=" + permission);
        sb.append("; isSymlink=" + isSymlink());
        if (isSymlink()) {
            try {
                sb.append("; symlink=" + getSymlink());
            } catch (IOException e) {
                throw new RuntimeException("Unexpected exception", e);
            }
        }
        sb.append("; hasAcl=" + hasAcl());
        sb.append("; isEncrypted=" + isEncrypted());
        sb.append("; isErasureCoded=" + isErasureCoded());
        sb.append("}");
        return sb.toString();
    }

    /**
     * Read instance encoded as protobuf from stream.
     * @param in Input stream
     * @see PBHelper#convert(FileStatus)
     * @deprecated Use the {@link PBHelper} and protobuf serialization directly.
     */
    @Override
    @Deprecated
    public void readFields(DataInput in) throws IOException {
        int size = in.readInt();
        if (size < 0) {
            throw new IOException("Can't read FileStatusProto with negative " + "size of " + size);
        }
        byte[] buf = new byte[size];
        in.readFully(buf);
        FileStatusProto proto = FileStatusProto.parseFrom(buf);
        FileStatus other = PBHelper.convert(proto);
        isdir = other.isDirectory();
        length = other.getLen();
        block_replication = other.getReplication();
        blocksize = other.getBlockSize();
        modification_time = other.getModificationTime();
        access_time = other.getAccessTime();
        setPermission(other.getPermission());
        setOwner(other.getOwner());
        setGroup(other.getGroup());
        setSymlink((other.isSymlink() ? other.getSymlink() : null));
        setPath(other.getPath());
        attr = attributes(other.hasAcl(), other.isEncrypted(), other.isErasureCoded(), other.isSnapshotEnabled());
        assert !(isDirectory() && isSymlink()) : "A directory cannot be a symlink";
    }

    /**
     * Write instance encoded as protobuf to stream.
     * @param out Output stream
     * @see PBHelper#convert(FileStatus)
     * @deprecated Use the {@link PBHelper} and protobuf serialization directly.
     */
    @Override
    @Deprecated
    public void write(DataOutput out) throws IOException {
        FileStatusProto proto = PBHelper.convert(this);
        int size = proto.getSerializedSize();
        out.writeInt(size);
        out.write(proto.toByteArray());
    }

    @Override
    public void validateObject() throws InvalidObjectException {
        if (null == path) {
            throw new InvalidObjectException("No Path in deserialized FileStatus");
        }
        if (null == isdir) {
            throw new InvalidObjectException("No type in deserialized FileStatus");
        }
    }

}