From fe86d86dd2ec6c1fee5f8a0407570f46bde4b8f7 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 5 Mar 2020 09:10:05 -0500 Subject: [PATCH] abstracted TranslateTextTask --- .../TextTranslatableComponent.java | 2 +- .../contentviewers/TranslatablePanel.java | 4 +- .../texttranslation/ui/TranslateTextTask.java | 160 ++++++++++++++++++ .../ui/TranslatedTextViewer.java | 118 ++----------- 4 files changed, 175 insertions(+), 109 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslateTextTask.java diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/TextTranslatableComponent.java b/Core/src/org/sleuthkit/autopsy/contentviewers/TextTranslatableComponent.java index 74f2fddf03..ea456cd5eb 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/TextTranslatableComponent.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/TextTranslatableComponent.java @@ -110,7 +110,7 @@ final class TextTranslatableComponent implements TranslatablePanel.TranslatableC this.translated = this.translationService.translate(originalContent); } catch (NoServiceProviderException | TranslationException ex) { LOGGER.log(Level.WARNING, "Unable to translate text with translation service", ex); - return Bundle.TextTranslatableComponent_setTranslated_onTranslateError(); + //return Bundle.TextTranslatableComponent_setTranslated_onTranslateError(); } }); } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/TranslatablePanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/TranslatablePanel.java index 107dae8cb1..48c4006785 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/TranslatablePanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/TranslatablePanel.java @@ -30,7 +30,9 @@ import org.sleuthkit.autopsy.texttranslation.TextTranslationService; * A panel for translation with a subcomponent that allows for translation */ final class TranslatablePanel extends JPanel { - + interface ContentSetter { + void set(String content) throws Exception; + } /** * an option in drop down of whether or not to translate diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslateTextTask.java b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslateTextTask.java new file mode 100644 index 0000000000..ddfcc5b155 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslateTextTask.java @@ -0,0 +1,160 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit 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.ui; + +import java.awt.ComponentOrientation; +import java.awt.Font; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.TextUtil; +import org.sleuthkit.autopsy.texttranslation.NoServiceProviderException; +import org.sleuthkit.autopsy.texttranslation.TextTranslationService; +import org.sleuthkit.autopsy.texttranslation.TranslationException; + +/** +* abstract class for translating text and displaying to the user +*/ +public abstract class TranslateTextTask extends SwingWorker { + private static final Logger logger = Logger.getLogger(TranslatedTextViewer.class.getName()); + + private final boolean translateText; + private final String contentDescriptor; + + + /** + * + * @param translateText whether or not to translate text + * @param contentDescriptor the content descriptor for the item being translated (used for logging errors) + */ + public TranslateTextTask(boolean translateText, String fileDescriptor) { + this.translateText = translateText; + this.contentDescriptor = fileDescriptor; + } + + + protected abstract String retrieveText() throws Exception; + + protected abstract void onTextDisplay(String text, ComponentOrientation orientation, int font); + + @NbBundle.Messages({ + "TranslatedContentViewer.extractingText=Extracting text, please wait...", + "TranslatedContentViewer.translatingText=Translating text, please wait...", + "# {0} - exception message", "TranslatedContentViewer.errorExtractingText=An error occurred while extracting the text ({0}).", + "TranslatedContentViewer.fileHasNoText=File has no text.", + "TranslatedContentViewer.noServiceProvider=The machine translation software was not found.", + "# {0} - exception message", "TranslatedContentViewer.translationException=An error occurred while translating the text ({0})." + }) + @Override + public String doInBackground() throws InterruptedException { + if (this.isCancelled()) { + throw new InterruptedException(); + } + + SwingUtilities.invokeLater(() -> { + onTextDisplay(Bundle.TranslatedContentViewer_extractingText(), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC); + }); + String fileText; + try { + fileText = retrieveText(); + } catch (InterruptedException | CancellationException e) { + // bubble up cancellation instead of continuing + throw e; + } catch (Exception ex) { + logger.log(Level.WARNING, "Error extracting text for file " + this.contentDescriptor, ex); + return Bundle.TranslatedContentViewer_errorExtractingText(ex.getMessage()); + } + + if (this.isCancelled()) { + throw new InterruptedException(); + } + + if (fileText == null || fileText.isEmpty()) { + return Bundle.TranslatedContentViewer_fileHasNoText(); + } + + if (!this.translateText) { + return fileText; + } + + SwingUtilities.invokeLater(() -> { + onTextDisplay(Bundle.TranslatedContentViewer_translatingText(), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC); + }); + String translation; + try { + translation = translate(fileText); + } catch (NoServiceProviderException ex) { + logger.log(Level.WARNING, "Error translating text for file " + this.contentDescriptor, ex); + translation = Bundle.TranslatedContentViewer_noServiceProvider(); + } catch (TranslationException ex) { + logger.log(Level.WARNING, "Error translating text for file " + this.contentDescriptor, ex); + translation = Bundle.TranslatedContentViewer_translationException(ex.getMessage()); + } + + if (this.isCancelled()) { + throw new InterruptedException(); + } + + return translation; + } + + @Override + public void done() { + try { + String result = get(); + if (this.isCancelled()) { + throw new InterruptedException(); + } + int len = result.length(); + int maxOrientChars = Math.min(len, 1024); + String orientDetectSubstring = result.substring(0, maxOrientChars); + ComponentOrientation orientation = TextUtil.getTextDirection(orientDetectSubstring); + onTextDisplay(result, orientation, Font.PLAIN); + + } catch (InterruptedException | CancellationException ignored) { + // Task cancelled, no error. + } catch (ExecutionException ex) { + logger.log(Level.WARNING, "Error occurred during background task execution for file " + this.contentDescriptor, ex); + onTextDisplay(Bundle.TranslatedContentViewer_translationException(ex.getMessage()), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC); + } + } + + /** + * Pass the translation off to the Translation service provider. + * + * @param input Text to be translated + * + * @return Translated text or error message + */ + @NbBundle.Messages({ + "TranslatedContentViewer.emptyTranslation=The machine translation software did not return any text." + }) + private String translate(String input) throws NoServiceProviderException, TranslationException { + TextTranslationService translatorInstance = TextTranslationService.getInstance(); + String translatedResult = translatorInstance.translate(input); + if (translatedResult.isEmpty()) { + return Bundle.TranslatedContentViewer_emptyTranslation(); + } + return translatedResult; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslatedTextViewer.java b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslatedTextViewer.java index 7e07545b49..ecae3645c3 100644 --- a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslatedTextViewer.java +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslatedTextViewer.java @@ -160,112 +160,13 @@ public final class TranslatedTextViewer implements TextViewer { /** * Extracts text from a file and optionally translates it. */ - private class ExtractAndTranslateTextTask extends SwingWorker { + private class ExtractAndTranslateTextTask extends TranslateTextTask { private final AbstractFile file; - private final boolean translateText; private ExtractAndTranslateTextTask(AbstractFile file, boolean translateText) { + super(translateText, String.format("%s (objId=%d)", file.getName(), file.getId())); this.file = file; - this.translateText = translateText; - } - - @NbBundle.Messages({ - "TranslatedContentViewer.extractingText=Extracting text, please wait...", - "TranslatedContentViewer.translatingText=Translating text, please wait...", - "# {0} - exception message", "TranslatedContentViewer.errorExtractingText=An error occurred while extracting the text ({0}).", - "TranslatedContentViewer.fileHasNoText=File has no text.", - "TranslatedContentViewer.noServiceProvider=The machine translation software was not found.", - "# {0} - exception message", "TranslatedContentViewer.translationException=An error occurred while translating the text ({0})." - }) - @Override - public String doInBackground() throws InterruptedException { - if (this.isCancelled()) { - throw new InterruptedException(); - } - - SwingUtilities.invokeLater(() -> { - panel.display(Bundle.TranslatedContentViewer_extractingText(), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC); - }); - String fileText; - try { - fileText = getFileText(file); - } catch (IOException | TextExtractor.InitReaderException ex) { - logger.log(Level.WARNING, String.format("Error extracting text for file %s (objId=%d)", file.getName(), file.getId()), ex); - return Bundle.TranslatedContentViewer_errorExtractingText(ex.getMessage()); - } - - if (this.isCancelled()) { - throw new InterruptedException(); - } - - if (fileText == null || fileText.isEmpty()) { - return Bundle.TranslatedContentViewer_fileHasNoText(); - } - - if (!this.translateText) { - return fileText; - } - - SwingUtilities.invokeLater(() -> { - panel.display(Bundle.TranslatedContentViewer_translatingText(), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC); - }); - String translation; - try { - translation = translate(fileText); - } catch (NoServiceProviderException ex) { - logger.log(Level.WARNING, String.format("Error translating text for file %s (objId=%d)", file.getName(), file.getId()), ex); - translation = Bundle.TranslatedContentViewer_noServiceProvider(); - } catch (TranslationException ex) { - logger.log(Level.WARNING, String.format("Error translating text for file %s (objId=%d)", file.getName(), file.getId()), ex); - translation = Bundle.TranslatedContentViewer_translationException(ex.getMessage()); - } - - if (this.isCancelled()) { - throw new InterruptedException(); - } - - return translation; - } - - @Override - public void done() { - try { - String result = get(); - if (this.isCancelled()) { - throw new InterruptedException(); - } - int len = result.length(); - int maxOrientChars = Math.min(len, 1024); - String orientDetectSubstring = result.substring(0, maxOrientChars); - ComponentOrientation orientation = TextUtil.getTextDirection(orientDetectSubstring); - panel.display(result, orientation, Font.PLAIN); - - } catch (InterruptedException | CancellationException ignored) { - // Task cancelled, no error. - } catch (ExecutionException ex) { - logger.log(Level.WARNING, String.format("Error occurred during background task execution for file %s (objId=%d)", file.getName(), file.getId()), ex); - panel.display(Bundle.TranslatedContentViewer_translationException(ex.getMessage()), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC); - } - } - - /** - * Pass the translation off to the Translation service provider. - * - * @param input Text to be translated - * - * @return Translated text or error message - */ - @NbBundle.Messages({ - "TranslatedContentViewer.emptyTranslation=The machine translation software did not return any text." - }) - private String translate(String input) throws NoServiceProviderException, TranslationException { - TextTranslationService translatorInstance = TextTranslationService.getInstance(); - String translatedResult = translatorInstance.translate(input); - if (translatedResult.isEmpty()) { - return Bundle.TranslatedContentViewer_emptyTranslation(); - } - return translatedResult; } /** @@ -275,13 +176,9 @@ public final class TranslatedTextViewer implements TextViewer { * * @return Extracted text * - * @throws IOException - * @throws InterruptedException - * @throws - * org.sleuthkit.autopsy.textextractors.TextExtractor.InitReaderException + * @throws Exception */ - private String getFileText(AbstractFile file) throws IOException, - InterruptedException, TextExtractor.InitReaderException { + protected String retrieveText() throws Exception { final boolean isImage = file.getMIMEType().toLowerCase().startsWith("image/"); // NON-NLS String result; @@ -382,8 +279,15 @@ public final class TranslatedTextViewer implements TextViewer { return TextExtractorFactory.getStringsExtractor(file, context).getReader(); } } + + + @Override + protected void onTextDisplay(String text, ComponentOrientation orientation, int font) { + panel.display(text, orientation, font); + } } + /** * Listens for drop-down selection changes and pushes processing off of the * EDT and into a SwingWorker.