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}