<commit_before>/*
 * Autopsy Forensic Browser
 *
 * Copyright 2017-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.casemodule;

import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.SwingUtilities;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
import org.sleuthkit.autopsy.datamodel.NodeProperty;

/**
 * A root node containing child nodes of the multi user cases
 */
public final class MultiUserNode extends AbstractNode {

    @Messages({"CaseNode.column.name=Name",
        "CaseNode.column.createdTime=Created Time",
        "CaseNode.column.status=Status",
        "CaseNode.column.metadataFilePath=Path"})
    private static final Logger LOGGER = Logger.getLogger(MultiUserNode.class.getName());

    /**
     * Provides a root node with children which each represent a case.
     *
     * @param caseMap the map of cases and a boolean indicating if they have an
     *                alert
     */
    MultiUserNode(Map<CaseMetadata, Boolean> caseMap) {
        super(Children.create(new MultiUserNodeChildren(caseMap), true));
    }

    static class MultiUserNodeChildren extends ChildFactory<Entry<CaseMetadata, Boolean>> {

        private final Map<CaseMetadata, Boolean> caseMap;

        MultiUserNodeChildren(Map<CaseMetadata, Boolean> caseMap) {
            this.caseMap = caseMap;
        }

        @Override
        protected boolean createKeys(List<Entry<CaseMetadata, Boolean>> list) {
            if (caseMap != null && caseMap.size() > 0) {
                list.addAll(caseMap.entrySet());
            }
            return true;
        }

        @Override
        protected Node createNodeForKey(Entry<CaseMetadata, Boolean> key) {
            return new MultiUserCaseNode(key);
        }

    }

    /**
     * A node which represents a single multi user case.
     */
    public static final class MultiUserCaseNode extends DisplayableItemNode {

        private final String caseName;
        private final String caseCreatedDate;
        private final String caseMetadataFilePath;
        private final boolean caseHasAlert;

        MultiUserCaseNode(Entry<CaseMetadata, Boolean> multiUserCase) {
            super(Children.LEAF);
            caseName = multiUserCase.getKey().getCaseDisplayName();
            caseCreatedDate = multiUserCase.getKey().getCreatedDate();
            caseHasAlert = multiUserCase.getValue();
            super.setName(caseName);
            setName(caseName);
            setDisplayName(caseName);
            caseMetadataFilePath = multiUserCase.getKey().getFilePath().toString();
        }

        @Override
        public boolean isLeafTypeNode() {
            return true;
        }

        @Override
        public <T> T accept(DisplayableItemNodeVisitor<T> v) {
            return v.visit(this);
        }

        @Override
        public String getItemType() {
            return getClass().getName();
        }

        public String getMetadataFilePath() {
            return caseMetadataFilePath;
        }

        @Override
        protected Sheet createSheet() {
            Sheet s = super.createSheet();
            Sheet.Set ss = s.get(Sheet.PROPERTIES);
            if (ss == null) {
                ss = Sheet.createPropertiesSet();
                s.put(ss);
            }
            ss.put(new NodeProperty<>(Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(),
                    caseName));
            ss.put(new NodeProperty<>(Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(),
                    caseCreatedDate));
            ss.put(new NodeProperty<>(Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(),
                    (caseHasAlert == true ? "Alert" : "")));
            ss.put(new NodeProperty<>(Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(),
                    caseMetadataFilePath));
            return s;
        }

        @Override
        public Action[] getActions(boolean context) {
            List<Action> actions = new ArrayList<>();
            actions.add(new OpenMultiUserCaseAction(caseMetadataFilePath));  //open case context menu option
            return actions.toArray(new Action[actions.size()]);
        }
    }

    /**
     * An action that opens the specified case and hides the multi user case
     * panel.
     */
    private static final class OpenMultiUserCaseAction extends AbstractAction {

        private static final long serialVersionUID = 1L;

        private final String caseMetadataFilePath;

