-
Notifications
You must be signed in to change notification settings - Fork 668
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
IO-568: AutoCloseInputStream should disable mark/reset #55
base: master
Are you sure you want to change the base?
Changes from 1 commit
7c042b8
56d2264
508c6ab
2b1cdb3
f6d18f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,11 +16,11 @@ | |
*/ | ||
package org.apache.commons.io.input; | ||
|
||
import static org.apache.commons.io.IOUtils.EOF; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
|
||
import static org.apache.commons.io.IOUtils.EOF; | ||
|
||
/** | ||
* Proxy stream that closes and discards the underlying stream as soon as the | ||
* end of input has been reached or when the stream is explicitly closed. | ||
|
@@ -37,6 +37,8 @@ | |
*/ | ||
public class AutoCloseInputStream extends ProxyInputStream { | ||
|
||
private boolean marked; | ||
|
||
/** | ||
* Creates an automatically closing proxy for the given input stream. | ||
* | ||
|
@@ -66,19 +68,47 @@ public void close() throws IOException { | |
} | ||
|
||
/** | ||
* Automatically closes the stream if the end of stream was reached. | ||
* Automatically closes the stream if the end of stream was reached unless the stream was marked. | ||
* | ||
* @param n number of bytes read, or -1 if no more bytes are available | ||
* @throws IOException if the stream could not be closed | ||
* @since 2.0 | ||
*/ | ||
@Override | ||
protected void afterRead(final int n) throws IOException { | ||
if (n == EOF) { | ||
if (n == EOF && !marked) { | ||
close(); | ||
} | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
* <p> | ||
* Make sure to remember that the stream was makred to not close it when reaching the end. | ||
* | ||
* @see org.apache.commons.io.input.ProxyInputStream#mark(int) | ||
*/ | ||
@Override | ||
public synchronized void mark(int readlimit) { | ||
super.mark(readlimit); | ||
|
||
marked = true; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
* <p> | ||
* Reset the marked flag. | ||
* | ||
* @see org.apache.commons.io.input.ProxyInputStream#reset() | ||
*/ | ||
@Override | ||
public synchronized void reset() throws IOException { | ||
super.reset(); | ||
|
||
marked = false; | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @tmortagne Again, this completely changes the contract of the existing class and will break existing call sites. I think there are two kinds of solutions here: Gary There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really don't understand this "again". The whole point of the previous conversation was that it was simpler to make AutoCloseInputStream just cancel mark/reset support since it's too complex to really support it properly and you said yourself
As I said AutoCloseInputStream does not make much sense in its current state since it break InputStream contract regarding mark/reset support which is not so great. Cancel mark/rest support is one way to prevent this inconsistency which is what I suggested several times and that you seemed to agree on. If you are suggesting that a new class should be introduced and AutoCloseInputStream deprecated because broken but not fixable it was not very clear. |
||
/** | ||
* Ensures that the stream is closed before it gets garbage-collected. | ||
* As mentioned in {@link #close()}, this is a no-op if the stream has | ||
|
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 changes the contract of the method and the whole class. The class Javadoc states "Proxy stream that closes and discards the underlying stream as soon as the end of input has been reached or when the stream is explicitly closed." If feels like you need a different class. Now, it is possible that the original author did not even think of the mark and reset use cases, but still, this has the potential of defeating the purpose of the class: which is to auto close no matter what. Maybe you need a class called "AutoCloseUnmarkedInputStream"?
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 thing is AutoCloseInputStream itself does not respect the contract of mark/reset API (which makes Tika confuse) and I feel this use case was simply forgotten. Before anything, it's supposed to act as a valid InputStream (which happen to be automatically closed when you don't need it anymore). I assumed that if you mark it it means you will reset it at some point so there is no much risk IMO.
IMO either AutoCloseInputStream support mark/rest or it should force override mark/reset and return false for markSupported() (which is fine with me too since it fixes my use case, I just assumed a more subtle solution would be preferred :)).
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 do see your point and let me rephrase it to make sure I understand: Either we should implement the mark/reset APIs properly or we should implement markSupported() to return false.
My concern remains for this use case, today:
With this change, my random calls to mark() before I read to the end of the stream cause the stream to remain open. Clearly a leak. Granted, I should close a stream that I open somewhere or in a try-with-resources block but this class lives outside of this use case.
It seems to me like the simplest solution would be for markSupported() to return false. WDYT? Or create a new 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.
My main point is that it cannot stay like it currently is.
So yes if you want to be sure mark() can be a random mistake then mark/reset should throw an exception and markSupported() should always return false.
I can change my pull request in that directly, no problem. Both works.