mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
Merge pull request #3861 from APriestman/3888_refactorOtherOccurrences
3888 Refactor other occurrences table
This commit is contained in:
commit
f6d533a966
@ -83,8 +83,13 @@ public final class AddEditCentralRepoCommentAction extends AbstractAction {
|
|||||||
* comment. The comment will be updated in the database if the file instance
|
* comment. The comment will be updated in the database if the file instance
|
||||||
* exists there, or a new file instance will be added to the database with
|
* exists there, or a new file instance will be added to the database with
|
||||||
* the comment attached otherwise.
|
* the comment attached otherwise.
|
||||||
|
*
|
||||||
|
* The current comment for this instance is returned in case it is needed to
|
||||||
|
* update the display.
|
||||||
|
*
|
||||||
|
* @return the current comment for this instance
|
||||||
*/
|
*/
|
||||||
public void addEditCentralRepoComment() {
|
public String addEditCentralRepoComment() {
|
||||||
CentralRepoCommentDialog centralRepoCommentDialog = new CentralRepoCommentDialog(correlationAttribute, title);
|
CentralRepoCommentDialog centralRepoCommentDialog = new CentralRepoCommentDialog(correlationAttribute, title);
|
||||||
centralRepoCommentDialog.display();
|
centralRepoCommentDialog.display();
|
||||||
|
|
||||||
@ -103,6 +108,7 @@ public final class AddEditCentralRepoCommentAction extends AbstractAction {
|
|||||||
logger.log(Level.SEVERE, "Error connecting to Central Repository database.", ex);
|
logger.log(Level.SEVERE, "Error connecting to Central Repository database.", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return centralRepoCommentDialog.getComment();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,6 +31,7 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog {
|
|||||||
|
|
||||||
private final CorrelationAttribute correlationAttribute;
|
private final CorrelationAttribute correlationAttribute;
|
||||||
private boolean commentUpdated = false;
|
private boolean commentUpdated = false;
|
||||||
|
private String currentComment = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance.
|
* Create an instance.
|
||||||
@ -45,6 +46,11 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog {
|
|||||||
|
|
||||||
CorrelationAttributeInstance instance = correlationAttribute.getInstances().get(0);
|
CorrelationAttributeInstance instance = correlationAttribute.getInstances().get(0);
|
||||||
|
|
||||||
|
// Store the original comment
|
||||||
|
if (instance.getComment() != null) {
|
||||||
|
currentComment = instance.getComment();
|
||||||
|
}
|
||||||
|
|
||||||
pathLabel.setText(instance.getFilePath());
|
pathLabel.setText(instance.getFilePath());
|
||||||
commentTextArea.setText(instance.getComment());
|
commentTextArea.setText(instance.getComment());
|
||||||
|
|
||||||
@ -72,6 +78,16 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog {
|
|||||||
return commentUpdated;
|
return commentUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current comment.
|
||||||
|
* If the user hit OK, this will be the new comment.
|
||||||
|
* If the user canceled, this will be the original comment.
|
||||||
|
* @return the comment
|
||||||
|
*/
|
||||||
|
String getComment() {
|
||||||
|
return currentComment;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called from within the constructor to initialize the form.
|
* This method is called from within the constructor to initialize the form.
|
||||||
* WARNING: Do NOT modify this code. The content of this method is always
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
@ -168,8 +184,8 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog {
|
|||||||
}//GEN-LAST:event_cancelButtonActionPerformed
|
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||||
|
|
||||||
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||||
String comment = commentTextArea.getText();
|
currentComment = commentTextArea.getText();
|
||||||
correlationAttribute.getInstances().get(0).setComment(comment);
|
correlationAttribute.getInstances().get(0).setComment(currentComment);
|
||||||
commentUpdated = true;
|
commentUpdated = true;
|
||||||
|
|
||||||
dispose();
|
dispose();
|
||||||
|
@ -56,7 +56,6 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
|
|||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource;
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
@ -69,7 +68,6 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
|||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskData;
|
import org.sleuthkit.datamodel.TskData;
|
||||||
import org.sleuthkit.datamodel.TskDataException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View correlation results from other cases
|
* View correlation results from other cases
|
||||||
@ -119,10 +117,15 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
} else if (jmi.equals(showCommonalityMenuItem)) {
|
} else if (jmi.equals(showCommonalityMenuItem)) {
|
||||||
showCommonalityDetails();
|
showCommonalityDetails();
|
||||||
} else if (jmi.equals(addCommentMenuItem)) {
|
} else if (jmi.equals(addCommentMenuItem)) {
|
||||||
CorrelationAttribute selectedAttribute = (CorrelationAttribute) tableModel.getRow(otherCasesTable.getSelectedRow());
|
try {
|
||||||
AddEditCentralRepoCommentAction action = AddEditCentralRepoCommentAction.createAddEditCommentAction(selectedAttribute);
|
OtherOccurrenceNodeData selectedNode = (OtherOccurrenceNodeData) tableModel.getRow(otherCasesTable.getSelectedRow());
|
||||||
action.addEditCentralRepoComment();
|
AddEditCentralRepoCommentAction action = AddEditCentralRepoCommentAction.createAddEditCommentAction(selectedNode.createCorrelationAttribute());
|
||||||
otherCasesTable.repaint();
|
String currentComment = action.addEditCentralRepoComment();
|
||||||
|
selectedNode.updateComment(currentComment);
|
||||||
|
otherCasesTable.repaint();
|
||||||
|
} catch (EamDbException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error performing Add/Edit Comment action", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -202,8 +205,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
if (-1 != selectedRowViewIdx) {
|
if (-1 != selectedRowViewIdx) {
|
||||||
EamDb dbManager = EamDb.getInstance();
|
EamDb dbManager = EamDb.getInstance();
|
||||||
int selectedRowModelIdx = otherCasesTable.convertRowIndexToModel(selectedRowViewIdx);
|
int selectedRowModelIdx = otherCasesTable.convertRowIndexToModel(selectedRowViewIdx);
|
||||||
CorrelationAttribute eamArtifact = (CorrelationAttribute) tableModel.getRow(selectedRowModelIdx);
|
OtherOccurrenceNodeData nodeData = (OtherOccurrenceNodeData) tableModel.getRow(selectedRowModelIdx);
|
||||||
CorrelationCase eamCasePartial = eamArtifact.getInstances().get(0).getCorrelationCase();
|
CorrelationCase eamCasePartial = nodeData.getCorrelationAttributeInstance().getCorrelationCase();
|
||||||
if (eamCasePartial == null) {
|
if (eamCasePartial == null) {
|
||||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
||||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference(),
|
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference(),
|
||||||
@ -454,9 +457,10 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query the database for artifact instances from other cases correlated to
|
* Query the central repo database (if enabled) and the case database to find all
|
||||||
* the given central repository artifact. Instances from the same datasource
|
* artifact instances correlated to the given central repository artifact. If the
|
||||||
* / device will also be included.
|
* central repo is not enabled, this will only return files from the current case
|
||||||
|
* with matching MD5 hashes.
|
||||||
*
|
*
|
||||||
* @param corAttr CorrelationAttribute to query for
|
* @param corAttr CorrelationAttribute to query for
|
||||||
* @param dataSourceName Data source to filter results
|
* @param dataSourceName Data source to filter results
|
||||||
@ -464,33 +468,46 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
*
|
*
|
||||||
* @return A collection of correlated artifact instances
|
* @return A collection of correlated artifact instances
|
||||||
*/
|
*/
|
||||||
private Map<UniquePathKey, CorrelationAttributeInstance> getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) {
|
private Map<UniquePathKey,OtherOccurrenceNodeData> getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) {
|
||||||
// @@@ Check exception
|
// @@@ Check exception
|
||||||
try {
|
try {
|
||||||
final Case openCase = Case.getCurrentCase();
|
final Case openCase = Case.getCurrentCase();
|
||||||
String caseUUID = openCase.getName();
|
String caseUUID = openCase.getName();
|
||||||
String filePath = (file.getParentPath() + file.getName()).toLowerCase();
|
|
||||||
HashMap<UniquePathKey, CorrelationAttributeInstance> artifactInstances = new HashMap<>();
|
HashMap<UniquePathKey,OtherOccurrenceNodeData> nodeDataMap = new HashMap<>();
|
||||||
|
|
||||||
if (EamDb.isEnabled()) {
|
if (EamDb.isEnabled()) {
|
||||||
EamDb dbManager = EamDb.getInstance();
|
List<CorrelationAttributeInstance> instances = EamDb.getInstance().getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue());
|
||||||
artifactInstances.putAll(dbManager.getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue()).stream()
|
|
||||||
.filter(artifactInstance -> !artifactInstance.getFilePath().equals(filePath)
|
|
||||||
|| !artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID)
|
|
||||||
|| !artifactInstance.getCorrelationDataSource().getName().equals(dataSourceName)
|
|
||||||
|| !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId))
|
|
||||||
.collect(Collectors.toMap(correlationAttr -> new UniquePathKey(correlationAttr.getCorrelationDataSource().getDeviceID(), correlationAttr.getFilePath()),
|
|
||||||
correlationAttr -> correlationAttr)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
|
for (CorrelationAttributeInstance artifactInstance:instances) {
|
||||||
List<AbstractFile> caseDbFiles = addCaseDbMatches(corAttr, openCase);
|
|
||||||
for (AbstractFile caseDbFile : caseDbFiles) {
|
// Only add the attribute if it isn't the object the user selected.
|
||||||
addOrUpdateAttributeInstance(openCase, artifactInstances, caseDbFile);
|
// We consider it to be a different object if at least one of the following is true:
|
||||||
|
// - the case UUID is different
|
||||||
|
// - the data source name is different
|
||||||
|
// - the data source device ID is different
|
||||||
|
// - the file path is different
|
||||||
|
if (!artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID)
|
||||||
|
|| !artifactInstance.getCorrelationDataSource().getName().equals(dataSourceName)
|
||||||
|
|| !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId)
|
||||||
|
|| !artifactInstance.getFilePath().equalsIgnoreCase(file.getParentPath() + file.getName())) {
|
||||||
|
|
||||||
|
OtherOccurrenceNodeData newNode = new OtherOccurrenceNodeData(artifactInstance, corAttr.getCorrelationType(), corAttr.getCorrelationValue());
|
||||||
|
UniquePathKey uniquePathKey = new UniquePathKey(newNode);
|
||||||
|
nodeDataMap.put(uniquePathKey, newNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return artifactInstances;
|
if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
|
||||||
|
List<AbstractFile> caseDbFiles = getCaseDbMatches(corAttr, openCase);
|
||||||
|
|
||||||
|
for (AbstractFile caseDbFile : caseDbFiles) {
|
||||||
|
addOrUpdateNodeData(openCase, nodeDataMap, caseDbFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeDataMap;
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
logger.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
@ -504,7 +521,16 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
return new HashMap<>(0);
|
return new HashMap<>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<AbstractFile> addCaseDbMatches(CorrelationAttribute corAttr, Case openCase) throws NoCurrentCaseException, TskCoreException, EamDbException {
|
/**
|
||||||
|
* Get all other abstract files in the current case with the same MD5 as the selected node.
|
||||||
|
* @param corAttr The CorrelationAttribute containing the MD5 to search for
|
||||||
|
* @param openCase The current case
|
||||||
|
* @return List of matching AbstractFile objects
|
||||||
|
* @throws NoCurrentCaseException
|
||||||
|
* @throws TskCoreException
|
||||||
|
* @throws EamDbException
|
||||||
|
*/
|
||||||
|
private List<AbstractFile> getCaseDbMatches(CorrelationAttribute corAttr, Case openCase) throws NoCurrentCaseException, TskCoreException, EamDbException {
|
||||||
String md5 = corAttr.getCorrelationValue();
|
String md5 = corAttr.getCorrelationValue();
|
||||||
|
|
||||||
SleuthkitCase tsk = openCase.getSleuthkitCase();
|
SleuthkitCase tsk = openCase.getSleuthkitCase();
|
||||||
@ -522,75 +548,64 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the file to the artifactInstances map if it does not already exist
|
* Adds the file to the nodeDataMap map if it does not already exist
|
||||||
*
|
*
|
||||||
* @param autopsyCase
|
* @param autopsyCase
|
||||||
* @param artifactInstances
|
* @param nodeDataMap
|
||||||
* @param newFile
|
* @param newFile
|
||||||
*
|
*
|
||||||
* @throws TskCoreException
|
* @throws TskCoreException
|
||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
private void addOrUpdateAttributeInstance(final Case autopsyCase, Map<UniquePathKey, CorrelationAttributeInstance> artifactInstances, AbstractFile newFile) throws TskCoreException, EamDbException {
|
private void addOrUpdateNodeData(final Case autopsyCase, Map<UniquePathKey,OtherOccurrenceNodeData> nodeDataMap, AbstractFile newFile) throws TskCoreException, EamDbException {
|
||||||
|
|
||||||
// figure out if the casedb file is known via either hash or tags
|
OtherOccurrenceNodeData newNode = new OtherOccurrenceNodeData(newFile, autopsyCase);
|
||||||
TskData.FileKnown localKnown = newFile.getKnown();
|
|
||||||
|
|
||||||
if (localKnown != TskData.FileKnown.BAD) {
|
// If the caseDB object has a notable tag associated with it, update
|
||||||
|
// the known status to BAD
|
||||||
|
if (newNode.getKnown() != TskData.FileKnown.BAD) {
|
||||||
List<ContentTag> fileMatchTags = autopsyCase.getServices().getTagsManager().getContentTagsByContent(newFile);
|
List<ContentTag> fileMatchTags = autopsyCase.getServices().getTagsManager().getContentTagsByContent(newFile);
|
||||||
for (ContentTag tag : fileMatchTags) {
|
for (ContentTag tag : fileMatchTags) {
|
||||||
TskData.FileKnown tagKnownStatus = tag.getName().getKnownStatus();
|
TskData.FileKnown tagKnownStatus = tag.getName().getKnownStatus();
|
||||||
if (tagKnownStatus.equals(TskData.FileKnown.BAD)) {
|
if (tagKnownStatus.equals(TskData.FileKnown.BAD)) {
|
||||||
localKnown = TskData.FileKnown.BAD;
|
newNode.updateKnown(TskData.FileKnown.BAD);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make a key to see if the file is already in the map
|
// Make a key to see if the file is already in the map
|
||||||
String filePath = newFile.getParentPath() + newFile.getName();
|
UniquePathKey uniquePathKey = new UniquePathKey(newNode);
|
||||||
String deviceId;
|
|
||||||
try {
|
|
||||||
deviceId = autopsyCase.getSleuthkitCase().getDataSource(newFile.getDataSource().getId()).getDeviceId();
|
|
||||||
} catch (TskDataException | TskCoreException ex) {
|
|
||||||
logger.log(Level.WARNING, "Error getting data source info: {0}", ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
UniquePathKey uniquePathKey = new UniquePathKey(deviceId, filePath);
|
|
||||||
|
|
||||||
// double check that the CR version is BAD if the caseDB version is BAD.
|
// If this node is already in the list, the only thing we need to do is
|
||||||
if (artifactInstances.containsKey(uniquePathKey)) {
|
// update the known status to BAD if the caseDB version had known status BAD.
|
||||||
if (localKnown == TskData.FileKnown.BAD) {
|
// Otherwise this is a new node so add the new node to the map.
|
||||||
CorrelationAttributeInstance prevInstance = artifactInstances.get(uniquePathKey);
|
if (nodeDataMap.containsKey(uniquePathKey)) {
|
||||||
prevInstance.setKnownStatus(localKnown);
|
if (newNode.getKnown() == TskData.FileKnown.BAD) {
|
||||||
|
OtherOccurrenceNodeData prevInstance = nodeDataMap.get(uniquePathKey);
|
||||||
|
prevInstance.updateKnown(newNode.getKnown());
|
||||||
}
|
}
|
||||||
} // add the data from the case DB by pushing data into CorrelationAttributeInstance class
|
} else {
|
||||||
else {
|
nodeDataMap.put(uniquePathKey, newNode);
|
||||||
// NOTE: If we are in here, it is likely because CR is not enabled. So, we cannot rely
|
|
||||||
// on any of the methods that query the DB.
|
|
||||||
CorrelationCase correlationCase = new CorrelationCase(autopsyCase.getName(), autopsyCase.getDisplayName());
|
|
||||||
|
|
||||||
CorrelationDataSource correlationDataSource = CorrelationDataSource.fromTSKDataSource(correlationCase, newFile.getDataSource());
|
|
||||||
|
|
||||||
CorrelationAttributeInstance caseDbInstance = new CorrelationAttributeInstance(correlationCase, correlationDataSource, filePath, "", localKnown);
|
|
||||||
artifactInstances.put(uniquePathKey, caseDbInstance);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSupported(Node node) {
|
public boolean isSupported(Node node) {
|
||||||
this.file = this.getAbstractFileFromNode(node);
|
|
||||||
// Is supported if this node
|
|
||||||
// has correlatable content (File, BlackboardArtifact) OR
|
|
||||||
// other common files across datasources.
|
|
||||||
|
|
||||||
|
// Is supported if one of the following is true:
|
||||||
|
// - The central repo is enabled and the node has correlatable content
|
||||||
|
// (either through the MD5 hash of the associated file or through a BlackboardArtifact)
|
||||||
|
// - The central repo is disabled and the backing file has a valid MD5 hash
|
||||||
|
this.file = this.getAbstractFileFromNode(node);
|
||||||
if (EamDb.isEnabled()) {
|
if (EamDb.isEnabled()) {
|
||||||
return this.file != null
|
return this.file != null
|
||||||
&& this.file.getSize() > 0
|
&& this.file.getSize() > 0
|
||||||
&& !getCorrelationAttributesFromNode(node).isEmpty();
|
&& !getCorrelationAttributesFromNode(node).isEmpty();
|
||||||
} else {
|
} else {
|
||||||
return this.file != null
|
return this.file != null
|
||||||
&& this.file.getSize() > 0;
|
&& this.file.getSize() > 0
|
||||||
|
&& ((this.file.getMd5Hash() != null) && ( ! this.file.getMd5Hash().isEmpty()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,22 +647,14 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
// get the attributes we can correlate on
|
// get the attributes we can correlate on
|
||||||
correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
|
correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
|
||||||
for (CorrelationAttribute corAttr : correlationAttributes) {
|
for (CorrelationAttribute corAttr : correlationAttributes) {
|
||||||
Map<UniquePathKey, CorrelationAttributeInstance> corAttrInstances = new HashMap<>(0);
|
Map<UniquePathKey,OtherOccurrenceNodeData> correlatedNodeDataMap = new HashMap<>(0);
|
||||||
|
|
||||||
// get correlation and reference set instances from DB
|
// get correlation and reference set instances from DB
|
||||||
corAttrInstances.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
|
correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
|
||||||
|
|
||||||
|
correlatedNodeDataMap.values().forEach((nodeData) -> {
|
||||||
|
tableModel.addNodeData(nodeData);
|
||||||
|
|
||||||
corAttrInstances.values().forEach((corAttrInstance) -> {
|
|
||||||
try {
|
|
||||||
CorrelationAttribute newCeArtifact = new CorrelationAttribute(
|
|
||||||
corAttr.getCorrelationType(),
|
|
||||||
corAttr.getCorrelationValue()
|
|
||||||
);
|
|
||||||
newCeArtifact.addInstance(corAttrInstance);
|
|
||||||
tableModel.addEamArtifact(newCeArtifact);
|
|
||||||
} catch (EamDbException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Error creating correlation attribute", ex);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -816,18 +823,19 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
private void rightClickPopupMenuPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
|
private void rightClickPopupMenuPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
|
||||||
boolean addCommentMenuItemVisible = false;
|
boolean enableCentralRepoActions = false;
|
||||||
|
|
||||||
if (EamDbUtil.useCentralRepo() && otherCasesTable.getSelectedRowCount() == 1) {
|
if (EamDbUtil.useCentralRepo() && otherCasesTable.getSelectedRowCount() == 1) {
|
||||||
int rowIndex = otherCasesTable.getSelectedRow();
|
int rowIndex = otherCasesTable.getSelectedRow();
|
||||||
CorrelationAttribute selectedAttribute = (CorrelationAttribute) tableModel.getRow(rowIndex);
|
OtherOccurrenceNodeData selectedNode = (OtherOccurrenceNodeData) tableModel.getRow(rowIndex);
|
||||||
if (selectedAttribute.getInstances().get(0).isDatabaseInstance()
|
if (selectedNode.isCentralRepoNode()) {
|
||||||
&& selectedAttribute.getCorrelationType().getId() == CorrelationAttribute.FILES_TYPE_ID) {
|
enableCentralRepoActions = true;
|
||||||
addCommentMenuItemVisible = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addCommentMenuItem.setVisible(addCommentMenuItemVisible);
|
addCommentMenuItem.setVisible(enableCentralRepoActions);
|
||||||
|
showCaseDetailsMenuItem.setVisible(enableCentralRepoActions);
|
||||||
|
showCommonalityMenuItem.setVisible(enableCentralRepoActions);
|
||||||
}//GEN-LAST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
|
}//GEN-LAST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
@ -854,33 +862,26 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
|
|
||||||
private final String dataSourceID;
|
private final String dataSourceID;
|
||||||
private final String filePath;
|
private final String filePath;
|
||||||
|
private final String type;
|
||||||
|
|
||||||
UniquePathKey(String theDataSource, String theFilePath) {
|
UniquePathKey(OtherOccurrenceNodeData nodeData) {
|
||||||
super();
|
super();
|
||||||
dataSourceID = theDataSource;
|
dataSourceID = nodeData.getDeviceID();
|
||||||
filePath = theFilePath.toLowerCase();
|
if (nodeData.getFilePath() != null) {
|
||||||
}
|
filePath = nodeData.getFilePath().toLowerCase();
|
||||||
|
} else {
|
||||||
/**
|
filePath = null;
|
||||||
*
|
}
|
||||||
* @return the dataSourceID device ID
|
type = nodeData.getType();
|
||||||
*/
|
|
||||||
String getDataSourceID() {
|
|
||||||
return dataSourceID;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return the filPath including the filename and extension.
|
|
||||||
*/
|
|
||||||
String getFilePath() {
|
|
||||||
return filePath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (other instanceof UniquePathKey) {
|
if (other instanceof UniquePathKey) {
|
||||||
return ((UniquePathKey) other).getDataSourceID().equals(dataSourceID) && ((UniquePathKey) other).getFilePath().equals(filePath);
|
UniquePathKey otherKey = (UniquePathKey)(other);
|
||||||
|
return ( Objects.equals(otherKey.dataSourceID, this.dataSourceID)
|
||||||
|
&& Objects.equals(otherKey.filePath, this.filePath)
|
||||||
|
&& Objects.equals(otherKey.type, this.type));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -890,7 +891,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
//int hash = 7;
|
//int hash = 7;
|
||||||
//hash = 67 * hash + this.dataSourceID.hashCode();
|
//hash = 67 * hash + this.dataSourceID.hashCode();
|
||||||
//hash = 67 * hash + this.filePath.hashCode();
|
//hash = 67 * hash + this.filePath.hashCode();
|
||||||
return Objects.hash(dataSourceID, filePath);
|
return Objects.hash(dataSourceID, filePath, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,10 +68,10 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
List<CorrelationAttribute> eamArtifacts;
|
List<OtherOccurrenceNodeData> nodeDataList;
|
||||||
|
|
||||||
DataContentViewerOtherCasesTableModel() {
|
DataContentViewerOtherCasesTableModel() {
|
||||||
eamArtifacts = new ArrayList<>();
|
nodeDataList = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -95,7 +95,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRowCount() {
|
public int getRowCount() {
|
||||||
return eamArtifacts.size();
|
return nodeDataList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -105,15 +105,15 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValueAt(int rowIdx, int colIdx) {
|
public Object getValueAt(int rowIdx, int colIdx) {
|
||||||
if (0 == eamArtifacts.size()) {
|
if (0 == nodeDataList.size()) {
|
||||||
return Bundle.DataContentViewerOtherCasesTableModel_noData();
|
return Bundle.DataContentViewerOtherCasesTableModel_noData();
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapValueById(rowIdx, TableColumns.values()[colIdx]);
|
return mapValueById(rowIdx, TableColumns.values()[colIdx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getRow(int rowIdx) {
|
Object getRow(int rowIdx) {
|
||||||
return eamArtifacts.get(rowIdx);
|
return nodeDataList.get(rowIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,40 +125,39 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
* @return value in the cell
|
* @return value in the cell
|
||||||
*/
|
*/
|
||||||
private Object mapValueById(int rowIdx, TableColumns colId) {
|
private Object mapValueById(int rowIdx, TableColumns colId) {
|
||||||
CorrelationAttribute eamArtifact = eamArtifacts.get(rowIdx);
|
OtherOccurrenceNodeData nodeData = nodeDataList.get(rowIdx);
|
||||||
CorrelationAttributeInstance eamArtifactInstance = eamArtifact.getInstances().get(0);
|
|
||||||
String value = Bundle.DataContentViewerOtherCasesTableModel_noData();
|
String value = Bundle.DataContentViewerOtherCasesTableModel_noData();
|
||||||
|
|
||||||
switch (colId) {
|
switch (colId) {
|
||||||
case CASE_NAME:
|
case CASE_NAME:
|
||||||
if (null != eamArtifactInstance.getCorrelationCase()) {
|
if (null != nodeData.getCaseName()) {
|
||||||
value = eamArtifactInstance.getCorrelationCase().getDisplayName();
|
value = nodeData.getCaseName();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DEVICE:
|
case DEVICE:
|
||||||
if (null != eamArtifactInstance.getCorrelationDataSource()) {
|
if (null != nodeData.getDeviceID()) {
|
||||||
value = eamArtifactInstance.getCorrelationDataSource().getDeviceID();
|
value = nodeData.getDeviceID();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DATA_SOURCE:
|
case DATA_SOURCE:
|
||||||
if (null != eamArtifactInstance.getCorrelationDataSource()) {
|
if (null != nodeData.getDataSourceName()) {
|
||||||
value = eamArtifactInstance.getCorrelationDataSource().getName();
|
value = nodeData.getDataSourceName();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FILE_PATH:
|
case FILE_PATH:
|
||||||
value = eamArtifactInstance.getFilePath();
|
value = nodeData.getFilePath();
|
||||||
break;
|
break;
|
||||||
case TYPE:
|
case TYPE:
|
||||||
value = eamArtifact.getCorrelationType().getDisplayName();
|
value = nodeData.getType();
|
||||||
break;
|
break;
|
||||||
case VALUE:
|
case VALUE:
|
||||||
value = eamArtifact.getCorrelationValue();
|
value = nodeData.getValue();
|
||||||
break;
|
break;
|
||||||
case KNOWN:
|
case KNOWN:
|
||||||
value = eamArtifactInstance.getKnownStatus().getName();
|
value = nodeData.getKnown().getName();
|
||||||
break;
|
break;
|
||||||
case COMMENT:
|
case COMMENT:
|
||||||
value = eamArtifactInstance.getComment();
|
value = nodeData.getComment();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
@ -170,18 +169,17 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add one local central repository artifact to the table.
|
* Add one correlated instance object to the table
|
||||||
*
|
*
|
||||||
* @param eamArtifact central repository artifact to add to the
|
* @param newNodeData data to add to the table
|
||||||
* table
|
|
||||||
*/
|
*/
|
||||||
public void addEamArtifact(CorrelationAttribute eamArtifact) {
|
void addNodeData(OtherOccurrenceNodeData newNodeData) {
|
||||||
eamArtifacts.add(eamArtifact);
|
nodeDataList.add(newNodeData);
|
||||||
fireTableDataChanged();
|
fireTableDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearTable() {
|
void clearTable() {
|
||||||
eamArtifacts.clear();
|
nodeDataList.clear();
|
||||||
fireTableDataChanged();
|
fireTableDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,233 @@
|
|||||||
|
/*
|
||||||
|
* Central Repository
|
||||||
|
*
|
||||||
|
* Copyright 2018 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
||||||
|
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
import org.sleuthkit.datamodel.TskDataException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for populating the Other Occurrences tab
|
||||||
|
*/
|
||||||
|
class OtherOccurrenceNodeData {
|
||||||
|
|
||||||
|
// For now hard code the string for the central repo files type, since
|
||||||
|
// getting it dynamically can fail.
|
||||||
|
private static final String FILE_TYPE_STR = "Files";
|
||||||
|
|
||||||
|
private final String caseName;
|
||||||
|
private String deviceID;
|
||||||
|
private String dataSourceName;
|
||||||
|
private final String filePath;
|
||||||
|
private final String typeStr;
|
||||||
|
private final CorrelationAttribute.Type type;
|
||||||
|
private final String value;
|
||||||
|
private TskData.FileKnown known;
|
||||||
|
private String comment;
|
||||||
|
|
||||||
|
private AbstractFile originalAbstractFile = null;
|
||||||
|
private CorrelationAttributeInstance originalCorrelationInstance = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a node from a central repo instance.
|
||||||
|
* @param instance The central repo instance
|
||||||
|
* @param type The type of the instance
|
||||||
|
* @param value The value of the instance
|
||||||
|
*/
|
||||||
|
OtherOccurrenceNodeData(CorrelationAttributeInstance instance, CorrelationAttribute.Type type, String value) {
|
||||||
|
caseName = instance.getCorrelationCase().getDisplayName();
|
||||||
|
deviceID = instance.getCorrelationDataSource().getDeviceID();
|
||||||
|
dataSourceName = instance.getCorrelationDataSource().getName();
|
||||||
|
filePath = instance.getFilePath();
|
||||||
|
this.typeStr = type.getDisplayName();
|
||||||
|
this.type = type;
|
||||||
|
this.value = value;
|
||||||
|
known = instance.getKnownStatus();
|
||||||
|
comment = instance.getComment();
|
||||||
|
|
||||||
|
originalCorrelationInstance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a node from an abstract file.
|
||||||
|
* @param newFile The abstract file
|
||||||
|
* @param autopsyCase The current case
|
||||||
|
* @throws EamDbException
|
||||||
|
*/
|
||||||
|
OtherOccurrenceNodeData(AbstractFile newFile, Case autopsyCase) throws EamDbException {
|
||||||
|
caseName = autopsyCase.getDisplayName();
|
||||||
|
try {
|
||||||
|
DataSource dataSource = autopsyCase.getSleuthkitCase().getDataSource(newFile.getDataSource().getId());
|
||||||
|
deviceID = dataSource.getDeviceId();
|
||||||
|
dataSourceName = dataSource.getName();
|
||||||
|
} catch (TskDataException | TskCoreException ex) {
|
||||||
|
throw new EamDbException("Error loading data source for abstract file ID " + newFile.getId(), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath = newFile.getParentPath() + newFile.getName();
|
||||||
|
typeStr = FILE_TYPE_STR;
|
||||||
|
this.type = null;
|
||||||
|
value = newFile.getMd5Hash();
|
||||||
|
known = newFile.getKnown();
|
||||||
|
comment = "";
|
||||||
|
|
||||||
|
originalAbstractFile = newFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this node is a "file" type
|
||||||
|
* @return true if it is a file type
|
||||||
|
*/
|
||||||
|
boolean isFileType() {
|
||||||
|
return FILE_TYPE_STR.equals(typeStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the known status for this node
|
||||||
|
* @param newKnownStatus The new known status
|
||||||
|
*/
|
||||||
|
void updateKnown(TskData.FileKnown newKnownStatus) {
|
||||||
|
known = newKnownStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the comment for this node
|
||||||
|
* @param newComment The new comment
|
||||||
|
*/
|
||||||
|
void updateComment(String newComment) {
|
||||||
|
comment = newComment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this is a central repo node.
|
||||||
|
* @return true if this node was created from a central repo instance, false otherwise
|
||||||
|
*/
|
||||||
|
boolean isCentralRepoNode() {
|
||||||
|
return (originalCorrelationInstance != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the saved instance plus type and value to make a new CorrelationAttribute.
|
||||||
|
* Should only be called if isCentralRepoNode() is true.
|
||||||
|
* @return the newly created CorrelationAttribute
|
||||||
|
*/
|
||||||
|
CorrelationAttribute createCorrelationAttribute() throws EamDbException {
|
||||||
|
if (! isCentralRepoNode() ) {
|
||||||
|
throw new EamDbException("Can not create CorrelationAttribute for non central repo node");
|
||||||
|
}
|
||||||
|
CorrelationAttribute attr = new CorrelationAttribute(type, value);
|
||||||
|
attr.addInstance(originalCorrelationInstance);
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the case name
|
||||||
|
* @return the case name
|
||||||
|
*/
|
||||||
|
String getCaseName() {
|
||||||
|
return caseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the device ID
|
||||||
|
* @return the device ID
|
||||||
|
*/
|
||||||
|
String getDeviceID() {
|
||||||
|
return deviceID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data source name
|
||||||
|
* @return the data source name
|
||||||
|
*/
|
||||||
|
String getDataSourceName() {
|
||||||
|
return dataSourceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the file path
|
||||||
|
* @return the file path
|
||||||
|
*/
|
||||||
|
String getFilePath() {
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type (as a string)
|
||||||
|
* @return the type
|
||||||
|
*/
|
||||||
|
String getType() {
|
||||||
|
return typeStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value (MD5 hash for files)
|
||||||
|
* @return the value
|
||||||
|
*/
|
||||||
|
String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the known status
|
||||||
|
* @return the known status
|
||||||
|
*/
|
||||||
|
TskData.FileKnown getKnown() {
|
||||||
|
return known;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the comment
|
||||||
|
* @return the comment
|
||||||
|
*/
|
||||||
|
String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the backing abstract file.
|
||||||
|
* Should only be called if isCentralRepoNode() is false
|
||||||
|
* @return the original abstract file
|
||||||
|
*/
|
||||||
|
AbstractFile getAbstractFile() throws EamDbException {
|
||||||
|
if (originalCorrelationInstance == null) {
|
||||||
|
throw new EamDbException("AbstractFile is null");
|
||||||
|
}
|
||||||
|
return originalAbstractFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the backing CorrelationAttributeInstance.
|
||||||
|
* Should only be called if isCentralRepoNode() is true
|
||||||
|
* @return the original CorrelationAttributeInstance
|
||||||
|
* @throws EamDbException
|
||||||
|
*/
|
||||||
|
CorrelationAttributeInstance getCorrelationAttributeInstance() throws EamDbException {
|
||||||
|
if (originalCorrelationInstance == null) {
|
||||||
|
throw new EamDbException("CorrelationAttributeInstance is null");
|
||||||
|
}
|
||||||
|
return originalCorrelationInstance;
|
||||||
|
}
|
||||||
|
}
|
@ -1772,7 +1772,7 @@ abstract class AbstractSqlEamDb implements EamDb {
|
|||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
throw new EamDbException("Error getting all artifact instances from instances table", ex);
|
throw new EamDbException("Error getting all artifact instances from instances table", ex);
|
||||||
} finally {
|
} finally {
|
||||||
EamDbUtil.closePreparedStatement(preparedStatement);
|
EamDbUtil.closeStatement(preparedStatement);
|
||||||
EamDbUtil.closeResultSet(resultSet);
|
EamDbUtil.closeResultSet(resultSet);
|
||||||
EamDbUtil.closeConnection(conn);
|
EamDbUtil.closeConnection(conn);
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ public final class PostgresEamDbSettings {
|
|||||||
LOGGER.log(Level.SEVERE, "Failed to execute database existance query.", ex); // NON-NLS
|
LOGGER.log(Level.SEVERE, "Failed to execute database existance query.", ex); // NON-NLS
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
EamDbUtil.closePreparedStatement(ps);
|
EamDbUtil.closeStatement(ps);
|
||||||
EamDbUtil.closeResultSet(rs);
|
EamDbUtil.closeResultSet(rs);
|
||||||
EamDbUtil.closeConnection(conn);
|
EamDbUtil.closeConnection(conn);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user