All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sshtools.client.sftp.SftpFile Maven / Gradle / Ivy

package com.sshtools.client.sftp;

/*-
 * #%L
 * Client API
 * %%
 * Copyright (C) 2002 - 2024 JADAPTIVE Limited
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.nio.file.attribute.PosixFilePermission;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import com.sshtools.common.sftp.SftpFileAttributes;
import com.sshtools.common.sftp.SftpStatusException;
import com.sshtools.common.ssh.SshException;

/**
 * Represents an SFTP file object.
 */
public final class SftpFile {
	
  private final String filename;
  private final SftpChannel sftp;
  private final String absolutePath;
  private final String longname;
  private final Map properties = new HashMap<>();
  private SftpFileAttributes attrs;
  
  SftpFile(String path, SftpFileAttributes attrs, SftpChannel sftp, String longname) {
	  if(path == null || attrs == null || sftp == null)
		  throw new NullPointerException();
	  
      this.attrs = attrs;
      this.sftp = sftp;
      this.longname = longname;

      //set filename
      var absolutePath = path;
      if(absolutePath.equals("/")) {
          this.filename = "/";
      } else {

          //Remove trailing forward slash
          if (!Boolean.getBoolean("maverick.disableSlashRemoval") && absolutePath.endsWith("/")) {
              absolutePath = absolutePath.substring(0, absolutePath.length() - 1);
          }

          int i = absolutePath.lastIndexOf('/');

          //if absolutePath contains / then filename= name following last /, else filename=absolutePath
          if (i > -1) {
              this.filename = absolutePath.substring(i + 1);
          } else {
              this.filename = absolutePath;
          }
      }
      this.absolutePath = absolutePath;
  }
  
  /**
   * Create a new handle for this file given the handle data.
   * 
   * @param handle
   */
  public SftpHandle handle(byte[] handle) {
	  return new SftpHandle(handle, sftp, this);
  }
  
  /**
   * Get the attributes for this file as they were when this file object was obtained. To
   * get the latest attributes, call {@link #refresh()} to obtain a new {@link SftpFile} instance.
   * 
   * @return attributes
   */
  public SftpFileAttributes attributes() {
	  return attrs;
  }
  
 /**
  * Set the given attributes on the remote file represented by this {@link SftpFile}.
  * 
  * @param attributes
  * @return this
  * @throws SftpStatusException
  * @throws SshException
  */
  public SftpFile attributes(SftpFileAttributes attributes) throws SftpStatusException, SshException {
	  	sftp.setAttributes(absolutePath, attributes);
	  	this.attrs = attributes;
		return this;
  }
 
	/**
	 * Refresh the {@link SftpFileAttributes} from the the remote file. 
	 * 
	 * @return file new file instance
	 * @throws SftpStatusException
	 * @throws SshException
	 */
	public SftpFile refresh() throws SftpStatusException, SshException {
		attrs = sftp.getAttributes(absolutePath);
		return this;
	 }

  /**
   * Get the parent of the current file. This method determines the correct
   * path of the parent file; if no parent exists (i.e. the current file is
   * the root of the filesystem) then this method returns a null value.
   *
   * @return SftpFile
   * @throws SshException
   * @throws SftpStatusException
   */
  public SftpFile getParent() throws SshException, SftpStatusException {

    if(absolutePath.lastIndexOf('/') == -1) {
      // This is simply a filename so the parent is the users default directory
      String dir = sftp.getDefaultDirectory();
      return sftp.getFile(dir);

    }
	// Extract the filename from the absolute path and return the parent
	String path = sftp.getAbsolutePath(absolutePath);

	if(path.equals("/"))
	  return null;

	// If we have . or .. then strip the path and let getParent start over
	// again with the correct canonical path
	if(filename.equals(".") || filename.equals("..")) {
	  return sftp.getFile(path).getParent();
	}
	int idx = path.lastIndexOf('/');

	  String parent = path.substring(0, idx);

	  // Check if we at the root if so we will have to add /
	  if(parent.equals(""))
	    parent = "/";

	  return sftp.getFile(parent);

  }

  public String toString() {
      return absolutePath;
  }

  
  @Override
  public int hashCode() {
	  return Objects.hash(absolutePath);
  }

  @Override
  public boolean equals(Object obj) {
	  if (this == obj)
		  return true;
	  if (obj == null)
		  return false;
	  if (getClass() != obj.getClass())
		  return false;
	  SftpFile other = (SftpFile) obj;
	  return Objects.equals(absolutePath, other.absolutePath);
  }

/**
   * The longname supplied by the server. Note this will not be present if SFTP version is
   * > 3.
   * @return
   */
  public String getLongname() {
	  return longname;
  }

  /**
   * Creates a new SftpFile object.
   *
   * @param absolutePath
   */
/*  public SftpFile(String absolutePath) {
    this(absolutePath, new SftpFileAttributes());
  }*/

