FTPFile.java
- /*
- * 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.commons.net.ftp;
- import java.io.Serializable;
- import java.time.Instant;
- import java.util.Calendar;
- import java.util.Date;
- import java.util.Formatter;
- import java.util.TimeZone;
- /**
- * The FTPFile class is used to represent information about files stored on an FTP server.
- *
- * @see FTPFileEntryParser
- * @see FTPClient#listFiles
- */
- public class FTPFile implements Serializable {
- private static final long serialVersionUID = 9010790363003271996L;
- /** A constant indicating an FTPFile is a file. */
- public static final int FILE_TYPE = 0;
- /** A constant indicating an FTPFile is a directory. */
- public static final int DIRECTORY_TYPE = 1;
- /** A constant indicating an FTPFile is a symbolic link. */
- public static final int SYMBOLIC_LINK_TYPE = 2;
- /** A constant indicating an FTPFile is of unknown type. */
- public static final int UNKNOWN_TYPE = 3;
- /** A constant indicating user access permissions. */
- public static final int USER_ACCESS = 0;
- /** A constant indicating group access permissions. */
- public static final int GROUP_ACCESS = 1;
- /** A constant indicating world access permissions. */
- public static final int WORLD_ACCESS = 2;
- /** A constant indicating file/directory read permission. */
- public static final int READ_PERMISSION = 0;
- /** A constant indicating file/directory write permission. */
- public static final int WRITE_PERMISSION = 1;
- /** A constant indicating file execute permission or directory listing permission. */
- public static final int EXECUTE_PERMISSION = 2;
- private int type = UNKNOWN_TYPE;
- /** 0 is invalid as a link count. */
- private int hardLinkCount;
- /** 0 is valid, so use -1. */
- private long size = -1;
- private String rawListing;
- private String user = "";
- private String group = "";
- private String name;
- private String link;
- // TODO Consider changing internal representation to java.time.
- private Calendar calendar;
- /** If this is null, then list entry parsing failed. */
- private final boolean[][] permissions; // e.g. _permissions[USER_ACCESS][READ_PERMISSION]
- /** Creates an empty FTPFile. */
- public FTPFile() {
- permissions = new boolean[3][3];
- }
- /**
- * Constructor for use by {@link FTPListParseEngine} only. Used to create FTPFile entries for failed parses
- *
- * @param rawListing line that could not be parsed.
- * @since 3.4
- */
- FTPFile(final String rawListing) {
- this.permissions = null; // flag that entry is invalid
- this.rawListing = rawListing;
- }
- private char formatType() {
- switch (type) {
- case FILE_TYPE:
- return '-';
- case DIRECTORY_TYPE:
- return 'd';
- case SYMBOLIC_LINK_TYPE:
- return 'l';
- default:
- return '?';
- }
- }
- /**
- * Gets the name of the group owning the file. Sometimes this will be a string representation of the group number.
- *
- * @return The name of the group owning the file.
- */
- public String getGroup() {
- return group;
- }
- /**
- * Gets the number of hard links to this file. This is not to be confused with symbolic links.
- *
- * @return The number of hard links to this file.
- */
- public int getHardLinkCount() {
- return hardLinkCount;
- }
- /**
- * If the FTPFile is a symbolic link, this method returns the name of the file being pointed to by the symbolic link.
- * Otherwise, it returns {@code null}.
- *
- * @return The file pointed to by the symbolic link ({@code null} if the FTPFile is not a symbolic link).
- */
- public String getLink() {
- return link;
- }
- /**
- * Gets the name of the file.
- *
- * @return The name of the file.
- */
- public String getName() {
- return name;
- }
- /**
- * Gets the original FTP server raw listing used to initialize the FTPFile.
- *
- * @return The original FTP server raw listing used to initialize the FTPFile.
- */
- public String getRawListing() {
- return rawListing;
- }
- /**
- * Gets the file size in bytes.
- *
- * @return The file size in bytes.
- */
- public long getSize() {
- return size;
- }
- /**
- * Gets the file timestamp. This usually the last modification time.
- *
- * @return A Calendar instance representing the file timestamp.
- */
- public Calendar getTimestamp() {
- return calendar;
- }
- /**
- * Gets the file timestamp. This usually the last modification time.
- *
- * @return A Calendar instance representing the file timestamp.
- * @since 3.9.0
- */
- public Instant getTimestampInstant() {
- return calendar == null ? null : calendar.toInstant();
- }
- /**
- * Gets the type of the file (one of the {@code _TYPE} constants), e.g., if it is a directory, a regular file, or a symbolic link.
- *
- * @return The type of the file.
- */
- public int getType() {
- return type;
- }
- /**
- * Gets the name of the user owning the file. Sometimes this will be a string representation of the user number.
- *
- * @return The name of the user owning the file.
- */
- public String getUser() {
- return user;
- }
- /**
- * Tests if the given access group (one of the {@code _ACCESS} constants) has the given access permission (one of the {@code _PERMISSION}
- * constants) to the file.
- *
- * @param access The access group (one of the {@code _ACCESS} constants)
- * @param permission The access permission (one of the {@code _PERMISSION} constants)
- * @throws ArrayIndexOutOfBoundsException if either of the parameters is out of range
- * @return {@code true} if {@link #isValid()} is {@code true} and the associated permission is set; {@code false} otherwise.
- */
- public boolean hasPermission(final int access, final int permission) {
- if (permissions == null) {
- return false;
- }
- return permissions[access][permission];
- }
- /**
- * Tests if the file is a directory.
- *
- * @return {@code true} if the file is of type {@code DIRECTORY_TYPE}, {@code false} if not.
- */
- public boolean isDirectory() {
- return type == DIRECTORY_TYPE;
- }
- /**
- * Tests if the file is a regular file.
- *
- * @return {@code true} if the file is of type {@code FILE_TYPE}, {@code false} if not.
- */
- public boolean isFile() {
- return type == FILE_TYPE;
- }
- /**
- * Tests if the file is a symbolic link.
- *
- * @return {@code true} if the file is of type {@code SYMBOLIC_LINK_TYPE}, {@code false} if not.
- */
- public boolean isSymbolicLink() {
- return type == SYMBOLIC_LINK_TYPE;
- }
- /**
- * Tests if the type of the file is unknown.
- *
- * @return {@code true} if the file is of type {@code UNKNOWN_TYPE}, {@code false} if not.
- */
- public boolean isUnknown() {
- return type == UNKNOWN_TYPE;
- }
- /**
- * Tests whether an entry is valid or not. If the entry is invalid, only the {@link #getRawListing()} method will be useful. Other methods may fail.
- *
- * Used in conjunction with list parsing that preserves entries that failed to parse.
- *
- * @see FTPClientConfig#setUnparseableEntries(boolean)
- * @return {@code true} if the entry is valid; {@code false} otherwise
- * @since 3.4
- */
- public boolean isValid() {
- return permissions != null;
- }
- private String permissionToString(final int access) {
- final StringBuilder sb = new StringBuilder();
- if (hasPermission(access, READ_PERMISSION)) {
- sb.append('r');
- } else {
- sb.append('-');
- }
- if (hasPermission(access, WRITE_PERMISSION)) {
- sb.append('w');
- } else {
- sb.append('-');
- }
- if (hasPermission(access, EXECUTE_PERMISSION)) {
- sb.append('x');
- } else {
- sb.append('-');
- }
- return sb.toString();
- }
- private void readObject(final java.io.ObjectInputStream in) {
- throw new UnsupportedOperationException("Serialization is not supported");
- }
- /**
- * Sets the name of the group owning the file. This may be a string representation of the group number.
- *
- * @param group The name of the group owning the file.
- */
- public void setGroup(final String group) {
- this.group = group;
- }
- /**
- * Sets the number of hard links to this file. This is not to be confused with symbolic links.
- *
- * @param links The number of hard links to this file.
- */
- public void setHardLinkCount(final int links) {
- this.hardLinkCount = links;
- }
- /**
- * If the FTPFile is a symbolic link, use this method to set the name of the file being pointed to by the symbolic link.
- *
- * @param link The file pointed to by the symbolic link.
- */
- public void setLink(final String link) {
- this.link = link;
- }
- /**
- * Sets the name of the file.
- *
- * @param name The name of the file.
- */
- public void setName(final String name) {
- this.name = name;
- }
- /**
- * Sets if the given access group (one of the {@code _ACCESS} constants) has the given access permission (one of the {@code _PERMISSION}
- * constants) to the file.
- *
- * @param access The access group (one of the {@code _ACCESS} constants)
- * @param permission The access permission (one of the {@code _PERMISSION} constants)
- * @param value {@code true} if permission is allowed, {@code false} if not.
- * @throws ArrayIndexOutOfBoundsException if either of the parameters is out of range
- */
- public void setPermission(final int access, final int permission, final boolean value) {
- // TODO: only allow permission setting if file is valid
- permissions[access][permission] = value;
- }
- /**
- * Sets the original FTP server raw listing from which the FTPFile was created.
- *
- * @param rawListing The raw FTP server listing.
- */
- public void setRawListing(final String rawListing) {
- this.rawListing = rawListing;
- }
- /**
- * Sets the file size in bytes.
- *
- * @param size The file size in bytes.
- */
- public void setSize(final long size) {
- this.size = size;
- }
- /**
- * Sets the file timestamp. This usually the last modification time. The parameter is not cloned, so do not alter its value after calling this method.
- *
- * @param date A Calendar instance representing the file timestamp.
- */
- public void setTimestamp(final Calendar date) {
- this.calendar = date;
- }
- /**
- * Sets the type of the file ({@code DIRECTORY_TYPE}, {@code FILE_TYPE}, etc.).
- *
- * @param type The integer code representing the type of the file.
- */
- public void setType(final int type) {
- this.type = type;
- }
- /**
- * Sets the name of the user owning the file. This may be a string representation of the user number;
- *
- * @param user The name of the user owning the file.
- */
- public void setUser(final String user) {
- this.user = user;
- }
- /**
- * Gets a string representation of the FTPFile information. This currently mimics the UNIX listing format. This method uses the time zone of the Calendar
- * entry, which is the server time zone (if one was provided) otherwise it is the local time zone.
- * <p>
- * Note: if the instance is not valid {@link #isValid()}, no useful information can be returned. In this case, use {@link #getRawListing()} instead.
- * </p>
- *
- * @return A string representation of the FTPFile information.
- * @since 3.0
- */
- public String toFormattedString() {
- return toFormattedString(null);
- }
- /**
- * Gets a string representation of the FTPFile information. This currently mimics the UNIX listing format. This method allows the Calendar time zone to be
- * overridden.
- * <p>
- * Note: if the instance is not valid {@link #isValid()}, no useful information can be returned. In this case, use {@link #getRawListing()} instead.
- * </p>
- *
- * @param timezone the time zone to use for displaying the time stamp If {@code null}, then use the Calendar ({@link #getTimestamp()}) entry
- * @return A string representation of the FTPFile information.
- * @since 3.4
- */
- public String toFormattedString(final String timezone) {
- if (!isValid()) {
- return "[Invalid: could not parse file entry]";
- }
- final StringBuilder sb = new StringBuilder();
- try (final Formatter fmt = new Formatter(sb)) {
- sb.append(formatType());
- sb.append(permissionToString(USER_ACCESS));
- sb.append(permissionToString(GROUP_ACCESS));
- sb.append(permissionToString(WORLD_ACCESS));
- fmt.format(" %4d", Integer.valueOf(getHardLinkCount()));
- fmt.format(" %-8s %-8s", getUser(), getGroup());
- fmt.format(" %8d", Long.valueOf(getSize()));
- Calendar timestamp = getTimestamp();
- if (timestamp != null) {
- if (timezone != null) {
- final TimeZone newZone = TimeZone.getTimeZone(timezone);
- if (!newZone.equals(timestamp.getTimeZone())) {
- final Date original = timestamp.getTime();
- final Calendar newStamp = Calendar.getInstance(newZone);
- newStamp.setTime(original);
- timestamp = newStamp;
- }
- }
- fmt.format(" %1$tY-%1$tm-%1$td", timestamp);
- // Only display time units if they are present
- if (timestamp.isSet(Calendar.HOUR_OF_DAY)) {
- fmt.format(" %1$tH", timestamp);
- if (timestamp.isSet(Calendar.MINUTE)) {
- fmt.format(":%1$tM", timestamp);
- if (timestamp.isSet(Calendar.SECOND)) {
- fmt.format(":%1$tS", timestamp);
- if (timestamp.isSet(Calendar.MILLISECOND)) {
- fmt.format(".%1$tL", timestamp);
- }
- }
- }
- fmt.format(" %1$tZ", timestamp);
- }
- }
- sb.append(' ');
- sb.append(getName());
- }
- return sb.toString();
- }
- /*
- * Serialization is unnecessary for this class. Reject attempts to do so until such time as the Serializable attribute can be dropped.
- */
- /**
- * Gets a string representation of the FTPFile information.
- * Delegates to {@link #getRawListing()}
- *
- * @see #getRawListing()
- * @return A string representation of the FTPFile information.
- */
- @Override
- public String toString() {
- return getRawListing();
- }
- private void writeObject(final java.io.ObjectOutputStream out) {
- throw new UnsupportedOperationException("Serialization is not supported");
- }
- }