Skip to content

Commit

Permalink
Add a URLHelper factory API to ParsingUtils (#1421)
Browse files Browse the repository at this point in the history
* Add a URLHelper factory API to ParsingUtils -- this is a replacement for the previous implementation which used reflection to accomplish the same thing.  This is necessary because the reflection code no longer worked under Java 11
* Remove old reflection-based method `registerHelperClass`  and public static variable `urlHelperClass`
* This is a breaking change, users of the old api (registerHelperClass) will have to update to use the new factory API (setURLHelperFactory).
  • Loading branch information
jrobinso authored and lbergelson committed Oct 11, 2019
1 parent 4d73aff commit c33b695
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 49 deletions.
1 change: 0 additions & 1 deletion src/main/java/htsjdk/tribble/util/FTPHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ public InputStream openInputStream() throws IOException {
}

@Override
@Deprecated
public InputStream openInputStreamForRange(long start, long end) throws IOException {
throw new UnsupportedOperationException("Cannot perform range operations over FTP");
}
Expand Down
19 changes: 12 additions & 7 deletions src/main/java/htsjdk/tribble/util/HTTPHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public URL getUrl() {
}

/**
* @return content length of the resource
* @return content length of the resource, or -1 if not available
* @throws IOException
*/
@Override
Expand All @@ -88,30 +88,35 @@ public long getContentLength() throws IOException {

@Override
public InputStream openInputStream() throws IOException {

HttpURLConnection connection = openConnection();
return new WrapperInputStream(connection, connection.getInputStream());
}


/**
* Open an input stream for the requested byte range. Its the client's responsibility to close the stream.
* Open an InputStream to stream a slice (range) of the resource. The host server must support
* range byte requests and return a 206 response code (partial response). If it does not an IOException will
* be thrown.
*
* Its the client's responsibility to close the stream.
*
* @param start start of range in bytes
* @param end end of range ni bytes
* @return
* @throws IOException
*
* @deprecated since 12/10/14 Will be removed in a future release, as is somewhat fragile
* and not used.
*/
@Override
@Deprecated
public InputStream openInputStreamForRange(long start, long end) throws IOException {

HttpURLConnection connection = openConnection();
String byteRange = "bytes=" + start + "-" + end;
connection.setRequestProperty("Range", byteRange);

if (connection.getResponseCode() != 206) {
String msg = "Error: range requested, expected response code 206 but found " + connection.getResponseCode();
throw new IOException(msg);
}

return new WrapperInputStream(connection, connection.getInputStream());
}

Expand Down
53 changes: 18 additions & 35 deletions src/main/java/htsjdk/tribble/util/ParsingUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,10 @@ public class ParsingUtils {

public static final Map<Object, Color> colorCache = new WeakHashMap<>(100);

// HTML 4.1 color table, + orange and magenta
static Map<String, String> colorSymbols = new HashMap();
private static URLHelperFactory urlHelperFactory = RemoteURLHelper::new;

private static final Class defaultUrlHelperClass = RemoteURLHelper.class;
public static Class urlHelperClass = defaultUrlHelperClass;
// HTML 4.1 color table, + orange and magenta
private static Map<String, String> colorSymbols = new HashMap();

static {
colorSymbols.put("white", "FFFFFF");
Expand Down Expand Up @@ -423,50 +422,34 @@ public static boolean resourceExists(String resource) throws IOException{
}

/**
* Return the registered URLHelper, constructed with the provided URL
* @see #registerHelperClass(Class)
* Return a URLHelper from the current URLHelperFactory
* @see #setURLHelperFactory(URLHelperFactory)
*
* @param url
* @return
*/
public static URLHelper getURLHelper(URL url) {
try {
return getURLHelper(urlHelperClass, url);
} catch (Exception e) {
return getURLHelper(defaultUrlHelperClass, url);
}
}

private static URLHelper getURLHelper(Class helperClass, URL url) {
try {
Constructor constr = helperClass.getConstructor(URL.class);
return (URLHelper) constr.newInstance(url);
} catch (Exception e) {
String errMsg = "Error instantiating url helper for class: " + helperClass;
throw new IllegalStateException(errMsg, e);
}
return urlHelperFactory.getHelper(url);
}

/**
* Register a {@code URLHelper} class to be used for URL operations. The helper
* may be used for both FTP and HTTP operations, so if any FTP URLs are used
* the {@code URLHelper} must support it.
*
* The default helper class is {@link RemoteURLHelper}, which delegates to FTP/HTTP
* helpers as appropriate.
* Set the factory object for providing URLHelpers. {@see URLHelperFactory}.
*
* @see URLHelper
* @param helperClass Class which implements {@link URLHelper}, and have a constructor
* which takes a URL as it's only argument.
* @param factory
*/
public static void registerHelperClass(Class helperClass) {
if (!URLHelper.class.isAssignableFrom(helperClass)) {
throw new IllegalArgumentException("helperClass must implement URLHelper");
//TODO check that it has 1 arg constructor of proper type
public static void setURLHelperFactory(URLHelperFactory factory) {
if(factory == null) {
throw new NullPointerException("Null URLHelperFactory");
}
urlHelperClass = helperClass;
urlHelperFactory = factory;
}

public static URLHelperFactory getURLHelperFactory() {
return urlHelperFactory;
}

/**
*
* Add the {@code indexExtension} to the {@code filepath}, preserving
* query string elements if present. Intended for use where {@code filepath}
* is a URL. Will behave correctly on regular file paths (just add the extension
Expand Down
1 change: 0 additions & 1 deletion src/main/java/htsjdk/tribble/util/RemoteURLHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ public InputStream openInputStream() throws IOException {
}

@Override
@Deprecated
public InputStream openInputStreamForRange(long start, long end) throws IOException {
return this.wrappedHelper.openInputStreamForRange(start, end);
}
Expand Down
24 changes: 19 additions & 5 deletions src/main/java/htsjdk/tribble/util/URLHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
import java.net.URL;

/**
* Interface defining a helper class for dealing with URL resources. Purpose of this class is to provide the
* flexibility to use either URLConnection or Apache HTTPClient. Also want to delegate to either HTTP or FTP
* Interface defining a helper class for dealing with URL resources. The purpose of this class is to provide the
* flexibility to use alternative http implementations, for example Apache HTTPClient, and secondly to provide
* a hook for clients to inject custom headers, for example oAuth tokens, into the requests. An instance of
* URLHelper is created for a URL (there is a 1-1 relation between a URL and HRLHelper).
*
* @see HTTPHelper
* @see FTPHelper
Expand All @@ -33,22 +35,34 @@
*/
public interface URLHelper {

/**
* @return URL of the associated resource
*/
URL getUrl();

/**
* @return content length of the resource, or -1 if not available
* @throws IOException
*/
long getContentLength() throws IOException;

/**
* Open an InputStream to stream the contents of the resource
* @return
* @throws IOException
*/
InputStream openInputStream() throws IOException;

/**
* Open an InputStream to stream a slice (range) of the resource.
*
* May throw an OperationUnsupportedException
* @deprecated Will be removed in a future release, as is somewhat fragile
* and not used.
* @param start
* @param end
* @return
* @throws IOException
*/
@Deprecated

InputStream openInputStreamForRange(long start, long end) throws IOException;

public boolean exists() throws IOException;
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/htsjdk/tribble/util/URLHelperFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package htsjdk.tribble.util;

import java.net.URL;

/**
* A factory for creating {@link URLHelper} instances. The factory contains a single function
* @see #getHelper(URL) which should return a <code>URLHelper</code> instance for the given URL.
*/
public interface URLHelperFactory {

/**
* @param url
* @return a {@link URLHelper} object for the given URL
*/
URLHelper getHelper(URL url);

}

0 comments on commit c33b695

Please sign in to comment.