Did codacy suggestions

This commit is contained in:
U-BASIS\dsmyda 2018-11-12 09:07:29 -05:00
parent b1708f777e
commit d8e65c70e7
2 changed files with 78 additions and 97 deletions

View File

@ -41,30 +41,30 @@ import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Reads row by row through SQLite tables and performs user-defined actions on the row values. * Reads row by row through SQLite tables and performs user-defined actions on
* Table values are processed by data type. Users configure these actions for certain data types * the row values. Table values are processed by data type. Users configure
* in the Builder. Example usage: * these actions for certain data types in the Builder. Example usage:
* *
* SQLiteTableReader reader = new SQLiteTableReader.Builder(file) * SQLiteTableReader reader = new SQLiteTableReader.Builder(file)
* .onInteger((i) -> { * .onInteger((i)
* System.out.println(i); * -> { System.out.println(i); })
* }).build(); * .build();
* reader.read(tableName);
* *
* or * reader.read(tableName);
* *
* SQLiteTableReader reader = new SQLiteTableReader.Builder(file) * or
* .onInteger(new Consumer<Integer>() {
* @Override
* public void accept(Integer i) {
* System.out.println(i);
* }
* }).build();
* reader.reader(tableName);
* *
* Invocation of read(String tableName) causes that table name to be processed row by row. * SQLiteTableReader reader = new SQLiteTableReader.Builder(file)
* When an Integer is encountered, its value will be passed to the Consumer that * .onInteger(new Consumer<Integer>() {
* was defined above. * @Override public void accept(Integer i) {
* System.out.println(i);
* }
* }).build();
*
* reader.reader(tableName);
*
* Invocation of read(String tableName) reads row by row. When an Integer is
* encountered, its value will be passed to the Consumer that was defined above.
*/ */
public class SQLiteTableReader implements AutoCloseable { public class SQLiteTableReader implements AutoCloseable {
@ -74,8 +74,8 @@ public class SQLiteTableReader implements AutoCloseable {
public static class Builder { public static class Builder {
private final AbstractFile file; private final AbstractFile file;
private Consumer<String> onColumnNameAction;
private Consumer<String> onColumnNameAction;
private Consumer<String> onStringAction; private Consumer<String> onStringAction;
private Consumer<Long> onLongAction; private Consumer<Long> onLongAction;
private Consumer<Integer> onIntegerAction; private Consumer<Integer> onIntegerAction;
@ -83,6 +83,10 @@ public class SQLiteTableReader implements AutoCloseable {
private Consumer<byte[]> onBlobAction; private Consumer<byte[]> onBlobAction;
private Consumer<Object> forAllAction; private Consumer<Object> forAllAction;
static <T> Consumer<T> doNothing() {
return NOOP -> {};
}
/** /**
* Creates a Builder for this abstract file. * Creates a Builder for this abstract file.
* *
@ -90,6 +94,14 @@ public class SQLiteTableReader implements AutoCloseable {
*/ */
public Builder(AbstractFile file) { public Builder(AbstractFile file) {
this.file = file; this.file = file;
this.onColumnNameAction = Builder.doNothing();
this.onStringAction = Builder.doNothing();
this.onLongAction = Builder.doNothing();
this.onIntegerAction = Builder.doNothing();
this.onFloatAction = Builder.doNothing();
this.onBlobAction = Builder.doNothing();
this.forAllAction = Builder.doNothing();
} }
/** /**
@ -196,61 +208,32 @@ public class SQLiteTableReader implements AutoCloseable {
} }
private final AbstractFile file; private final AbstractFile file;
private final Builder builder;
private final String SELECT_ALL_QUERY = "SELECT * FROM \"%s\"";
private Connection conn; private Connection conn;
private PreparedStatement statement; private PreparedStatement statement;
private ResultSet queryResults; private ResultSet queryResults;
private ResultSetMetaData currentMetadata;
private final Consumer<String> onColumnNameAction; //Iteration state
private final Consumer<String> onStringAction;
private final Consumer<Long> onLongAction;
private final Consumer<Integer> onIntegerAction;
private final Consumer<Double> onFloatAction;
private final Consumer<byte[]> onBlobAction;
private final Consumer<Object> forAllAction;
//Iteration state variables
private int currRowColumnIndex; private int currRowColumnIndex;
private int columnNameIndex; private int columnNameIndex;
private int totalColumnCount; private int totalColumnCount;
private boolean unfinishedRow; private boolean unfinishedRow;
private ResultSetMetaData currentMetadata;
private boolean liveResultSet; private boolean liveResultSet;
private String prevTableName; private String prevTableName;
/** /**
* Assigns references to each action based on the Builder configuration. * Holds reference to the builder instance so that we can use its actions
* during iteration.
*/ */
private SQLiteTableReader(Builder builder) { private SQLiteTableReader(Builder builder) {
this.builder = builder;
this.onColumnNameAction = nonNullValue(builder.onColumnNameAction);
this.onStringAction = nonNullValue(builder.onStringAction);
this.onIntegerAction = nonNullValue(builder.onIntegerAction);
this.onLongAction = nonNullValue(builder.onLongAction);
this.onFloatAction = nonNullValue(builder.onFloatAction);
this.onBlobAction = nonNullValue(builder.onBlobAction);
this.forAllAction = nonNullValue(builder.forAllAction);
this.file = builder.file; this.file = builder.file;
} }
/**
* Ensures the action is null safe. If action is left null, then during
* iteration null checks would be necessary. To mitigate against that, no-op
* lambdas are substituted for null values.
*
* @param <T> Generic type of consumer
* @param action Consumer for generic type, supplied by Builder.
*
* @return If action is null, then a no-op lambda, if not then the action
* itself.
*/
private <T> Consumer<T> nonNullValue(Consumer<T> action) {
return (Objects.nonNull(action)) ? action : NO_OP -> {
};
}
/** /**
* Fetches all table names from the database. * Fetches all table names from the database.
* *
@ -306,8 +289,7 @@ public class SQLiteTableReader implements AutoCloseable {
public int getColumnCount(String tableName) throws SQLiteTableReaderException { public int getColumnCount(String tableName) throws SQLiteTableReaderException {
ensureOpen(); ensureOpen();
try (ResultSet columnCount = conn.createStatement() try (ResultSet columnCount = conn.createStatement()
.executeQuery("SELECT * FROM " .executeQuery(String.format(SELECT_ALL_QUERY, tableName))) {
+ "\"" + tableName + "\"")) {
return columnCount.getMetaData().getColumnCount(); return columnCount.getMetaData().getColumnCount();
} catch (SQLException ex) { } catch (SQLException ex) {
throw new SQLiteTableReaderException(ex); throw new SQLiteTableReaderException(ex);
@ -325,23 +307,24 @@ public class SQLiteTableReader implements AutoCloseable {
* @throws SQLiteTableReaderException * @throws SQLiteTableReaderException
*/ */
public void read(String tableName) throws SQLiteTableReaderException { public void read(String tableName) throws SQLiteTableReaderException {
readHelper("SELECT * FROM \"" + tableName + "\"", () -> false); readHelper(String.format(SELECT_ALL_QUERY, tableName), () -> false);
} }
/** /**
* Reads column names and values from the table. Only actions that were * Reads column names and values from the table. Only actions that were
* configured in the Builder will be invoked during iteration. Iteration will stop * configured in the Builder will be invoked during iteration. Iteration
* when the table read has completed or an exception was encountered. * will stop when the table read has completed or an exception was
* encountered.
* *
* @param tableName Source table to perform a read * @param tableName Source table to perform a read
* @param limit Number of rows to read from the table * @param limit Number of rows to read from the table
* @param offset Starting row to read from in the table * @param offset Starting row to read from in the table
* *
* @throws SQLiteTableReaderException * @throws SQLiteTableReaderException
* *
*/ */
public void read(String tableName, int limit, int offset) throws SQLiteTableReaderException { public void read(String tableName, int limit, int offset) throws SQLiteTableReaderException {
readHelper("SELECT * FROM \"" + tableName + "\" LIMIT " + limit readHelper(String.format(SELECT_ALL_QUERY, tableName)+ " LIMIT " + limit
+ " OFFSET " + offset, () -> false); + " OFFSET " + offset, () -> false);
} }
@ -356,18 +339,16 @@ public class SQLiteTableReader implements AutoCloseable {
* *
*/ */
public void read(String tableName, BooleanSupplier condition) throws SQLiteTableReaderException { public void read(String tableName, BooleanSupplier condition) throws SQLiteTableReaderException {
if (Objects.nonNull(prevTableName) && prevTableName.equals(tableName)) { if (Objects.isNull(prevTableName) || !prevTableName.equals(tableName)) {
readHelper("SELECT * FROM \"" + tableName + "\"", condition);
} else {
prevTableName = tableName; prevTableName = tableName;
closeTableResources(); closeTableResources();
readHelper("SELECT * FROM \"" + tableName + "\"", condition);
} }
readHelper(String.format(SELECT_ALL_QUERY, tableName), condition);
} }
/** /**
* Performs the result set iteration and is responsible for maintaining state * Performs the result set iteration and is responsible for maintaining
* of the read over multiple invocations. * state of the read over multiple invocations.
* *
* @throws SQLiteTableReaderException * @throws SQLiteTableReaderException
*/ */
@ -379,16 +360,16 @@ public class SQLiteTableReader implements AutoCloseable {
} }
//Process column names before reading the database table values //Process column names before reading the database table values
while(columnNameIndex < totalColumnCount) { while (columnNameIndex < totalColumnCount) {
if (condition.getAsBoolean()) { if (condition.getAsBoolean()) {
return; return;
} }
this.onColumnNameAction.accept(currentMetadata builder.onColumnNameAction.accept(currentMetadata
.getColumnName(++columnNameIndex)); .getColumnName(++columnNameIndex));
} }
while (unfinishedRow || queryResults.next()) { while (unfinishedRow || queryResults.next()) {
while(currRowColumnIndex < totalColumnCount) { while (currRowColumnIndex < totalColumnCount) {
if (condition.getAsBoolean()) { if (condition.getAsBoolean()) {
unfinishedRow = true; unfinishedRow = true;
return; return;
@ -396,18 +377,18 @@ public class SQLiteTableReader implements AutoCloseable {
Object item = queryResults.getObject(++currRowColumnIndex); Object item = queryResults.getObject(++currRowColumnIndex);
if (item instanceof String) { if (item instanceof String) {
this.onStringAction.accept((String) item); builder.onStringAction.accept((String) item);
} else if (item instanceof Integer) { } else if (item instanceof Integer) {
this.onIntegerAction.accept((Integer) item); builder.onIntegerAction.accept((Integer) item);
} else if (item instanceof Double) { } else if (item instanceof Double) {
this.onFloatAction.accept((Double) item); builder.onFloatAction.accept((Double) item);
} else if (item instanceof Long) { } else if (item instanceof Long) {
this.onLongAction.accept((Long) item); builder.onLongAction.accept((Long) item);
} else if (item instanceof byte[]) { } else if (item instanceof byte[]) {
this.onBlobAction.accept((byte[]) item); builder.onBlobAction.accept((byte[]) item);
} }
this.forAllAction.accept(item); builder.forAllAction.accept(item);
} }
unfinishedRow = false; unfinishedRow = false;
//Wrap column index back around if we've reached the end of the row //Wrap column index back around if we've reached the end of the row
@ -480,18 +461,18 @@ public class SQLiteTableReader implements AutoCloseable {
* directory. * directory.
* *
* @param file AbstractFile from the data source * @param file AbstractFile from the data source
* @param id The input files id value * @param id The input files id value
* *
* @return The path of the file on disk * @return The path of the file on disk
* *
* @throws IOException Exception writing file contents * @throws IOException Exception writing file contents
* @throws NoCurrentCaseException Current case closed during file copying * @throws NoCurrentCaseException Current case closed during file copying
*/ */
private String copyFileToTempDirectory(AbstractFile file, long id) private String copyFileToTempDirectory(AbstractFile file, long fileId)
throws IOException, NoCurrentCaseException { throws IOException, NoCurrentCaseException {
String localDiskPath = Case.getCurrentCaseThrows().getTempDirectory() String localDiskPath = Case.getCurrentCaseThrows().getTempDirectory()
+ File.separator + id + file.getName(); + File.separator + fileId + file.getName();
File localDatabaseFile = new File(localDiskPath); File localDatabaseFile = new File(localDiskPath);
if (!localDatabaseFile.exists()) { if (!localDatabaseFile.exists()) {
ContentUtils.writeToFile(file, localDatabaseFile); ContentUtils.writeToFile(file, localDatabaseFile);
@ -568,12 +549,12 @@ public class SQLiteTableReader implements AutoCloseable {
* @throws Throwable * @throws Throwable
*/ */
@Override @Override
public void finalize() throws Throwable { protected void finalize() throws Throwable {
super.finalize();
try { try {
close(); close();
} catch (SQLiteTableReaderException ex) { } catch (SQLiteTableReaderException ex) {
//Do nothing, we tried out best to close the connection. //Do nothing, we tried out best to close the connection.
} }
super.finalize();
} }
} }

View File

@ -27,18 +27,18 @@ public class SQLiteTableReaderException extends Exception {
* Accepts both a message and a parent exception. * Accepts both a message and a parent exception.
* *
* @param msg Message detailing the cause * @param msg Message detailing the cause
* @param ex Parent exception * @param parentEx Parent exception
*/ */
public SQLiteTableReaderException(String msg, Throwable ex) { public SQLiteTableReaderException(String msg, Throwable parentEx) {
super(msg, ex); super(msg, parentEx);
} }
/** /**
* Accepts only a parent exception. * Accepts only a parent exception.
* *
* @param ex Parent exception * @param parentEx Parent exception
*/ */
public SQLiteTableReaderException(Throwable ex) { public SQLiteTableReaderException(Throwable parentEx) {
super(ex); super(parentEx);
} }
} }