        OpenMultiUserCaseAction(String path) {
            super("Open Case");
            caseMetadataFilePath = path;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            StartupWindowProvider.getInstance().close();
            MultiUserCasesDialog.getInstance().setVisible(false);
            new Thread(
                    () -> {
                        try {
                            Case.openAsCurrentCase(caseMetadataFilePath);
                        } catch (CaseActionException ex) {
                            if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
                                LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
                                MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage());
                            }
                            SwingUtilities.invokeLater(() -> {
                                //GUI changes done back on the EDT
                                StartupWindowProvider.getInstance().open();
                                MultiUserCasesDialog.getInstance().setVisible(true);
                            });
                        }
                    }
            ).start();
        }

        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone(); //To change body of generated methods, choose Tools | Templates.
        }
    }

}
<commit_msg>3408 basic context menu action for opening log file<commit_after>/*
 * Autopsy Forensic Browser
 *
 * Copyright 2017-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.casemodule;

import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
import org.sleuthkit.autopsy.datamodel.NodeProperty;

/**
 * A root node containing child nodes of the multi user cases
 */
public final class MultiUserNode extends AbstractNode {

    @Messages({"CaseNode.column.name=Name",
        "CaseNode.column.createdTime=Created Time",
        "CaseNode.column.status=Status",
        "CaseNode.column.metadataFilePath=Path"})
    private static final Logger LOGGER = Logger.getLogger(MultiUserNode.class.getName());
    private static final String LOG_FILE_NAME = "auto_ingest_log.txt";

    /**
     * Provides a root node with children which each represent a case.
     *
     * @param caseMap the map of cases and a boolean indicating if they have an
     *                alert
     */
    MultiUserNode(Map<CaseMetadata, Boolean> caseMap) {
        super(Children.create(new MultiUserNodeChildren(caseMap), true));
    }

    static class MultiUserNodeChildren extends ChildFactory<Entry<CaseMetadata, Boolean>> {

        private final Map<CaseMetadata, Boolean> caseMap;

        MultiUserNodeChildren(Map<CaseMetadata, Boolean> caseMap) {
            this.caseMap = caseMap;
        }

        @Override
        protected boolean createKeys(List<Entry<CaseMetadata, Boolean>> list) {
            if (caseMap != null && caseMap.size() > 0) {
                list.addAll(caseMap.entrySet());
            }
            return true;
        }

        @Override
        protected Node createNodeForKey(Entry<CaseMetadata, Boolean> key) {
            return new MultiUserCaseNode(key);
        }

    }

    /**
     * A node which represents a single multi user case.
     */
    public static final class MultiUserCaseNode extends DisplayableItemNode {

        private final String caseName;
        private final String caseCreatedDate;
        private final String caseMetadataFilePath;
        private final boolean caseHasAlert;
        private final Path caseLogFilePath;

        MultiUserCaseNode(Entry<CaseMetadata, Boolean> multiUserCase) {
            super(Children.LEAF);
            caseName = multiUserCase.getKey().getCaseDisplayName();
            caseCreatedDate = multiUserCase.getKey().getCreatedDate();
            caseHasAlert = multiUserCase.getValue();
            super.setName(caseName);
            setName(caseName);
            setDisplayName(caseName);
            caseMetadataFilePath = multiUserCase.getKey().getFilePath().toString();
            caseLogFilePath = Paths.get(multiUserCase.getKey().getCaseDirectory(), LOG_FILE_NAME);
        }

        @Override
        public boolean isLeafTypeNode() {
            return true;
        }

        @Override
        public <T> T accept(DisplayableItemNodeVisitor<T> v) {
            return v.visit(this);
        }

        @Override
        public String getItemType() {
            return getClass().getName();
        }

        public String getMetadataFilePath() {
            return caseMetadataFilePath;
        }

