factory fixes

This commit is contained in:
Greg DiCristofaro 2022-01-19 09:36:32 -05:00
parent d6a239f7bd
commit 2e9082bf65
3 changed files with 80 additions and 142 deletions

View File

@ -232,27 +232,37 @@ public class EmailsDAO extends AbstractDAO {
return safePath;
}
public static class EmailTreeItem extends TreeItemDTO<EmailSearchParams> {
private final Optional<Boolean> hasChildren;
EmailTreeItem(String fullFolder, Long dataSourceId, TreeDisplayCount count,
Boolean hasChildren) {
super(
EmailSearchParams.getTypeId(),
new EmailSearchParams(dataSourceId, fullFolder),
fullFolder == null ? 0 : fullFolder,
getFolderDisplayName(fullFolder),
count
);
this.hasChildren = Optional.ofNullable(hasChildren);
}
public Optional<Boolean> getHasChildren() {
return hasChildren;
}
public TreeItemDTO<EmailSearchParams> createEmailTreeItem(String fullFolder, Long dataSourceId, TreeDisplayCount count) {
return new TreeItemDTO<>(
EmailSearchParams.getTypeId(),
new EmailSearchParams(dataSourceId, fullFolder),
fullFolder == null ? 0 : fullFolder,
getFolderDisplayName(fullFolder),
count
);
}
public Optional<String> getNextSubFolder(String folderParent, String folder) {
String normalizedParent = folderParent == null ? null : getNormalizedPath(folderParent);
String normalizedFolder = folder == null ? null : getNormalizedPath(folder);
if (normalizedParent == null || normalizedFolder.startsWith(normalizedParent)) {
if (normalizedFolder == null) {
return Optional.of(null);
} else {
int nextDelim = normalizedFolder.indexOf(PATH_DELIMITER, normalizedParent.length());
if (nextDelim >= 0) {
return Optional.of(normalizedFolder.substring(normalizedParent.length(), nextDelim));
} else {
return Optional.of(normalizedFolder.substring(normalizedParent.length()));
}
}
} else {
return Optional.empty();
}
}
/**
* Returns sql to query for email counts.
*
@ -383,8 +393,7 @@ public class EmailsDAO extends AbstractDAO {
? TreeDisplayCount.INDETERMINATE
: TreeResultsDTO.TreeDisplayCount.getDeterminate(resultSet.getLong("count"));
accumulatedData.add(
new EmailTreeItem(getNormalizedPath(rsPath), dataSourceId, treeDisplayCount, hasChildren));
accumulatedData.add(createEmailTreeItem(getNormalizedPath(rsPath), dataSourceId, treeDisplayCount));
}
} catch (SQLException ex) {
throw new IllegalStateException("A sql exception occurred.", ex);
@ -414,11 +423,10 @@ public class EmailsDAO extends AbstractDAO {
Set<? extends DAOEvent> handleIngestComplete() {
return SubDAOUtils.getIngestCompleteEvents(
this.emailCounts,
(daoEvt, count) -> new EmailTreeItem(
(daoEvt, count) -> createEmailTreeItem(
getNormalizedPath(daoEvt.getFolder()),
daoEvt.getDataSourceId(),
count,
daoEvt.getHasChildren().orElse(null)
count
));
}
@ -426,11 +434,10 @@ public class EmailsDAO extends AbstractDAO {
Set<TreeEvent> shouldRefreshTree() {
return SubDAOUtils.getRefreshEvents(
this.emailCounts,
(daoEvt, count) -> new EmailTreeItem(
(daoEvt, count) -> createEmailTreeItem(
getNormalizedPath(daoEvt.getFolder()),
daoEvt.getDataSourceId(),
count,
daoEvt.getHasChildren().orElse(null)
count
));
}
@ -469,18 +476,17 @@ public class EmailsDAO extends AbstractDAO {
for (Entry<String, Set<Long>> folderEntry : emailMap.entrySet()) {
String folder = folderEntry.getKey();
for (Long dsObjId : folderEntry.getValue()) {
emailEvents.add(new EmailEvent(dsObjId, folder, null));
emailEvents.add(new EmailEvent(dsObjId, folder));
}
}
Stream<TreeEvent> treeEvents = this.emailCounts.enqueueAll(emailEvents).stream()
.map(daoEvt -> {
return new TreeEvent(
new EmailTreeItem(
createEmailTreeItem(
daoEvt.getFolder(),
daoEvt.getDataSourceId(),
TreeResultsDTO.TreeDisplayCount.INDETERMINATE,
null),
TreeResultsDTO.TreeDisplayCount.INDETERMINATE),
false);
});
@ -509,6 +515,7 @@ public class EmailsDAO extends AbstractDAO {
}
}
/**
* Handles fetching and paging of data for communication accounts.
*/

View File

@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.mainui.datamodel.events;
import java.util.Objects;
import java.util.Optional;
import org.sleuthkit.datamodel.BlackboardArtifact;
/**
@ -28,7 +27,6 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
public class EmailEvent extends DataArtifactEvent {
private final String folder;
private final Optional<Boolean> hasChildren;
/**
* Main constructor.
@ -36,22 +34,16 @@ public class EmailEvent extends DataArtifactEvent {
* @param dataSourceId The data source id that the email message belongs to.
* @param account The email message account.
* @param folder The folder within that account of the email message.
* @param hasChildren True if this folder has further tree folders. Null if unknown.
*/
public EmailEvent(long dataSourceId, String folder, Boolean hasChildren) {
public EmailEvent(long dataSourceId, String folder) {
super(BlackboardArtifact.Type.TSK_EMAIL_MSG, dataSourceId);
this.folder = folder;
this.hasChildren = Optional.ofNullable(hasChildren);
}
public String getFolder() {
return folder;
}
public Optional<Boolean> getHasChildren() {
return hasChildren;
}
@Override
public int hashCode() {
int hash = 7;

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.mainui.nodes;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import org.apache.commons.lang3.StringUtils;
import org.openide.nodes.Children;
@ -135,7 +136,7 @@ public class DataArtifactTypeFactory extends TreeChildFactory<DataArtifactSearch
super(itemData.getSearchParams().getArtifactType().getTypeName(),
getIconPath(itemData.getSearchParams().getArtifactType()),
itemData,
Children.create(new EmailAccountTypeFactory(itemData.getSearchParams().getDataSourceId()), true),
Children.create(new EmailFolderFactory(null, itemData.getSearchParams().getDataSourceId()), true),
getDefaultLookup(itemData)
);
}
@ -268,19 +269,22 @@ public class DataArtifactTypeFactory extends TreeChildFactory<DataArtifactSearch
/**
* Factory for displaying account types.
*/
static class EmailAccountTypeFactory extends TreeChildFactory<EmailSearchParams> {
static class EmailFolderFactory extends TreeChildFactory<EmailSearchParams> {
private final String folderParent;
private final Long dataSourceId;
/**
* Main constructor.
*
* @param folderParent The email parent folder for the factory.
* @param dataSourceId The data source object id for which the results
* should be filtered or null if no data source
* filtering.
*/
public EmailAccountTypeFactory(Long dataSourceId) {
public EmailFolderFactory(String folderParent, Long dataSourceId) {
this.dataSourceId = dataSourceId;
this.folderParent = folderParent;
}
private EmailsDAO getDAO() {
@ -289,12 +293,12 @@ public class DataArtifactTypeFactory extends TreeChildFactory<DataArtifactSearch
@Override
protected TreeResultsDTO<? extends EmailSearchParams> getChildResults() throws IllegalArgumentException, ExecutionException {
return getDAO().getEmailCounts(dataSourceId, null);
return getDAO().getEmailCounts(dataSourceId, this.folderParent);
}
@Override
protected TreeNode<EmailSearchParams> createNewNode(TreeResultsDTO.TreeItemDTO<? extends EmailSearchParams> rowData) {
return new EmailAccountTypeNode(rowData);
return new EmailNode(rowData);
}
@Override
@ -303,103 +307,20 @@ public class DataArtifactTypeFactory extends TreeChildFactory<DataArtifactSearch
TreeItemDTO<EmailSearchParams> originalTreeItem = getTypedTreeItem(treeEvt, EmailSearchParams.class);
if (originalTreeItem != null
// ensure data source id for factory is null or data sources are equal
&& (this.dataSourceId == null || Objects.equals(this.dataSourceId, originalTreeItem.getSearchParams().getDataSourceId()))) {
EmailSearchParams originalSearchParam = originalTreeItem.getSearchParams();
return getDAO().createEmailTreeItem(
originalSearchParam.getAccount(),
null,
getDAO().getAccountDisplayName(originalSearchParam.getAccount(), null),
dataSourceId,
originalTreeItem.getDisplayCount());
}
return null;
}
Optional<String> thisSubFolderOpt = getDAO().getNextSubFolder(this.folderParent, originalSearchParam.getFolder());
if (thisSubFolderOpt.isPresent()) {
String thisSubFolder = thisSubFolderOpt.get();
@Override
public int compare(TreeItemDTO<? extends EmailSearchParams> o1, TreeItemDTO<? extends EmailSearchParams> o2) {
boolean firstDown = o1.getSearchParams().getAccount() == null;
boolean secondDown = o2.getSearchParams().getAccount() == null;
if (firstDown == secondDown) {
return o1.getDisplayName().compareToIgnoreCase(o2.getDisplayName());
} else {
return Boolean.compare(firstDown, secondDown);
}
}
}
/**
* A node representing a single account type in the tree.
*/
static class EmailAccountTypeNode extends TreeNode<EmailSearchParams> {
/**
* Main constructor.
*
* @param itemData The data to display.
*/
public EmailAccountTypeNode(TreeResultsDTO.TreeItemDTO<? extends EmailSearchParams> itemData) {
super(itemData.getSearchParams().getAccount(),
"org/sleuthkit/autopsy/images/account-icon-16.png",
itemData,
Children.create(new EmailFolderTypeFactory(itemData.getSearchParams().getAccount(), itemData.getSearchParams().getDataSourceId()), true),
getDefaultLookup(itemData)
);
}
}
/**
* Factory for displaying account types.
*/
static class EmailFolderTypeFactory extends TreeChildFactory<EmailSearchParams> {
private final String account;
private final Long dataSourceId;
/**
* Main constructor.
*
* @param account The email account for the factory.
* @param dataSourceId The data source object id for which the results
* should be filtered or null if no data source
* filtering.
*/
public EmailFolderTypeFactory(String account, Long dataSourceId) {
this.dataSourceId = dataSourceId;
this.account = account;
}
private EmailsDAO getDAO() {
return MainDAO.getInstance().getEmailsDAO();
}
@Override
protected TreeResultsDTO<? extends EmailSearchParams> getChildResults() throws IllegalArgumentException, ExecutionException {
return getDAO().getEmailCounts(dataSourceId, account);
}
@Override
protected TreeNode<EmailSearchParams> createNewNode(TreeResultsDTO.TreeItemDTO<? extends EmailSearchParams> rowData) {
return new EmailFolderTypeNode(rowData);
}
@Override
protected TreeItemDTO<? extends EmailSearchParams> getOrCreateRelevantChild(TreeEvent treeEvt) {
TreeItemDTO<EmailSearchParams> originalTreeItem = getTypedTreeItem(treeEvt, EmailSearchParams.class);
if (originalTreeItem != null
&& Objects.equals(this.account, originalTreeItem.getSearchParams().getAccount())
&& (this.dataSourceId == null || Objects.equals(this.dataSourceId, originalTreeItem.getSearchParams().getDataSourceId()))) {
EmailSearchParams originalSearchParam = originalTreeItem.getSearchParams();
return getDAO().createEmailTreeItem(
originalSearchParam.getAccount(),
originalSearchParam.getFolder(),
getDAO().getFolderDisplayName(originalSearchParam.getFolder()),
dataSourceId,
originalTreeItem.getDisplayCount());
return getDAO().createEmailTreeItem(
thisSubFolder,
dataSourceId,
originalTreeItem.getDisplayCount());
}
}
return null;
@ -421,22 +342,40 @@ public class DataArtifactTypeFactory extends TreeChildFactory<DataArtifactSearch
/**
* A node representing a single account type in the tree.
*/
static class EmailFolderTypeNode extends TreeNode<EmailSearchParams> {
static class EmailNode extends TreeNode<EmailSearchParams> {
private final Children children;
/**
* Main constructor.
*
* @param itemData The data to display.
*/
public EmailFolderTypeNode(TreeResultsDTO.TreeItemDTO<? extends EmailSearchParams> itemData) {
public EmailNode(TreeResultsDTO.TreeItemDTO<? extends EmailSearchParams> itemData) {
this(itemData, Children.create(new EmailFolderFactory(itemData.getSearchParams().getFolder(), itemData.getSearchParams().getDataSourceId()), true));
}
private EmailNode(TreeResultsDTO.TreeItemDTO<? extends EmailSearchParams> itemData, Children children) {
super(itemData.getSearchParams().getFolder(),
"org/sleuthkit/autopsy/images/folder-icon-16.png",
itemData);
itemData,
children,
getDefaultLookup(itemData));
this.children = children;
}
private boolean hasChildren() {
return this.children.getNodesCount(true) > 0;
}
@Override
public void respondSelection(DataResultTopComponent dataResultPanel) {
dataResultPanel.displayEmailMessages(super.getItemData().getSearchParams());
if (hasChildren()) {
super.respondSelection(dataResultPanel);
} else {
dataResultPanel.displayEmailMessages(super.getItemData().getSearchParams());
}
}
}