    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017
    018package org.apache.commons.net.ftp;
    019import java.io.Serializable;
    020import java.util.Calendar;
    021import java.util.Formatter;
    022
    023/***
    024 * The FTPFile class is used to represent information about files stored
    025 * on an FTP server.
    026 * <p>
    027 * <p>
    028 * @see FTPFileEntryParser
    029 * @see FTPClient#listFiles
    030 ***/
    031
    032public class FTPFile implements Serializable
    033{
    034    private static final long serialVersionUID = 9010790363003271996L;
    035
    036    /** A constant indicating an FTPFile is a file. ***/
    037    public static final int FILE_TYPE = 0;
    038    /** A constant indicating an FTPFile is a directory. ***/
    039    public static final int DIRECTORY_TYPE = 1;
    040    /** A constant indicating an FTPFile is a symbolic link. ***/
    041    public static final int SYMBOLIC_LINK_TYPE = 2;
    042    /** A constant indicating an FTPFile is of unknown type. ***/
    043    public static final int UNKNOWN_TYPE = 3;
    044
    045    /** A constant indicating user access permissions. ***/
    046    public static final int USER_ACCESS = 0;
    047    /** A constant indicating group access permissions. ***/
    048    public static final int GROUP_ACCESS = 1;
    049    /** A constant indicating world access permissions. ***/
    050    public static final int WORLD_ACCESS = 2;
    051
    052    /** A constant indicating file/directory read permission. ***/
    053    public static final int READ_PERMISSION = 0;
    054    /** A constant indicating file/directory write permission. ***/
    055    public static final int WRITE_PERMISSION = 1;
    056    /**
    057     * A constant indicating file execute permission or directory listing
    058     * permission.
    059     ***/
    060    public static final int EXECUTE_PERMISSION = 2;
    061
    062    private int _type, _hardLinkCount;
    063    private long _size;
    064    private String _rawListing, _user, _group, _name, _link;
    065    private Calendar _date;
    066    private final boolean[] _permissions[]; // e.g. _permissions[USER_ACCESS][READ_PERMISSION]
    067
    068    /*** Creates an empty FTPFile. ***/
    069    public FTPFile()
    070    {
    071        _permissions = new boolean[3][3];
    072        _rawListing = null;
    073        _type = UNKNOWN_TYPE;
    074        // init these to values that do not occur in listings
    075        // so can distinguish which fields are unset
    076        _hardLinkCount = 0; // 0 is invalid as a link count
    077        _size = -1; // 0 is valid, so use -1
    078        _user = "";
    079        _group = "";
    080        _date = null;
    081        _name = null;
    082    }
    083
    084
    085    /***
    086     * Set the original FTP server raw listing from which the FTPFile was
    087     * created.
    088     * <p>
    089     * @param rawListing  The raw FTP server listing.
    090     ***/
    091    public void setRawListing(String rawListing)
    092    {
    093        _rawListing = rawListing;
    094    }
    095
    096    /***
    097     * Get the original FTP server raw listing used to initialize the FTPFile.
    098     * <p>
    099     * @return The original FTP server raw listing used to initialize the
    100     *         FTPFile.
    101     ***/
    102    public String getRawListing()
    103    {
    104        return _rawListing;
    105    }
    106
    107
    108    /***
    109     * Determine if the file is a directory.
    110     * <p>
    111     * @return True if the file is of type <code>DIRECTORY_TYPE</code>, false if
    112     *         not.
    113     ***/
    114    public boolean isDirectory()
    115    {
    116        return (_type == DIRECTORY_TYPE);
    117    }
    118
    119    /***
    120     * Determine if the file is a regular file.
    121     * <p>
    122     * @return True if the file is of type <code>FILE_TYPE</code>, false if
    123     *         not.
    124     ***/
    125    public boolean isFile()
    126    {
    127        return (_type == FILE_TYPE);
    128    }
    129
    130    /***
    131     * Determine if the file is a symbolic link.
    132     * <p>
    133     * @return True if the file is of type <code>UNKNOWN_TYPE</code>, false if
    134     *         not.
    135     ***/
    136    public boolean isSymbolicLink()
    137    {
    138        return (_type == SYMBOLIC_LINK_TYPE);
    139    }
    140
    141    /***
    142     * Determine if the type of the file is unknown.
    143     * <p>
    144     * @return True if the file is of type <code>UNKNOWN_TYPE</code>, false if
    145     *         not.
    146     ***/
    147    public boolean isUnknown()
    148    {
    149        return (_type == UNKNOWN_TYPE);
    150    }
    151
    152
    153    /***
    154     * Set the type of the file (<code>DIRECTORY_TYPE</code>,
    155     * <code>FILE_TYPE</code>, etc.).
    156     * <p>
    157     * @param type  The integer code representing the type of the file.
    158     ***/
    159    public void setType(int type)
    160    {
    161        _type = type;
    162    }
    163
    164
    165    /***
    166     * Return the type of the file (one of the <code>_TYPE</code> constants),
    167     * e.g., if it is a directory, a regular file, or a symbolic link.
    168     * <p>
    169     * @return The type of the file.
    170     ***/
    171    public int getType()
    172    {
    173        return _type;
    174    }
    175
    176
    177    /***
    178     * Set the name of the file.
    179     * <p>
    180     * @param name  The name of the file.
    181     ***/
    182    public void setName(String name)
    183    {
    184        _name = name;
    185    }
    186
    187    /***
    188     * Return the name of the file.
    189     * <p>
    190     * @return The name of the file.
    191     ***/
    192    public String getName()
    193    {
    194        return _name;
    195    }
    196
    197
    198    /**
    199     * Set the file size in bytes.
    200     * @param size The file size in bytes.
    201     */
    202    public void setSize(long size)
    203    {
    204        _size = size;
    205    }
    206
    207
    208    /***
    209     * Return the file size in bytes.
    210     * <p>
    211     * @return The file size in bytes.
    212     ***/
    213    public long getSize()
    214    {
    215        return _size;
    216    }
    217
    218
    219    /***
    220     * Set the number of hard links to this file.  This is not to be
    221     * confused with symbolic links.
    222     * <p>
    223     * @param links  The number of hard links to this file.
    224     ***/
    225    public void setHardLinkCount(int links)
    226    {
    227        _hardLinkCount = links;
    228    }
    229
    230
    231    /***
    232     * Return the number of hard links to this file.  This is not to be
    233     * confused with symbolic links.
    234     * <p>
    235     * @return The number of hard links to this file.
    236     ***/
    237    public int getHardLinkCount()
    238    {
    239        return _hardLinkCount;
    240    }
    241
    242
    243    /***
    244     * Set the name of the group owning the file.  This may be
    245     * a string representation of the group number.
    246     * <p>
    247     * @param group The name of the group owning the file.
    248     ***/
    249    public void setGroup(String group)
    250    {
    251        _group = group;
    252    }
    253
    254
    255    /***
    256     * Returns the name of the group owning the file.  Sometimes this will be
    257     * a string representation of the group number.
    258     * <p>
    259     * @return The name of the group owning the file.
    260     ***/
    261    public String getGroup()
    262    {
    263        return _group;
    264    }
    265
    266
    267    /***
    268     * Set the name of the user owning the file.  This may be
    269     * a string representation of the user number;
    270     * <p>
    271     * @param user The name of the user owning the file.
    272     ***/
    273    public void setUser(String user)
    274    {
    275        _user = user;
    276    }
    277
    278    /***
    279     * Returns the name of the user owning the file.  Sometimes this will be
    280     * a string representation of the user number.
    281     * <p>
    282     * @return The name of the user owning the file.
    283     ***/
    284    public String getUser()
    285    {
    286        return _user;
    287    }
    288
    289
    290    /***
    291     * If the FTPFile is a symbolic link, use this method to set the name of the
    292     * file being pointed to by the symbolic link.
    293     * <p>
    294     * @param link  The file pointed to by the symbolic link.
    295     ***/
    296    public void setLink(String link)
    297    {
    298        _link = link;
    299    }
    300
    301
    302    /***
    303     * If the FTPFile is a symbolic link, this method returns the name of the
    304     * file being pointed to by the symbolic link.  Otherwise it returns null.
    305     * <p>
    306     * @return The file pointed to by the symbolic link (null if the FTPFile
    307     *         is not a symbolic link).
    308     ***/
    309    public String getLink()
    310    {
    311        return _link;
    312    }
    313
    314
    315    /***
    316     * Set the file timestamp.  This usually the last modification time.
    317     * The parameter is not cloned, so do not alter its value after calling
    318     * this method.
    319     * <p>
    320     * @param date A Calendar instance representing the file timestamp.
    321     ***/
    322    public void setTimestamp(Calendar date)
    323    {
    324        _date = date;
    325    }
    326
    327
    328    /***
    329     * Returns the file timestamp.  This usually the last modification time.
    330     * <p>
    331     * @return A Calendar instance representing the file timestamp.
    332     ***/
    333    public Calendar getTimestamp()
    334    {
    335        return _date;
    336    }
    337
    338
    339    /***
    340     * Set if the given access group (one of the <code> _ACCESS </code>
    341     * constants) has the given access permission (one of the
    342     * <code> _PERMISSION </code> constants) to the file.
    343     * <p>
    344     * @param access The access group (one of the <code> _ACCESS </code>
    345     *               constants)
    346     * @param permission The access permission (one of the
    347     *               <code> _PERMISSION </code> constants)
    348     * @param value  True if permission is allowed, false if not.
    349     ***/
    350    public void setPermission(int access, int permission, boolean value)
    351    {
    352        _permissions[access][permission] = value;
    353    }
    354
    355
    356    /***
    357     * Determines if the given access group (one of the <code> _ACCESS </code>
    358     * constants) has the given access permission (one of the
    359     * <code> _PERMISSION </code> constants) to the file.
    360     * <p>
    361     * @param access The access group (one of the <code> _ACCESS </code>
    362     *               constants)
    363     * @param permission The access permission (one of the
    364     *               <code> _PERMISSION </code> constants)
    365     ***/
    366    public boolean hasPermission(int access, int permission)
    367    {
    368        return _permissions[access][permission];
    369    }
    370
    371    /***
    372     * Returns a string representation of the FTPFile information.
    373     *
    374     * @return A string representation of the FTPFile information.
    375     */
    376    @Override
    377    public String toString()
    378    {
    379        return getRawListing();
    380    }
    381
    382    /***
    383     * Returns a string representation of the FTPFile information.
    384     * This currently mimics the Unix listing format.
    385     *
    386     * @return A string representation of the FTPFile information.
    387     * @since 3.0
    388     */
    389    public String toFormattedString()
    390    {
    391        StringBuilder sb = new StringBuilder();
    392        Formatter fmt = new Formatter(sb);
    393        sb.append(formatType());
    394        sb.append(permissionToString(USER_ACCESS));
    395        sb.append(permissionToString(GROUP_ACCESS));
    396        sb.append(permissionToString(WORLD_ACCESS));
    397        fmt.format(" %4d", Integer.valueOf(getHardLinkCount()));
    398        fmt.format(" %-8s %-8s", getGroup(), getUser());
    399        fmt.format(" %8d", Long.valueOf(getSize()));
    400        Calendar timestamp = getTimestamp();
    401        if (timestamp != null) {
    402            fmt.format(" %1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS", timestamp);
    403            fmt.format(" %1$tZ", timestamp);
    404            sb.append(' ');
    405        }
    406        sb.append(' ');
    407        sb.append(getName());
    408        fmt.close();
    409        return sb.toString();
    410    }
    411
    412    private char formatType(){
    413        switch(_type) {
    414            case FILE_TYPE:
    415                return '-';
    416            case DIRECTORY_TYPE:
    417                return 'd';
    418            case SYMBOLIC_LINK_TYPE:
    419                return 'l';
    420        }
    421        return '?';
    422    }
    423
    424    private String permissionToString(int access ){
    425        StringBuilder sb = new StringBuilder();
    426        if (hasPermission(access, READ_PERMISSION)) {
    427            sb.append('r');
    428        } else {
    429            sb.append('-');
    430        }
    431        if (hasPermission(access, WRITE_PERMISSION)) {
    432            sb.append('w');
    433        } else {
    434            sb.append('-');
    435        }
    436        if (hasPermission(access, EXECUTE_PERMISSION)) {
    437            sb.append('x');
    438        } else {
    439            sb.append('-');
    440        }
    441        return sb.toString();
    442    }
    443}