23
23
*/
24
24
package htsjdk .samtools .seekablestream ;
25
25
26
- import htsjdk .samtools .util .IOUtil ;
27
- import java .io .File ;
26
+ import htsjdk .io .HtsPath ;
27
+ import htsjdk .io .IOPath ;
28
+ import htsjdk .tribble .TribbleException ;
29
+
28
30
import java .io .IOException ;
29
- import java .net .URI ;
30
31
import java .net .URL ;
31
32
import java .nio .channels .SeekableByteChannel ;
33
+ import java .nio .file .Path ;
34
+ import java .util .Set ;
32
35
import java .util .function .Function ;
33
36
34
37
/**
40
43
public class SeekableStreamFactory {
41
44
42
45
private static final ISeekableStreamFactory DEFAULT_FACTORY ;
46
+ private static final String HTTP = "http" ;
47
+ private static final String HTTPS = "https" ;
48
+ private static final String FTP = "ftp" ;
49
+ /**
50
+ * the set of url schemes that have special support in htsjdk that isn't through a FileSystemProvider
51
+ */
52
+ private static final Set <String > URL_SCHEMES_WITH_LEGACY_SUPPORT = Set .of (HTTP , FTP , HTTPS );
53
+ public static final String FILE_SCHEME = "file" ;
43
54
private static ISeekableStreamFactory currentFactory ;
44
55
45
56
static {
@@ -61,9 +72,28 @@ public static ISeekableStreamFactory getInstance(){
61
72
* Does this path point to a regular file on disk and not something like a URL?
62
73
* @param path the path to test
63
74
* @return true if the path is to a file on disk
75
+ * @deprecated this method is simplistic and no longer particularly useful since IOPath allows similar access to
76
+ * various non-file data sources, internal use has been replaced with {@link #isBeingHandledByLegacyUrlSupport(String)}
64
77
*/
78
+ @ Deprecated
65
79
public static boolean isFilePath (final String path ) {
66
- return ! ( path .startsWith ("http:" ) || path .startsWith ("https:" ) || path .startsWith ("ftp:" ) );
80
+ return !canBeHandledByLegacyUrlSupport (path );
81
+ }
82
+
83
+ /**
84
+ * is this path being handled by one of the legacy SeekableStream types (http(s) / ftp)
85
+ *
86
+ * @param path a path to check
87
+ * @return if the path is not being handled by a FileSystemProvider and it can be read by legacy streams
88
+ */
89
+ public static boolean isBeingHandledByLegacyUrlSupport (final String path ){
90
+ return !new HtsPath (path ).hasFileSystemProvider () //if we have a provider for it that's what we'll use
91
+ && canBeHandledByLegacyUrlSupport (path ); // otherwise we fall back to the special handlers
92
+ }
93
+
94
+ //is this one of the url types that has legacy htsjdk support built in?
95
+ public static boolean canBeHandledByLegacyUrlSupport (final String path ) {
96
+ return URL_SCHEMES_WITH_LEGACY_SUPPORT .stream ().anyMatch (scheme -> path .startsWith (scheme +"://" ));
67
97
}
68
98
69
99
private static class DefaultSeekableStreamFactory implements ISeekableStreamFactory {
@@ -79,7 +109,7 @@ public SeekableStream getStreamFor(final String path) throws IOException {
79
109
}
80
110
81
111
/**
82
- * The wrapper will only be applied to the stream if the stream is treated as a {@link java.nio.file. Path}
112
+ * The wrapper will only be applied to the stream if the stream is treated as a {@link Path}
83
113
*
84
114
* This currently means any uri with a scheme that is not http, https, ftp, or file will have the wrapper applied to it
85
115
*
@@ -89,26 +119,30 @@ public SeekableStream getStreamFor(final String path) throws IOException {
89
119
@ Override
90
120
public SeekableStream getStreamFor (final String path ,
91
121
Function <SeekableByteChannel , SeekableByteChannel > wrapper ) throws IOException {
92
- // todo -- add support for SeekableBlockInputStream
93
-
94
- if ( path . startsWith ( "http:" ) || path . startsWith ( "https:" )) {
95
- final URL url = new URL ( path );
96
- return new SeekableHTTPStream ( url );
97
- } else if ( path . startsWith ( "ftp:" )) {
98
- return new SeekableFTPStream ( new URL ( path ));
99
- } else if ( path . startsWith ( "file:" )) {
100
- try {
101
- // convert to URI in order to obtain a decoded version of the path string suitable
102
- // for use with the File constructor
103
- final String decodedPath = new URI ( path ). getPath ();
104
- return new SeekableFileStream ( new File ( decodedPath ));
105
- } catch ( java . net . URISyntaxException e ) {
106
- throw new IllegalArgumentException ( String . format ( "The input string %s contains a URI scheme but is not a valid URI" , path ), e );
107
- }
108
- } else if ( IOUtil . hasScheme ( path )) {
109
- return new SeekablePathStream (IOUtil . getPath ( path ), wrapper );
122
+ return getStreamFor ( new HtsPath ( path ), wrapper );
123
+ }
124
+
125
+
126
+ /**
127
+ * The wrapper will only be applied to the stream if the stream is treated as a non file:// {@link Path}
128
+ *
129
+ * This has a fall back to htsjdk's built in http and ftp providers if no FileSystemProvder is available for them
130
+ *
131
+ * @param path an IOPath to be opened
132
+ * @param wrapper a wrapper to apply to the stream allowing direct transformations on the byte stream to be applied
133
+ * @throws IOException
134
+ */
135
+ public static SeekableStream getStreamFor ( final IOPath path , Function < SeekableByteChannel , SeekableByteChannel > wrapper ) throws IOException {
136
+ if ( path . hasFileSystemProvider ()) {
137
+ return path . getScheme (). equals ( FILE_SCHEME )
138
+ ? new SeekableFileStream ( path . toPath (). toFile ()) //don't apply the wrapper to local files
139
+ : new SeekablePathStream (path . toPath ( ), wrapper );
110
140
} else {
111
- return new SeekableFileStream (new File (path ));
141
+ return switch (path .getScheme ()){
142
+ case HTTP , HTTPS -> new SeekableHTTPStream (new URL (path .getRawInputString ()));
143
+ case FTP -> new SeekableFTPStream ((new URL (path .getRawInputString ())));
144
+ default -> throw new TribbleException ("Unknown path type. No FileSystemProvider available for " + path .getRawInputString ());
145
+ };
112
146
}
113
147
}
114
148
0 commit comments