-
Notifications
You must be signed in to change notification settings - Fork 244
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a URLHelper factory API to ParsingUtils #1421
Conversation
…for the previous implementation which used reflection to accomplish the same thing. Reflection won't work for Java 11 clients, its illegal across module boundaries for the most part, and bad practice as well. The reflection API was left in place in case anyone is using it with Java 8.
Codecov Report
@@ Coverage Diff @@
## master #1421 +/- ##
===============================================
- Coverage 68.122% 68.118% -0.004%
+ Complexity 8382 8381 -1
===============================================
Files 573 573
Lines 33989 33988 -1
Branches 5668 5669 +1
===============================================
- Hits 23154 23152 -2
- Misses 8645 8646 +1
Partials 2190 2190
|
…ative to using reflection for URLHelper, forbidden across modules in Java 11.
@jrobinso Is reflection really not working for java 11? I was under the impression that java 11 was giving a nasty warning but allowing it and it would be disabled at some time in the future. |
Not between modules.
On Fri, Oct 4, 2019 at 12:41 PM Louis Bergelson ***@***.***> wrote:
@jrobinso <https://github.com/jrobinso> Is reflection really not working
for java 11? I was under the impression that java 11 was giving a nasty
warning but allowing it and it would be disabled at some time in the future.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1421?email_source=notifications&email_token=AAHD2HDVBGUJCWDZFILLJX3QM6L75A5CNFSM4I45F7VKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEAMWHPQ#issuecomment-538534846>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAHD2HHNFS2GFLNV7LD6WVLQM6L75ANCNFSM4I45F7VA>
.
--
Sent from Gmail Mobile
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jrobinso This seems like a good improvement for java 8 users as well. The current system is really ancient and gross. Since I think this is not called by many users, and it should be pretty obvious how to upgrade, I wouldn't be opposed to just making a breaking change here and removing the old setter mechanism.
As it is, if we deprecate it we still have to default to the old mechanism (Which is the very reasonable choice that you made.) in order to not override existing code, or add a bunch of extra complication where setting the class nulls out the factory etc.
It's made worse by that publicly visible and settable static class field which makes it really hard to change this in an absolutely safe way since someone could be setting that directly.
In either case, a bit more documentation would be helpful for future viewers.
|
||
import java.net.URL; | ||
|
||
public interface URLHelperFactory { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add javadoc explaining what this interface is for and what the contract of getHelper is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added, although not much to say. What else would you like to know here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, thank you, it's basically boilerplate but it lets you know where to look for more information and it makes it clear that someone at least cared enough to write SOMETHING. Maybe it's just me, but I'm always suspicious of library code with 0 documentation.
I think the updated doc in URLHelper saying that there is a 1-1 relationship between urls and helpers is a useful addition. Naively I would have assumed that a helper could be used for many URL's so it's good to spell that out.
@@ -466,6 +474,11 @@ public static void registerHelperClass(Class helperClass) { | |||
urlHelperClass = helperClass; | |||
} | |||
|
|||
|
|||
public static void registerHelperFactory(URLHelperFactory factory) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a getter for this as well. There's always someone who comes along afterwards and needs one. Javadoc would be good too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, and renamed to set/get per convention
@@ -429,10 +430,16 @@ public static boolean resourceExists(String resource) throws IOException{ | |||
* @return | |||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update the javadoc here to point to the new method instead of the deprecated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The deprecated (reflection) method has been removed.
if(urlHelperFactory != null) { | ||
return urlHelperFactory.getHelper(url); | ||
} | ||
else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to add a comment here saying that this path is necessary for backwards compatibility with the old deprecated code path.
@@ -454,6 +461,7 @@ private static URLHelper getURLHelper(Class helperClass, URL url) { | |||
* The default helper class is {@link RemoteURLHelper}, which delegates to FTP/HTTP | |||
* helpers as appropriate. | |||
* | |||
* @deprecated use {@code registerHelperFactory} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you use an @link
or @see
tag instead the javadoc and IDE can provide links which is nice.
@lbergelson Thanks for the quick review and comments! I'll take care these early next week, but first would you prefer a breaking change that removes the old reflection stuff? As you say its ugly and not forward compatible with Java 11 and on, so maybe we should just get rid of it. Ditto removing or making private that public static variable. Let me know. |
I vote for removing the old reflection code and that public static variable. |
@lbergelson OK I'll give that a try and update the PR. |
@lbergelson working on this now, but slightly off-topic I stumbled on a deprecation warming for the method
|
@jrobinso That was deprecated in 2013 by Jacob Siltera, so I figured that IGV didn't need it. We can undeprecate it if it's useful and well used. |
* More javadoc * Remove old reflection-based code and global * add getter for helper factory
@lbergelson updated, have a look I'm using this version in IGV now (in my dev environment) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jrobinso A few comments, mostly nitpicky. Thank you for adding the extra documentation. I appreciate it even if it's mostly boilerplate. 👍 after the last few comments.
@@ -48,7 +64,7 @@ | |||
* @return | |||
* @throws IOException | |||
*/ | |||
@Deprecated | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick, unecessary newline here.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line saying it's deprecated should be removed too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
* @throws | ||
*/ | ||
default URLHelper getHelper(URL url) { | ||
return new RemoteURLHelper(url); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would probably not make this a default method, since we probably want to require that anyone who implements this to actually override this method. If this is non-default it lets us easily provide a lambda in place of a factory class as well since this would be a functional interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -46,11 +46,10 @@ | |||
|
|||
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 = new URLHelperFactory() {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems strange to have this interface have default implementation of its only method. Lets remove that and just replace this with
private static URLHelperFactory urlHelperFactory = RemoteURLHelper::new;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I thought it strange too but didn't want to make a concrete implementation. I wasn't aware of the syntax you used, nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah! In java 8+ if you have an interface with exactly 1 abstract method you can use a lambda instead of a named or anonymous class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good check to add if this is important. I definitely did not know this detail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If servers don't support range requests they are free according to the spec to return the entire file with response code 200. This is bad when its a 300 gb BAM
|
||
import java.net.URL; | ||
|
||
public interface URLHelperFactory { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, thank you, it's basically boilerplate but it lets you know where to look for more information and it makes it clear that someone at least cared enough to write SOMETHING. Maybe it's just me, but I'm always suspicious of library code with 0 documentation.
I think the updated doc in URLHelper saying that there is a 1-1 relationship between urls and helpers is a useful addition. Naively I would have assumed that a helper could be used for many URL's so it's good to spell that out.
//TODO check that it has 1 arg constructor of proper type | ||
} | ||
urlHelperClass = helperClass; | ||
public static void setURLHelperFactory(URLHelperFactory factory) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably throw if the value is null.
/** | ||
* @param url | ||
* @return a {@link URLHelper} object for the given URL | ||
* @throws |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd drop the throws unless there's something useful to say about what it throws.
* default method in URLHelperFactory interface is removed * update some comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. 👍
This PR adds a URLHelper factory interface and function on ParsingUtils to set the factory. It is a replacement or alternative to the previous implementation which used reflection to accomplish the same thing. Reflection won't work for Java 11 clients, its illegal across module boundaries for the most part, and bad practice as well. The reflection API was left in place in case anyone is using it with Java 8.