From 084c9b0effa480d31976009985982895ab46b649 Mon Sep 17 00:00:00 2001 From: Joao Azevedo Date: Tue, 5 Nov 2024 16:11:28 +0000 Subject: [PATCH] Add a uri method to FileDescriptor Enables the FileDescriptor interface with a uri method that returns a java.net.URI with a reference to the file's location. --- .../com/kevel/apso/io/FileDescriptor.scala | 8 ++++++++ .../kevel/apso/io/LocalFileDescriptor.scala | 7 ++++++- .../com/kevel/apso/io/S3FileDescriptor.scala | 7 ++++++- .../kevel/apso/io/SftpFileDescriptor.scala | 8 ++++++-- .../apso/io/LocalFileDescriptorSpec.scala | 8 ++++++++ .../kevel/apso/io/S3FileDescriptorSpec.scala | 14 ++++++++++++++ .../apso/io/SftpFileDescriptorSpec.scala | 19 +++++++++++++++++++ 7 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 io/src/test/scala/com/kevel/apso/io/S3FileDescriptorSpec.scala create mode 100644 io/src/test/scala/com/kevel/apso/io/SftpFileDescriptorSpec.scala diff --git a/io/src/main/scala/com/kevel/apso/io/FileDescriptor.scala b/io/src/main/scala/com/kevel/apso/io/FileDescriptor.scala index 866e5fb8..cc767702 100644 --- a/io/src/main/scala/com/kevel/apso/io/FileDescriptor.scala +++ b/io/src/main/scala/com/kevel/apso/io/FileDescriptor.scala @@ -1,6 +1,7 @@ package com.kevel.apso.io import java.io.InputStream +import java.net.URI import scala.io.Source @@ -15,6 +16,13 @@ trait FileDescriptor { */ def path: String + /** Returns a Uniform Resource Identifier (URI) that references this file's location. + * + * @return + * the URI that references this file's location. + */ + def uri: URI + /** The name of the file associated with the file descriptor. * @return * the file name. diff --git a/io/src/main/scala/com/kevel/apso/io/LocalFileDescriptor.scala b/io/src/main/scala/com/kevel/apso/io/LocalFileDescriptor.scala index ee944477..b88b4b55 100644 --- a/io/src/main/scala/com/kevel/apso/io/LocalFileDescriptor.scala +++ b/io/src/main/scala/com/kevel/apso/io/LocalFileDescriptor.scala @@ -1,6 +1,7 @@ package com.kevel.apso.io import java.io.{FileInputStream, FileWriter, InputStream} +import java.net.URI import java.nio.file.{Files, Path, Paths, StandardCopyOption} import scala.io.Source @@ -21,6 +22,9 @@ case class LocalFileDescriptor(initialPath: String) extends FileDescriptor with lazy val path: String = file.getAbsolutePath + def uri: URI = + new URI(s"file://$path") + lazy val name: String = file.getName val isLocal: Boolean = true @@ -208,7 +212,8 @@ case class LocalFileDescriptor(initialPath: String) extends FileDescriptor with */ def readString: String = Source.fromFile(file, "UTF-8").mkString - override def toString: String = s"file://$path" + override def toString: String = + uri.toString override def equals(other: Any): Boolean = other match { case that: LocalFileDescriptor => path == that.path diff --git a/io/src/main/scala/com/kevel/apso/io/S3FileDescriptor.scala b/io/src/main/scala/com/kevel/apso/io/S3FileDescriptor.scala index ae9eca09..707b3197 100644 --- a/io/src/main/scala/com/kevel/apso/io/S3FileDescriptor.scala +++ b/io/src/main/scala/com/kevel/apso/io/S3FileDescriptor.scala @@ -1,6 +1,7 @@ package com.kevel.apso.io import java.io.InputStream +import java.net.URI import scala.collection.concurrent.TrieMap @@ -29,6 +30,9 @@ case class S3FileDescriptor( protected def duplicate(elements: List[String]) = this.copy(elements = elements) + def uri: URI = + new URI(s"s3://$path") + def size = summary match { case Some(info) => info.getSize case None => bucket.size(builtPath) @@ -134,7 +138,8 @@ case class S3FileDescriptor( result } - override def toString: String = s"s3://$path" + override def toString: String = + uri.toString } object S3FileDescriptor { diff --git a/io/src/main/scala/com/kevel/apso/io/SftpFileDescriptor.scala b/io/src/main/scala/com/kevel/apso/io/SftpFileDescriptor.scala index a13903e6..85b2d2cd 100644 --- a/io/src/main/scala/com/kevel/apso/io/SftpFileDescriptor.scala +++ b/io/src/main/scala/com/kevel/apso/io/SftpFileDescriptor.scala @@ -1,6 +1,7 @@ package com.kevel.apso.io import java.io.{FileDescriptor => _, _} +import java.net.URI import java.util.concurrent.{ConcurrentHashMap, TimeoutException} import scala.concurrent.duration._ @@ -100,6 +101,10 @@ case class SftpFileDescriptor( withFileAttributes(f) } + def uri: URI = + if (port != 22) new URI(s"sftp://$username@$host:$port$path") + else new URI(s"sftp://$username@$host$path") + def size = withFileAttributes(_.getSize) def lastModifiedTimestamp = withFileAttributes(_.getMtime()) @@ -200,8 +205,7 @@ case class SftpFileDescriptor( } override def toString: String = - if (port != 22) s"sftp://$username@$host:$port$path" - else s"sftp://$username@$host$path" + uri.toString override def equals(other: Any): Boolean = other match { case that: SftpFileDescriptor => diff --git a/io/src/test/scala/com/kevel/apso/io/LocalFileDescriptorSpec.scala b/io/src/test/scala/com/kevel/apso/io/LocalFileDescriptorSpec.scala index 075bbccd..4c0fdd97 100644 --- a/io/src/test/scala/com/kevel/apso/io/LocalFileDescriptorSpec.scala +++ b/io/src/test/scala/com/kevel/apso/io/LocalFileDescriptorSpec.scala @@ -1,6 +1,7 @@ package com.kevel.apso.io import java.io.{File, InputStream} +import java.net.URI import java.nio.file.Files import java.util.UUID @@ -23,6 +24,13 @@ class LocalFileDescriptorSpec extends Specification { file.getAbsolutePath == fd.path } + "have a correct URI that exposes the full path" in { + val file = new File("/tmp/one/two/three") + val fd = LocalFileDescriptor("/tmp/one/two/three") + fd.uri ==== new URI("file:///tmp/one/two/three") + file.toURI() ==== fd.uri + } + "retrieve the size of a file" in { val fd1 = LocalFileDescriptor("/tmp") / randomFolder / randomString fd1.write("hello world") diff --git a/io/src/test/scala/com/kevel/apso/io/S3FileDescriptorSpec.scala b/io/src/test/scala/com/kevel/apso/io/S3FileDescriptorSpec.scala new file mode 100644 index 00000000..5133f354 --- /dev/null +++ b/io/src/test/scala/com/kevel/apso/io/S3FileDescriptorSpec.scala @@ -0,0 +1,14 @@ +package com.kevel.apso.io + +import java.net.URI + +import org.specs2.mutable.Specification + +class S3FileDescriptorSpec extends Specification { + "A S3FileDescriptor" should { + "have a correct URI that exposes the full path" in { + val file = S3FileDescriptor("bucket/key") + file.uri ==== new URI("s3://bucket/key") + } + } +} diff --git a/io/src/test/scala/com/kevel/apso/io/SftpFileDescriptorSpec.scala b/io/src/test/scala/com/kevel/apso/io/SftpFileDescriptorSpec.scala new file mode 100644 index 00000000..ffae75e4 --- /dev/null +++ b/io/src/test/scala/com/kevel/apso/io/SftpFileDescriptorSpec.scala @@ -0,0 +1,19 @@ +package com.kevel.apso.io + +import java.net.URI + +import org.specs2.mutable.Specification + +import com.kevel.apso.io.config.Credentials + +class SftpFileDescriptorSpec extends Specification { + "A SftpFileDescriptor" should { + "have a correct URI that exposes the full path" in { + val file = SftpFileDescriptor( + "localhost/tmp/file", + Credentials.Sftp(default = Some(Credentials.Sftp.Entry.Basic(username = "user123", password = "pass456"))) + ) + file.uri ==== new URI("sftp://user123@localhost/tmp/file") + } + } +}