    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     */
    018    package org.apache.hadoop.fs;
    019
    020    import java.io.DataInput;
    021    import java.io.DataOutput;
    022    import java.io.IOException;
    023
    024    import org.apache.hadoop.classification.InterfaceAudience;
    025    import org.apache.hadoop.classification.InterfaceStability;
    026    import org.apache.hadoop.fs.permission.FsPermission;
    027    import org.apache.hadoop.io.Text;
    028    import org.apache.hadoop.io.Writable;
    029
    030    /** Interface that represents the client side information for a file.
    031     */
    032    @InterfaceAudience.Public
    033    @InterfaceStability.Stable
    034    public class FileStatus implements Writable, Comparable {
    035
    036      private Path path;
    037      private long length;
    038      private boolean isdir;
    039      private short block_replication;
    040      private long blocksize;
    041      private long modification_time;
    042      private long access_time;
    043      private FsPermission permission;
    044      private String owner;
    045      private String group;
    046      private Path symlink;
    047
    048      public FileStatus() { this(0, false, 0, 0, 0, 0, null, null, null, null); }
    049
    050      //We should deprecate this soon?
    051      public FileStatus(long length, boolean isdir, int block_replication,
    052                        long blocksize, long modification_time, Path path) {
    053
    054        this(length, isdir, block_replication, blocksize, modification_time,
    055             0, null, null, null, path);
    056      }
    057
    058      /**
    059       * Constructor for file systems on which symbolic links are not supported
    060       */
    061      public FileStatus(long length, boolean isdir,
    062                        int block_replication,
    063                        long blocksize, long modification_time, long access_time,
    064                        FsPermission permission, String owner, String group,
    065                        Path path) {
    066        this(length, isdir, block_replication, blocksize, modification_time,
    067             access_time, permission, owner, group, null, path);
    068      }
    069
    070      public FileStatus(long length, boolean isdir,
    071                        int block_replication,
    072                        long blocksize, long modification_time, long access_time,
    073                        FsPermission permission, String owner, String group,
    074                        Path symlink,
    075                        Path path) {
    076        this.length = length;
    077        this.isdir = isdir;
    078        this.block_replication = (short)block_replication;
    079        this.blocksize = blocksize;
    080        this.modification_time = modification_time;
    081        this.access_time = access_time;
    082        this.permission = (permission == null) ?
    083                          FsPermission.getDefault() : permission;
    084        this.owner = (owner == null) ? "" : owner;
    085        this.group = (group == null) ? "" : group;
    086        this.symlink = symlink;
    087        this.path = path;
    088        // The variables isdir and symlink indicate the type:
    089        // 1. isdir implies directory, in which case symlink must be null.
    090        // 2. !isdir implies a file or symlink, symlink != null implies a
    091        //    symlink, otherwise it's a file.
    092        assert (isdir && symlink == null) || !isdir;
    093      }
    094
    095      /**
    096       * Get the length of this file, in bytes.
    097       * @return the length of this file, in bytes.
    098       */
    099      public long getLen() {
    100        return length;
    101      }
    102
    103      /**
    104       * Is this a file?
    105       * @return true if this is a file
    106       */
    107      public boolean isFile() {
    108        return !isdir && !isSymlink();
    109      }
    110
    111      /**
    112       * Is this a directory?
    113       * @return true if this is a directory
    114       */
    115      public boolean isDirectory() {
    116        return isdir;
    117      }
    118
    119      /**
    120       * Old interface, instead use the explicit {@link FileStatus#isFile()},
    121       * {@link FileStatus#isDirectory()}, and {@link FileStatus#isSymlink()}
    122       * @return true if this is a directory.
    123       * @deprecated Use {@link FileStatus#isFile()},
    124       * {@link FileStatus#isDirectory()}, and {@link FileStatus#isSymlink()}
    125       * instead.
    126       */
    127      @Deprecated
    128      public boolean isDir() {
    129        return isdir;
    130      }
    131
    132      /**
    133       * Is this a symbolic link?
    134       * @return true if this is a symbolic link
    135       */
    136      public boolean isSymlink() {
    137        return symlink != null;
    138      }
    139
    140      /**
    141       * Get the block size of the file.
    142       * @return the number of bytes
    143       */
    144      public long getBlockSize() {
    145        return blocksize;
    146      }
    147
    148      /**
    149       * Get the replication factor of a file.
    150       * @return the replication factor of a file.
    151       */
    152      public short getReplication() {
    153        return block_replication;
    154      }
    155
    156      /**
    157       * Get the modification time of the file.
    158       * @return the modification time of file in milliseconds since January 1, 1970 UTC.
    159       */
    160      public long getModificationTime() {
    161        return modification_time;
    162      }
    163
    164      /**
    165       * Get the access time of the file.
    166       * @return the access time of file in milliseconds since January 1, 1970 UTC.
    167       */
    168      public long getAccessTime() {
    169        return access_time;
    170      }
    171
    172      /**
    173       * Get FsPermission associated with the file.
    174       * @return permssion. If a filesystem does not have a notion of permissions
    175       *         or if permissions could not be determined, then default
    176       *         permissions equivalent of "rwxrwxrwx" is returned.
    177       */
    178      public FsPermission getPermission() {
    179        return permission;
    180      }
    181
    182      /**
    183       * Get the owner of the file.
    184       * @return owner of the file. The string could be empty if there is no
    185       *         notion of owner of a file in a filesystem or if it could not
    186       *         be determined (rare).
    187       */
    188      public String getOwner() {
    189        return owner;
    190      }
    191
    192      /**
    193       * Get the group associated with the file.
    194       * @return group for the file. The string could be empty if there is no
    195       *         notion of group of a file in a filesystem or if it could not
    196       *         be determined (rare).
    197       */
    198      public String getGroup() {
    199        return group;
    200      }
    201
    202      public Path getPath() {
    203        return path;
    204      }
    205
    206      public void setPath(final Path p) {
    207        path = p;
    208      }
    209
    210      /* These are provided so that these values could be loaded lazily
    211       * by a filesystem (e.g. local file system).
    212       */
    213
    214      /**
    215       * Sets permission.
    216       * @param permission if permission is null, default value is set
    217       */
    218      protected void setPermission(FsPermission permission) {
    219        this.permission = (permission == null) ?
    220                          FsPermission.getDefault() : permission;
    221      }
    222
    223      /**
    224       * Sets owner.
    225       * @param owner if it is null, default value is set
    226       */
    227      protected void setOwner(String owner) {
    228        this.owner = (owner == null) ? "" : owner;
    229      }
    230
    231      /**
    232       * Sets group.
    233       * @param group if it is null, default value is set
    234       */
    235      protected void setGroup(String group) {
    236        this.group = (group == null) ? "" :  group;
    237      }
    238
    239      /**
    240       * @return The contents of the symbolic link.
    241       */
    242      public Path getSymlink() throws IOException {
    243        if (!isSymlink()) {
    244          throw new IOException("Path " + path + " is not a symbolic link");
    245        }
    246        return symlink;
    247      }
    248
    249      public void setSymlink(final Path p) {
    250        symlink = p;
    251      }
    252
    253      //////////////////////////////////////////////////
    254      // Writable
    255      //////////////////////////////////////////////////
    256      public void write(DataOutput out) throws IOException {
    257        Text.writeString(out, getPath().toString());
    258        out.writeLong(getLen());
    259        out.writeBoolean(isDirectory());
    260        out.writeShort(getReplication());
    261        out.writeLong(getBlockSize());
    262        out.writeLong(getModificationTime());
    263        out.writeLong(getAccessTime());
    264        getPermission().write(out);
    265        Text.writeString(out, getOwner());
    266        Text.writeString(out, getGroup());
    267        out.writeBoolean(isSymlink());
    268        if (isSymlink()) {
    269          Text.writeString(out, getSymlink().toString());
    270        }
    271      }
    272
    273      public void readFields(DataInput in) throws IOException {
    274        String strPath = Text.readString(in);
    275        this.path = new Path(strPath);
    276        this.length = in.readLong();
    277        this.isdir = in.readBoolean();
    278        this.block_replication = in.readShort();
    279        blocksize = in.readLong();
    280        modification_time = in.readLong();
    281        access_time = in.readLong();
    282        permission.readFields(in);
    283        owner = Text.readString(in);
    284        group = Text.readString(in);
    285        if (in.readBoolean()) {
    286          this.symlink = new Path(Text.readString(in));
    287        } else {
    288          this.symlink = null;
    289        }
    290      }
    291
    292      /**
    293       * Compare this object to another object
    294       *
    295       * @param   o the object to be compared.
    296       * @return  a negative integer, zero, or a positive integer as this object
    297       *   is less than, equal to, or greater than the specified object.
    298       *
    299       * @throws ClassCastException if the specified object's is not of
    300       *         type FileStatus
    301       */
    302      public int compareTo(Object o) {
    303        FileStatus other = (FileStatus)o;
    304        return this.getPath().compareTo(other.getPath());
    305      }
    306
    307      /** Compare if this object is equal to another object
    308       * @param   o the object to be compared.
    309       * @return  true if two file status has the same path name; false if not.
    310       */
    311      public boolean equals(Object o) {
    312        if (o == null) {
    313          return false;
    314        }
    315        if (this == o) {
    316          return true;
    317        }
    318        if (!(o instanceof FileStatus)) {
    319          return false;
    320        }
    321        FileStatus other = (FileStatus)o;
    322        return this.getPath().equals(other.getPath());
    323      }
    324
    325      /**
    326       * Returns a hash code value for the object, which is defined as
    327       * the hash code of the path name.
    328       *
    329       * @return  a hash code value for the path name.
    330       */
    331      public int hashCode() {
    332        return getPath().hashCode();
    333      }
    334    }