        @Messages({"MultiUserNode.AlertColumn.text=Alert"})  //text to display when there is an alert present
        @Override
        protected Sheet createSheet() {
            Sheet s = super.createSheet();
            Sheet.Set ss = s.get(Sheet.PROPERTIES);
            if (ss == null) {
                ss = Sheet.createPropertiesSet();
                s.put(ss);
            }
            ss.put(new NodeProperty<>(Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(),
                    caseName));
            ss.put(new NodeProperty<>(Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(),
                    caseCreatedDate));
            ss.put(new NodeProperty<>(Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(),
                    (caseHasAlert == true ? Bundle.MultiUserNode_AlertColumn_text() : "")));
            ss.put(new NodeProperty<>(Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(),
                    caseMetadataFilePath));
            return s;
        }

        @Override
        public Action[] getActions(boolean context) {
            List<Action> actions = new ArrayList<>();
            actions.add(new OpenMultiUserCaseAction(caseMetadataFilePath));  //open case context menu option
            if (caseLogFilePath != null && caseLogFilePath.toFile().exists()) {
                actions.add(new OpenCaseLogAction(caseLogFilePath));
            }
            return actions.toArray(new Action[actions.size()]);
        }
    }

    @Messages({"MultiUserNode.OpenMultiUserCaseAction.text=Open Case"})
    /**
     * An action that opens the specified case and hides the multi user case
     * panel.
     */
    private static final class OpenMultiUserCaseAction extends AbstractAction {

        private static final long serialVersionUID = 1L;

        private final String caseMetadataFilePath;

        OpenMultiUserCaseAction(String path) {
            super(Bundle.MultiUserNode_OpenMultiUserCaseAction_text());
            caseMetadataFilePath = path;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            StartupWindowProvider.getInstance().close();
            MultiUserCasesDialog.getInstance().setVisible(false);
            new Thread(
                    () -> {
                        try {
                            Case.openAsCurrentCase(caseMetadataFilePath);
                        } catch (CaseActionException ex) {
                            if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
                                LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
                                MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage());
                            }
                            SwingUtilities.invokeLater(() -> {
                                //GUI changes done back on the EDT
                                StartupWindowProvider.getInstance().open();
                                MultiUserCasesDialog.getInstance().setVisible(true);
                            });
                        }
                    }
            ).start();
        }

        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone(); //To change body of generated methods, choose Tools | Templates.
        }
    }
    @Messages({"MultiUserNode.OpenCaseLogAction.text=Open Log File"})
    /**
     * An action that opens the specified case and hides the multi user case
     * panel.
     */
    private static final class OpenCaseLogAction extends AbstractAction {

        private static final long serialVersionUID = 1L;

        private final Path pathToLog;

        OpenCaseLogAction(Path caseLogFilePath) {
            super(Bundle.MultiUserNode_OpenCaseLogAction_text());
            pathToLog = caseLogFilePath;
        }

        @Override
        public void actionPerformed(ActionEvent e) {

            if (pathToLog != null) {
                try {
                    if (pathToLog.toFile().exists()) {
                        Desktop.getDesktop().edit(pathToLog.toFile());

                    } else {
                        JOptionPane.showMessageDialog(MultiUserCasesDialog.getInstance(), org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotFindLog"),
                                org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE);
                    }
                } catch (IOException ex) {
                    LOGGER.log(Level.SEVERE, String.format("Error attempting to open case auto ingest log file %s", pathToLog), ex);
                    JOptionPane.showMessageDialog(MultiUserCasesDialog.getInstance(),
                            org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotOpenLog"),
                            org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"),
                            JOptionPane.PLAIN_MESSAGE);
                }
            }
        }

        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone(); //To change body of generated methods, choose Tools | Templates.
        }
    }

}

{'fraction_non_alphanumeric': 0.09052916925509685, 'fraction_numerical': 0.0018636697351329982, 'mean_word_length': 2.322326454033771, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6344005', 'n_tokens_mistral': 4543, 'n_tokens_neox': 4382, 'n_words': 1071}