Skip to content

Commit

Permalink
[#4593] Improper Resource Shutdown or Release in LoaderImpl
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaseder committed Oct 7, 2015
1 parent 567de0a commit 5f371fa
Showing 1 changed file with 94 additions and 33 deletions.
127 changes: 94 additions & 33 deletions jOOQ/src/main/java/org/jooq/impl/LoaderImpl.java
Expand Up @@ -43,8 +43,6 @@
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
Expand Down Expand Up @@ -146,7 +144,7 @@ class LoaderImpl<R extends TableRecord<R>> implements
private int bulk = BULK_NONE; private int bulk = BULK_NONE;
private int bulkAfter = 1; private int bulkAfter = 1;
private int content = CONTENT_CSV; private int content = CONTENT_CSV;
private BufferedReader data; private final InputDelay data = new InputDelay();
private Iterator<? extends Object[]> arrays; private Iterator<? extends Object[]> arrays;


// CSV configuration data // CSV configuration data
Expand Down Expand Up @@ -322,23 +320,28 @@ public final Object[] map(Record value) {
} }


@Override @Override
public final LoaderImpl<R> loadCSV(File file) throws FileNotFoundException { public final LoaderImpl<R> loadCSV(File file) {
return loadCSV(new FileReader(file)); content = CONTENT_CSV;
data.file = file;
return this;
} }


@Override @Override
public final LoaderImpl<R> loadCSV(File file, String charsetName) throws FileNotFoundException, UnsupportedEncodingException { public final LoaderImpl<R> loadCSV(File file, String charsetName) {
return loadCSV(new FileInputStream(file), charsetName); data.charsetName = charsetName;
return loadCSV(file);
} }


@Override @Override
public final LoaderImpl<R> loadCSV(File file, Charset cs) throws FileNotFoundException { public final LoaderImpl<R> loadCSV(File file, Charset cs) {
return loadCSV(new FileInputStream(file), cs); data.cs = cs;
return loadCSV(file);
} }


@Override @Override
public final LoaderImpl<R> loadCSV(File file, CharsetDecoder dec) throws FileNotFoundException { public final LoaderImpl<R> loadCSV(File file, CharsetDecoder dec) {
return loadCSV(new FileInputStream(file), dec); data.dec = dec;
return loadCSV(file);
} }


@Override @Override
Expand Down Expand Up @@ -369,28 +372,33 @@ public final LoaderImpl<R> loadCSV(InputStream stream, CharsetDecoder dec) {
@Override @Override
public final LoaderImpl<R> loadCSV(Reader reader) { public final LoaderImpl<R> loadCSV(Reader reader) {
content = CONTENT_CSV; content = CONTENT_CSV;
data = new BufferedReader(reader); data.reader = new BufferedReader(reader);
return this; return this;
} }


@Override @Override
public final LoaderImpl<R> loadXML(File file) throws FileNotFoundException { public final LoaderImpl<R> loadXML(File file) {
return loadXML(new FileReader(file)); content = CONTENT_XML;
data.file = file;
return this;
} }


@Override @Override
public final LoaderImpl<R> loadXML(File file, String charsetName) throws FileNotFoundException, UnsupportedEncodingException { public final LoaderImpl<R> loadXML(File file, String charsetName) {
return loadXML(new FileInputStream(file), charsetName); data.charsetName = charsetName;
return loadXML(file);
} }


@Override @Override
public final LoaderImpl<R> loadXML(File file, Charset cs) throws FileNotFoundException { public final LoaderImpl<R> loadXML(File file, Charset cs) {
return loadXML(new FileInputStream(file), cs); data.cs = cs;
return loadXML(file);
} }


@Override @Override
public final LoaderImpl<R> loadXML(File file, CharsetDecoder dec) throws FileNotFoundException { public final LoaderImpl<R> loadXML(File file, CharsetDecoder dec) {
return loadXML(new FileInputStream(file), dec); data.dec = dec;
return loadXML(file);
} }


@Override @Override
Expand Down Expand Up @@ -431,23 +439,28 @@ public final LoaderImpl<R> loadXML(InputSource source) {
} }