  /**
   * Delete this file/directory from the remote server.
   *
   * @throws SshException
   * @throws SftpStatusException
   */
  public void delete() throws SftpStatusException, SshException {
    if (sftp == null) {
      throw new SshException("Instance not connected to SFTP subsystem",
                             SshException.BAD_API_USAGE);
    }

    if (isDirectory()) {
      sftp.removeDirectory(getAbsolutePath());
    }
    else {
      sftp.removeFile(getAbsolutePath());
    }
  }

  /**
   * Determine whether the user has write access to the file. This
   * checks the S_IWUSR flag is set in permissions.
   *
   * @return boolean
   * @throws SftpStatusException
   * @throws SshException
   */
  @Deprecated(since = "3.1.0", forRemoval = true)
  public boolean canWrite() throws SftpStatusException, SshException {
	if(attrs.permissions().has(PosixFilePermission.OWNER_WRITE)) {
      return true;
    }
	return false;
  }

  /**
   * Determine whether the user has read access to the file. This
   * checks the S_IRUSR flag is set in permissions. 
   *
   * @return boolean
   * @throws SftpStatusException
   * @throws SshException
   */
  @Deprecated(since = "3.1.0", forRemoval = true)
  public boolean canRead() throws SftpStatusException, SshException {
    if(attrs.permissions().has(PosixFilePermission.OWNER_READ)) {
      return true;
    }
	return false;
  }

  /**
   * Get the SFTP subsystem channel that created this file object.
   *
   * @return SftpSubsystemChannel
   */
  public SftpChannel getSFTPChannel() {
    return sftp;
  }

  /**
   * Get the filename.
   *
   * @return String
   */
  public String getFilename() {
    return filename;
  }

  /**
   * Get the files attributes.
   *
   * @return SftpFileAttributes
   * @throws SshException
   * @throws SftpStatusException
   * @deprecated 
   * @see #attributes()
*/
  @Deprecated(since = "3.1.0", forRemoval = true)
  public SftpFileAttributes getAttributes() throws SshException, SftpStatusException {
    return attrs;
  }

  /**
   * Get the absolute path
   *
   * @return String
   */
  public String getAbsolutePath() {
    return absolutePath;
  }

  /**
   * Determine whether the file object is pointing to a directory. Note,
   * if the file is a symbolic link pointing to a directory then false
   * will be returned. Use {@link com.sshtools.sftp.SftpClient#isDirectoryOrLinkedDirectory(SftpFile)} instead if you
   * wish to follow links.
   * 

* Deprecated, see {@link SftpFileAttributes#isDirectory()}. * * @return is directory * @throws SshException on SSH error * @throws SftpStatusException on SFTP error */ @Deprecated(since = "3.1.0", forRemoval = true) public boolean isDirectory() throws SftpStatusException, SshException { return attrs.isDirectory(); } /** * Determine whether the file object is pointing to a file. *

* Deprecated, see {@link SftpFileAttributes#isDirectory()}. * * @return is file * @throws SshException on SSH error * @throws SftpStatusException on SFTP error */ @Deprecated(since = "3.1.0", forRemoval = true) public boolean isFile() throws SftpStatusException, SshException { return attrs.isFile(); } /** * Determine whether the file object is a symbolic link. * * @return is link * @throws SshException on SSH error * @throws SftpStatusException on SFTP error */ public boolean isLink() throws SftpStatusException, SshException { return getAttributes().isLink(); } /** * Determine whether the file is pointing to a pipe. * * @return is fifo * @throws SshException on SSH error * @throws SftpStatusException on SFTP error */ @Deprecated(since = "3.1.0", forRemoval = true) public boolean isFifo() throws SftpStatusException, SshException { return getAttributes().isFifo(); } /** * Determine whether the file is pointing to a block special file. * * @return is block special file * @throws SshException on SSH error * @throws SftpStatusException on SFTP error */ @Deprecated(since = "3.1.0", forRemoval = true) public boolean isBlock() throws SftpStatusException, SshException { return getAttributes().isBlock(); } /** * Determine whether the file is pointing to a character mode device. * * @return is character mode device * @throws SshException on SSH error * @throws SftpStatusException on SFTP error */ @Deprecated(since = "3.1.0", forRemoval = true) public boolean isCharacter() throws SftpStatusException, SshException { return getAttributes().isCharacter(); } /** * Determine whether the file is pointing to a socket. * * @return is socket file * @throws SshException on SSH error * @throws SftpStatusException on SFTP error */ @Deprecated(since = "3.1.0", forRemoval = true) public boolean isSocket() throws SftpStatusException, SshException { return getAttributes().isSocket(); } /** * Set an arbitrary property in this file object. *

* Deprecated, no replacement. * * @param key key * @param value vlaue * @deprecated */ @Deprecated(since = "3.1.0", forRemoval = true) public void setProperty(String key, Object value) { properties.put(key, value); } /** * Get an arbitrary property stored in this file object. *

* Deprecated, no replacement. * * @param key key * @return value * @deprecated */ @Deprecated(since = "3.1.0", forRemoval = true) public Object getProperty(String key) { return properties.get(key); } SftpHandle openFile(int flags) throws SftpStatusException, SshException { return sftp.openFile(absolutePath, flags); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy