mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-20 03:24:55 +00:00
Merged in TTS to changes to AAFN, now we have reduction in public api changes and support for translation column
This commit is contained in:
commit
003a1f6662
@ -338,6 +338,10 @@
|
|||||||
<package>org.sleuthkit.autopsy.modules.vmextractor</package>
|
<package>org.sleuthkit.autopsy.modules.vmextractor</package>
|
||||||
<package>org.sleuthkit.autopsy.progress</package>
|
<package>org.sleuthkit.autopsy.progress</package>
|
||||||
<package>org.sleuthkit.autopsy.report</package>
|
<package>org.sleuthkit.autopsy.report</package>
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
<package>org.sleuthkit.autopsy.tabulardatareader</package>
|
||||||
|
>>>>>>> 4316-text-translation-service
|
||||||
<package>org.sleuthkit.autopsy.texttranslation</package>
|
<package>org.sleuthkit.autopsy.texttranslation</package>
|
||||||
<package>org.sleuthkit.datamodel</package>
|
<package>org.sleuthkit.datamodel</package>
|
||||||
</public-packages>
|
</public-packages>
|
||||||
|
@ -72,6 +72,7 @@ public final class UserPreferences {
|
|||||||
public static final String GROUP_ITEMS_IN_TREE_BY_DATASOURCE = "GroupItemsInTreeByDataSource"; //NON-NLS
|
public static final String GROUP_ITEMS_IN_TREE_BY_DATASOURCE = "GroupItemsInTreeByDataSource"; //NON-NLS
|
||||||
public static final String SHOW_ONLY_CURRENT_USER_TAGS = "ShowOnlyCurrentUserTags";
|
public static final String SHOW_ONLY_CURRENT_USER_TAGS = "ShowOnlyCurrentUserTags";
|
||||||
public static final String HIDE_CENTRAL_REPO_COMMENTS_AND_OCCURRENCES = "HideCentralRepoCommentsAndOccurrences";
|
public static final String HIDE_CENTRAL_REPO_COMMENTS_AND_OCCURRENCES = "HideCentralRepoCommentsAndOccurrences";
|
||||||
|
public static final String DISPLAY_TRANSLATED_NAMES = "DisplayTranslatedNames";
|
||||||
|
|
||||||
// Prevent instantiation.
|
// Prevent instantiation.
|
||||||
private UserPreferences() {
|
private UserPreferences() {
|
||||||
@ -245,6 +246,14 @@ public final class UserPreferences {
|
|||||||
preferences.putBoolean(HIDE_CENTRAL_REPO_COMMENTS_AND_OCCURRENCES, value);
|
preferences.putBoolean(HIDE_CENTRAL_REPO_COMMENTS_AND_OCCURRENCES, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setDisplayTranslationFileNames(boolean value) {
|
||||||
|
preferences.putBoolean(DISPLAY_TRANSLATED_NAMES, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean displayTranslationFileNames() {
|
||||||
|
return preferences.getBoolean(DISPLAY_TRANSLATED_NAMES, false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads persisted case database connection info.
|
* Reads persisted case database connection info.
|
||||||
*
|
*
|
||||||
|
@ -192,3 +192,5 @@ ViewPreferencesPanel.centralRepoLabel.text=Do not use Central Repository for:
|
|||||||
ViewPreferencesPanel.commentsOccurencesColumnsCheckbox.text=C(omments) and O(ccurences) columns to reduce loading times
|
ViewPreferencesPanel.commentsOccurencesColumnsCheckbox.text=C(omments) and O(ccurences) columns to reduce loading times
|
||||||
ViewPreferencesPanel.deletedFilesLimitCheckbox.text=Limit to 10,000
|
ViewPreferencesPanel.deletedFilesLimitCheckbox.text=Limit to 10,000
|
||||||
ViewPreferencesPanel.deletedFilesLimitLabel.text=Limit number of deleted files displayed:
|
ViewPreferencesPanel.deletedFilesLimitLabel.text=Limit number of deleted files displayed:
|
||||||
|
ViewPreferencesPanel.fileDisplayLabel.text=Translate text in the:
|
||||||
|
ViewPreferencesPanel.translatedNamesButton.text=Table
|
||||||
|
@ -92,6 +92,8 @@
|
|||||||
</Group>
|
</Group>
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="centralRepoLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="deletedFilesLimitLabel" alignment="0" min="-2" pref="215" max="-2" attributes="0"/>
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="hideKnownFilesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="hideKnownFilesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
@ -114,9 +116,11 @@
|
|||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
|
<Component id="hideOtherUsersTagsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="fileDisplayLabel" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="displayTimeLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="displayTimeLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||||
@ -125,14 +129,12 @@
|
|||||||
<Component id="useBestViewerRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="useBestViewerRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="useGMTTimeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="useGMTTimeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="useLocalTimeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="useLocalTimeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="translatedNamesButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<Component id="selectFileLabel" min="-2" max="-2" attributes="0"/>
|
<Component id="selectFileLabel" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<Component id="hideOtherUsersTagsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
|
||||||
<Component id="centralRepoLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
|
||||||
<Component id="deletedFilesLimitLabel" alignment="0" min="-2" pref="215" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace min="0" pref="10" max="32767" attributes="0"/>
|
<EmptySpace min="0" pref="10" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
@ -174,9 +176,15 @@
|
|||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
<Component id="hideOtherUsersTagsLabel" min="-2" max="-2" attributes="0"/>
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="fileDisplayLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="hideOtherUsersTagsLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="hideOtherUsersTagsCheckbox" min="-2" max="-2" attributes="0"/>
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
|
<Component id="hideOtherUsersTagsCheckbox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="translatedNamesButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
<Component id="centralRepoLabel" min="-2" max="-2" attributes="0"/>
|
<Component id="centralRepoLabel" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
@ -356,6 +364,23 @@
|
|||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component class="javax.swing.JRadioButton" name="translatedNamesButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="ViewPreferencesPanel.translatedNamesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="translatedNamesButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="fileDisplayLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="ViewPreferencesPanel.fileDisplayLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
<Container class="javax.swing.JPanel" name="currentCaseSettingsPanel">
|
<Container class="javax.swing.JPanel" name="currentCaseSettingsPanel">
|
||||||
|
@ -27,6 +27,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
|
|||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
import org.sleuthkit.autopsy.deletedFiles.DeletedFilePreferences;
|
import org.sleuthkit.autopsy.deletedFiles.DeletedFilePreferences;
|
||||||
import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent;
|
import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent;
|
||||||
|
import org.sleuthkit.autopsy.texttranslation.TextTranslationService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Panel for configuring view preferences.
|
* Panel for configuring view preferences.
|
||||||
@ -44,6 +45,14 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
public ViewPreferencesPanel(boolean immediateUpdates) {
|
public ViewPreferencesPanel(boolean immediateUpdates) {
|
||||||
initComponents();
|
initComponents();
|
||||||
this.immediateUpdates = immediateUpdates;
|
this.immediateUpdates = immediateUpdates;
|
||||||
|
|
||||||
|
//If there is not Text Translator implementation, then hide these buttons
|
||||||
|
//from the user.
|
||||||
|
TextTranslationService tts = TextTranslationService.getInstance();
|
||||||
|
if(!tts.hasProvider()) {
|
||||||
|
translatedNamesButton.setVisible(false);
|
||||||
|
fileDisplayLabel.setVisible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -67,6 +76,7 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
commentsOccurencesColumnsCheckbox.setSelected(UserPreferences.hideCentralRepoCommentsAndOccurrences());
|
commentsOccurencesColumnsCheckbox.setSelected(UserPreferences.hideCentralRepoCommentsAndOccurrences());
|
||||||
|
|
||||||
deletedFilesLimitCheckbox.setSelected(DeletedFilePreferences.getDefault().getShouldLimitDeletedFiles());
|
deletedFilesLimitCheckbox.setSelected(DeletedFilePreferences.getDefault().getShouldLimitDeletedFiles());
|
||||||
|
translatedNamesButton.setSelected(UserPreferences.displayTranslationFileNames());
|
||||||
|
|
||||||
// Current Case Settings
|
// Current Case Settings
|
||||||
boolean caseIsOpen = Case.isCaseOpen();
|
boolean caseIsOpen = Case.isCaseOpen();
|
||||||
@ -90,6 +100,7 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
UserPreferences.setHideSlackFilesInViewsTree(viewsHideSlackCheckbox.isSelected());
|
UserPreferences.setHideSlackFilesInViewsTree(viewsHideSlackCheckbox.isSelected());
|
||||||
UserPreferences.setShowOnlyCurrentUserTags(hideOtherUsersTagsCheckbox.isSelected());
|
UserPreferences.setShowOnlyCurrentUserTags(hideOtherUsersTagsCheckbox.isSelected());
|
||||||
UserPreferences.setHideCentralRepoCommentsAndOccurrences(commentsOccurencesColumnsCheckbox.isSelected());
|
UserPreferences.setHideCentralRepoCommentsAndOccurrences(commentsOccurencesColumnsCheckbox.isSelected());
|
||||||
|
UserPreferences.setDisplayTranslationFileNames(translatedNamesButton.isSelected());
|
||||||
|
|
||||||
storeGroupItemsInTreeByDataSource();
|
storeGroupItemsInTreeByDataSource();
|
||||||
|
|
||||||
@ -142,6 +153,8 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
centralRepoLabel = new javax.swing.JLabel();
|
centralRepoLabel = new javax.swing.JLabel();
|
||||||
deletedFilesLimitCheckbox = new javax.swing.JCheckBox();
|
deletedFilesLimitCheckbox = new javax.swing.JCheckBox();
|
||||||
deletedFilesLimitLabel = new javax.swing.JLabel();
|
deletedFilesLimitLabel = new javax.swing.JLabel();
|
||||||
|
translatedNamesButton = new javax.swing.JRadioButton();
|
||||||
|
fileDisplayLabel = new javax.swing.JLabel();
|
||||||
currentCaseSettingsPanel = new javax.swing.JPanel();
|
currentCaseSettingsPanel = new javax.swing.JPanel();
|
||||||
groupByDataSourceCheckbox = new javax.swing.JCheckBox();
|
groupByDataSourceCheckbox = new javax.swing.JCheckBox();
|
||||||
currentSessionSettingsPanel = new javax.swing.JPanel();
|
currentSessionSettingsPanel = new javax.swing.JPanel();
|
||||||
@ -244,6 +257,15 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
|
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(deletedFilesLimitLabel, org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.deletedFilesLimitLabel.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(deletedFilesLimitLabel, org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.deletedFilesLimitLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(translatedNamesButton, org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.translatedNamesButton.text")); // NOI18N
|
||||||
|
translatedNamesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
translatedNamesButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(fileDisplayLabel, org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.fileDisplayLabel.text")); // NOI18N
|
||||||
|
|
||||||
javax.swing.GroupLayout globalSettingsPanelLayout = new javax.swing.GroupLayout(globalSettingsPanel);
|
javax.swing.GroupLayout globalSettingsPanelLayout = new javax.swing.GroupLayout(globalSettingsPanel);
|
||||||
globalSettingsPanel.setLayout(globalSettingsPanelLayout);
|
globalSettingsPanel.setLayout(globalSettingsPanelLayout);
|
||||||
globalSettingsPanelLayout.setHorizontalGroup(
|
globalSettingsPanelLayout.setHorizontalGroup(
|
||||||
@ -259,6 +281,8 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
.addComponent(deletedFilesLimitCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
.addComponent(deletedFilesLimitCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||||
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(centralRepoLabel)
|
||||||
|
.addComponent(deletedFilesLimitLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(hideKnownFilesLabel)
|
.addComponent(hideKnownFilesLabel)
|
||||||
@ -274,9 +298,11 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
.addGap(10, 10, 10)
|
.addGap(10, 10, 10)
|
||||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(dataSourcesHideKnownCheckbox)
|
.addComponent(dataSourcesHideKnownCheckbox)
|
||||||
.addComponent(viewsHideKnownCheckbox)))))
|
.addComponent(viewsHideKnownCheckbox))))
|
||||||
|
.addComponent(hideOtherUsersTagsLabel))
|
||||||
.addGap(18, 18, 18)
|
.addGap(18, 18, 18)
|
||||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(fileDisplayLabel)
|
||||||
.addComponent(displayTimeLabel)
|
.addComponent(displayTimeLabel)
|
||||||
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||||
.addGap(10, 10, 10)
|
.addGap(10, 10, 10)
|
||||||
@ -284,11 +310,9 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
.addComponent(keepCurrentViewerRadioButton)
|
.addComponent(keepCurrentViewerRadioButton)
|
||||||
.addComponent(useBestViewerRadioButton)
|
.addComponent(useBestViewerRadioButton)
|
||||||
.addComponent(useGMTTimeRadioButton)
|
.addComponent(useGMTTimeRadioButton)
|
||||||
.addComponent(useLocalTimeRadioButton)))
|
.addComponent(useLocalTimeRadioButton)
|
||||||
.addComponent(selectFileLabel)))
|
.addComponent(translatedNamesButton)))
|
||||||
.addComponent(hideOtherUsersTagsLabel)
|
.addComponent(selectFileLabel))))
|
||||||
.addComponent(centralRepoLabel)
|
|
||||||
.addComponent(deletedFilesLimitLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
|
|
||||||
.addGap(0, 10, Short.MAX_VALUE)))
|
.addGap(0, 10, Short.MAX_VALUE)))
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
@ -322,9 +346,13 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(useGMTTimeRadioButton)))
|
.addComponent(useGMTTimeRadioButton)))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
.addComponent(hideOtherUsersTagsLabel)
|
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(fileDisplayLabel)
|
||||||
|
.addComponent(hideOtherUsersTagsLabel))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(hideOtherUsersTagsCheckbox)
|
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
|
.addComponent(hideOtherUsersTagsCheckbox)
|
||||||
|
.addComponent(translatedNamesButton))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
.addComponent(centralRepoLabel)
|
.addComponent(centralRepoLabel)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
@ -535,6 +563,14 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
}
|
}
|
||||||
}//GEN-LAST:event_deletedFilesLimitCheckboxActionPerformed
|
}//GEN-LAST:event_deletedFilesLimitCheckboxActionPerformed
|
||||||
|
|
||||||
|
private void translatedNamesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_translatedNamesButtonActionPerformed
|
||||||
|
if (immediateUpdates) {
|
||||||
|
UserPreferences.setDisplayTranslationFileNames(translatedNamesButton.isSelected());
|
||||||
|
} else {
|
||||||
|
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||||
|
}
|
||||||
|
}//GEN-LAST:event_translatedNamesButtonActionPerformed
|
||||||
|
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JLabel centralRepoLabel;
|
private javax.swing.JLabel centralRepoLabel;
|
||||||
@ -546,6 +582,7 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
private javax.swing.JCheckBox deletedFilesLimitCheckbox;
|
private javax.swing.JCheckBox deletedFilesLimitCheckbox;
|
||||||
private javax.swing.JLabel deletedFilesLimitLabel;
|
private javax.swing.JLabel deletedFilesLimitLabel;
|
||||||
private javax.swing.JLabel displayTimeLabel;
|
private javax.swing.JLabel displayTimeLabel;
|
||||||
|
private javax.swing.JLabel fileDisplayLabel;
|
||||||
private javax.swing.JPanel globalSettingsPanel;
|
private javax.swing.JPanel globalSettingsPanel;
|
||||||
private javax.swing.JCheckBox groupByDataSourceCheckbox;
|
private javax.swing.JCheckBox groupByDataSourceCheckbox;
|
||||||
private javax.swing.JLabel hideKnownFilesLabel;
|
private javax.swing.JLabel hideKnownFilesLabel;
|
||||||
@ -555,6 +592,7 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
private javax.swing.JLabel hideSlackFilesLabel;
|
private javax.swing.JLabel hideSlackFilesLabel;
|
||||||
private javax.swing.JRadioButton keepCurrentViewerRadioButton;
|
private javax.swing.JRadioButton keepCurrentViewerRadioButton;
|
||||||
private javax.swing.JLabel selectFileLabel;
|
private javax.swing.JLabel selectFileLabel;
|
||||||
|
private javax.swing.JRadioButton translatedNamesButton;
|
||||||
private javax.swing.JRadioButton useBestViewerRadioButton;
|
private javax.swing.JRadioButton useBestViewerRadioButton;
|
||||||
private javax.swing.JRadioButton useGMTTimeRadioButton;
|
private javax.swing.JRadioButton useGMTTimeRadioButton;
|
||||||
private javax.swing.JRadioButton useLocalTimeRadioButton;
|
private javax.swing.JRadioButton useLocalTimeRadioButton;
|
||||||
|
@ -30,6 +30,7 @@ import java.util.Optional;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
@ -52,8 +53,13 @@ import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable.Score;
|
|||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import static org.sleuthkit.autopsy.datamodel.Bundle.*;
|
import static org.sleuthkit.autopsy.datamodel.Bundle.*;
|
||||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable.HasCommentStatus;
|
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable.HasCommentStatus;
|
||||||
|
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
|
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
|
||||||
|
import org.sleuthkit.autopsy.texttranslation.NoServiceProviderException;
|
||||||
|
import org.sleuthkit.autopsy.texttranslation.TextTranslationService;
|
||||||
|
import org.sleuthkit.autopsy.texttranslation.TranslationCallback;
|
||||||
|
import org.sleuthkit.autopsy.texttranslation.TranslationException;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
@ -72,9 +78,14 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
|||||||
@NbBundle.Messages("AbstractAbstractFileNode.addFileProperty.desc=no description")
|
@NbBundle.Messages("AbstractAbstractFileNode.addFileProperty.desc=no description")
|
||||||
private static final String NO_DESCR = AbstractAbstractFileNode_addFileProperty_desc();
|
private static final String NO_DESCR = AbstractAbstractFileNode_addFileProperty_desc();
|
||||||
|
|
||||||
|
private static final String TRANSLATION_AVAILABLE_EVENT = "TRANSLATION_AVAILABLE";
|
||||||
|
private static final String NO_TRANSLATION = "";
|
||||||
|
|
||||||
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE,
|
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE,
|
||||||
Case.Events.CONTENT_TAG_ADDED, Case.Events.CONTENT_TAG_DELETED, Case.Events.CR_COMMENT_CHANGED);
|
Case.Events.CONTENT_TAG_ADDED, Case.Events.CONTENT_TAG_DELETED, Case.Events.CR_COMMENT_CHANGED);
|
||||||
|
|
||||||
|
private String translatedFileName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param abstractFile file to wrap
|
* @param abstractFile file to wrap
|
||||||
*/
|
*/
|
||||||
@ -89,6 +100,7 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
|||||||
IngestManager.getInstance().addIngestModuleEventListener(weakPcl);
|
IngestManager.getInstance().addIngestModuleEventListener(weakPcl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
translatedFileName = null;
|
||||||
// Listen for case events so that we can detect when the case is closed
|
// Listen for case events so that we can detect when the case is closed
|
||||||
// or when tags are added.
|
// or when tags are added.
|
||||||
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl);
|
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl);
|
||||||
@ -165,6 +177,9 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
|||||||
if (event.getContentID() == content.getId()) {
|
if (event.getContentID() == content.getId()) {
|
||||||
updateSheet();
|
updateSheet();
|
||||||
}
|
}
|
||||||
|
} else if (eventType.equals(TRANSLATION_AVAILABLE_EVENT)) {
|
||||||
|
this.translatedFileName = (String) evt.getNewValue();
|
||||||
|
updateSheet();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -211,6 +226,7 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
|||||||
"AbstractAbstractFileNode.createSheet.score.name=S",
|
"AbstractAbstractFileNode.createSheet.score.name=S",
|
||||||
"AbstractAbstractFileNode.createSheet.comment.name=C",
|
"AbstractAbstractFileNode.createSheet.comment.name=C",
|
||||||
"AbstractAbstractFileNode.createSheet.count.name=O",
|
"AbstractAbstractFileNode.createSheet.count.name=O",
|
||||||
|
"AbstractAbstractFileNode.translateFileName=Translated Name",
|
||||||
"AbstractAbstractFileNode.locationColLbl=Location",
|
"AbstractAbstractFileNode.locationColLbl=Location",
|
||||||
"AbstractAbstractFileNode.modifiedTimeColLbl=Modified Time",
|
"AbstractAbstractFileNode.modifiedTimeColLbl=Modified Time",
|
||||||
"AbstractAbstractFileNode.changeTimeColLbl=Change Time",
|
"AbstractAbstractFileNode.changeTimeColLbl=Change Time",
|
||||||
@ -454,6 +470,41 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts translation on the file name by kicking off a background task to do the
|
||||||
|
* translation. Once the background task is done, it will fire a PropertyChangeEvent,
|
||||||
|
* which will force this node to refresh itself, thus updating its translated name
|
||||||
|
* column.
|
||||||
|
*
|
||||||
|
* @return The file names translation.
|
||||||
|
*/
|
||||||
|
protected String getTranslatedFileName() {
|
||||||
|
//If already in complete English, don't translate.
|
||||||
|
if (this.content.getName().matches("^\\p{ASCII}+$")) {
|
||||||
|
return NO_TRANSLATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we already have a translation use that one.
|
||||||
|
if (translatedFileName != null) {
|
||||||
|
return translatedFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If not, lets fire off a background translation that will update the UI
|
||||||
|
//when it is done.
|
||||||
|
TextTranslationService tts = TextTranslationService.getInstance();
|
||||||
|
if (tts.hasProvider()) {
|
||||||
|
//Seperate out the base and ext from the contents file name.
|
||||||
|
String base = FilenameUtils.getBaseName(this.content.getName());
|
||||||
|
|
||||||
|
//Send only the base file name to be translated. Once the translation comes
|
||||||
|
//back fire a PropertyChangeEvent on this nodes PropertyChangeListener.
|
||||||
|
tts.translateAsynchronously(base, new TranslateFileNameCallback(this.content, weakPcl));
|
||||||
|
}
|
||||||
|
|
||||||
|
//In the mean time, return a blank translation.
|
||||||
|
return NO_TRANSLATION;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill map with AbstractFile properties
|
* Fill map with AbstractFile properties
|
||||||
*
|
*
|
||||||
@ -659,4 +710,72 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the TranslationCallback interface so that the TextTranslationService
|
||||||
|
* can call these methods when an asynchronous translation task is complete.
|
||||||
|
*/
|
||||||
|
private class TranslateFileNameCallback implements TranslationCallback {
|
||||||
|
private final String ext;
|
||||||
|
private final String originalFileName;
|
||||||
|
|
||||||
|
private final PropertyChangeListener listener;
|
||||||
|
|
||||||
|
public TranslateFileNameCallback(AbstractFile file, PropertyChangeListener listener) {
|
||||||
|
this.ext = FilenameUtils.getExtension(content.getName());
|
||||||
|
this.originalFileName = content.getName();
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires a PropertyChangeEvent on this nodes PropertyChangeListener
|
||||||
|
* when the translation is finished. Reconstruct the file name so we
|
||||||
|
* can properly display the translation.
|
||||||
|
*
|
||||||
|
* @param translation Result from the translation job submitted to
|
||||||
|
* Text translation service.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onTranslationResult(String translation) {
|
||||||
|
//If we have no extension, then we shouldn't add the .
|
||||||
|
String extensionDelimiter = (ext.isEmpty()) ? "" : ".";
|
||||||
|
|
||||||
|
//Talk directly to this nodes pcl, fire an update when the translation
|
||||||
|
//is complete.
|
||||||
|
if (translation.isEmpty()) {
|
||||||
|
listener.propertyChange(new PropertyChangeEvent(
|
||||||
|
AutopsyEvent.SourceType.LOCAL.toString(),
|
||||||
|
TRANSLATION_AVAILABLE_EVENT, null, translation));
|
||||||
|
} else {
|
||||||
|
listener.propertyChange(new PropertyChangeEvent(
|
||||||
|
AutopsyEvent.SourceType.LOCAL.toString(),
|
||||||
|
TRANSLATION_AVAILABLE_EVENT, null,
|
||||||
|
translation + extensionDelimiter + ext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do nothing on a translation exception except log, the column will remain empty
|
||||||
|
* and there is nothing we can do as a fallback.
|
||||||
|
*
|
||||||
|
* @param ex Exception caught while translating.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onTranslationException(TranslationException noTranslationEx) {
|
||||||
|
logger.log(Level.WARNING, "Could not successfully translate file name " + originalFileName, noTranslationEx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do nothing on a no service provider exception except log, in this implemention we
|
||||||
|
* are only calling for translation to be done if we know that a TextTranslator
|
||||||
|
* service provider is already defined.
|
||||||
|
*
|
||||||
|
* @param ex
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onNoServiceProviderException(NoServiceProviderException noServiceEx) {
|
||||||
|
logger.log(Level.WARNING, "Translate unsuccessful because no TextTranslator "
|
||||||
|
+ "implementation was provided.", noServiceEx);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,6 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T accept(ContentNodeVisitor<T> visitor) {
|
public <T> T accept(ContentNodeVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,59 @@ public class LocalDirectoryNode extends SpecialDirectoryNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"LocalDirectoryNode.createSheet.name.name=Name",
|
||||||
|
"LocalDirectoryNode.createSheet.name.displayName=Name",
|
||||||
|
"LocalDirectoryNode.createSheet.name.desc=no description",
|
||||||
|
"LocalDirectoryNode.createSheet.noDesc=no description"})
|
||||||
|
protected Sheet createSheet() {
|
||||||
|
Sheet sheet = super.createSheet();
|
||||||
|
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||||
|
if (sheetSet == null) {
|
||||||
|
sheetSet = Sheet.createPropertiesSet();
|
||||||
|
sheet.put(sheetSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ContentTag> tags = getContentTagsFromDatabase();
|
||||||
|
sheetSet.put(new NodeProperty<>(Bundle.LocalDirectoryNode_createSheet_name_name(),
|
||||||
|
Bundle.LocalDirectoryNode_createSheet_name_displayName(),
|
||||||
|
Bundle.LocalDirectoryNode_createSheet_name_desc(),
|
||||||
|
getName()));
|
||||||
|
|
||||||
|
final String NO_DESCR = Bundle.LocalDirectoryNode_createSheet_noDesc();
|
||||||
|
if(UserPreferences.displayTranslationFileNames()) {
|
||||||
|
String translation = getTranslatedFileName();
|
||||||
|
sheetSet.put(new NodeProperty<>(Bundle.AbstractAbstractFileNode_translateFileName(),
|
||||||
|
Bundle.AbstractAbstractFileNode_translateFileName(), NO_DESCR, translation));
|
||||||
|
}
|
||||||
|
|
||||||
|
addScoreProperty(sheetSet, tags);
|
||||||
|
|
||||||
|
CorrelationAttributeInstance correlationAttribute = null;
|
||||||
|
if (EamDbUtil.useCentralRepo() && UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
|
||||||
|
correlationAttribute = getCorrelationAttributeInstance();
|
||||||
|
}
|
||||||
|
addCommentProperty(sheetSet, tags, correlationAttribute);
|
||||||
|
|
||||||
|
if (EamDbUtil.useCentralRepo() && UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
|
||||||
|
addCountProperty(sheetSet, correlationAttribute);
|
||||||
|
}
|
||||||
|
// At present, a LocalDirectory will never be a datasource - the top level of a logical
|
||||||
|
// file set is a VirtualDirectory
|
||||||
|
Map<String, Object> map = new LinkedHashMap<>();
|
||||||
|
fillPropertyMap(map, getContent());
|
||||||
|
|
||||||
|
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||||
|
sheetSet.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
>>>>>>> 4316-text-translation-service
|
||||||
public <T> T accept(ContentNodeVisitor<T> visitor) {
|
public <T> T accept(ContentNodeVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,6 @@ public class LocalFileNode extends AbstractAbstractFileNode<AbstractFile> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Action[] getActions(boolean context) {
|
public Action[] getActions(boolean context) {
|
||||||
List<Action> actionsList = new ArrayList<>();
|
List<Action> actionsList = new ArrayList<>();
|
||||||
actionsList.addAll(Arrays.asList(super.getActions(true)));
|
actionsList.addAll(Arrays.asList(super.getActions(true)));
|
||||||
|
@ -170,6 +170,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
case UserPreferences.HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE:
|
case UserPreferences.HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE:
|
||||||
case UserPreferences.HIDE_SLACK_FILES_IN_DATA_SRCS_TREE:
|
case UserPreferences.HIDE_SLACK_FILES_IN_DATA_SRCS_TREE:
|
||||||
case UserPreferences.HIDE_CENTRAL_REPO_COMMENTS_AND_OCCURRENCES:
|
case UserPreferences.HIDE_CENTRAL_REPO_COMMENTS_AND_OCCURRENCES:
|
||||||
|
case UserPreferences.DISPLAY_TRANSLATED_NAMES:
|
||||||
case UserPreferences.KEEP_PREFERRED_VIEWER:
|
case UserPreferences.KEEP_PREFERRED_VIEWER:
|
||||||
refreshContentTreeSafe();
|
refreshContentTreeSafe();
|
||||||
break;
|
break;
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2018-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.texttranslation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception to indicate that no Service Provider could be found during the
|
||||||
|
* Lookup action.
|
||||||
|
*/
|
||||||
|
public class NoServiceProviderException extends Exception {
|
||||||
|
|
||||||
|
public NoServiceProviderException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
@ -18,27 +18,41 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.texttranslation;
|
package org.sleuthkit.autopsy.texttranslation;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
|
||||||
import org.openide.util.Lookup;
|
import org.openide.util.Lookup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service for finding and running TextTranslator implementations
|
* Performs a lookup for a TextTranslator service provider and if present,
|
||||||
|
* will use this provider to run translation on the input.
|
||||||
*/
|
*/
|
||||||
public class TextTranslationService {
|
public final class TextTranslationService {
|
||||||
|
|
||||||
|
private final static TextTranslationService tts = new TextTranslationService();
|
||||||
|
|
||||||
private final Optional<TextTranslator> translator;
|
private final Optional<TextTranslator> translator;
|
||||||
|
|
||||||
/**
|
private static ExecutorService pool;
|
||||||
*
|
private final static Integer MAX_POOL_SIZE = 10;
|
||||||
*/
|
|
||||||
public TextTranslationService() {
|
private TextTranslationService(){
|
||||||
|
//Perform look up for Text Translation implementations ONLY ONCE during
|
||||||
|
//class loading.
|
||||||
translator = Optional.ofNullable(Lookup.getDefault()
|
translator = Optional.ofNullable(Lookup.getDefault()
|
||||||
.lookup(TextTranslator.class));
|
.lookup(TextTranslator.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TextTranslationService getInstance() {
|
||||||
|
return tts;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a lookup for a TextTranslator service provider and if present,
|
* Translates the input string using whichever TextTranslator Service Provider
|
||||||
* will use this provider to run translation on the input.
|
* was found during lookup.
|
||||||
*
|
*
|
||||||
* @param input Input string to be translated
|
* @param input Input string to be translated
|
||||||
*
|
*
|
||||||
@ -59,13 +73,51 @@ public class TextTranslationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception to indicate that no Service Provider could be found during the
|
* Makes the call to translate(String) happen asynchronously on a background
|
||||||
* Lookup action.
|
* thread. When it is done, it will use the appropriate TranslationCallback
|
||||||
|
* method.
|
||||||
|
*
|
||||||
|
* @param input String to be translated
|
||||||
|
* @param tcb Interface for handling the translation result or any
|
||||||
|
* exceptions thrown while running translate.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class NoServiceProviderException extends Exception {
|
public void translateAsynchronously(String input, TranslationCallback tcb) {
|
||||||
|
if (translator.isPresent()) {
|
||||||
|
//Delay thread pool initialization until an asynchronous task is first called.
|
||||||
|
//That way we don't have threads sitting parked in the background for no reason.
|
||||||
|
if (pool == null) {
|
||||||
|
ThreadFactory translationFactory = new ThreadFactoryBuilder()
|
||||||
|
.setNameFormat("translation-thread-%d")
|
||||||
|
.build();
|
||||||
|
pool = Executors.newFixedThreadPool(MAX_POOL_SIZE, translationFactory);
|
||||||
|
}
|
||||||
|
|
||||||
public NoServiceProviderException(String msg) {
|
//Submit the task to the pool, calling the appropriate method depending
|
||||||
super(msg);
|
//on the result of the translate operation.
|
||||||
|
pool.submit(() -> {
|
||||||
|
try {
|
||||||
|
String translation = translate(input);
|
||||||
|
tcb.onTranslationResult(translation);
|
||||||
|
} catch (NoServiceProviderException ex) {
|
||||||
|
tcb.onNoServiceProviderException(ex);
|
||||||
|
} catch (TranslationException ex) {
|
||||||
|
tcb.onTranslationException(ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tcb.onNoServiceProviderException(new NoServiceProviderException(
|
||||||
|
"Could not find a TextTranslator service provider"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if a TextTranslator lookup successfully found an implementing
|
||||||
|
* class.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean hasProvider() {
|
||||||
|
return translator.isPresent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,6 @@ package org.sleuthkit.autopsy.texttranslation;
|
|||||||
*/
|
*/
|
||||||
public interface TextTranslator {
|
public interface TextTranslator {
|
||||||
|
|
||||||
public String translate(String input) throws TranslationException;
|
String translate(String input) throws TranslationException;
|
||||||
|
|
||||||
public default String[] translate(String[] inputs) throws TranslationException {
|
|
||||||
String[] outputs = new String[inputs.length];
|
|
||||||
for(int i = 0; i < inputs.length; i++) {
|
|
||||||
outputs[i] = translate(inputs[i]);
|
|
||||||
}
|
|
||||||
return outputs;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
49
Core/src/org/sleuthkit/autopsy/texttranslation/TranslationCallback.java
Executable file
49
Core/src/org/sleuthkit/autopsy/texttranslation/TranslationCallback.java
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2018-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.texttranslation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This callback interface will be used by TextTranslationService when doing
|
||||||
|
* translations on background tasks. When the translation is done, it's result will
|
||||||
|
* be delegated to one of the following methods. It can either be successful or fail with
|
||||||
|
* exceptions.
|
||||||
|
*/
|
||||||
|
public interface TranslationCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a method to handle the translation result
|
||||||
|
*
|
||||||
|
* @param translation result of calling TextTranslationService.
|
||||||
|
*/
|
||||||
|
void onTranslationResult(String translation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a way to handle Translation Exceptions.
|
||||||
|
*
|
||||||
|
* @param noTranslationEx
|
||||||
|
*/
|
||||||
|
void onTranslationException(TranslationException noTranslationEx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a way to handle NoServiceProviderExceptions.
|
||||||
|
*
|
||||||
|
* @param noServiceEx
|
||||||
|
*/
|
||||||
|
void onNoServiceProviderException(NoServiceProviderException noServiceEx);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user