@Override @Override
public final LoaderImpl<R> loadJSON(File file) throws FileNotFoundException { public final LoaderImpl<R> loadJSON(File file) {
return loadJSON(new FileReader(file)); content = CONTENT_JSON;
data.file = file;
return this;
} }


@Override @Override
public final LoaderImpl<R> loadJSON(File file, String charsetName) throws FileNotFoundException, UnsupportedEncodingException { public final LoaderImpl<R> loadJSON(File file, String charsetName) {
return loadJSON(new FileInputStream(file), charsetName); data.charsetName = charsetName;
return loadJSON(file);
} }


@Override @Override
public final LoaderImpl<R> loadJSON(File file, Charset cs) throws FileNotFoundException { public final LoaderImpl<R> loadJSON(File file, Charset cs) {
return loadJSON(new FileInputStream(file), cs); data.cs = cs;
return loadJSON(file);
} }


@Override @Override
public final LoaderImpl<R> loadJSON(File file, CharsetDecoder dec) throws FileNotFoundException { public final LoaderImpl<R> loadJSON(File file, CharsetDecoder dec) {
return loadJSON(new FileInputStream(file), dec); data.dec = dec;
return loadJSON(file);
} }


@Override @Override
Expand Down Expand Up @@ -478,7 +491,7 @@ public final LoaderImpl<R> loadJSON(InputStream stream, CharsetDecoder dec) {
@Override @Override
public final LoaderImpl<R> loadJSON(Reader reader) { public final LoaderImpl<R> loadJSON(Reader reader) {
content = CONTENT_JSON; content = CONTENT_JSON;
data = new BufferedReader(reader); data.reader = new BufferedReader(reader);
return this; return this;
} }


Expand Down Expand Up @@ -585,9 +598,10 @@ private void checkFlags() {
} }


private void executeJSON() throws IOException { private void executeJSON() throws IOException {
JSONReader reader = new JSONReader(data); JSONReader reader = null;


try { try {
reader = new JSONReader(data.reader());


// The current json format is not designed for streaming. Thats why // The current json format is not designed for streaming. Thats why
// all records are loaded at once. // all records are loaded at once.
Expand All @@ -601,14 +615,16 @@ private void executeJSON() throws IOException {
throw Utils.translate(null, e); throw Utils.translate(null, e);
} }
finally { finally {
reader.close(); if (reader != null)
reader.close();
} }
} }


private final void executeCSV() throws IOException { private final void executeCSV() throws IOException {
CSVReader reader = new CSVReader(data, separator, quote, ignoreRows); CSVReader reader = null;


try { try {
reader = new CSVReader(data.reader(), separator, quote, ignoreRows);
executeSQL(reader); executeSQL(reader);
} }


Expand All @@ -618,7 +634,8 @@ private final void executeCSV() throws IOException {
throw Utils.translate(null, e); throw Utils.translate(null, e);
} }
finally { finally {
reader.close(); if (reader != null)
reader.close();
} }
} }


Expand Down Expand Up @@ -899,4 +916,48 @@ public final int stored() {
return stored; return stored;
} }
} }

/**
* An "input delay" type.
* <p>
* [#4593] To make sure we do not spill file handles due to improper
* resource shutdown (e.g. when a loader is created but never executed),
* this type helps delaying creating resources from input until the input is
* really needed.
*/
private class InputDelay {

// Either, we already have an external Reader resource, in case of which
// client code is responsible for resource management...
BufferedReader reader;

// ... or we create the resource explicitly as late as possible
File file;
String charsetName;
Charset cs;
CharsetDecoder dec;

BufferedReader reader() throws IOException {
if (reader != null)
return reader;

if (file != null) {
try {
if (charsetName != null)
return new BufferedReader(new InputStreamReader(new FileInputStream(file), charsetName));
else if (cs != null)
return new BufferedReader(new InputStreamReader(new FileInputStream(file), cs));
else if (dec != null)
return new BufferedReader(new InputStreamReader(new FileInputStream(file), dec));
else
return new BufferedReader(new InputStreamReader(new FileInputStream(file)));
}
catch (Exception e) {
throw new IOException(e);
}
}

return null;
}
}
} }

0 comments on commit 5f371fa

Please sign in to comment.