Skip to content

Instantly share code, notes, and snippets.

@sirolf2009
Last active February 26, 2019 13:50
Show Gist options
  • Save sirolf2009/534baca5a598a2b7f8bf5653c0ec302a to your computer and use it in GitHub Desktop.
Save sirolf2009/534baca5a598a2b7f8bf5653c0ec302a to your computer and use it in GitHub Desktop.
WarningInputStream is an InputStream that you can wrap around another InputStream. It's purpose is
private void closeLingeringResources() { //make sure to run this at the end of whatever you're running. It should be part of a cleanup phase.
final List<InputStreamDescriptor> streams = new ArrayList<>();
WarningInputStream.retrieveAndClearInputs().forEach(value -> {
log.error("A resource was not closed\n" + value.describe());
streams.add(value);
});
streams.forEach(value -> {
getClosingService().submit(() -> {
try {
value.getStream().close();
} catch(final IOException e) {
log.error("Could not close resource:\n"+value.describe(), e);
}
});
});
}
Feb 26 14:45:02 pebi.northpool.pvt java[19735]: ERROR 2019-02-26 14:45:02,500 [pool-1-thread-1] nl.northpool.scraper.GenericScraper:lambda$closeLingeringResources$1(165): A resource was not closed
Feb 26 14:45:02 pebi.northpool.pvt java[19735]: regelleistung-mrl
Feb 26 14:45:02 pebi.northpool.pvt java[19735]: at Thread.java:1559 getStackTrace
Feb 26 14:45:02 pebi.northpool.pvt java[19735]: at WarningInputStream.java:27 register
Feb 26 14:45:02 pebi.northpool.pvt java[19735]: at WarningInputStream.java:22 <init>
Feb 26 14:45:02 pebi.northpool.pvt java[19735]: at GenericScraper.java:187 readVersion
Feb 26 14:45:02 pebi.northpool.pvt java[19735]: at GenericScraper.java:81 <init>
Feb 26 14:45:02 pebi.northpool.pvt java[19735]: at GenericHTMLScraper.java:35 <init>
Feb 26 14:45:02 pebi.northpool.pvt java[19735]: at RegelleistungScraper.java:48 <init>
Feb 26 14:45:02 pebi.northpool.pvt java[19735]: at RegelleistungScraper.java:44 <init>
Feb 26 14:45:02 pebi.northpool.pvt java[19735]: at ServletRegelleistungMRL.java:22 initScraper
try(WarningInputStream in = new WarningInputStream(conn.getInputStream())) { //should this stream not close for some reason, you would figure that out when calling closeLingeringResources()
String xml = IOUtils.toString(saveInput(in, name), Charset.defaultCharset());
return XmlUtil.parse(xml);
}
package nl.northpool.scraper;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class WarningInputStream extends InputStream implements AutoCloseable {
private static Map<UUID, InputStreamDescriptor> inputs = new HashMap<>();
final InputStream stream;
final UUID id;
public WarningInputStream(InputStream stream) {
this.stream = stream;
this.id = UUID.randomUUID();
register();
}
private synchronized void register() {
final Thread t = Thread.currentThread();
inputs.put(id, new InputStreamDescriptor(t.getName(), t.getStackTrace(), this));
}
public static synchronized List<InputStreamDescriptor> retrieveAndClearInputs() {
List<InputStreamDescriptor> values = new ArrayList<>(inputs.values());
inputs.values().clear();
return values;
}
@Override
public int read() throws IOException {
return stream.read();
}
@Override
public int available() throws IOException {
return stream.available();
}
@Override
public void close() throws IOException {
inputs.remove(id);
stream.close();
}
public static class InputStreamDescriptor {
private final String threadName;
private final StackTraceElement[] elements;
private final WarningInputStream stream;
public InputStreamDescriptor(String threadName, StackTraceElement[] elements, WarningInputStream stream) {
this.threadName = threadName;
this.elements = elements;
this.stream = stream;
}
public String describe() {
final StringBuffer buffer = new StringBuffer(threadName + "\n");
for(final StackTraceElement trace : elements) {
buffer.append("\tat " + trace.getFileName() + ":" + trace.getLineNumber() + " " + trace.getMethodName() + "\n");
}
return buffer.toString();
}
@Override
public String toString() {
return "InputStreamDescriptor [threadName=" + threadName + ", elements=" + Arrays.toString(elements) + ", stream=" + stream + "]";
}
public String getThreadName() {
return threadName;
}
public StackTraceElement[] getElements() {
return elements;
}
public WarningInputStream getStream() {
return stream;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment