diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 597af6c0735330705330881fda9e50677c194cfb..d3ac663a28d8335a844a675bbf525f11682025b5 100644 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -232,7 +232,8 @@ <build-prerequisite/> <compile-dependency/> <run-dependency> - <specification-version>1.0</specification-version> + <release-version>1</release-version> + <specification-version>23</specification-version> </run-dependency> </dependency> <dependency> diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index 3dc28a49be96bd49ab0a7d7ec005f275bda0d815..08c6f8f6d499cb85629a358873a4a7e9a2d1af2a 100644 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -62,6 +62,7 @@ public final class UserPreferences { private static final String MESSAGE_SERVICE_HOST = "MessageServiceHost"; //NON-NLS private static final String MESSAGE_SERVICE_PORT = "MessageServicePort"; //NON-NLS public static final String TEXT_TRANSLATOR_NAME = "TextTranslatorName"; + public static final String OCR_TRANSLATION_ENABLED = "OcrTranslationEnabled"; public static final String PROCESS_TIME_OUT_ENABLED = "ProcessTimeOutEnabled"; //NON-NLS public static final String PROCESS_TIME_OUT_HOURS = "ProcessTimeOutHours"; //NON-NLS private static final int DEFAULT_PROCESS_TIMEOUT_HR = 60; @@ -347,6 +348,14 @@ public static void setTextTranslatorName(String textTranslatorName) { public static String getTextTranslatorName() { return preferences.get(TEXT_TRANSLATOR_NAME, null); } + + public static void setUseOcrInTranslation(boolean enableOcr) { + preferences.putBoolean(OCR_TRANSLATION_ENABLED, enableOcr); + } + + public static boolean getUseOcrInTranslation() { + return preferences.getBoolean(OCR_TRANSLATION_ENABLED, true); + } /** * Persists message service connection info. @@ -623,4 +632,4 @@ public static String getAppTempDirectory() { return Paths.get(UserMachinePreferences.getBaseTempDirectory(), getAppName()) .toAbsolutePath().toString(); } -} +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutoWrappingJTextPane.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutoWrappingJTextPane.java index 8b739b8dcf792ce9cb962b535a993ce74ffd9527..1e4c1f4c6310b990c6b9231546594455d5e2eb88 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutoWrappingJTextPane.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutoWrappingJTextPane.java @@ -27,6 +27,7 @@ import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.InlineView; import javax.swing.text.html.ParagraphView; +import org.sleuthkit.autopsy.coreutils.EscapeUtil; /** * JTextPane extension that auto wraps input text using an HTMLEditorKit trick. @@ -98,6 +99,6 @@ protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirem @Override public void setText(String text) { - super.setText("<pre>" + text + "</pre>"); + super.setText("<pre>" + EscapeUtil.escapeHtml(text) + "</pre>"); } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java index fd833b59a77666559766fc0b4a558c624528845d..dc9e7c6d1df8f6f82227d50a958671bd08fefa30 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java @@ -20,7 +20,12 @@ import java.io.File; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; +import javax.imageio.ImageIO; +import javax.imageio.spi.IIORegistry; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.datamodel.AbstractFile; @@ -122,8 +127,53 @@ public void startUp(IngestJobContext context) throws IngestModuleException { } catch (NoCurrentCaseException ex) { throw new IngestModuleException(Bundle.EmbeddedFileExtractorIngestModule_UnableToGetMSOfficeExtractor_errMsg(), ex); } + + /** + * Initialize Java's Image I/O API so that image reading and writing + * (needed for image extraction) happens consistently through the + * same providers. See JIRA-6951 for more details. + */ + initializeImageIO(); } + + /** + * Initializes the ImageIO API and sorts the providers for + * deterministic image reading and writing. + */ + private void initializeImageIO() { + ImageIO.scanForPlugins(); + + // Sift through each registry category and sort category providers by + // their canonical class name. + IIORegistry pluginRegistry = IIORegistry.getDefaultInstance(); + Iterator<Class<?>> categories = pluginRegistry.getCategories(); + while(categories.hasNext()) { + sortPluginsInCategory(pluginRegistry, categories.next()); + } + } + + /** + * Sorts all ImageIO SPI providers by their class name. + */ + private <T> void sortPluginsInCategory(IIORegistry pluginRegistry, Class<T> category) { + Iterator<T> serviceProviderIter = pluginRegistry.getServiceProviders(category, false); + ArrayList<T> providers = new ArrayList<>(); + while (serviceProviderIter.hasNext()) { + providers.add(serviceProviderIter.next()); + } + Collections.sort(providers, (first, second) -> { + return first.getClass().getCanonicalName().compareToIgnoreCase(second.getClass().getCanonicalName()); + }); + for(int i = 0; i < providers.size() - 1; i++) { + for(int j = i + 1; j < providers.size(); j++) { + // The registry only accepts pairwise orderings. To guarantee a + // total order, all pairs need to be exhausted. + pluginRegistry.setOrdering(category, providers.get(i), + providers.get(j)); + } + } + } @Override public ProcessResult process(AbstractFile abstractFile) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/PDFAttachmentExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/PDFAttachmentExtractor.java index 15b1f1beb7cf590aa492688b5138f27a05dca080..9cea0f63e7d533fd7a82ebf357d978baba44b278 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/PDFAttachmentExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/PDFAttachmentExtractor.java @@ -123,7 +123,7 @@ public boolean shouldParseEmbedded(Metadata mtdt) { @Override public void parseEmbedded(InputStream in, ContentHandler ch, Metadata mtdt, boolean bln) throws SAXException, IOException { //Resource naming scheme is used internally in autopsy, therefore we can guarentee uniqueness. - String uniqueExtractedName = parentID + "_attch_" + attachmentCount++; //NON-NLS + String uniqueExtractedName = "extract_" + attachmentCount++; //NON-NLS String name = mtdt.get(Metadata.RESOURCE_NAME_KEY); String ext = FilenameUtils.getExtension(name); diff --git a/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java b/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java index a8bf0591fb8be981497c9752c7f97379311532e2..ee5b8d8fc340d8223abcdbb2328066d49026912b 100644 --- a/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2019 Basis Technology Corp. + * Copyright 2011-2020 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -46,7 +46,6 @@ import org.apache.tika.exception.TikaException; import org.apache.tika.metadata.Metadata; import org.apache.tika.parser.AutoDetectParser; -import org.apache.tika.parser.EmptyParser; import org.apache.tika.parser.ParseContext; import org.apache.tika.parser.Parser; import org.apache.tika.parser.ParsingReader; @@ -72,6 +71,9 @@ import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import com.google.common.collect.ImmutableMap; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import org.apache.tika.parser.pdf.PDFParserConfig.OCR_STRATEGY; /** * Extracts text from Tika supported content. Protects against Tika parser hangs @@ -126,16 +128,6 @@ final class TikaTextExtractor implements TextExtractor { "application/x-z", //NON-NLS "application/x-compress"); //NON-NLS - //Tika should ignore types with embedded files that can be handled by the unpacking modules - private static final List<String> EMBEDDED_FILE_MIME_TYPES - = ImmutableList.of("application/msword", //NON-NLS - "application/vnd.openxmlformats-officedocument.wordprocessingml.document", //NON-NLS - "application/vnd.ms-powerpoint", //NON-NLS - "application/vnd.openxmlformats-officedocument.presentationml.presentation", //NON-NLS - "application/vnd.ms-excel", //NON-NLS - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", //NON-NLS - "application/pdf"); //NON-NLS - // Used to log to the tika file that is why it uses the java.util.logging.logger class instead of the Autopsy one private static final java.util.logging.Logger TIKA_LOGGER = java.util.logging.Logger.getLogger("Tika"); //NON-NLS private static final Logger AUTOPSY_LOGGER = Logger.getLogger(TikaTextExtractor.class.getName()); @@ -193,52 +185,31 @@ private boolean ocrEnabled() { */ @Override public Reader getReader() throws InitReaderException { - InputStream stream = null; + if (!this.isSupported()) { + throw new InitReaderException("Content is not supported"); + } - ParseContext parseContext = new ParseContext(); + // Only abstract files are supported, see isSupported() + final AbstractFile file = ((AbstractFile) content); + // This mime type must be non-null, see isSupported() + final String mimeType = file.getMIMEType(); - //Disable appending embedded file text to output for EFE supported types - //JIRA-4975 - if(content instanceof AbstractFile && EMBEDDED_FILE_MIME_TYPES.contains(((AbstractFile)content).getMIMEType())) { - parseContext.set(Parser.class, new EmptyParser()); - } else { - parseContext.set(Parser.class, parser); + // Handle images seperately so the OCR task can be cancelled. + // See JIRA-4519 for the need to have cancellation in the UI and ingest. + if (ocrEnabled() && mimeType.toLowerCase().startsWith("image/")) { + InputStream imageOcrStream = performOCR(file); + return new InputStreamReader(imageOcrStream, Charset.forName("UTF-8")); } - if (ocrEnabled() && content instanceof AbstractFile) { - AbstractFile file = ((AbstractFile) content); - //Run OCR on images with Tesseract directly. - if (file.getMIMEType().toLowerCase().startsWith("image/")) { - stream = performOCR(file); - } else { - //Otherwise, go through Tika for PDFs so that it can - //extract images and run Tesseract on them. - PDFParserConfig pdfConfig = new PDFParserConfig(); - - // Extracting the inline images and letting Tesseract run on each inline image. - // https://wiki.apache.org/tika/PDFParser%20%28Apache%20PDFBox%29 - // https://tika.apache.org/1.7/api/org/apache/tika/parser/pdf/PDFParserConfig.html - pdfConfig.setExtractInlineImages(true); - // Multiple pages within a PDF file might refer to the same underlying image. - pdfConfig.setExtractUniqueInlineImagesOnly(true); - parseContext.set(PDFParserConfig.class, pdfConfig); - - // Configure Tesseract parser to perform OCR - TesseractOCRConfig ocrConfig = new TesseractOCRConfig(); - String tesseractFolder = TESSERACT_PATH.getParent(); - ocrConfig.setTesseractPath(tesseractFolder); - - ocrConfig.setLanguage(languagePacks); - ocrConfig.setTessdataPath(PlatformUtil.getOcrLanguagePacksPath()); - parseContext.set(TesseractOCRConfig.class, ocrConfig); - - stream = new ReadContentInputStream(content); - } - } else { - stream = new ReadContentInputStream(content); - } + // Set up Tika + final InputStream stream = new ReadContentInputStream(content); + final ParseContext parseContext = new ParseContext(); + + // Documents can contain other documents. By adding + // the parser back into the context, Tika will recursively + // parse embedded documents. + parseContext.set(Parser.class, parser); - Metadata metadata = new Metadata(); // Use the more memory efficient Tika SAX parsers for DOCX and // PPTX files (it already uses SAX for XLSX). OfficeParserConfig officeParserConfig = new OfficeParserConfig(); @@ -246,6 +217,30 @@ public Reader getReader() throws InitReaderException { officeParserConfig.setUseSAXDocxExtractor(true); parseContext.set(OfficeParserConfig.class, officeParserConfig); + if (ocrEnabled()) { + // Configure OCR for Tika if it chooses to run OCR + // during extraction + TesseractOCRConfig ocrConfig = new TesseractOCRConfig(); + String tesseractFolder = TESSERACT_PATH.getParent(); + ocrConfig.setTesseractPath(tesseractFolder); + ocrConfig.setLanguage(languagePacks); + ocrConfig.setTessdataPath(PlatformUtil.getOcrLanguagePacksPath()); + parseContext.set(TesseractOCRConfig.class, ocrConfig); + + // Configure how Tika handles OCRing PDFs + PDFParserConfig pdfConfig = new PDFParserConfig(); + + // This stategy tries to pick between OCRing a page in the + // PDF and doing text extraction. It makes this choice by + // first running text extraction and then counting characters. + // If there are too few characters or too many unmapped + // unicode characters, it'll run the entire page through OCR + // and take that output instead. See JIRA-6938 + pdfConfig.setOcrStrategy(OCR_STRATEGY.AUTO); + parseContext.set(PDFParserConfig.class, pdfConfig); + } + + Metadata metadata = new Metadata(); //Make the creation of a TikaReader a cancellable future in case it takes too long Future<Reader> future = executorService.submit( new GetTikaReader(parser, stream, metadata, parseContext)); @@ -568,4 +563,4 @@ public Reader openStream() throws IOException { return reader; } } -} +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/Bundle.properties b/Core/src/org/sleuthkit/autopsy/texttranslation/Bundle.properties index 5fcf80851cecb213007e7afdfc6620e247f46014..bd321cf49245a08d4ba4d6273a4faaddfb6d2350 100755 --- a/Core/src/org/sleuthkit/autopsy/texttranslation/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/Bundle.properties @@ -6,3 +6,4 @@ TranslationOptionsPanelController.moduleErr.msg=A module caused an error listeni TranslationContentPanel.showLabel.text=Show: TranslationOptionsPanel.translationServiceLabel.text=Text translator: TranslationOptionsPanel.translationOptionsDescription.text=Configure a 3rd party text translation service to enable text and file name translation. +TranslationOptionsPanel.enableOcrCheckBox.text=Enable Optical Character Recognition (OCR) in the translation content viewer diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/texttranslation/Bundle.properties-MERGED index 665c07c36f38a71178e045205ae64d61d2c48489..2da3aab4a42ece52fe1ce488c3d682020b7eb34e 100755 --- a/Core/src/org/sleuthkit/autopsy/texttranslation/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/Bundle.properties-MERGED @@ -10,3 +10,4 @@ TranslationOptionsPanelController.moduleErr.msg=A module caused an error listeni TranslationContentPanel.showLabel.text=Show: TranslationOptionsPanel.translationServiceLabel.text=Text translator: TranslationOptionsPanel.translationOptionsDescription.text=Configure a 3rd party text translation service to enable text and file name translation. +TranslationOptionsPanel.enableOcrCheckBox.text=Enable Optical Character Recognition (OCR) in the translation content viewer diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/TranslationOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/texttranslation/TranslationOptionsPanel.form index 52cd0fb65cd56c787bdc285f80e6ff9a1713f8a4..aadca0381f5f9243ea5fb27558a45c9180ac920c 100644 --- a/Core/src/org/sleuthkit/autopsy/texttranslation/TranslationOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/TranslationOptionsPanel.form @@ -16,17 +16,23 @@ <Layout> <DimensionLayout dim="0"> <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jSeparator1" alignment="0" max="32767" attributes="0"/> <Group type="102" attributes="0"> <EmptySpace max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> <Component id="translationServicePanel" max="32767" attributes="0"/> + <Component id="translationOptionsDescription" alignment="0" pref="462" max="32767" attributes="0"/> <Group type="102" attributes="0"> - <Component id="translationServiceLabel" min="-2" max="-2" attributes="0"/> - <EmptySpace min="-2" pref="10" max="-2" attributes="0"/> - <Component id="translatorComboBox" min="-2" pref="214" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <Component id="translationServiceLabel" min="-2" max="-2" attributes="0"/> + <EmptySpace min="-2" pref="10" max="-2" attributes="0"/> + <Component id="translatorComboBox" min="-2" pref="214" max="-2" attributes="0"/> + </Group> + <Component id="enableOcrCheckBox" alignment="0" min="-2" max="-2" attributes="0"/> + </Group> <EmptySpace min="0" pref="0" max="32767" attributes="0"/> </Group> - <Component id="translationOptionsDescription" alignment="0" pref="462" max="32767" attributes="0"/> </Group> <EmptySpace max="-2" attributes="0"/> </Group> @@ -42,9 +48,13 @@ <Component id="translatorComboBox" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="translationServiceLabel" alignment="3" min="-2" max="-2" attributes="0"/> </Group> - <EmptySpace min="-2" max="-2" attributes="0"/> - <Component id="translationServicePanel" max="32767" attributes="0"/> - <EmptySpace min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="translationServicePanel" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Component id="jSeparator1" min="-2" pref="10" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="enableOcrCheckBox" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> </Group> </Group> </DimensionLayout> @@ -76,5 +86,17 @@ </Property> </Properties> </Component> + <Component class="javax.swing.JSeparator" name="jSeparator1"> + </Component> + <Component class="javax.swing.JCheckBox" name="enableOcrCheckBox"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/sleuthkit/autopsy/texttranslation/Bundle.properties" key="TranslationOptionsPanel.enableOcrCheckBox.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="enableOcrCheckBoxActionPerformed"/> + </Events> + </Component> </SubComponents> -</Form> +</Form> \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/TranslationOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/texttranslation/TranslationOptionsPanel.java index 3c9ee7dc7b596fcffe3543bd5e17fa036ce1c3da..9fdb95b2b195424004ef2ab57a93425db8155ab7 100644 --- a/Core/src/org/sleuthkit/autopsy/texttranslation/TranslationOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/TranslationOptionsPanel.java @@ -111,6 +111,7 @@ final void load() { } translatorComboBox.setSelectedItem(currentSelection); loadSelectedPanelSettings(); + enableOcrCheckBox.setSelected(UserPreferences.getUseOcrInTranslation()); } /** @@ -128,6 +129,8 @@ void store() { logger.log(Level.WARNING, "Unable to save settings for TextTranslator named: " + currentSelection, ex); } } + // Save whether OCR is enabled in the content viewer + UserPreferences.setUseOcrInTranslation(enableOcrCheckBox.isSelected()); } @@ -144,6 +147,8 @@ private void initComponents() { translationServiceLabel = new javax.swing.JLabel(); translationServicePanel = new javax.swing.JPanel(); translationOptionsDescription = new javax.swing.JLabel(); + jSeparator1 = new javax.swing.JSeparator(); + enableOcrCheckBox = new javax.swing.JCheckBox(); translatorComboBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -157,20 +162,31 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { org.openide.awt.Mnemonics.setLocalizedText(translationOptionsDescription, org.openide.util.NbBundle.getMessage(TranslationOptionsPanel.class, "TranslationOptionsPanel.translationOptionsDescription.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(enableOcrCheckBox, org.openide.util.NbBundle.getMessage(TranslationOptionsPanel.class, "TranslationOptionsPanel.enableOcrCheckBox.text")); // NOI18N + enableOcrCheckBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + enableOcrCheckBoxActionPerformed(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSeparator1) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(translationServicePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(translationOptionsDescription, javax.swing.GroupLayout.DEFAULT_SIZE, 462, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() - .addComponent(translationServiceLabel) - .addGap(10, 10, 10) - .addComponent(translatorComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 214, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, Short.MAX_VALUE)) - .addComponent(translationOptionsDescription, javax.swing.GroupLayout.PREFERRED_SIZE, 462, Short.MAX_VALUE)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(translationServiceLabel) + .addGap(10, 10, 10) + .addComponent(translatorComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 214, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(enableOcrCheckBox)) + .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); layout.setVerticalGroup( @@ -183,8 +199,12 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { .addComponent(translatorComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(translationServiceLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(translationServicePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addContainerGap()) + .addComponent(translationServicePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(enableOcrCheckBox) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); }// </editor-fold>//GEN-END:initComponents @@ -192,12 +212,18 @@ private void translatorComboBoxActionPerformed(java.awt.event.ActionEvent evt) { updatePanel(); }//GEN-LAST:event_translatorComboBoxActionPerformed + private void enableOcrCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enableOcrCheckBoxActionPerformed + controller.changed(); + }//GEN-LAST:event_enableOcrCheckBoxActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox enableOcrCheckBox; + private javax.swing.JSeparator jSeparator1; private javax.swing.JLabel translationOptionsDescription; private javax.swing.JLabel translationServiceLabel; private javax.swing.JPanel translationServicePanel; private javax.swing.JComboBox<String> translatorComboBox; // End of variables declaration//GEN-END:variables -} +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties-MERGED index 802b117c351825b0d356d2edc3a92e7d8241b992..c87d7ae238f3a370f268e24307cc8dc203a97189 100644 --- a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties-MERGED @@ -8,6 +8,7 @@ TranslatedContentViewer.errorExtractingText=An error occurred while extracting t TranslatedContentViewer.extractingText=Extracting text, please wait... TranslatedContentViewer.fileHasNoText=File has no text. TranslatedContentViewer.noServiceProvider=The machine translation software was not found. +TranslatedContentViewer.ocrNotEnabled=OCR is not enabled. To change, go to Tools->Options->Machine Translation TranslatedContentViewer.translatingText=Translating text, please wait... # {0} - exception message TranslatedContentViewer.translationException=An error occurred while translating the text ({0}). diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslatedTextViewer.java b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslatedTextViewer.java index ab0b9de083dae2a21e885286e7725d2531fd1132..6b04427e92724cfdbc62e25e5c20d65944e6c585 100644 --- a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslatedTextViewer.java +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslatedTextViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2020 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,16 +38,15 @@ import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.lookup.Lookups; -import org.sleuthkit.autopsy.corecomponents.DataContentViewerUtility; import org.sleuthkit.autopsy.coreutils.ExecUtil.ProcessTerminator; import org.sleuthkit.autopsy.textextractors.TextExtractor; import org.sleuthkit.autopsy.textextractors.TextExtractorFactory; import org.sleuthkit.autopsy.textextractors.configs.ImageConfig; import org.sleuthkit.autopsy.texttranslation.TextTranslationService; -import org.sleuthkit.datamodel.Content; import java.util.List; import java.util.logging.Level; import javax.swing.SwingUtilities; +import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.texttranslation.ui.TranslationContentPanel.DisplayDropdownOptions; @@ -60,8 +59,6 @@ public final class TranslatedTextViewer implements TextViewer { private static final Logger logger = Logger.getLogger(TranslatedTextViewer.class.getName()); - private static final boolean OCR_ENABLED = true; - private static final boolean OCR_DISABLED = false; private static final int MAX_EXTRACT_SIZE_BYTES = 25600; private static final List<String> INSTALLED_LANGUAGE_PACKS = PlatformUtil.getOcrLanguagePacks(); private final TranslationContentPanel panel = new TranslationContentPanel(); @@ -81,15 +78,10 @@ public void setNode(final Node node) { SelectionChangeListener displayDropDownListener = new DisplayDropDownChangeListener(); panel.addDisplayTextActionListener(displayDropDownListener); panel.addOcrDropDownActionListener(new OCRDropdownChangeListener()); - Content source = DataContentViewerUtility.getDefaultContent(node); - - if (source instanceof AbstractFile) { - boolean isImage = ((AbstractFile) source).getMIMEType().toLowerCase().startsWith("image/"); - if (isImage) { - panel.enableOCRSelection(OCR_ENABLED); - panel.addLanguagePackNames(INSTALLED_LANGUAGE_PACKS); - } + if (UserPreferences.getUseOcrInTranslation()) { + panel.addLanguagePackNames(INSTALLED_LANGUAGE_PACKS); } + panel.enableOCRSelection(UserPreferences.getUseOcrInTranslation()); int payloadMaxInKB = TextTranslationService.getInstance().getMaxTextChars() / 1000; panel.setWarningLabelMsg(String.format(Bundle.TranslatedTextViewer_maxPayloadSize(), payloadMaxInKB)); @@ -201,14 +193,16 @@ protected String retrieveText() throws IOException, InterruptedException, Illega * @throws * org.sleuthkit.autopsy.textextractors.TextExtractor.InitReaderException */ + @NbBundle.Messages({ + "TranslatedContentViewer.ocrNotEnabled=OCR is not enabled. To change, go to Tools->Options->Machine Translation", + }) private String getFileText(AbstractFile file) throws IOException, InterruptedException, TextExtractor.InitReaderException { final boolean isImage = file.getMIMEType().toLowerCase().startsWith("image/"); // NON-NLS - String result; - if (isImage) { - result = extractText(file, OCR_ENABLED); - } else { - result = extractText(file, OCR_DISABLED); + if (isImage && ! UserPreferences.getUseOcrInTranslation()) { + return Bundle.TranslatedContentViewer_ocrNotEnabled(); } + + String result = extractText(file, UserPreferences.getUseOcrInTranslation()); //Correct for UTF-8 byte[] resultInUTF8Bytes = result.getBytes("UTF8"); @@ -363,4 +357,4 @@ String getSelection() { return panel.getSelectedOcrLanguagePack(); } } -} +} \ No newline at end of file diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/README.txt b/Core/test/qa-functional/src/org/sleuthkit/autopsy/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..139b74c67f5b237438881f0bf0cd6a7bf27ff860 --- /dev/null +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/README.txt @@ -0,0 +1 @@ +Netbeans platform does not properly scope classloaders while running qa-functional test code. The result is that NoClassDefError's occur in instances where an external jar (i.e. importing a class from common-io) is referenced in test code and the same external jar is referenced in multiple NBM's. Importing from external jars in qa-functional should be avoided. See jira issue 6954 for more information. \ No newline at end of file diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccountsTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccountsTest.java index ff8bd34250a18244b06e5020360aefef0e6a8c40..a87c2959badf359285f1e25271cc84660c47f092 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccountsTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccountsTest.java @@ -25,11 +25,10 @@ import junit.framework.Assert; import junit.framework.TestCase; import junit.framework.Test; -import org.apache.commons.io.FileUtils; import org.netbeans.junit.NbModuleSuite; -import org.openide.util.Exceptions; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount.CentralRepoAccountType; +import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.InvalidAccountIDException; @@ -95,7 +94,8 @@ public void tearDown() throws CentralRepoException, IOException { if (CentralRepository.isEnabled()) { CentralRepository.getInstance().shutdownConnections(); } - FileUtils.deleteDirectory(testDirectory.toFile()); + + FileUtil.deleteDir(testDirectory.toFile()); } public void testPredefinedAccountTypes() { diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index bf71e5f6a7be0a1dae04083894f2a475bd583177..357d5e0641786ffa040ca6c314144d544c43407a 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -35,7 +35,6 @@ import java.util.stream.IntStream; import junit.framework.Test; import junit.framework.TestCase; -import org.apache.commons.io.FileUtils; import org.netbeans.junit.NbModuleSuite; import org.openide.util.Exceptions; import junit.framework.Assert; @@ -47,6 +46,7 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.coreutils.FileUtil; /** * Functional tests for the Central Repository data model. @@ -100,8 +100,8 @@ public void setUp() { if (CentralRepository.isEnabled()) { CentralRepository.getInstance().shutdownConnections(); } - FileUtils.deleteDirectory(testDirectory.toFile()); - } catch (IOException | CentralRepoException ex) { + FileUtil.deleteDir(testDirectory.toFile()); + } catch (CentralRepoException ex) { Assert.fail(ex.getMessage()); } } @@ -194,8 +194,8 @@ public void tearDown() { if (CentralRepository.isEnabled()) { CentralRepository.getInstance().shutdownConnections(); } - FileUtils.deleteDirectory(testDirectory.toFile()); - } catch (CentralRepoException | IOException ex) { + FileUtil.deleteDir(testDirectory.toFile()); + } catch (CentralRepoException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoPersonasTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoPersonasTest.java index bbe5ae58f5ad797866212191920eb34b8bed19bb..60636e5f54b5f11793cf5c9fe1d225db88e7f2b9 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoPersonasTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoPersonasTest.java @@ -28,10 +28,10 @@ import static junit.framework.Assert.assertTrue; import junit.framework.TestCase; import junit.framework.Test; -import org.apache.commons.io.FileUtils; import org.netbeans.junit.NbModuleSuite; import org.openide.util.Exceptions; +import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.InvalidAccountIDException; import org.sleuthkit.datamodel.TskData; @@ -257,12 +257,12 @@ public void setUp() throws CentralRepoException, IOException { // This function is run after every test, NOT after the entire collection of // tests defined in the class are run. @Override - public void tearDown() throws CentralRepoException, IOException { + public void tearDown() throws CentralRepoException { // Close and delete the test case and central repo db if (CentralRepository.isEnabled()) { CentralRepository.getInstance().shutdownConnections(); } - FileUtils.deleteDirectory(testDirectory.toFile()); + FileUtil.deleteDir(testDirectory.toFile()); } diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseTestUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseTestUtils.java index 85fe4d91c7e01650bf160572b4316d739fb177bf..014b08fe84bdaa59a7620f197276bb055af7106e 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseTestUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseTestUtils.java @@ -28,7 +28,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; -import org.apache.commons.io.FileUtils; import org.netbeans.junit.NbTestCase; import org.openide.util.Exceptions; import org.sleuthkit.autopsy.casemodule.Case; @@ -63,6 +62,7 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.RdbmsCentralRepoFactory; +import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.modules.pictureanalyzer.PictureAnalyzerIngestModuleFactory; /** @@ -247,8 +247,8 @@ void clearTestDir() { if (CentralRepository.isEnabled()) { CentralRepository.getInstance().shutdownConnections(); } - FileUtils.deleteDirectory(CENTRAL_REPO_DIRECTORY_PATH.toFile()); - } catch (IOException | CentralRepoException ex) { + FileUtil.deleteDir(CENTRAL_REPO_DIRECTORY_PATH.toFile()); + } catch (CentralRepoException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } diff --git a/Experimental/nbproject/project.xml b/Experimental/nbproject/project.xml index 1679c1c1230be00fd7095fe7d6c7ad53d84184e5..5f0b81a006a7447b3d9dc79e2e173e1007e66d14 100644 --- a/Experimental/nbproject/project.xml +++ b/Experimental/nbproject/project.xml @@ -134,7 +134,8 @@ <build-prerequisite/> <compile-dependency/> <run-dependency> - <specification-version>1.0</specification-version> + <release-version>1</release-version> + <specification-version>23</specification-version> </run-dependency> </dependency> <dependency> diff --git a/KeywordSearch/nbproject/project.xml b/KeywordSearch/nbproject/project.xml index 930acbf4dbf897a4244c3343d6bf386dca35c93b..bc85fdb6e58bd0a55d1fca545385818f6b31923f 100644 --- a/KeywordSearch/nbproject/project.xml +++ b/KeywordSearch/nbproject/project.xml @@ -118,7 +118,8 @@ <build-prerequisite/> <compile-dependency/> <run-dependency> - <specification-version>1.0</specification-version> + <release-version>1</release-version> + <specification-version>23</specification-version> </run-dependency> </dependency> <dependency> diff --git a/Tika/manifest.mf b/Tika/manifest.mf index 770d374a5dae80ad25a8523b23518be57616a903..d5e404d1e321247c95869053adb97024d560007c 100755 --- a/Tika/manifest.mf +++ b/Tika/manifest.mf @@ -1,6 +1,7 @@ Manifest-Version: 1.0 AutoUpdate-Show-In-Client: true -OpenIDE-Module: org.sleuthkit.autopsy.Tika +OpenIDE-Module: org.sleuthkit.autopsy.Tika/1 +OpenIDE-Module-Implementation-Version: 1 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/Tika/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 +OpenIDE-Module-Specification-Version: 23 diff --git a/ZookeeperNodeMigration/.gitignore b/ZookeeperNodeMigration/.gitignore new file mode 100755 index 0000000000000000000000000000000000000000..0e56a449c757c3333320e858ada0ebab0df8aff1 --- /dev/null +++ b/ZookeeperNodeMigration/.gitignore @@ -0,0 +1,3 @@ +/nbproject/private/ +/build/ + diff --git a/ZookeeperNodeMigration/build.xml b/ZookeeperNodeMigration/build.xml new file mode 100755 index 0000000000000000000000000000000000000000..9705ad356248cef6782814262fc6f228f2317ef6 --- /dev/null +++ b/ZookeeperNodeMigration/build.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See commented blocks below for --> +<!-- some examples of how to customize the build. --> +<!-- (If you delete it and reopen the project it will be recreated.) --> +<!-- By default, only the Clean and Build commands use this build script. --> +<!-- Commands such as Run, Debug, and Test only use this build script if --> +<!-- the Compile on Save feature is turned off for the project. --> +<!-- You can turn off the Compile on Save (or Deploy on Save) setting --> +<!-- in the project's Project Properties dialog box.--> +<project name="ZookeeperNodeMigration" default="default" basedir="."> + <description>Builds, tests, and runs the project ZookeeperNodeMigration.</description> + <import file="nbproject/build-impl.xml"/> + <!-- + + There exist several targets which are by default empty and which can be + used for execution of your tasks. These targets are usually executed + before and after some main targets. They are: + + -pre-init: called before initialization of project properties + -post-init: called after initialization of project properties + -pre-compile: called before javac compilation + -post-compile: called after javac compilation + -pre-compile-single: called before javac compilation of single file + -post-compile-single: called after javac compilation of single file + -pre-compile-test: called before javac compilation of JUnit tests + -post-compile-test: called after javac compilation of JUnit tests + -pre-compile-test-single: called before javac compilation of single JUnit test + -post-compile-test-single: called after javac compilation of single JUunit test + -pre-jar: called before JAR building + -post-jar: called after JAR building + -post-clean: called after cleaning build products + + (Targets beginning with '-' are not intended to be called on their own.) + + Example of inserting an obfuscator after compilation could look like this: + + <target name="-post-compile"> + <obfuscate> + <fileset dir="${build.classes.dir}"/> + </obfuscate> + </target> + + For list of available properties check the imported + nbproject/build-impl.xml file. + + + Another way to customize the build is by overriding existing main targets. + The targets of interest are: + + -init-macrodef-javac: defines macro for javac compilation + -init-macrodef-junit: defines macro for junit execution + -init-macrodef-debug: defines macro for class debugging + -init-macrodef-java: defines macro for class execution + -do-jar: JAR building + run: execution of project + -javadoc-build: Javadoc generation + test-report: JUnit report generation + + An example of overriding the target for project execution could look like this: + + <target name="run" depends="ZookeeperNodeMigration-impl.jar"> + <exec dir="bin" executable="launcher.exe"> + <arg file="${dist.jar}"/> + </exec> + </target> + + Notice that the overridden target depends on the jar target and not only on + the compile target as the regular run target does. Again, for a list of available + properties which you can use, check the target you are overriding in the + nbproject/build-impl.xml file. + + --> +</project> diff --git a/ZookeeperNodeMigration/dist/README.TXT b/ZookeeperNodeMigration/dist/README.TXT new file mode 100755 index 0000000000000000000000000000000000000000..087be91dc31eb0fb650174d53e82429dc4ad988a --- /dev/null +++ b/ZookeeperNodeMigration/dist/README.TXT @@ -0,0 +1,32 @@ +======================== +BUILD OUTPUT DESCRIPTION +======================== + +When you build an Java application project that has a main class, the IDE +automatically copies all of the JAR +files on the projects classpath to your projects dist/lib folder. The IDE +also adds each of the JAR files to the Class-Path element in the application +JAR files manifest file (MANIFEST.MF). + +To run the project from the command line, go to the dist folder and +type the following: + +java -jar "ZookeeperNodeMigration.jar" + +To distribute this project, zip up the dist folder (including the lib folder) +and distribute the ZIP file. + +Notes: + +* If two JAR files on the project classpath have the same name, only the first +JAR file is copied to the lib folder. +* Only JAR files are copied to the lib folder. +If the classpath contains other types of files or folders, these files (folders) +are not copied. +* If a library on the projects classpath also has a Class-Path element +specified in the manifest,the content of the Class-Path element has to be on +the projects runtime path. +* To set a main class in a standard Java project, right-click the project node +in the Projects window and choose Properties. Then click Run and enter the +class name in the Main Class field. Alternatively, you can manually type the +class name in the manifest Main-Class element. diff --git a/ZookeeperNodeMigration/dist/ZookeeperNodeMigration.jar b/ZookeeperNodeMigration/dist/ZookeeperNodeMigration.jar new file mode 100755 index 0000000000000000000000000000000000000000..92b11bc86ac07058ee7d31ad5a4a2028869611ca Binary files /dev/null and b/ZookeeperNodeMigration/dist/ZookeeperNodeMigration.jar differ diff --git a/ZookeeperNodeMigration/dist/lib/curator-client-2.8.0.jar b/ZookeeperNodeMigration/dist/lib/curator-client-2.8.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..4ccc265cc43f05ea6b11ecd7427bbd5614d6a34a Binary files /dev/null and b/ZookeeperNodeMigration/dist/lib/curator-client-2.8.0.jar differ diff --git a/ZookeeperNodeMigration/dist/lib/curator-framework-2.8.0.jar b/ZookeeperNodeMigration/dist/lib/curator-framework-2.8.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..5e488892d150125f0e8f68e6ebc48b1a8cc1efd1 Binary files /dev/null and b/ZookeeperNodeMigration/dist/lib/curator-framework-2.8.0.jar differ diff --git a/ZookeeperNodeMigration/dist/lib/curator-recipes-2.8.0.jar b/ZookeeperNodeMigration/dist/lib/curator-recipes-2.8.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..34eb9c9677da222d00eac423a49c594032e8c743 Binary files /dev/null and b/ZookeeperNodeMigration/dist/lib/curator-recipes-2.8.0.jar differ diff --git a/ZookeeperNodeMigration/dist/lib/guava-17.0.jar b/ZookeeperNodeMigration/dist/lib/guava-17.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..661fc7473f8760f5f81874ddc1fcc0b5634fd6cf Binary files /dev/null and b/ZookeeperNodeMigration/dist/lib/guava-17.0.jar differ diff --git a/ZookeeperNodeMigration/dist/lib/log4j-1.2.17.jar b/ZookeeperNodeMigration/dist/lib/log4j-1.2.17.jar new file mode 100755 index 0000000000000000000000000000000000000000..1d425cf7d7e25f81be64d32c406ff66cfb6c4766 Binary files /dev/null and b/ZookeeperNodeMigration/dist/lib/log4j-1.2.17.jar differ diff --git a/ZookeeperNodeMigration/dist/lib/slf4j-api-1.7.24.jar b/ZookeeperNodeMigration/dist/lib/slf4j-api-1.7.24.jar new file mode 100755 index 0000000000000000000000000000000000000000..05941a12f06a99523b748da14d31e76265ed8b78 Binary files /dev/null and b/ZookeeperNodeMigration/dist/lib/slf4j-api-1.7.24.jar differ diff --git a/ZookeeperNodeMigration/dist/lib/slf4j-log4j12-1.7.6.jar b/ZookeeperNodeMigration/dist/lib/slf4j-log4j12-1.7.6.jar new file mode 100755 index 0000000000000000000000000000000000000000..d1cc2456e4a4bb35a87215ab9264b631d98dbf05 Binary files /dev/null and b/ZookeeperNodeMigration/dist/lib/slf4j-log4j12-1.7.6.jar differ diff --git a/ZookeeperNodeMigration/dist/lib/zookeeper-3.4.6.jar b/ZookeeperNodeMigration/dist/lib/zookeeper-3.4.6.jar new file mode 100755 index 0000000000000000000000000000000000000000..7c340be9f5d25d753508297c0b35f2b5a9d6ab85 Binary files /dev/null and b/ZookeeperNodeMigration/dist/lib/zookeeper-3.4.6.jar differ diff --git a/ZookeeperNodeMigration/docs/README.TXT b/ZookeeperNodeMigration/docs/README.TXT new file mode 100755 index 0000000000000000000000000000000000000000..9f5b8f4ca9b92f2d2c881d423da24ee618de8c5c --- /dev/null +++ b/ZookeeperNodeMigration/docs/README.TXT @@ -0,0 +1,23 @@ +To run the project from the command line, go to the folder that contains "ZookeeperNodeMigration.jar" and +type the following: + +java -jar ZookeeperNodeMigration.jar + +To distribute this project, zip up the dist folder (including the lib folder) +and distribute the ZIP file. + +Usage: +ZookeeperNodeMigration input needs to be: +[Input Zookeeper IP Address or Hostname] [Input Zookeeper Port Number] [Output Zookeeper IP Address or Hostname] [Output Zookeeper Port Number] + +For example, if you execute the following command from command line line, the Zookeeper +nodes will get copied from Zookeeper server on localhost:9983 to Zookeeper server on localhost:19983 : + +java -jar ZookeeperNodeMigration.jar localhost 9983 localhost 19983 + + +If you do not have Java installed on the machine, you can use the packaged version of Java that is distributed along +with Autopsy. For example: + +"C:\Program Files\Autopsy-4.16.0\jre\bin\java.exe" -jar ZookeeperNodeMigration.jar localhost 9983 localhost 19983 + diff --git a/ZookeeperNodeMigration/manifest.mf b/ZookeeperNodeMigration/manifest.mf new file mode 100755 index 0000000000000000000000000000000000000000..328e8e5bc3b7f1f7bad2bc0751a933e00c801983 --- /dev/null +++ b/ZookeeperNodeMigration/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/ZookeeperNodeMigration/nbproject/build-impl.xml b/ZookeeperNodeMigration/nbproject/build-impl.xml new file mode 100755 index 0000000000000000000000000000000000000000..76af3c9f63e71e8635a4f2a0e7489b3af2a0d80a --- /dev/null +++ b/ZookeeperNodeMigration/nbproject/build-impl.xml @@ -0,0 +1,1770 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** + +For the purpose of easier reading the script +is divided into following sections: + + - initialization + - compilation + - jar + - execution + - debugging + - javadoc + - test compilation + - test execution + - test debugging + - applet + - cleanup + + --> +<project xmlns:if="ant:if" xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" xmlns:unless="ant:unless" basedir=".." default="default" name="ZookeeperNodeMigration-impl"> + <fail message="Please build using Ant 1.8.0 or higher."> + <condition> + <not> + <antversion atleast="1.8.0"/> + </not> + </condition> + </fail> + <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/> + <!-- + ====================== + INITIALIZATION SECTION + ====================== + --> + <target name="-pre-init"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="-pre-init" name="-init-private"> + <property file="nbproject/private/config.properties"/> + <property file="nbproject/private/configs/${config}.properties"/> + <property file="nbproject/private/private.properties"/> + </target> + <target depends="-pre-init,-init-private" name="-init-user"> + <property file="${user.properties.file}"/> + <!-- The two properties below are usually overridden --> + <!-- by the active platform. Just a fallback. --> + <property name="default.javac.source" value="1.6"/> + <property name="default.javac.target" value="1.6"/> + </target> + <target depends="-pre-init,-init-private,-init-user" name="-init-project"> + <property file="nbproject/configs/${config}.properties"/> + <property file="nbproject/project.properties"/> + </target> + <target name="-init-modules-supported"> + <condition property="modules.supported.internal" value="true"> + <not> + <matches pattern="1\.[0-8](\..*)?" string="${javac.source}"/> + </not> + </condition> + </target> + <target depends="-init-modules-supported" if="modules.supported.internal" name="-init-macrodef-modulename"> + <macrodef name="modulename" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute name="property"/> + <attribute name="sourcepath"/> + <sequential> + <loadresource property="@{property}" quiet="true"> + <javaresource classpath="@{sourcepath}" name="module-info.java" parentFirst="false"/> + <filterchain> + <stripjavacomments/> + <linecontainsregexp> + <regexp pattern="module .* \{"/> + </linecontainsregexp> + <tokenfilter> + <linetokenizer/> + <replaceregex flags="s" pattern="(\s*module\s+)(\S*)(\s*\{.*)" replace="\2"/> + </tokenfilter> + <striplinebreaks/> + </filterchain> + </loadresource> + </sequential> + </macrodef> + </target> + <target depends="-init-modules-supported,-init-macrodef-modulename" if="modules.supported.internal" name="-init-source-module-properties"> + <fail message="Java 9 support requires Ant 1.10.0 or higher."> + <condition> + <not> + <antversion atleast="1.10.0"/> + </not> + </condition> + </fail> + <j2seproject3:modulename property="module.name" sourcepath="${src.dir}"/> + <condition property="named.module.internal"> + <and> + <isset property="module.name"/> + <length length="0" string="${module.name}" when="greater"/> + </and> + </condition> + <condition property="unnamed.module.internal"> + <not> + <isset property="named.module.internal"/> + </not> + </condition> + <property name="javac.modulepath" value=""/> + <property name="run.modulepath" value="${javac.modulepath}"/> + <property name="module.build.classes.dir" value="${build.classes.dir}"/> + <property name="debug.modulepath" value="${run.modulepath}"/> + <property name="javac.upgrademodulepath" value=""/> + <property name="run.upgrademodulepath" value="${javac.upgrademodulepath}"/> + <condition else="" property="javac.systemmodulepath.cmd.line.arg" value="--system '${javac.systemmodulepath}'"> + <and> + <isset property="javac.systemmodulepath"/> + <length length="0" string="${javac.systemmodulepath}" when="greater"/> + </and> + </condition> + <property name="dist.jlink.dir" value="${dist.dir}/jlink"/> + <property name="dist.jlink.output" value="${dist.jlink.dir}/${application.title}"/> + <property name="module.name" value=""/> + </target> + <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property,-init-modules-supported" name="-do-init"> + <property name="platform.java" value="${java.home}/bin/java"/> + <available file="${manifest.file}" property="manifest.available"/> + <condition property="splashscreen.available"> + <and> + <not> + <equals arg1="${application.splash}" arg2="" trim="true"/> + </not> + <available file="${application.splash}"/> + </and> + </condition> + <condition property="main.class.available"> + <and> + <isset property="main.class"/> + <not> + <equals arg1="${main.class}" arg2="" trim="true"/> + </not> + </and> + </condition> + <condition property="profile.available"> + <and> + <isset property="javac.profile"/> + <length length="0" string="${javac.profile}" when="greater"/> + <not> + <matches pattern="1\.[0-7](\..*)?" string="${javac.source}"/> + </not> + </and> + </condition> + <condition property="do.archive"> + <or> + <not> + <istrue value="${jar.archive.disabled}"/> + </not> + <istrue value="${not.archive.disabled}"/> + </or> + </condition> + <condition property="do.archive+manifest.available"> + <and> + <isset property="manifest.available"/> + <istrue value="${do.archive}"/> + </and> + </condition> + <condition property="do.archive+main.class.available"> + <and> + <isset property="main.class.available"/> + <istrue value="${do.archive}"/> + </and> + </condition> + <condition property="do.archive+splashscreen.available"> + <and> + <isset property="splashscreen.available"/> + <istrue value="${do.archive}"/> + </and> + </condition> + <condition property="do.archive+profile.available"> + <and> + <isset property="profile.available"/> + <istrue value="${do.archive}"/> + </and> + </condition> + <condition property="have.tests"> + <or> + <available file="${test.src.dir}"/> + </or> + </condition> + <condition property="have.sources"> + <or> + <available file="${src.dir}"/> + </or> + </condition> + <condition property="netbeans.home+have.tests"> + <and> + <isset property="netbeans.home"/> + <isset property="have.tests"/> + </and> + </condition> + <condition property="no.javadoc.preview"> + <and> + <isset property="javadoc.preview"/> + <isfalse value="${javadoc.preview}"/> + </and> + </condition> + <property name="run.jvmargs" value=""/> + <property name="run.jvmargs.ide" value=""/> + <property name="javac.compilerargs" value=""/> + <property name="work.dir" value="${basedir}"/> + <condition property="no.deps"> + <and> + <istrue value="${no.dependencies}"/> + </and> + </condition> + <property name="javac.debug" value="true"/> + <property name="javadoc.preview" value="true"/> + <property name="application.args" value=""/> + <property name="source.encoding" value="${file.encoding}"/> + <property name="runtime.encoding" value="${source.encoding}"/> + <property name="manifest.encoding" value="${source.encoding}"/> + <condition property="javadoc.encoding.used" value="${javadoc.encoding}"> + <and> + <isset property="javadoc.encoding"/> + <not> + <equals arg1="${javadoc.encoding}" arg2=""/> + </not> + </and> + </condition> + <property name="javadoc.encoding.used" value="${source.encoding}"/> + <property name="includes" value="**"/> + <property name="excludes" value=""/> + <property name="do.depend" value="false"/> + <condition property="do.depend.true"> + <istrue value="${do.depend}"/> + </condition> + <path id="endorsed.classpath.path" path="${endorsed.classpath}"/> + <condition else="" property="endorsed.classpath.cmd.line.arg" value="-Xbootclasspath/p:'${toString:endorsed.classpath.path}'"> + <and> + <isset property="endorsed.classpath"/> + <not> + <equals arg1="${endorsed.classpath}" arg2="" trim="true"/> + </not> + </and> + </condition> + <condition else="" property="javac.profile.cmd.line.arg" value="-profile ${javac.profile}"> + <isset property="profile.available"/> + </condition> + <condition else="false" property="jdkBug6558476"> + <and> + <matches pattern="1\.[56]" string="${java.specification.version}"/> + <not> + <os family="unix"/> + </not> + </and> + </condition> + <condition else="false" property="javac.fork"> + <or> + <istrue value="${jdkBug6558476}"/> + <istrue value="${javac.external.vm}"/> + </or> + </condition> + <property name="jar.index" value="false"/> + <property name="jar.index.metainf" value="${jar.index}"/> + <property name="copylibs.rebase" value="true"/> + <available file="${meta.inf.dir}/persistence.xml" property="has.persistence.xml"/> + <condition property="junit.available"> + <or> + <available classname="org.junit.Test" classpath="${run.test.classpath}"/> + <available classname="junit.framework.Test" classpath="${run.test.classpath}"/> + </or> + </condition> + <condition property="testng.available"> + <available classname="org.testng.annotations.Test" classpath="${run.test.classpath}"/> + </condition> + <condition property="junit+testng.available"> + <and> + <istrue value="${junit.available}"/> + <istrue value="${testng.available}"/> + </and> + </condition> + <condition else="testng" property="testng.mode" value="mixed"> + <istrue value="${junit+testng.available}"/> + </condition> + <condition else="" property="testng.debug.mode" value="-mixed"> + <istrue value="${junit+testng.available}"/> + </condition> + <property name="java.failonerror" value="true"/> + </target> + <target name="-post-init"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check"> + <fail unless="src.dir">Must set src.dir</fail> + <fail unless="test.src.dir">Must set test.src.dir</fail> + <fail unless="build.dir">Must set build.dir</fail> + <fail unless="dist.dir">Must set dist.dir</fail> + <fail unless="build.classes.dir">Must set build.classes.dir</fail> + <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail> + <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail> + <fail unless="build.test.results.dir">Must set build.test.results.dir</fail> + <fail unless="build.classes.excludes">Must set build.classes.excludes</fail> + <fail unless="dist.jar">Must set dist.jar</fail> + </target> + <target name="-init-macrodef-property"> + <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + </target> + <target depends="-init-ap-cmdline-properties,-init-source-module-properties" if="modules.supported.internal" name="-init-macrodef-javac-with-module"> + <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${src.dir}" name="srcdir"/> + <attribute default="${build.classes.dir}" name="destdir"/> + <attribute default="${javac.classpath}" name="classpath"/> + <attribute default="${javac.modulepath}" name="modulepath"/> + <attribute default="${javac.upgrademodulepath}" name="upgrademodulepath"/> + <attribute default="${javac.processorpath}" name="processorpath"/> + <attribute default="${javac.processormodulepath}" name="processormodulepath"/> + <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="${javac.debug}" name="debug"/> + <attribute default="${empty.dir}" name="sourcepath" unless:set="named.module.internal"/> + <attribute default="${src.dir}" if:set="named.module.internal" name="sourcepath"/> + <attribute default="${empty.dir}" name="gensrcdir"/> + <element name="customize" optional="true"/> + <sequential> + <condition property="warn.excludes.internal"> + <and> + <isset property="named.module.internal"/> + <length length="0" string="@{excludes}" trim="true" when="greater"/> + </and> + </condition> + <echo if:set="warn.excludes.internal" level="warning" message="The javac excludes are not supported in the JDK 9 Named Module."/> + <property location="${build.dir}/empty" name="empty.dir"/> + <mkdir dir="${empty.dir}"/> + <mkdir dir="@{apgeneratedsrcdir}"/> + <condition property="processormodulepath.set"> + <resourcecount count="0" when="greater"> + <path> + <pathelement path="@{processormodulepath}"/> + </path> + </resourcecount> + </condition> + <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}"> + <src> + <dirset dir="@{gensrcdir}" erroronmissingdir="false"> + <include name="*"/> + </dirset> + </src> + <classpath> + <path path="@{classpath}"/> + </classpath> + <modulepath> + <path path="@{modulepath}"/> + </modulepath> + <upgrademodulepath> + <path path="@{upgrademodulepath}"/> + </upgrademodulepath> + <compilerarg line="${javac.systemmodulepath.cmd.line.arg}"/> + <compilerarg line="${javac.profile.cmd.line.arg}"/> + <compilerarg line="${javac.compilerargs}"/> + <compilerarg if:set="processormodulepath.set" value="--processor-module-path"/> + <compilerarg if:set="processormodulepath.set" path="@{processormodulepath}"/> + <compilerarg unless:set="processormodulepath.set" value="-processorpath"/> + <compilerarg path="@{processorpath}:${empty.dir}" unless:set="processormodulepath.set"/> + <compilerarg line="${ap.processors.internal}"/> + <compilerarg line="${annotation.processing.processor.options}"/> + <compilerarg value="-s"/> + <compilerarg path="@{apgeneratedsrcdir}"/> + <compilerarg line="${ap.proc.none.internal}"/> + <customize/> + </javac> + </sequential> + </macrodef> + </target> + <target depends="-init-ap-cmdline-properties,-init-source-module-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors" unless="modules.supported.internal"> + <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${src.dir}" name="srcdir"/> + <attribute default="${build.classes.dir}" name="destdir"/> + <attribute default="${javac.classpath}" name="classpath"/> + <attribute default="${javac.modulepath}" name="modulepath"/> + <attribute default="${javac.upgrademodulepath}" name="upgrademodulepath"/> + <attribute default="${javac.processorpath}" name="processorpath"/> + <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="${javac.debug}" name="debug"/> + <attribute default="${empty.dir}" name="sourcepath"/> + <attribute default="${empty.dir}" name="gensrcdir"/> + <element name="customize" optional="true"/> + <sequential> + <property location="${build.dir}/empty" name="empty.dir"/> + <mkdir dir="${empty.dir}"/> + <mkdir dir="@{apgeneratedsrcdir}"/> + <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}"> + <src> + <dirset dir="@{gensrcdir}" erroronmissingdir="false"> + <include name="*"/> + </dirset> + </src> + <classpath> + <path path="@{classpath}"/> + </classpath> + <compilerarg line="${endorsed.classpath.cmd.line.arg}"/> + <compilerarg line="${javac.profile.cmd.line.arg}"/> + <compilerarg line="${javac.compilerargs}"/> + <compilerarg value="-processorpath"/> + <compilerarg path="@{processorpath}:${empty.dir}"/> + <compilerarg line="${ap.processors.internal}"/> + <compilerarg line="${annotation.processing.processor.options}"/> + <compilerarg value="-s"/> + <compilerarg path="@{apgeneratedsrcdir}"/> + <compilerarg line="${ap.proc.none.internal}"/> + <customize/> + </javac> + </sequential> + </macrodef> + </target> + <target depends="-init-ap-cmdline-properties,-init-source-module-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal"> + <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${src.dir}" name="srcdir"/> + <attribute default="${build.classes.dir}" name="destdir"/> + <attribute default="${javac.classpath}" name="classpath"/> + <attribute default="${javac.modulepath}" name="modulepath"/> + <attribute default="${javac.upgrademodulepath}" name="upgrademodulepath"/> + <attribute default="${javac.processorpath}" name="processorpath"/> + <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="${javac.debug}" name="debug"/> + <attribute default="${empty.dir}" name="sourcepath"/> + <attribute default="${empty.dir}" name="gensrcdir"/> + <element name="customize" optional="true"/> + <sequential> + <property location="${build.dir}/empty" name="empty.dir"/> + <mkdir dir="${empty.dir}"/> + <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}"> + <src> + <dirset dir="@{gensrcdir}" erroronmissingdir="false"> + <include name="*"/> + </dirset> + </src> + <classpath> + <path path="@{classpath}"/> + </classpath> + <compilerarg line="${endorsed.classpath.cmd.line.arg}"/> + <compilerarg line="${javac.profile.cmd.line.arg}"/> + <compilerarg line="${javac.compilerargs}"/> + <customize/> + </javac> + </sequential> + </macrodef> + </target> + <target depends="-init-macrodef-javac-with-module,-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac"> + <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${src.dir}" name="srcdir"/> + <attribute default="${build.classes.dir}" name="destdir"/> + <attribute default="${javac.classpath}" name="classpath"/> + <sequential> + <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}"> + <classpath> + <path path="@{classpath}"/> + </classpath> + </depend> + </sequential> + </macrodef> + <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${build.classes.dir}" name="destdir"/> + <sequential> + <fail unless="javac.includes">Must set javac.includes</fail> + <pathconvert pathsep="${line.separator}" property="javac.includes.binary"> + <path> + <filelist dir="@{destdir}" files="${javac.includes}"/> + </path> + <globmapper from="*.java" to="*.class"/> + </pathconvert> + <tempfile deleteonexit="true" property="javac.includesfile.binary"/> + <echo file="${javac.includesfile.binary}" message="${javac.includes.binary}"/> + <delete> + <files includesfile="${javac.includesfile.binary}"/> + </delete> + <delete> + <fileset file="${javac.includesfile.binary}"/> + </delete> + </sequential> + </macrodef> + </target> + <target if="${junit.available}" name="-init-macrodef-junit-init"> + <condition else="false" property="nb.junit.batch" value="true"> + <and> + <istrue value="${junit.available}"/> + <not> + <isset property="test.method"/> + </not> + </and> + </condition> + <condition else="false" property="nb.junit.single" value="true"> + <and> + <istrue value="${junit.available}"/> + <isset property="test.method"/> + </and> + </condition> + </target> + <target name="-init-test-properties"> + <property name="test.binaryincludes" value="<nothing>"/> + <property name="test.binarytestincludes" value=""/> + <property name="test.binaryexcludes" value=""/> + </target> + <target depends="-init-modules-supported" if="modules.supported.internal" name="-init-macrodef-junit-prototype-with-module"> + <macrodef name="junit-prototype" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <element name="customizePrototype" optional="true"/> + <sequential> + <property name="junit.forkmode" value="perTest"/> + <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}"> + <syspropertyset> + <propertyref prefix="test-sys-prop."/> + <mapper from="test-sys-prop.*" to="*" type="glob"/> + </syspropertyset> + <classpath> + <path path="${run.test.classpath}"/> + </classpath> + <modulepath> + <path path="${run.test.modulepath}"/> + </modulepath> + <formatter type="brief" usefile="false"/> + <formatter type="xml"/> + <jvmarg line="${endorsed.classpath.cmd.line.arg}"/> + <jvmarg value="-ea"/> + <jvmarg line="${run.test.jvmargs}"/> + <customizePrototype/> + </junit> + </sequential> + </macrodef> + </target> + <target depends="-init-modules-supported" name="-init-macrodef-junit-prototype-without-module" unless="modules.supported.internal"> + <macrodef name="junit-prototype" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <element name="customizePrototype" optional="true"/> + <sequential> + <property name="junit.forkmode" value="perTest"/> + <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}"> + <syspropertyset> + <propertyref prefix="test-sys-prop."/> + <mapper from="test-sys-prop.*" to="*" type="glob"/> + </syspropertyset> + <classpath> + <path path="${run.test.classpath}"/> + </classpath> + <formatter type="brief" usefile="false"/> + <formatter type="xml"/> + <jvmarg line="${endorsed.classpath.cmd.line.arg}"/> + <jvmarg value="-ea"/> + <customizePrototype/> + </junit> + </sequential> + </macrodef> + </target> + <target depends="-init-test-properties,-init-macrodef-junit-prototype-with-module,-init-macrodef-junit-prototype-without-module" if="${nb.junit.single}" name="-init-macrodef-junit-single" unless="${nb.junit.batch}"> + <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="**" name="testincludes"/> + <attribute default="" name="testmethods"/> + <element name="customize" optional="true"/> + <sequential> + <j2seproject3:junit-prototype> + <customizePrototype> + <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/> + <customize/> + </customizePrototype> + </j2seproject3:junit-prototype> + </sequential> + </macrodef> + </target> + <target depends="-init-test-properties,-init-macrodef-junit-prototype-with-module,-init-macrodef-junit-prototype-without-module" if="${nb.junit.batch}" name="-init-macrodef-junit-batch" unless="${nb.junit.single}"> + <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="**" name="testincludes"/> + <attribute default="" name="testmethods"/> + <element name="customize" optional="true"/> + <sequential> + <j2seproject3:junit-prototype> + <customizePrototype> + <batchtest todir="${build.test.results.dir}"> + <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}"> + <filename name="@{testincludes}"/> + </fileset> + <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}"> + <filename name="${test.binarytestincludes}"/> + </fileset> + </batchtest> + <customize/> + </customizePrototype> + </j2seproject3:junit-prototype> + </sequential> + </macrodef> + </target> + <target depends="-init-macrodef-junit-init,-init-macrodef-junit-single, -init-macrodef-junit-batch" if="${junit.available}" name="-init-macrodef-junit"/> + <target if="${testng.available}" name="-init-macrodef-testng"> + <macrodef name="testng" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="**" name="testincludes"/> + <attribute default="" name="testmethods"/> + <element name="customize" optional="true"/> + <sequential> + <condition else="" property="testng.methods.arg" value="@{testincludes}.@{testmethods}"> + <isset property="test.method"/> + </condition> + <union id="test.set"> + <fileset dir="${test.src.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}"> + <filename name="@{testincludes}"/> + </fileset> + </union> + <taskdef classname="org.testng.TestNGAntTask" classpath="${run.test.classpath}" name="testng"/> + <testng classfilesetref="test.set" failureProperty="tests.failed" listeners="org.testng.reporters.VerboseReporter" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="ZookeeperNodeMigration" testname="TestNG tests" workingDir="${work.dir}"> + <xmlfileset dir="${build.test.classes.dir}" includes="@{testincludes}"/> + <propertyset> + <propertyref prefix="test-sys-prop."/> + <mapper from="test-sys-prop.*" to="*" type="glob"/> + </propertyset> + <classpath> + <path path="${run.test.classpath}"/> + </classpath> + <jvmarg line="${endorsed.classpath.cmd.line.arg}"/> + <customize/> + </testng> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-test-impl"> + <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="**" name="testincludes"/> + <attribute default="" name="testmethods"/> + <element implicit="true" name="customize" optional="true"/> + <sequential> + <echo>No tests executed.</echo> + </sequential> + </macrodef> + </target> + <target depends="-init-macrodef-junit" if="${junit.available}" name="-init-macrodef-junit-impl"> + <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="**" name="testincludes"/> + <attribute default="" name="testmethods"/> + <element implicit="true" name="customize" optional="true"/> + <sequential> + <j2seproject3:junit excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}"> + <customize/> + </j2seproject3:junit> + </sequential> + </macrodef> + </target> + <target depends="-init-macrodef-testng" if="${testng.available}" name="-init-macrodef-testng-impl"> + <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="**" name="testincludes"/> + <attribute default="" name="testmethods"/> + <element implicit="true" name="customize" optional="true"/> + <sequential> + <j2seproject3:testng excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}"> + <customize/> + </j2seproject3:testng> + </sequential> + </macrodef> + </target> + <target depends="-init-macrodef-test-impl,-init-macrodef-junit-impl,-init-macrodef-testng-impl" name="-init-macrodef-test"> + <macrodef name="test" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="**" name="testincludes"/> + <attribute default="" name="testmethods"/> + <sequential> + <j2seproject3:test-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}"> + <customize> + <jvmarg line="${run.jvmargs}"/> + <jvmarg line="${run.jvmargs.ide}"/> + </customize> + </j2seproject3:test-impl> + </sequential> + </macrodef> + </target> + <target depends="-init-macrodef-junit" if="${junit.available}" name="-init-macrodef-junit-debug-impl"> + <macrodef name="test-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="**" name="testincludes"/> + <attribute default="" name="testmethods"/> + <element name="customizeDebuggee" optional="true"/> + <sequential> + <j2seproject3:junit excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}"> + <customize> + <jvmarg value="-agentlib:jdwp=transport=${debug-transport},address=${jpda.address}"/> + <customizeDebuggee/> + </customize> + </j2seproject3:junit> + </sequential> + </macrodef> + </target> + <target if="${testng.available}" name="-init-macrodef-testng-debug"> + <macrodef name="testng-debug" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${main.class}" name="testClass"/> + <attribute default="" name="testMethod"/> + <element name="customize2" optional="true"/> + <sequential> + <condition else="-testclass @{testClass}" property="test.class.or.method" value="-methods @{testClass}.@{testMethod}"> + <isset property="test.method"/> + </condition> + <condition else="-suitename ZookeeperNodeMigration -testname @{testClass} ${test.class.or.method}" property="testng.cmd.args" value="@{testClass}"> + <matches pattern=".*\.xml" string="@{testClass}"/> + </condition> + <delete dir="${build.test.results.dir}" quiet="true"/> + <mkdir dir="${build.test.results.dir}"/> + <j2seproject3:debug classname="org.testng.TestNG" classpath="${debug.test.classpath}"> + <customizeDebuggee> + <customize2/> + <jvmarg value="-ea"/> + <arg line="${testng.debug.mode}"/> + <arg line="-d ${build.test.results.dir}"/> + <arg line="-listener org.testng.reporters.VerboseReporter"/> + <arg line="${testng.cmd.args}"/> + </customizeDebuggee> + </j2seproject3:debug> + </sequential> + </macrodef> + </target> + <target depends="-init-macrodef-testng-debug" if="${testng.available}" name="-init-macrodef-testng-debug-impl"> + <macrodef name="testng-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${main.class}" name="testClass"/> + <attribute default="" name="testMethod"/> + <element implicit="true" name="customize2" optional="true"/> + <sequential> + <j2seproject3:testng-debug testClass="@{testClass}" testMethod="@{testMethod}"> + <customize2/> + </j2seproject3:testng-debug> + </sequential> + </macrodef> + </target> + <target depends="-init-macrodef-junit-debug-impl" if="${junit.available}" name="-init-macrodef-test-debug-junit"> + <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="**" name="testincludes"/> + <attribute default="" name="testmethods"/> + <attribute default="${main.class}" name="testClass"/> + <attribute default="" name="testMethod"/> + <sequential> + <j2seproject3:test-debug-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}"> + <customizeDebuggee> + <jvmarg line="${run.jvmargs}"/> + <jvmarg line="${run.jvmargs.ide}"/> + </customizeDebuggee> + </j2seproject3:test-debug-impl> + </sequential> + </macrodef> + </target> + <target depends="-init-macrodef-testng-debug-impl" if="${testng.available}" name="-init-macrodef-test-debug-testng"> + <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="**" name="testincludes"/> + <attribute default="" name="testmethods"/> + <attribute default="${main.class}" name="testClass"/> + <attribute default="" name="testMethod"/> + <sequential> + <j2seproject3:testng-debug-impl testClass="@{testClass}" testMethod="@{testMethod}"> + <customize2> + <syspropertyset> + <propertyref prefix="test-sys-prop."/> + <mapper from="test-sys-prop.*" to="*" type="glob"/> + </syspropertyset> + </customize2> + </j2seproject3:testng-debug-impl> + </sequential> + </macrodef> + </target> + <target depends="-init-macrodef-test-debug-junit,-init-macrodef-test-debug-testng" name="-init-macrodef-test-debug"/> + <!-- + pre NB7.2 profiling section; consider it deprecated + --> + <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile, -profile-init-check" if="profiler.info.jvmargs.agent" name="profile-init"/> + <target if="profiler.info.jvmargs.agent" name="-profile-pre-init"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target if="profiler.info.jvmargs.agent" name="-profile-post-init"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target if="profiler.info.jvmargs.agent" name="-profile-init-macrodef-profile"> + <macrodef name="resolve"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${env.@{value}}"/> + </sequential> + </macrodef> + <macrodef name="profile"> + <attribute default="${main.class}" name="classname"/> + <element name="customize" optional="true"/> + <sequential> + <property environment="env"/> + <resolve name="profiler.current.path" value="${profiler.info.pathvar}"/> + <java classname="@{classname}" dir="${profiler.info.dir}" failonerror="${java.failonerror}" fork="true" jvm="${profiler.info.jvm}"> + <jvmarg line="${endorsed.classpath.cmd.line.arg}"/> + <jvmarg value="${profiler.info.jvmargs.agent}"/> + <jvmarg line="${profiler.info.jvmargs}"/> + <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/> + <arg line="${application.args}"/> + <classpath> + <path path="${run.classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="run-sys-prop."/> + <mapper from="run-sys-prop.*" to="*" type="glob"/> + </syspropertyset> + <customize/> + </java> + </sequential> + </macrodef> + </target> + <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile" if="profiler.info.jvmargs.agent" name="-profile-init-check"> + <fail unless="profiler.info.jvm">Must set JVM to use for profiling in profiler.info.jvm</fail> + <fail unless="profiler.info.jvmargs.agent">Must set profiler agent JVM arguments in profiler.info.jvmargs.agent</fail> + </target> + <!-- + end of pre NB7.2 profiling section + --> + <target depends="-init-debug-args" name="-init-macrodef-nbjpda"> + <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute default="${main.class}" name="name"/> + <attribute default="${debug.modulepath}" name="modulepath"/> + <attribute default="${debug.classpath}" name="classpath"/> + <attribute default="" name="stopclassname"/> + <sequential> + <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}"> + <modulepath> + <path path="@{modulepath}"/> + </modulepath> + <classpath> + <path path="@{classpath}"/> + </classpath> + </nbjpdastart> + </sequential> + </macrodef> + <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute default="${build.classes.dir}" name="dir"/> + <sequential> + <nbjpdareload> + <fileset dir="@{dir}" includes="${fix.classes}"> + <include name="${fix.includes}*.class"/> + </fileset> + </nbjpdareload> + </sequential> + </macrodef> + </target> + <target name="-init-debug-args"> + <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem"> + <os family="windows"/> + </condition> + <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}"> + <isset property="debug.transport"/> + </condition> + </target> + <target depends="-init-debug-args" name="-init-macrodef-debug"> + <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${module.name}" name="modulename"/> + <attribute default="${main.class}" name="classname"/> + <attribute default="${debug.modulepath}" name="modulepath"/> + <attribute default="${debug.classpath}" name="classpath"/> + <element name="customizeDebuggee" optional="true"/> + <sequential> + <j2seproject1:java classname="@{classname}" classpath="@{classpath}" modulename="@{modulename}" modulepath="@{modulepath}"> + <customize> + <jvmarg value="-agentlib:jdwp=transport=${debug-transport},address=${jpda.address}"/> + <customizeDebuggee/> + </customize> + </j2seproject1:java> + </sequential> + </macrodef> + </target> + <target depends="-init-source-module-properties" if="named.module.internal" name="-init-macrodef-java-with-module"> + <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute default="${module.name}" name="modulename"/> + <attribute default="${main.class}" name="classname"/> + <attribute default="${run.modulepath}" name="modulepath"/> + <attribute default="${run.upgrademodulepath}" name="upgrademodulepath"/> + <attribute default="${run.classpath}" name="classpath"/> + <attribute default="jvm" name="jvm"/> + <element name="customize" optional="true"/> + <sequential> + <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true" module="@{modulename}"> + <classpath> + <path path="@{classpath}"/> + </classpath> + <modulepath> + <pathelement path="@{modulepath}"/> + <pathelement location="${module.build.classes.dir}"/> + </modulepath> + <upgrademodulepath> + <path path="@{upgrademodulepath}"/> + </upgrademodulepath> + <jvmarg value="-Dfile.encoding=${runtime.encoding}"/> + <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/> + <jvmarg line="${run.jvmargs}"/> + <jvmarg line="${run.jvmargs.ide}"/> + <syspropertyset> + <propertyref prefix="run-sys-prop."/> + <mapper from="run-sys-prop.*" to="*" type="glob"/> + </syspropertyset> + <customize/> + </java> + </sequential> + </macrodef> + </target> + <target depends="-init-source-module-properties" if="unnamed.module.internal" name="-init-macrodef-java-with-unnamed-module"> + <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute default="" name="modulename"/> + <attribute default="${main.class}" name="classname"/> + <attribute default="${run.modulepath}" name="modulepath"/> + <attribute default="${run.upgrademodulepath}" name="upgrademodulepath"/> + <attribute default="${run.classpath}" name="classpath"/> + <attribute default="jvm" name="jvm"/> + <element name="customize" optional="true"/> + <sequential> + <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true"> + <classpath> + <path path="@{classpath}"/> + </classpath> + <modulepath> + <path path="@{modulepath}"/> + </modulepath> + <upgrademodulepath> + <path path="@{upgrademodulepath}"/> + </upgrademodulepath> + <jvmarg value="-Dfile.encoding=${runtime.encoding}"/> + <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/> + <jvmarg line="${run.jvmargs}"/> + <jvmarg line="${run.jvmargs.ide}"/> + <syspropertyset> + <propertyref prefix="run-sys-prop."/> + <mapper from="run-sys-prop.*" to="*" type="glob"/> + </syspropertyset> + <customize/> + </java> + </sequential> + </macrodef> + </target> + <target depends="-init-source-module-properties" name="-init-macrodef-java-without-module" unless="modules.supported.internal"> + <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute default="" name="modulename"/> + <attribute default="${main.class}" name="classname"/> + <attribute default="" name="modulepath"/> + <attribute default="${run.classpath}" name="classpath"/> + <attribute default="jvm" name="jvm"/> + <element name="customize" optional="true"/> + <sequential> + <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true"> + <jvmarg line="${endorsed.classpath.cmd.line.arg}"/> + <jvmarg value="-Dfile.encoding=${runtime.encoding}"/> + <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/> + <jvmarg line="${run.jvmargs}"/> + <jvmarg line="${run.jvmargs.ide}"/> + <classpath> + <path path="@{classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="run-sys-prop."/> + <mapper from="run-sys-prop.*" to="*" type="glob"/> + </syspropertyset> + <customize/> + </java> + </sequential> + </macrodef> + </target> + <target depends="-init-macrodef-java-with-module, -init-macrodef-java-with-unnamed-module, -init-macrodef-java-without-module" name="-init-macrodef-java"/> + <target name="-init-macrodef-copylibs"> + <macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${manifest.file}" name="manifest"/> + <element name="customize" optional="true"/> + <sequential> + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/> + <pathconvert property="run.classpath.without.build.classes.dir"> + <path path="${run.classpath}"/> + <map from="${build.classes.dir.resolved}" to=""/> + </pathconvert> + <pathconvert pathsep=" " property="jar.classpath"> + <path path="${run.classpath.without.build.classes.dir}"/> + <chainedmapper> + <flattenmapper/> + <filtermapper> + <replacestring from=" " to="%20"/> + </filtermapper> + <globmapper from="*" to="lib/*"/> + </chainedmapper> + </pathconvert> + <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/> + <copylibs compress="${jar.compress}" excludeFromCopy="${copylibs.excludes}" index="${jar.index}" indexMetaInf="${jar.index.metainf}" jarfile="${dist.jar}" manifest="@{manifest}" manifestencoding="UTF-8" rebase="${copylibs.rebase}" runtimeclasspath="${run.classpath.without.build.classes.dir}"> + <fileset dir="${build.classes.dir}" excludes="${dist.archive.excludes}"/> + <manifest> + <attribute name="Class-Path" value="${jar.classpath}"/> + <customize/> + </manifest> + </copylibs> + </sequential> + </macrodef> + </target> + <target name="-init-presetdef-jar"> + <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1"> + <jar compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}" manifestencoding="UTF-8"> + <j2seproject1:fileset dir="${build.classes.dir}" excludes="${dist.archive.excludes}"/> + </jar> + </presetdef> + </target> + <target name="-init-ap-cmdline-properties"> + <property name="annotation.processing.enabled" value="true"/> + <property name="annotation.processing.processors.list" value=""/> + <property name="annotation.processing.processor.options" value=""/> + <property name="annotation.processing.run.all.processors" value="true"/> + <property name="javac.processorpath" value="${javac.classpath}"/> + <property name="javac.test.processorpath" value="${javac.test.classpath}"/> + <condition property="ap.supported.internal" value="true"> + <not> + <matches pattern="1\.[0-5](\..*)?" string="${javac.source}"/> + </not> + </condition> + </target> + <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-ap-cmdline-supported"> + <condition else="" property="ap.processors.internal" value="-processor ${annotation.processing.processors.list}"> + <isfalse value="${annotation.processing.run.all.processors}"/> + </condition> + <condition else="" property="ap.proc.none.internal" value="-proc:none"> + <isfalse value="${annotation.processing.enabled}"/> + </condition> + </target> + <target depends="-init-ap-cmdline-properties,-init-ap-cmdline-supported" name="-init-ap-cmdline"> + <property name="ap.cmd.line.internal" value=""/> + </target> + <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-test,-init-macrodef-test-debug,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar,-init-ap-cmdline" name="init"/> + <!-- + =================== + COMPILATION SECTION + =================== + --> + <target name="-deps-jar-init" unless="built-jar.properties"> + <property location="${build.dir}/built-jar.properties" name="built-jar.properties"/> + <delete file="${built-jar.properties}" quiet="true"/> + </target> + <target if="already.built.jar.${basedir}" name="-warn-already-built-jar"> + <echo level="warn" message="Cycle detected: ZookeeperNodeMigration was already built"/> + </target> + <target depends="init,-deps-jar-init" name="deps-jar" unless="no.deps"> + <mkdir dir="${build.dir}"/> + <touch file="${built-jar.properties}" verbose="false"/> + <property file="${built-jar.properties}" prefix="already.built.jar."/> + <antcall target="-warn-already-built-jar"/> + <propertyfile file="${built-jar.properties}"> + <entry key="${basedir}" value=""/> + </propertyfile> + </target> + <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/> + <target depends="init" name="-check-automatic-build"> + <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/> + </target> + <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build"> + <antcall target="clean"> + <param name="no.dependencies" value="true"/> + </antcall> + </target> + <target depends="init,deps-jar" name="-pre-pre-compile"> + <mkdir dir="${build.classes.dir}"/> + </target> + <target name="-pre-compile"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target if="do.depend.true" name="-compile-depend"> + <pathconvert property="build.generated.subdirs"> + <dirset dir="${build.generated.sources.dir}" erroronmissingdir="false"> + <include name="*"/> + </dirset> + </pathconvert> + <j2seproject3:depend srcdir="${src.dir}:${build.generated.subdirs}"/> + </target> + <target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml,-compile-depend" if="have.sources" name="-do-compile"> + <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/> + <copy todir="${build.classes.dir}"> + <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/> + </copy> + </target> + <target if="has.persistence.xml" name="-copy-persistence-xml"> + <mkdir dir="${build.classes.dir}/META-INF"/> + <copy todir="${build.classes.dir}/META-INF"> + <fileset dir="${meta.inf.dir}" includes="persistence.xml orm.xml"/> + </copy> + </target> + <target name="-post-compile"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/> + <target name="-pre-compile-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single"> + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail> + <j2seproject3:force-recompile/> + <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}, module-info.java" sourcepath="${src.dir}"/> + </target> + <target name="-post-compile-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/> + <!-- + ==================== + JAR BUILDING SECTION + ==================== + --> + <target depends="init" name="-pre-pre-jar"> + <dirname file="${dist.jar}" property="dist.jar.dir"/> + <mkdir dir="${dist.jar.dir}"/> + </target> + <target name="-pre-jar"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,compile" name="-check-module-main-class"> + <pathconvert property="main.class.file"> + <string value="${main.class}"/> + <unpackagemapper from="*" to="*.class"/> + </pathconvert> + <condition property="do.module.main.class"> + <and> + <isset property="main.class.available"/> + <available file="${build.classes.dir}/module-info.class"/> + <available file="${build.classes.dir}/${main.class.file}"/> + <isset property="libs.CopyLibs.classpath"/> + <available classname="org.netbeans.modules.java.j2seproject.moduletask.ModuleMainClass" classpath="${libs.CopyLibs.classpath}"/> + </and> + </condition> + </target> + <target depends="-check-module-main-class" if="do.module.main.class" name="-set-module-main-class"> + <taskdef classname="org.netbeans.modules.java.j2seproject.moduletask.ModuleMainClass" classpath="${libs.CopyLibs.classpath}" name="modulemainclass"/> + <modulemainclass failonerror="false" mainclass="${main.class}" moduleinfo="${build.classes.dir}/module-info.class"/> + </target> + <target depends="init" if="do.archive" name="-do-jar-create-manifest" unless="manifest.available"> + <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/> + <touch file="${tmp.manifest.file}" verbose="false"/> + </target> + <target depends="init" if="do.archive+manifest.available" name="-do-jar-copy-manifest"> + <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/> + <copy encoding="${manifest.encoding}" file="${manifest.file}" outputencoding="UTF-8" tofile="${tmp.manifest.file}"/> + </target> + <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+main.class.available" name="-do-jar-set-mainclass"> + <manifest encoding="UTF-8" file="${tmp.manifest.file}" mode="update"> + <attribute name="Main-Class" value="${main.class}"/> + </manifest> + </target> + <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+profile.available" name="-do-jar-set-profile"> + <manifest encoding="UTF-8" file="${tmp.manifest.file}" mode="update"> + <attribute name="Profile" value="${javac.profile}"/> + </manifest> + </target> + <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+splashscreen.available" name="-do-jar-set-splashscreen"> + <basename file="${application.splash}" property="splashscreen.basename"/> + <mkdir dir="${build.classes.dir}/META-INF"/> + <copy failonerror="false" file="${application.splash}" todir="${build.classes.dir}/META-INF"/> + <manifest encoding="UTF-8" file="${tmp.manifest.file}" mode="update"> + <attribute name="SplashScreen-Image" value="META-INF/${splashscreen.basename}"/> + </manifest> + </target> + <target depends="init,compile" name="-check-do-mkdist"> + <condition property="do.mkdist"> + <and> + <isset property="do.archive"/> + <isset property="libs.CopyLibs.classpath"/> + <not> + <istrue value="${mkdist.disabled}"/> + </not> + <not> + <available file="${build.classes.dir}/module-info.class"/> + </not> + </and> + </condition> + </target> + <target depends="init,-init-macrodef-copylibs,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-check-do-mkdist" if="do.mkdist" name="-do-jar-copylibs"> + <j2seproject3:copylibs manifest="${tmp.manifest.file}"/> + <echo level="info">To run this application from the command line without Ant, try:</echo> + <property location="${dist.jar}" name="dist.jar.resolved"/> + <echo level="info">java -jar "${dist.jar.resolved}"</echo> + </target> + <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-check-do-mkdist" if="do.archive" name="-do-jar-jar" unless="do.mkdist"> + <j2seproject1:jar manifest="${tmp.manifest.file}"/> + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/> + <property location="${dist.jar}" name="dist.jar.resolved"/> + <condition else="${dist.jar.resolved}" property="jar.usage.message.class.path.replacement" value=""> + <isset property="named.module.internal"/> + </condition> + <pathconvert property="run.classpath.with.dist.jar"> + <path path="${run.classpath}"/> + <map from="${build.classes.dir.resolved}" to="${jar.usage.message.class.path.replacement}"/> + </pathconvert> + <pathconvert property="run.modulepath.with.dist.jar"> + <path location="${dist.jar.resolved}"/> + <path path="${run.modulepath}"/> + <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/> + </pathconvert> + <condition else="${run.modulepath}" property="jar.usage.message.run.modulepath.with.dist.jar" value="${run.modulepath.with.dist.jar}"> + <isset property="named.module.internal"/> + </condition> + <condition else="" property="jar.usage.message.module.path" value=" -p ${jar.usage.message.run.modulepath.with.dist.jar}"> + <and> + <isset property="modules.supported.internal"/> + <length length="0" string="${jar.usage.message.run.modulepath.with.dist.jar}" when="greater"/> + </and> + </condition> + <condition else="" property="jar.usage.message.class.path" value=" -cp ${run.classpath.with.dist.jar}"> + <length length="0" string="${run.classpath.with.dist.jar}" when="greater"/> + </condition> + <condition else="/${main.class}" property="jar.usage.message.main.class.class.selector" value=""> + <isset property="do.module.main.class"/> + </condition> + <condition else=" ${main.class}" property="jar.usage.message.main.class" value=" -m ${module.name}${jar.usage.message.main.class.class.selector}"> + <isset property="named.module.internal"/> + </condition> + <condition else="" property="jar.usage.message" value="To run this application from the command line without Ant, try:${line.separator}${platform.java}${jar.usage.message.module.path}${jar.usage.message.class.path}${jar.usage.message.main.class}"> + <isset property="main.class.available"/> + </condition> + <condition else="debug" property="jar.usage.level" value="info"> + <isset property="main.class.available"/> + </condition> + <echo level="${jar.usage.level}" message="${jar.usage.message}"/> + </target> + <target depends="-do-jar-copylibs" if="do.archive" name="-do-jar-delete-manifest"> + <delete> + <fileset file="${tmp.manifest.file}"/> + </delete> + </target> + <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-do-jar-jar,-do-jar-delete-manifest" name="-do-jar-without-libraries"/> + <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-do-jar-copylibs,-do-jar-delete-manifest" name="-do-jar-with-libraries"/> + <target name="-post-jar"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,compile,-pre-jar,-set-module-main-class,-do-jar-without-libraries,-do-jar-with-libraries,-post-jar" name="-do-jar"/> + <target depends="init,compile,-pre-jar,-do-jar,-post-jar,deploy" description="Build JAR." name="jar"/> + <!-- + ================= + DEPLOY SECTION + ================= + --> + <target name="-pre-deploy"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init" name="-check-jlink"> + <condition property="do.jlink.internal"> + <and> + <istrue value="${do.jlink}"/> + <isset property="do.archive"/> + <isset property="named.module.internal"/> + </and> + </condition> + </target> + <target depends="init,-do-jar,-post-jar,-pre-deploy,-check-jlink" if="do.jlink.internal" name="-do-deploy"> + <delete dir="${dist.jlink.dir}" failonerror="false" quiet="true"/> + <property name="jlink.launcher.name" value="${application.title}"/> + <condition else="${module.name}" property="jlink.add.modules" value="${module.name},${jlink.additionalmodules}"> + <and> + <isset property="jlink.additionalmodules"/> + <length length="0" string="${jlink.additionalmodules}" when="greater"/> + </and> + </condition> + <condition property="jlink.do.strip.internal"> + <and> + <isset property="jlink.strip"/> + <istrue value="${jlink.strip}"/> + </and> + </condition> + <condition property="jlink.do.additionalparam.internal"> + <and> + <isset property="jlink.additionalparam"/> + <length length="0" string="${jlink.additionalparam}" when="greater"/> + </and> + </condition> + <condition property="jlink.do.launcher.internal"> + <and> + <istrue value="${jlink.launcher}"/> + <isset property="main.class.available"/> + </and> + </condition> + <property name="platform.jlink" value="${jdk.home}/bin/jlink"/> + <property name="jlink.systemmodules.internal" value="${jdk.home}/jmods"/> + <exec executable="${platform.jlink}"> + <arg value="--module-path"/> + <arg path="${jlink.systemmodules.internal}:${run.modulepath}:${dist.jar}"/> + <arg value="--add-modules"/> + <arg value="${jlink.add.modules}"/> + <arg if:set="jlink.do.strip.internal" value="--strip-debug"/> + <arg if:set="jlink.do.launcher.internal" value="--launcher"/> + <arg if:set="jlink.do.launcher.internal" value="${jlink.launcher.name}=${module.name}/${main.class}"/> + <arg if:set="jlink.do.additionalparam.internal" line="${jlink.additionalparam}"/> + <arg value="--output"/> + <arg value="${dist.jlink.output}"/> + </exec> + </target> + <target name="-post-deploy"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="-do-jar,-post-jar,-pre-deploy,-do-deploy,-post-deploy" name="deploy"/> + <!-- + ================= + EXECUTION SECTION + ================= + --> + <target depends="init,compile" description="Run a main class." name="run"> + <j2seproject1:java> + <customize> + <arg line="${application.args}"/> + </customize> + </j2seproject1:java> + </target> + <target name="-do-not-recompile"> + <property name="javac.includes.binary" value=""/> + </target> + <target depends="init,compile-single" name="run-single"> + <fail unless="run.class">Must select one file in the IDE or set run.class</fail> + <j2seproject1:java classname="${run.class}"/> + </target> + <target depends="init,compile-test-single" name="run-test-with-main"> + <fail unless="run.class">Must select one file in the IDE or set run.class</fail> + <j2seproject1:java classname="${run.class}" classpath="${run.test.classpath}"/> + </target> + <!-- + ================= + DEBUGGING SECTION + ================= + --> + <target depends="init" if="netbeans.home" name="-debug-start-debugger"> + <j2seproject1:nbjpdastart name="${debug.class}"/> + </target> + <target depends="init" if="netbeans.home" name="-debug-start-debugger-main-test"> + <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${debug.class}"/> + </target> + <target depends="init,compile" name="-debug-start-debuggee"> + <j2seproject3:debug> + <customizeDebuggee> + <arg line="${application.args}"/> + </customizeDebuggee> + </j2seproject3:debug> + </target> + <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/> + <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto"> + <j2seproject1:nbjpdastart stopclassname="${main.class}"/> + </target> + <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/> + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single"> + <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail> + <j2seproject3:debug classname="${debug.class}"/> + </target> + <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/> + <target depends="init,compile-test-single" if="netbeans.home" name="-debug-start-debuggee-main-test"> + <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail> + <j2seproject3:debug classname="${debug.class}" classpath="${debug.test.classpath}"/> + </target> + <target depends="init,compile-test-single,-debug-start-debugger-main-test,-debug-start-debuggee-main-test" if="netbeans.home" name="debug-test-with-main"/> + <target depends="init" name="-pre-debug-fix"> + <fail unless="fix.includes">Must set fix.includes</fail> + <property name="javac.includes" value="${fix.includes}.java"/> + </target> + <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix"> + <j2seproject1:nbjpdareload/> + </target> + <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/> + <!-- + ================= + PROFILING SECTION + ================= + --> + <!-- + pre NB7.2 profiler integration + --> + <target depends="profile-init,compile" description="Profile a project in the IDE." if="profiler.info.jvmargs.agent" name="-profile-pre72"> + <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail> + <nbprofiledirect> + <classpath> + <path path="${run.classpath}"/> + </classpath> + </nbprofiledirect> + <profile/> + </target> + <target depends="profile-init,compile-single" description="Profile a selected class in the IDE." if="profiler.info.jvmargs.agent" name="-profile-single-pre72"> + <fail unless="profile.class">Must select one file in the IDE or set profile.class</fail> + <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail> + <nbprofiledirect> + <classpath> + <path path="${run.classpath}"/> + </classpath> + </nbprofiledirect> + <profile classname="${profile.class}"/> + </target> + <target depends="profile-init,compile-single" if="profiler.info.jvmargs.agent" name="-profile-applet-pre72"> + <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail> + <nbprofiledirect> + <classpath> + <path path="${run.classpath}"/> + </classpath> + </nbprofiledirect> + <profile classname="sun.applet.AppletViewer"> + <customize> + <arg value="${applet.url}"/> + </customize> + </profile> + </target> + <target depends="-init-macrodef-junit,profile-init,compile-test-single" if="profiler.info.jvmargs.agent" name="-profile-test-single-pre72"> + <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail> + <nbprofiledirect> + <classpath> + <path path="${run.test.classpath}"/> + </classpath> + </nbprofiledirect> + <j2seproject3:junit excludes="${excludes}" includes="${includes}" testincludes="${profile.class}" testmethods=""> + <customize> + <jvmarg value="-agentlib:jdwp=transport=${debug-transport},address=${jpda.address}"/> + <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/> + <jvmarg value="${profiler.info.jvmargs.agent}"/> + <jvmarg line="${profiler.info.jvmargs}"/> + <classpath> + <path path="${run.test.classpath}"/> + </classpath> + </customize> + </j2seproject3:junit> + </target> + <!-- + end of pre NB72 profiling section + --> + <target if="netbeans.home" name="-profile-check"> + <condition property="profiler.configured"> + <or> + <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-agentpath:"/> + <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-javaagent:"/> + </or> + </condition> + </target> + <target depends="-profile-check,-profile-pre72" description="Profile a project in the IDE." if="profiler.configured" name="profile" unless="profiler.info.jvmargs.agent"> + <startprofiler/> + <antcall target="run"/> + </target> + <target depends="-profile-check,-profile-single-pre72" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-single" unless="profiler.info.jvmargs.agent"> + <fail unless="run.class">Must select one file in the IDE or set run.class</fail> + <startprofiler/> + <antcall target="run-single"/> + </target> + <target depends="-profile-test-single-pre72" description="Profile a selected test in the IDE." name="profile-test-single"/> + <target depends="-profile-check" description="Profile a selected test in the IDE." if="profiler.configured" name="profile-test" unless="profiler.info.jvmargs"> + <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail> + <startprofiler/> + <antcall target="test-single"/> + </target> + <target depends="-profile-check" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-test-with-main"> + <fail unless="run.class">Must select one file in the IDE or set run.class</fail> + <startprofiler/> + <antcall target="run-test-with-main"/> + </target> + <target depends="-profile-check,-profile-applet-pre72" if="profiler.configured" name="profile-applet" unless="profiler.info.jvmargs.agent"> + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> + <startprofiler/> + <antcall target="run-applet"/> + </target> + <!-- + =============== + JAVADOC SECTION + =============== + --> + <target depends="init" if="have.sources" name="-javadoc-build"> + <mkdir dir="${dist.javadoc.dir}"/> + <condition else="" property="javadoc.endorsed.classpath.cmd.line.arg" value="-J${endorsed.classpath.cmd.line.arg}"> + <and> + <isset property="endorsed.classpath.cmd.line.arg"/> + <not> + <equals arg1="${endorsed.classpath.cmd.line.arg}" arg2=""/> + </not> + </and> + </condition> + <condition else="" property="bug5101868workaround" value="*.java"> + <matches pattern="1\.[56](\..*)?" string="${java.version}"/> + </condition> + <condition else="" property="javadoc.html5.cmd.line.arg" value="-html5"> + <and> + <isset property="javadoc.html5"/> + <available file="${jdk.home}${file.separator}lib${file.separator}jrt-fs.jar"/> + </and> + </condition> + <javadoc additionalparam="-J-Dfile.encoding=${file.encoding} ${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}"> + <classpath> + <path path="${javac.classpath}"/> + </classpath> + <fileset dir="${src.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}"> + <filename name="**/*.java"/> + </fileset> + <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false"> + <include name="**/*.java"/> + <exclude name="*.java"/> + </fileset> + <arg line="${javadoc.endorsed.classpath.cmd.line.arg}"/> + <arg line="${javadoc.html5.cmd.line.arg}"/> + </javadoc> + <copy todir="${dist.javadoc.dir}"> + <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}"> + <filename name="**/doc-files/**"/> + </fileset> + <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false"> + <include name="**/doc-files/**"/> + </fileset> + </copy> + </target> + <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview"> + <nbbrowse file="${dist.javadoc.dir}/index.html"/> + </target> + <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/> + <!-- + ========================= + TEST COMPILATION SECTION + ========================= + --> + <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test"> + <mkdir dir="${build.test.classes.dir}"/> + </target> + <target name="-pre-compile-test"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="-init-source-module-properties" if="named.module.internal" name="-init-test-javac-module-properties-with-module"> + <j2seproject3:modulename property="test.module.name" sourcepath="${test.src.dir}"/> + <condition else="${empty.dir}" property="javac.test.sourcepath" value="${test.src.dir}"> + <and> + <isset property="test.module.name"/> + <length length="0" string="${test.module.name}" when="greater"/> + </and> + </condition> + <condition else="--patch-module ${module.name}=${test.src.dir} --add-reads ${module.name}=ALL-UNNAMED" property="javac.test.compilerargs" value="--add-reads ${test.module.name}=ALL-UNNAMED"> + <and> + <isset property="test.module.name"/> + <length length="0" string="${test.module.name}" when="greater"/> + </and> + </condition> + </target> + <target depends="-init-source-module-properties" if="named.module.internal" name="-init-test-run-module-properties"> + <condition else="${module.name}" property="run.test.addexport.source.module.internal" value="${test.module.name}"> + <and> + <isset property="test.module.name"/> + <length length="0" string="${test.module.name}" when="greater"/> + </and> + </condition> + <fileset dir="${build.test.classes.dir}" id="run.test.packages.internal" includes="**/*.class"/> + <property location="${build.test.classes.dir}" name="build.test.classes.dir.abs.internal"/> + <pathconvert pathsep=" " property="run.test.addexports.internal" refid="run.test.packages.internal"> + <chainedmapper> + <regexpmapper from="^(.*)\Q${file.separator}\E.*\.class$$" to="\1"/> + <filtermapper> + <uniqfilter/> + <replacestring from="${build.test.classes.dir.abs.internal}" to=""/> + </filtermapper> + <cutdirsmapper dirs="1"/> + <packagemapper from="*" to="--add-exports ${run.test.addexport.source.module.internal}/*=ALL-UNNAMED"/> + </chainedmapper> + </pathconvert> + <condition else="--patch-module ${module.name}=${build.test.classes.dir} --add-modules ${module.name} --add-reads ${module.name}=ALL-UNNAMED ${run.test.addexports.internal}" property="run.test.jvmargs" value="--add-modules ${test.module.name} --add-reads ${test.module.name}=ALL-UNNAMED ${run.test.addexports.internal}"> + <and> + <isset property="test.module.name"/> + <length length="0" string="${test.module.name}" when="greater"/> + </and> + </condition> + </target> + <target depends="-init-source-module-properties" name="-init-test-module-properties-without-module" unless="named.module.internal"> + <property name="javac.test.sourcepath" value="${empty.dir}"/> + <property name="javac.test.compilerargs" value=""/> + <property name="run.test.jvmargs" value=""/> + </target> + <target depends="-init-test-javac-module-properties-with-module,-init-test-module-properties-without-module" name="-init-test-module-properties"/> + <target if="do.depend.true" name="-compile-test-depend"> + <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/> + </target> + <target depends="init,deps-jar,compile,-init-test-module-properties,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test"> + <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" modulepath="${javac.test.modulepath}" processorpath="${javac.test.processorpath}" sourcepath="${javac.test.sourcepath}" srcdir="${test.src.dir}"> + <customize> + <compilerarg line="${javac.test.compilerargs}"/> + </customize> + </j2seproject3:javac> + <copy todir="${build.test.classes.dir}"> + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/> + </copy> + </target> + <target name="-post-compile-test"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/> + <target name="-pre-compile-test-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,deps-jar,compile,-init-test-module-properties,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single"> + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail> + <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/> + <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}, module-info.java" modulepath="${javac.test.modulepath}" processorpath="${javac.test.processorpath}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"> + <customize> + <compilerarg line="${javac.test.compilerargs}"/> + </customize> + </j2seproject3:javac> + <copy todir="${build.test.classes.dir}"> + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/> + </copy> + </target> + <target name="-post-compile-test-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/> + <!-- + ======================= + TEST EXECUTION SECTION + ======================= + --> + <target depends="init" if="have.tests" name="-pre-test-run"> + <mkdir dir="${build.test.results.dir}"/> + </target> + <target depends="init,compile-test,-init-test-run-module-properties,-pre-test-run" if="have.tests" name="-do-test-run"> + <j2seproject3:test includes="${includes}" testincludes="**/*Test.java"/> + </target> + <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run"> + <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail> + </target> + <target depends="init" if="have.tests" name="test-report"/> + <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/> + <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/> + <target depends="init" if="have.tests" name="-pre-test-run-single"> + <mkdir dir="${build.test.results.dir}"/> + </target> + <target depends="init,compile-test-single,-init-test-run-module-properties,-pre-test-run-single" if="have.tests" name="-do-test-run-single"> + <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail> + <j2seproject3:test excludes="" includes="${test.includes}" testincludes="${test.includes}"/> + </target> + <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single"> + <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail> + </target> + <target depends="init,compile-test-single,-init-test-run-module-properties,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/> + <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single-method"> + <fail unless="test.class">Must select some files in the IDE or set test.class</fail> + <fail unless="test.method">Must select some method in the IDE or set test.method</fail> + <j2seproject3:test excludes="" includes="${javac.includes}" testincludes="${test.class}" testmethods="${test.method}"/> + </target> + <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method" if="have.tests" name="-post-test-run-single-method"> + <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail> + </target> + <target depends="init,compile-test-single,-init-test-run-module-properties,-pre-test-run-single,-do-test-run-single-method,-post-test-run-single-method" description="Run single unit test." name="test-single-method"/> + <!-- + ======================= + TEST DEBUGGING SECTION + ======================= + --> + <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test"> + <fail unless="test.class">Must select one file in the IDE or set test.class</fail> + <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testincludes="${javac.includes}"/> + </target> + <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test-method"> + <fail unless="test.class">Must select one file in the IDE or set test.class</fail> + <fail unless="test.method">Must select some method in the IDE or set test.method</fail> + <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testMethod="${test.method}" testincludes="${test.class}" testmethods="${test.method}"/> + </target> + <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test"> + <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/> + </target> + <target depends="init,compile-test-single,-init-test-run-module-properties,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/> + <target depends="init,compile-test-single,-init-test-run-module-properties,-debug-start-debugger-test,-debug-start-debuggee-test-method" name="debug-test-method"/> + <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test"> + <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/> + </target> + <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/> + <!-- + ========================= + APPLET EXECUTION SECTION + ========================= + --> + <target depends="init,compile-single" name="run-applet"> + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> + <j2seproject1:java classname="sun.applet.AppletViewer"> + <customize> + <arg value="${applet.url}"/> + </customize> + </j2seproject1:java> + </target> + <!-- + ========================= + APPLET DEBUGGING SECTION + ========================= + --> + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet"> + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> + <j2seproject3:debug classname="sun.applet.AppletViewer"> + <customizeDebuggee> + <arg value="${applet.url}"/> + </customizeDebuggee> + </j2seproject3:debug> + </target> + <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/> + <!-- + =============== + CLEANUP SECTION + =============== + --> + <target name="-deps-clean-init" unless="built-clean.properties"> + <property location="${build.dir}/built-clean.properties" name="built-clean.properties"/> + <delete file="${built-clean.properties}" quiet="true"/> + </target> + <target if="already.built.clean.${basedir}" name="-warn-already-built-clean"> + <echo level="warn" message="Cycle detected: ZookeeperNodeMigration was already built"/> + </target> + <target depends="init,-deps-clean-init" name="deps-clean" unless="no.deps"> + <mkdir dir="${build.dir}"/> + <touch file="${built-clean.properties}" verbose="false"/> + <property file="${built-clean.properties}" prefix="already.built.clean."/> + <antcall target="-warn-already-built-clean"/> + <propertyfile file="${built-clean.properties}"> + <entry key="${basedir}" value=""/> + </propertyfile> + </target> + <target depends="init" name="-do-clean"> + <delete dir="${build.dir}"/> + <delete dir="${dist.jlink.output}"/> + <delete dir="${dist.dir}" followsymlinks="false" includeemptydirs="true"/> + </target> + <target name="-post-clean"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/> + <target name="-check-call-dep"> + <property file="${call.built.properties}" prefix="already.built."/> + <condition property="should.call.dep"> + <and> + <not> + <isset property="already.built.${call.subproject}"/> + </not> + <available file="${call.script}"/> + </and> + </condition> + </target> + <target depends="-check-call-dep" if="should.call.dep" name="-maybe-call-dep"> + <ant antfile="${call.script}" inheritall="false" target="${call.target}"> + <propertyset> + <propertyref prefix="transfer."/> + <mapper from="transfer.*" to="*" type="glob"/> + </propertyset> + </ant> + </target> +</project> diff --git a/ZookeeperNodeMigration/nbproject/project.properties b/ZookeeperNodeMigration/nbproject/project.properties new file mode 100755 index 0000000000000000000000000000000000000000..26892390a53d6dce41ba349ecd1746def9463cb1 --- /dev/null +++ b/ZookeeperNodeMigration/nbproject/project.properties @@ -0,0 +1,107 @@ +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=ZookeeperNodeMigration +application.vendor=elivis +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.modulepath=\ + ${run.modulepath} +debug.test.classpath=\ + ${run.test.classpath} +debug.test.modulepath=\ + ${run.test.modulepath} +# Files in build.classes.dir which should be excluded from distribution jar +dist.archive.excludes= +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/ZookeeperNodeMigration.jar +dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= +excludes= +file.reference.curator-client-2.8.0.jar=release/curator-client-2.8.0.jar +file.reference.curator-framework-2.8.0.jar=release/curator-framework-2.8.0.jar +file.reference.curator-recipes-2.8.0.jar=release/curator-recipes-2.8.0.jar +file.reference.guava-17.0.jar=release/guava-17.0.jar +file.reference.log4j-1.2.17.jar=release/log4j-1.2.17.jar +file.reference.slf4j-api-1.7.24.jar=release/slf4j-api-1.7.24.jar +file.reference.slf4j-log4j12-1.7.6.jar=release/slf4j-log4j12-1.7.6.jar +file.reference.zookeeper-3.4.6.jar=release/zookeeper-3.4.6.jar +includes=** +jar.compress=false +javac.classpath=\ + ${file.reference.curator-client-2.8.0.jar}:\ + ${file.reference.curator-framework-2.8.0.jar}:\ + ${file.reference.curator-recipes-2.8.0.jar}:\ + ${file.reference.zookeeper-3.4.6.jar}:\ + ${file.reference.slf4j-api-1.7.24.jar}:\ + ${file.reference.slf4j-log4j12-1.7.6.jar}:\ + ${file.reference.log4j-1.2.17.jar}:\ + ${file.reference.guava-17.0.jar} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.external.vm=true +javac.modulepath= +javac.processormodulepath= +javac.processorpath=\ + ${javac.classpath} +javac.source=1.8 +javac.target=1.8 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +javac.test.modulepath=\ + ${javac.modulepath} +javac.test.processorpath=\ + ${javac.test.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.html5=false +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +jlink.launcher=false +jlink.launcher.name=ZookeeperNodeMigration +main.class=zookeepernodemigration.ZookeeperNodeMigration +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=false +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project. +# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.modulepath=\ + ${javac.modulepath} +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +run.test.modulepath=\ + ${javac.test.modulepath} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/ZookeeperNodeMigration/nbproject/project.xml b/ZookeeperNodeMigration/nbproject/project.xml new file mode 100755 index 0000000000000000000000000000000000000000..1db04676a2cb9d793886978b56002f5ea8e7463d --- /dev/null +++ b/ZookeeperNodeMigration/nbproject/project.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.java.j2seproject</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/j2se-project/3"> + <name>ZookeeperNodeMigration</name> + <source-roots> + <root id="src.dir"/> + </source-roots> + <test-roots> + <root id="test.src.dir"/> + </test-roots> + </data> + </configuration> +</project> diff --git a/ZookeeperNodeMigration/release/curator-client-2.8.0.jar b/ZookeeperNodeMigration/release/curator-client-2.8.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..4ccc265cc43f05ea6b11ecd7427bbd5614d6a34a Binary files /dev/null and b/ZookeeperNodeMigration/release/curator-client-2.8.0.jar differ diff --git a/ZookeeperNodeMigration/release/curator-framework-2.8.0.jar b/ZookeeperNodeMigration/release/curator-framework-2.8.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..5e488892d150125f0e8f68e6ebc48b1a8cc1efd1 Binary files /dev/null and b/ZookeeperNodeMigration/release/curator-framework-2.8.0.jar differ diff --git a/ZookeeperNodeMigration/release/curator-recipes-2.8.0.jar b/ZookeeperNodeMigration/release/curator-recipes-2.8.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..34eb9c9677da222d00eac423a49c594032e8c743 Binary files /dev/null and b/ZookeeperNodeMigration/release/curator-recipes-2.8.0.jar differ diff --git a/ZookeeperNodeMigration/release/guava-17.0.jar b/ZookeeperNodeMigration/release/guava-17.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..661fc7473f8760f5f81874ddc1fcc0b5634fd6cf Binary files /dev/null and b/ZookeeperNodeMigration/release/guava-17.0.jar differ diff --git a/ZookeeperNodeMigration/release/log4j-1.2.17.jar b/ZookeeperNodeMigration/release/log4j-1.2.17.jar new file mode 100755 index 0000000000000000000000000000000000000000..1d425cf7d7e25f81be64d32c406ff66cfb6c4766 Binary files /dev/null and b/ZookeeperNodeMigration/release/log4j-1.2.17.jar differ diff --git a/ZookeeperNodeMigration/release/slf4j-api-1.7.24.jar b/ZookeeperNodeMigration/release/slf4j-api-1.7.24.jar new file mode 100755 index 0000000000000000000000000000000000000000..05941a12f06a99523b748da14d31e76265ed8b78 Binary files /dev/null and b/ZookeeperNodeMigration/release/slf4j-api-1.7.24.jar differ diff --git a/ZookeeperNodeMigration/release/slf4j-log4j12-1.7.6.jar b/ZookeeperNodeMigration/release/slf4j-log4j12-1.7.6.jar new file mode 100755 index 0000000000000000000000000000000000000000..d1cc2456e4a4bb35a87215ab9264b631d98dbf05 Binary files /dev/null and b/ZookeeperNodeMigration/release/slf4j-log4j12-1.7.6.jar differ diff --git a/ZookeeperNodeMigration/release/zookeeper-3.4.6.jar b/ZookeeperNodeMigration/release/zookeeper-3.4.6.jar new file mode 100755 index 0000000000000000000000000000000000000000..7c340be9f5d25d753508297c0b35f2b5a9d6ab85 Binary files /dev/null and b/ZookeeperNodeMigration/release/zookeeper-3.4.6.jar differ diff --git a/ZookeeperNodeMigration/src/zookeepernodemigration/AutoIngestJobNodeData.java b/ZookeeperNodeMigration/src/zookeepernodemigration/AutoIngestJobNodeData.java new file mode 100755 index 0000000000000000000000000000000000000000..82e75a7b1ca0a3855154bcf4d9716745efb3449f --- /dev/null +++ b/ZookeeperNodeMigration/src/zookeepernodemigration/AutoIngestJobNodeData.java @@ -0,0 +1,687 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 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 zookeepernodemigration; + +import java.io.Serializable; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Date; +import javax.lang.model.type.TypeKind; + +/** + * An object that converts auto ingest job data for an auto ingest job + * coordination service node to and from byte arrays. + */ +final class AutoIngestJobNodeData { + + private static final int CURRENT_VERSION = 2; + private static final int DEFAULT_PRIORITY = 0; + + /* + * This number is the sum of each piece of data, based on it's type. For the + * types boolean, int, and long, values 1, 4, and 8 will be added + * respectively. For String objects, the length of the string, plus either a + * byte or short respesenting the length of the string, will be added. + * + * This field is used to set the size of the buffer during the byte array + * creation in the 'toArray()' method. Since the final size of the array + * isn't immediately known at the time of creation, this number is used to + * create an array as large as could possibly be needed to store all the + * data. This avoids the need to continuously enlarge the buffer. Once the + * buffer has all the necessary data, it will be resized as appropriate. + */ + private static final int MAX_POSSIBLE_NODE_DATA_SIZE = 131637; + + /* + * Version 0 fields. + */ + private int processingStatus; + private int priority; + private int numberOfCrashes; + private long completedDate; + private boolean errorsOccurred; + + /* + * Version 1 fields. + */ + private int version; + private String manifestFilePath; // 'short' length used in byte array + private long manifestFileDate; + private String caseName; // 'byte' length used in byte array + private String deviceId; // 'byte' length used in byte array + private String dataSourcePath; // 'short' length used in byte array + private String caseDirectoryPath; // 'short' length used in byte array + private String processingHostName; // 'short' length used in byte array + private byte processingStage; + private long processingStageStartDate; + private String processingStageDetailsDescription; // 'byte' length used in byte array + private long processingStageDetailsStartDate; + + /* + * Version 2 fields. + */ + private long dataSourceSize; + + /** + * Processing statuses for an auto ingest job. + */ + enum ProcessingStatus { + PENDING, + PROCESSING, + COMPLETED, + DELETED + } + + /** + * Processing stages for an auto ingest job. + */ + enum Stage { + + PENDING("Pending"), + STARTING("Starting"), + UPDATING_SHARED_CONFIG("Updating shared configuration"), + CHECKING_SERVICES("Checking services"), + OPENING_CASE("Opening case"), + IDENTIFYING_DATA_SOURCE("Identifying data source type"), + ADDING_DATA_SOURCE("Adding data source"), + ANALYZING_DATA_SOURCE("Analyzing data source"), + ANALYZING_FILES("Analyzing files"), + EXPORTING_FILES("Exporting files"), + CANCELLING_MODULE("Cancelling module"), + CANCELLING("Cancelling"), + COMPLETED("Completed"); + + private final String displayText; + + private Stage(String displayText) { + this.displayText = displayText; + } + + String getDisplayText() { + return displayText; + } + + } + + + /** + * Processing stage details for an auto ingest job. + */ + static final class StageDetails implements Serializable { + + private static final long serialVersionUID = 1L; + private final String description; + private final Date startDate; + + StageDetails(String description, Date startDate) { + this.description = description; + this.startDate = startDate; + } + + String getDescription() { + return this.description; + } + + Date getStartDate() { + return new Date(this.startDate.getTime()); + } + + } + + /** + * Gets the current version of the auto ingest job coordination service node + * data. + * + * @return The version number. + */ + static int getCurrentVersion() { + return AutoIngestJobNodeData.CURRENT_VERSION; + } + + /** + * Uses a coordination service node data to construct an object that + * converts auto ingest job data for an auto ingest job coordination service + * node to and from byte arrays. + * + * @param nodeData The raw bytes received from the coordination service. + */ + AutoIngestJobNodeData(byte[] nodeData) throws InvalidDataException { + if (null == nodeData || nodeData.length == 0) { + throw new InvalidDataException(null == nodeData ? "Null nodeData byte array" : "Zero-length nodeData byte array"); + } + + /* + * Set default values for all fields. + */ + this.processingStatus = ProcessingStatus.PENDING.ordinal(); + this.priority = DEFAULT_PRIORITY; + this.numberOfCrashes = 0; + this.completedDate = 0L; + this.errorsOccurred = false; + this.version = 0; + this.manifestFilePath = ""; + this.manifestFileDate = 0L; + this.caseName = ""; + this.deviceId = ""; + this.dataSourcePath = ""; + this.caseDirectoryPath = ""; + this.processingHostName = ""; + this.processingStage = (byte) Stage.PENDING.ordinal(); + this.processingStageStartDate = 0L; + this.processingStageDetailsDescription = ""; + this.processingStageDetailsStartDate = 0L; + this.dataSourceSize = 0L; + + /* + * Get fields from node data. + */ + ByteBuffer buffer = ByteBuffer.wrap(nodeData); + try { + if (buffer.hasRemaining()) { + /* + * Get version 0 fields. + */ + this.processingStatus = buffer.getInt(); + this.priority = buffer.getInt(); + this.numberOfCrashes = buffer.getInt(); + this.completedDate = buffer.getLong(); + int errorFlag = buffer.getInt(); + this.errorsOccurred = (1 == errorFlag); + } + + if (buffer.hasRemaining()) { + /* + * Get version 1 fields. + */ + this.version = buffer.getInt(); + this.deviceId = getStringFromBuffer(buffer, TypeKind.BYTE); + this.caseName = getStringFromBuffer(buffer, TypeKind.BYTE); + this.caseDirectoryPath = getStringFromBuffer(buffer, TypeKind.SHORT); + this.manifestFileDate = buffer.getLong(); + this.manifestFilePath = getStringFromBuffer(buffer, TypeKind.SHORT); + this.dataSourcePath = getStringFromBuffer(buffer, TypeKind.SHORT); + this.processingStage = buffer.get(); + this.processingStageStartDate = buffer.getLong(); + this.processingStageDetailsDescription = getStringFromBuffer(buffer, TypeKind.BYTE); + this.processingStageDetailsStartDate = buffer.getLong(); + this.processingHostName = getStringFromBuffer(buffer, TypeKind.SHORT); + } + + if (buffer.hasRemaining()) { + /* + * Get version 2 fields. + */ + this.dataSourceSize = buffer.getLong(); + } + + } catch (BufferUnderflowException ex) { + throw new InvalidDataException("Node data is incomplete", ex); + } + } + + /** + * Gets the processing status of the job. + * + * @return The processing status. + */ + ProcessingStatus getProcessingStatus() { + return ProcessingStatus.values()[this.processingStatus]; + } + + /** + * Sets the processing status of the job. + * + * @param processingSatus The processing status. + */ + void setProcessingStatus(ProcessingStatus processingStatus) { + this.processingStatus = processingStatus.ordinal(); + } + + /** + * Gets the priority of the job. + * + * @return The priority. + */ + int getPriority() { + return this.priority; + } + + /** + * Sets the priority of the job. A higher number indicates a higheer + * priority. + * + * @param priority The priority. + */ + void setPriority(int priority) { + this.priority = priority; + } + + /** + * Gets the number of times the job has crashed during processing. + * + * @return The number of crashes. + */ + int getNumberOfCrashes() { + return this.numberOfCrashes; + } + + /** + * Sets the number of times the job has crashed during processing. + * + * @param numberOfCrashes The number of crashes. + */ + void setNumberOfCrashes(int numberOfCrashes) { + this.numberOfCrashes = numberOfCrashes; + } + + /** + * Gets the date the job was completed. A completion date equal to the epoch + * (January 1, 1970, 00:00:00 GMT), i.e., Date.getTime() returns 0L, + * indicates the job has not been completed. + * + * @return The job completion date. + */ + Date getCompletedDate() { + return new Date(this.completedDate); + } + + /** + * Sets the date the job was completed. A completion date equal to the epoch + * (January 1, 1970, 00:00:00 GMT), i.e., Date.getTime() returns 0L, + * indicates the job has not been completed. + * + * @param completedDate The job completion date. + */ + void setCompletedDate(Date completedDate) { + this.completedDate = completedDate.getTime(); + } + + /** + * Gets whether or not any errors occurred during the processing of the job. + * + * @return True or false. + */ + boolean getErrorsOccurred() { + return this.errorsOccurred; + } + + /** + * Sets whether or not any errors occurred during the processing of job. + * + * @param errorsOccurred True or false. + */ + void setErrorsOccurred(boolean errorsOccurred) { + this.errorsOccurred = errorsOccurred; + } + + /** + * Gets the node data version number. + * + * @return The version number. + */ + int getVersion() { + return this.version; + } + + /** + * Gets the device ID of the device associated with the data source for the + * job. + * + * @return The device ID. + */ + String getDeviceId() { + return this.deviceId; + } + + /** + * Sets the device ID of the device associated with the data source for the + * job. + * + * @param deviceId The device ID. + */ + void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + /** + * Gets the case name. + * + * @return The case name. + */ + String getCaseName() { + return this.caseName; + } + + /** + * Sets the case name. + * + * @param caseName The case name. + */ + void setCaseName(String caseName) { + this.caseName = caseName; + } + + /** + * Sets the path to the case directory of the case associated with the job. + * + * @param caseDirectoryPath The path to the case directory. + */ + synchronized void setCaseDirectoryPath(Path caseDirectoryPath) { + if (caseDirectoryPath == null) { + this.caseDirectoryPath = ""; + } else { + this.caseDirectoryPath = caseDirectoryPath.toString(); + } + } + + /** + * Gets the path to the case directory of the case associated with the job. + * + * @return The case directory path or an empty string path if the case + * directory has not been created yet. + */ + synchronized Path getCaseDirectoryPath() { + if (!caseDirectoryPath.isEmpty()) { + return Paths.get(caseDirectoryPath); + } else { + return Paths.get(""); + } + } + + /** + * Gets the date the manifest was created. + * + * @return The date the manifest was created. + */ + Date getManifestFileDate() { + return new Date(this.manifestFileDate); + } + + /** + * Sets the date the manifest was created. + * + * @param manifestFileDate The date the manifest was created. + */ + void setManifestFileDate(Date manifestFileDate) { + this.manifestFileDate = manifestFileDate.getTime(); + } + + /** + * Gets the manifest file path. + * + * @return The manifest file path. + */ + Path getManifestFilePath() { + return Paths.get(this.manifestFilePath); + } + + /** + * Sets the manifest file path. + * + * @param manifestFilePath The manifest file path. + */ + void setManifestFilePath(Path manifestFilePath) { + if (manifestFilePath != null) { + this.manifestFilePath = manifestFilePath.toString(); + } else { + this.manifestFilePath = ""; + } + } + + /** + * Gets the path of the data source for the job. + * + * @return The data source path. + */ + Path getDataSourcePath() { + return Paths.get(dataSourcePath); + } + + /** + * Get the file name portion of the path of the data source for the job. + * + * @return The data source file name. + */ + public String getDataSourceFileName() { + return Paths.get(dataSourcePath).getFileName().toString(); + } + + /** + * Sets the path of the data source for the job. + * + * @param dataSourcePath The data source path. + */ + void setDataSourcePath(Path dataSourcePath) { + if (dataSourcePath != null) { + this.dataSourcePath = dataSourcePath.toString(); + } else { + this.dataSourcePath = ""; + } + } + + /** + * Get the processing stage of the job. + * + * @return The processing stage. + */ + Stage getProcessingStage() { + return Stage.values()[this.processingStage]; + } + + /** + * Sets the processing stage job. + * + * @param processingStage The processing stage. + */ + void setProcessingStage(Stage processingStage) { + this.processingStage = (byte) processingStage.ordinal(); + } + + /** + * Gets the processing stage start date. + * + * @return The processing stage start date. + */ + Date getProcessingStageStartDate() { + return new Date(this.processingStageStartDate); + } + + /** + * Sets the processing stage start date. + * + * @param processingStageStartDate The processing stage start date. + */ + void setProcessingStageStartDate(Date processingStageStartDate) { + this.processingStageStartDate = processingStageStartDate.getTime(); + } + + /** + * Get the processing stage details. + * + * @return A processing stage details object. + */ + StageDetails getProcessingStageDetails() { + return new StageDetails(this.processingStageDetailsDescription, new Date(this.processingStageDetailsStartDate)); + } + + /** + * Sets the details of the current processing stage. + * + * @param stageDetails A stage details object. + */ + void setProcessingStageDetails(StageDetails stageDetails) { + this.processingStageDetailsDescription = stageDetails.getDescription(); + this.processingStageDetailsStartDate = stageDetails.getStartDate().getTime(); + } + + /** + * Gets the processing host name, may be the empty string. + * + * @return The processing host. The empty string if the job is not currently + * being processed. + */ + String getProcessingHostName() { + return this.processingHostName; + } + + /** + * Sets the processing host name. May be the empty string. + * + * @param processingHost The processing host name. The empty string if the + * job is not currently being processed. + */ + void setProcessingHostName(String processingHost) { + this.processingHostName = processingHost; + } + + /** + * Gets the total size of the data source. + * + * @return The data source size. + */ + long getDataSourceSize() { + return this.dataSourceSize; + } + + /** + * Sets the total size of the data source. + * + * @param dataSourceSize The data source size. + */ + void setDataSourceSize(long dataSourceSize) { + this.dataSourceSize = dataSourceSize; + } + + /** + * Gets the node data as a byte array that can be sent to the coordination + * service. + * + * @return The node data as a byte array. + */ + byte[] toArray() { + ByteBuffer buffer = ByteBuffer.allocate(MAX_POSSIBLE_NODE_DATA_SIZE); + + // Write data (compatible with version 0) + buffer.putInt(this.processingStatus); + buffer.putInt(this.priority); + buffer.putInt(this.numberOfCrashes); + buffer.putLong(this.completedDate); + buffer.putInt(this.errorsOccurred ? 1 : 0); + + if (this.version >= 1) { + // Write version + buffer.putInt(this.version); + + // Write data + putStringIntoBuffer(deviceId, buffer, TypeKind.BYTE); + putStringIntoBuffer(caseName, buffer, TypeKind.BYTE); + putStringIntoBuffer(caseDirectoryPath, buffer, TypeKind.SHORT); + buffer.putLong(this.manifestFileDate); + putStringIntoBuffer(manifestFilePath, buffer, TypeKind.SHORT); + putStringIntoBuffer(dataSourcePath, buffer, TypeKind.SHORT); + buffer.put(this.processingStage); + buffer.putLong(this.processingStageStartDate); + putStringIntoBuffer(this.processingStageDetailsDescription, buffer, TypeKind.BYTE); + buffer.putLong(this.processingStageDetailsStartDate); + putStringIntoBuffer(processingHostName, buffer, TypeKind.SHORT); + + if (this.version >= 2) { + buffer.putLong(this.dataSourceSize); + } + } + + // Prepare the array + byte[] array = new byte[buffer.position()]; + buffer.rewind(); + buffer.get(array, 0, array.length); + + return array; + } + + /** + * This method retrieves a string from a given buffer. Depending on the type + * specified, either a 'byte' or a 'short' will first be read out of the + * buffer which gives the length of the string so it can be properly parsed. + * + * @param buffer The buffer from which the string will be read. + * @param lengthType The size of the length data. + * + * @return The string read from the buffer. + */ + private String getStringFromBuffer(ByteBuffer buffer, TypeKind lengthType) { + int length = 0; + String output = ""; + + switch (lengthType) { + case BYTE: + length = buffer.get(); + break; + case SHORT: + length = buffer.getShort(); + break; + } + + if (length > 0) { + byte[] array = new byte[length]; + buffer.get(array, 0, length); + output = new String(array); + } + + return output; + } + + /** + * This method puts a given string into a given buffer. Depending on the + * type specified, either a 'byte' or a 'short' will be inserted prior to + * the string which gives the length of the string so it can be properly + * parsed. + * + * @param stringValue The string to write to the buffer. + * @param buffer The buffer to which the string will be written. + * @param lengthType The size of the length data. + */ + private void putStringIntoBuffer(String stringValue, ByteBuffer buffer, TypeKind lengthType) { + switch (lengthType) { + case BYTE: + buffer.put((byte) stringValue.length()); + break; + case SHORT: + buffer.putShort((short) stringValue.length()); + break; + } + + buffer.put(stringValue.getBytes()); + } + + final static class InvalidDataException extends Exception { + + private static final long serialVersionUID = 1L; + + private InvalidDataException(String message) { + super(message); + } + + private InvalidDataException(String message, Throwable cause) { + super(message, cause); + } + } + +} diff --git a/ZookeeperNodeMigration/src/zookeepernodemigration/TimeStampUtils.java b/ZookeeperNodeMigration/src/zookeepernodemigration/TimeStampUtils.java new file mode 100755 index 0000000000000000000000000000000000000000..c04feca3c1a2a66cbeca6263e870a67f7e8c73d5 --- /dev/null +++ b/ZookeeperNodeMigration/src/zookeepernodemigration/TimeStampUtils.java @@ -0,0 +1,93 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 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 zookeepernodemigration; + +import java.text.SimpleDateFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility methods for working with time stamps of the form + * 'yyyy_MM_dd_HH_mm_ss'. + */ +final class TimeStampUtils { + + /* + * Sample time stamp suffix: 2015_02_02_12_10_31 + */ + private static final Pattern TIME_STAMP_PATTERN = Pattern.compile("\\d{4}_\\d{2}_\\d{2}_\\d{2}_\\d{2}_\\d{2}$"); + private static final int LENGTH_OF_DATE_TIME_STAMP = 20; // length of the above time stamp + + /** + * Checks whether a string ends with a time stamp. + * + * @param inputString The string to check. + * + * @return True or false. + */ + static boolean endsWithTimeStamp(String inputString) { + Matcher m = TIME_STAMP_PATTERN.matcher(inputString); + return m.find(); + } + + /** + * Gets the fixed length of the time stamp suffix. + * + * @return The length. + */ + static int getTimeStampLength() { + return LENGTH_OF_DATE_TIME_STAMP; + } + + /** + * Removes the time stamp suffix from a string, if present. + * + * @param inputString The string to trim. + * + * @return The trimmed string. + */ + static String removeTimeStamp(String inputString) { + String trimmedString = inputString; + if (inputString != null && endsWithTimeStamp(inputString)) { + trimmedString = inputString.substring(0, inputString.length() - getTimeStampLength()); + } + return trimmedString; + } + + /** + * Gets the time stamp suffix from a string, if present. + * + * @param inputString the name to check for a timestamp + * + * @return The time stamp, may be the empty. + */ + static String getTimeStampOnly(String inputString) { + String timeStamp = ""; + if (inputString != null && endsWithTimeStamp(inputString)) { + timeStamp = inputString.substring(inputString.length() - getTimeStampLength(), inputString.length()); + } + return timeStamp; + } + + /* + * Private contructor to prevent instantiation. + */ + private TimeStampUtils() { + } +} diff --git a/ZookeeperNodeMigration/src/zookeepernodemigration/ZookeeperNodeMigration.java b/ZookeeperNodeMigration/src/zookeepernodemigration/ZookeeperNodeMigration.java new file mode 100755 index 0000000000000000000000000000000000000000..c62db26b84104f547e7bfd4ffa8586a5fa63a7bf --- /dev/null +++ b/ZookeeperNodeMigration/src/zookeepernodemigration/ZookeeperNodeMigration.java @@ -0,0 +1,464 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 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 zookeepernodemigration; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apache.curator.RetryPolicy; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.recipes.locks.InterProcessMutex; +import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock; +import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.KeeperException.NoNodeException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.ZooDefs; +import org.apache.zookeeper.ZooKeeper; + +/** + * Utility to migrate Autopsy coordination service data from one ZK database to + * another. + */ +public class ZookeeperNodeMigration { + + private static final Logger LOGGER = Logger.getLogger(ZookeeperNodeMigration.class.getName()); + private static final int SESSION_TIMEOUT_MILLISECONDS = 300000; + private static final int CONNECTION_TIMEOUT_MILLISECONDS = 300000; + private static final int ZOOKEEPER_SESSION_TIMEOUT_MILLIS = 3000; + private static final int ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS = 15000; + private static final String DEFAULT_NAMESPACE_ROOT = "autopsy"; + private static CuratorFramework inputCurator; + private static CuratorFramework outputCurator; + private static Map<String, String> categoryNodeToPath; + + private ZookeeperNodeMigration(){ + } + + /** + * Main method. + * + * @param args the command line arguments + */ + public static void main(String[] args) { + + String inputZkIpAddr, inputZkPort, outputZkIpAddr, outputZkPort; + + if (args.length == 4) { + inputZkIpAddr = args[0]; + inputZkPort = args[1]; + outputZkIpAddr = args[2]; + outputZkPort = args[3]; + } else { + System.out.println("Input needs to be [Input Zookeeper IP Address] [Input Zookeeper Port Number] [Output Zookeeper IP Address] [Output Zookeeper Port Number]"); + LOGGER.log(Level.SEVERE, "Input needs to be [Input Zookeeper IP Address] [Input Zookeeper Port Number] [Output Zookeeper IP Address] [Output Zookeeper Port Number]"); + return; + } + + if (inputZkIpAddr.isEmpty() || inputZkPort.isEmpty() || outputZkIpAddr.isEmpty() || outputZkPort.isEmpty()) { + System.out.println("Input needs to be [Input Zookeeper IP Address] [Input Zookeeper Port Number] [Output Zookeeper IP Address] [Output Zookeeper Port Number]"); + LOGGER.log(Level.SEVERE, "Input needs to be [Input Zookeeper IP Address] [Input Zookeeper Port Number] [Output Zookeeper IP Address] [Output Zookeeper Port Number]"); + return; + } + + inputCurator = initializeCurator(inputZkIpAddr, inputZkPort); + if (inputCurator == null) { + System.out.println("Unable to initialize Zookeeper or Curator: " + inputZkIpAddr + ":" + inputZkPort); + LOGGER.log(Level.SEVERE, "Unable to initialize Zookeeper or Curator: {0}:{1}", new Object[]{inputZkIpAddr, inputZkPort}); + return; + } + + try { + categoryNodeToPath = populateCategoryNodes(inputCurator); + } catch (KeeperException | CoordinationServiceException ex) { + System.out.println("Unable to initialize Curator: " + inputZkIpAddr + ":" + inputZkPort); + LOGGER.log(Level.SEVERE, "Unable to initialize Curator: {0}:{1}", new Object[]{inputZkIpAddr, inputZkPort}); + return; + } + + outputCurator = initializeCurator(outputZkIpAddr, outputZkPort); + if (outputCurator == null) { + System.out.println("Unable to initialize Zookeeper or Curator: " + outputZkIpAddr + ":" + outputZkPort); + LOGGER.log(Level.SEVERE, "Unable to initialize Zookeeper or Curator: {0}:{1}", new Object[]{outputZkIpAddr, outputZkPort}); + return; + } + + try { + // if output ZK database is new, we may have to ceate root "autopsy" node and it's sub-nodes + populateCategoryNodes(outputCurator); + } catch (KeeperException | CoordinationServiceException ex) { + System.out.println("Unable to initialize Curator: " + outputZkIpAddr + ":" + outputZkPort); + LOGGER.log(Level.SEVERE, "Unable to initialize Curator: {0}:{1}", new Object[]{outputZkIpAddr, outputZkPort}); + return; + } + + copyAllCategoryNodes(); + + System.out.println("Done..."); + } + + /** + * Copy all Autopsy coordination service nodes from one ZK database to + * another. + */ + private static void copyAllCategoryNodes() { + + for (CategoryNode category : CategoryNode.values()) { + List<String> inputNodeList = Collections.EMPTY_LIST; + try { + inputNodeList = getNodeList(category); + } catch (CoordinationServiceException ex) { + System.out.println("Unable to get ZK nodes for category: " + category.getDisplayName()); + LOGGER.log(Level.SEVERE, "Unable to get ZK nodes for category: " + category.getDisplayName(), ex); + continue; + } + + for (String zkNode : inputNodeList) { + try { + final byte[] nodeBytes = getNodeData(category, zkNode); + try (Lock manifestLock = tryGetExclusiveLock(outputCurator, category, zkNode)) { + setNodeData(outputCurator, category, zkNode, nodeBytes); + } + } catch (CoordinationServiceException | InterruptedException ex) { + System.out.println("Unable to write ZK node data for node: " + zkNode); + LOGGER.log(Level.SEVERE, "Unable to write ZK node data for node: " + zkNode, ex); + continue; + } + } + } + } + + /** + * Initialize Curator framework. + * + * @param zkIpAddr Zookeeper server IP address. + * @param zookeeperPort Zookeeper server port number. + * + * @return CuratorFramework object + */ + private static CuratorFramework initializeCurator(String zkIpAddr, String zookeeperPort) { + + try { + if (!isZooKeeperAccessible(zkIpAddr, zookeeperPort)) { + System.out.println("Unable to connect to Zookeeper"); + LOGGER.log(Level.SEVERE, "Unable to connect to Zookeeper"); + return null; + } + } catch (InterruptedException | IOException ex) { + System.out.println("Unable to connect to Zookeeper"); + LOGGER.log(Level.SEVERE, "Unable to connect to Zookeeper", ex); + return null; + } + + /* + * Connect to ZooKeeper via Curator. + */ + RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3); + String connectString = zkIpAddr + ":" + zookeeperPort; + CuratorFramework curator = CuratorFrameworkFactory.newClient(connectString, SESSION_TIMEOUT_MILLISECONDS, CONNECTION_TIMEOUT_MILLISECONDS, retryPolicy); + curator.start(); + return curator; + } + + /* + * Creates Autopsy coordination service root ZK nodes. + */ + private static Map<String, String> populateCategoryNodes(CuratorFramework curator) throws KeeperException, CoordinationServiceException { + /* + * Create the top-level root and category nodes. + */ + String rootNodeName = DEFAULT_NAMESPACE_ROOT; + String rootNode = rootNodeName; + + if (!rootNode.startsWith("/")) { + rootNode = "/" + rootNode; + } + Map<String, String> categoryPaths = new ConcurrentHashMap<>(); + for (CategoryNode node : CategoryNode.values()) { + String nodePath = rootNode + "/" + node.getDisplayName(); + try { + curator.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE).forPath(nodePath); + } catch (KeeperException ex) { + if (ex.code() != KeeperException.Code.NODEEXISTS) { + throw ex; + } + } catch (Exception ex) { + throw new CoordinationServiceException("Curator experienced an error", ex); + } + categoryPaths.put(node.getDisplayName(), nodePath); + } + return categoryPaths; + } + + /** + * Determines if ZooKeeper is accessible with the current settings. Closes + * the connection prior to returning. + * + * @return true if a connection was achieved, false otherwise + * + * @throws InterruptedException + * @throws IOException + */ + private static boolean isZooKeeperAccessible(String solrIpAddr, String zookeeperPort) throws InterruptedException, IOException { + boolean result = false; + Object workerThreadWaitNotifyLock = new Object(); + String connectString = solrIpAddr + ":" + zookeeperPort; + ZooKeeper zooKeeper = new ZooKeeper(connectString, ZOOKEEPER_SESSION_TIMEOUT_MILLIS, + (WatchedEvent event) -> { + synchronized (workerThreadWaitNotifyLock) { + workerThreadWaitNotifyLock.notifyAll(); + } + }); + synchronized (workerThreadWaitNotifyLock) { + workerThreadWaitNotifyLock.wait(ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS); + } + ZooKeeper.States state = zooKeeper.getState(); + if (state == ZooKeeper.States.CONNECTED || state == ZooKeeper.States.CONNECTEDREADONLY) { + result = true; + } + zooKeeper.close(); + return result; + } + + /** + * Tries to get an exclusive lock on a node path appended to a category path + * in the namespace managed by this coordination service. Returns + * immediately if the lock can not be acquired. + * + * IMPORTANT: The lock needs to be released in the same thread in which it + * is acquired. + * + * @param category The desired category in the namespace. + * @param nodePath The node path to use as the basis for the lock. + * + * @return The lock, or null if the lock could not be obtained. + * + * @throws CoordinationServiceException If there is an error during lock + * acquisition. + */ + private static Lock tryGetExclusiveLock(CuratorFramework curator, CategoryNode category, String nodePath) throws CoordinationServiceException { + String fullNodePath = getFullyQualifiedNodePath(category, nodePath); + try { + InterProcessReadWriteLock lock = new InterProcessReadWriteLock(curator, fullNodePath); + if (!lock.writeLock().acquire(0, TimeUnit.SECONDS)) { + return null; + } + return new Lock(nodePath, lock.writeLock()); + } catch (Exception ex) { + throw new CoordinationServiceException(String.format("Failed to get exclusive lock for %s", fullNodePath), ex); + } + } + + /** + * Retrieve the data associated with the specified node. + * + * @param category The desired category in the namespace. + * @param nodePath The node to retrieve the data for. + * + * @return The data associated with the node, if any, or null if the node + * has not been created yet. + * + * @throws CoordinationServiceException If there is an error setting the + * node data. + * @throws InterruptedException If interrupted while blocked during + * setting of node data. + */ + private static byte[] getNodeData(CategoryNode category, String nodePath) throws CoordinationServiceException, InterruptedException { + String fullNodePath = getFullyQualifiedNodePath(category, nodePath); + try { + return inputCurator.getData().forPath(fullNodePath); + } catch (NoNodeException ex) { + return null; + } catch (Exception ex) { + if (ex instanceof InterruptedException) { + throw (InterruptedException) ex; + } else { + throw new CoordinationServiceException(String.format("Failed to get data for %s", fullNodePath), ex); + } + } + } + + /** + * Store the given data with the specified node. + * + * @param category The desired category in the namespace. + * @param nodePath The node to associate the data with. + * @param data The data to store with the node. + * + * @throws CoordinationServiceException If there is an error setting the + * node data. + * @throws InterruptedException If interrupted while blocked during + * setting of node data. + */ + private static void setNodeData(CuratorFramework curator, CategoryNode category, String nodePath, byte[] data) throws CoordinationServiceException, InterruptedException { + String fullNodePath = getFullyQualifiedNodePath(category, nodePath); + try { + curator.setData().forPath(fullNodePath, data); + } catch (Exception ex) { + if (ex instanceof InterruptedException) { + throw (InterruptedException) ex; + } else { + throw new CoordinationServiceException(String.format("Failed to set data for %s", fullNodePath), ex); + } + } + } + + /** + * Delete the specified node. + * + * @param category The desired category in the namespace. + * @param nodePath The node to delete. + * + * @throws CoordinationServiceException If there is an error setting the + * node data. + * @throws InterruptedException If interrupted while blocked during + * setting of node data. + */ + private static void deleteNode(CategoryNode category, String nodePath) throws CoordinationServiceException, InterruptedException { + String fullNodePath = getFullyQualifiedNodePath(category, nodePath); + try { + inputCurator.delete().forPath(fullNodePath); + } catch (Exception ex) { + if (ex instanceof InterruptedException) { + throw (InterruptedException) ex; + } else { + throw new CoordinationServiceException(String.format("Failed to set data for %s", fullNodePath), ex); + } + } + } + + /** + * Gets a list of the child nodes of a category in the namespace. + * + * @param category The desired category in the namespace. + * + * @return A list of child node names. + * + * @throws CoordinationServiceException If there is an error getting the + * node list. + */ + private static List<String> getNodeList(CategoryNode category) throws CoordinationServiceException { + try { + List<String> list = inputCurator.getChildren().forPath(categoryNodeToPath.get(category.getDisplayName())); + return list; + } catch (Exception ex) { + throw new CoordinationServiceException(String.format("Failed to get node list for %s", category.getDisplayName()), ex); + } + } + + /** + * Creates a node path within a given category. + * + * @param category A category node. + * @param nodePath A node path relative to a category node path. + * + * @return + */ + private static String getFullyQualifiedNodePath(CategoryNode category, String nodePath) { + // nodePath on Unix systems starts with a "/" and ZooKeeper doesn't like two slashes in a row + if (nodePath.startsWith("/")) { + return categoryNodeToPath.get(category.getDisplayName()) + nodePath.toUpperCase(); + } else { + return categoryNodeToPath.get(category.getDisplayName()) + "/" + nodePath.toUpperCase(); + } + } + + /** + * Exception type thrown by the coordination service. + */ + private final static class CoordinationServiceException extends Exception { + + private static final long serialVersionUID = 1L; + + private CoordinationServiceException(String message) { + super(message); + } + + private CoordinationServiceException(String message, Throwable cause) { + super(message, cause); + } + } + + /** + * An opaque encapsulation of a lock for use in distributed synchronization. + * Instances are obtained by calling a get lock method and must be passed to + * a release lock method. + */ + private static class Lock implements AutoCloseable { + + /** + * This implementation uses the Curator read/write lock. see + * http://curator.apache.org/curator-recipes/shared-reentrant-read-write-lock.html + */ + private final InterProcessMutex interProcessLock; + private final String nodePath; + + private Lock(String nodePath, InterProcessMutex lock) { + this.nodePath = nodePath; + this.interProcessLock = lock; + } + + public String getNodePath() { + return nodePath; + } + + public void release() throws CoordinationServiceException { + try { + this.interProcessLock.release(); + } catch (Exception ex) { + throw new CoordinationServiceException(String.format("Failed to release the lock on %s", nodePath), ex); + } + } + + @Override + public void close() throws CoordinationServiceException { + release(); + } + } + + /** + * Category nodes are the immediate children of the root node of a shared + * hierarchical namespace managed by a coordination service. + */ + public enum CategoryNode { + + CASES("cases"), + MANIFESTS("manifests"), + CONFIG("config"), + CENTRAL_REPO("centralRepository"), + HEALTH_MONITOR("healthMonitor"); + + private final String displayName; + + private CategoryNode(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } + } +} diff --git a/build.xml b/build.xml index a7c64ef4bad203bc19efc5f1e9b1939f28e2693a..7377d59c04f238240221b2ae1bb1b1fdf88f299c 100644 --- a/build.xml +++ b/build.xml @@ -106,8 +106,7 @@ <copy file="${basedir}/NEWS.txt" tofile="${zip-tmp}/${app.name}/NEWS.txt"/> <copy file="${basedir}/Running_Linux_OSX.txt" tofile="${zip-tmp}/${app.name}/Running_Linux_OSX.txt"/> <copy file="${basedir}/unix_setup.sh" tofile="${zip-tmp}/${app.name}/unix_setup.sh"/> - <copy file="${basedir}/ManifestTool/ManifestTool.exe" todir="${zip-tmp}/${app.name}/bin"/> - + <copy file="${basedir}/ManifestTool/ManifestTool.exe" todir="${zip-tmp}/${app.name}/bin"/> <copy file="${basedir}/icons/icon.ico" tofile="${zip-tmp}/${app.name}/icon.ico" overwrite="true"/> @@ -115,6 +114,14 @@ <copy flatten="true" todir="${zip-tmp}/${app.name}/docs"> <fileset dir="${basedir}/docs/doxygen-user/user-docs"/> </copy> + + <!-- Copy the ZooKeeper migration tool, it's JAR files, and documentation --> + <copy flatten="false" todir="${zip-tmp}/${app.name}/autopsy/ZookeeperNodeMigration"> + <fileset dir="${basedir}/ZookeeperNodeMigration/dist"/> + </copy> + <copy flatten="false" todir="${zip-tmp}/${app.name}/autopsy/ZookeeperNodeMigration" overwrite="true"> + <fileset dir="${basedir}/ZookeeperNodeMigration/docs"/> + </copy> <property name="app.property.file" value="${zip-tmp}/${app.name}/etc/${app.name}.conf" /> <var name="jvm-value" value="--branding ${app.name} -J-Xms24m -J-Xmx4G -J-Xverify:none -J-XX:+UseG1GC -J-XX:+UseStringDeduplication"/> diff --git a/docs/doxygen-user/images/mt_config.png b/docs/doxygen-user/images/mt_config.png index e3022aec0da45d6dbd2ad29a1d361c4d4caaca25..b793191ae8592c349ec3a92a6fed0f0c27e34380 100644 Binary files a/docs/doxygen-user/images/mt_config.png and b/docs/doxygen-user/images/mt_config.png differ diff --git a/docs/doxygen-user/images/mt_ocr_image.png b/docs/doxygen-user/images/mt_ocr_image.png new file mode 100644 index 0000000000000000000000000000000000000000..b4e16bfa0944a6ca2f7ef738e5bb061b2c014898 Binary files /dev/null and b/docs/doxygen-user/images/mt_ocr_image.png differ diff --git a/docs/doxygen-user/images/mt_ocr_result.png b/docs/doxygen-user/images/mt_ocr_result.png new file mode 100644 index 0000000000000000000000000000000000000000..27d9af77f0a40e619a2b2440864fa3b6722b5180 Binary files /dev/null and b/docs/doxygen-user/images/mt_ocr_result.png differ diff --git a/docs/doxygen-user/keyword_search.dox b/docs/doxygen-user/keyword_search.dox index 271e660cac6666111635802306e71434cf6bc68a..fd207a6de29a721b11acd235df9a6351e712901c 100644 --- a/docs/doxygen-user/keyword_search.dox +++ b/docs/doxygen-user/keyword_search.dox @@ -57,6 +57,7 @@ The "Indexed Text" tab shows the results when running the keyword search module \image html keyword-search-ocr-indexed-text.png +\anchor keyword_search_ocr_config By default, OCR is only configured for English text. Its configuration depends on the presence of language files (called "traineddata" files) that exist in a location that Autopsy can understand. To add support for more languages, you will need to download additional "traineddata" and move them to the right location. The following steps breakdown this process for you: diff --git a/docs/doxygen-user/machine_translation.dox b/docs/doxygen-user/machine_translation.dox index cec795d932a47247d09a200266108a764c7c2072..4609c81257398b787150a0f9f68a8c1716c3cc24 100644 --- a/docs/doxygen-user/machine_translation.dox +++ b/docs/doxygen-user/machine_translation.dox @@ -17,6 +17,8 @@ To set up a machine translation service, go to Options->Tools and then select th Each service will require slightly different configuration steps. After setting everything up, you can run a quick check that the service is set up correctly using the "Test" button. +The checkbox at the bottom allows you to enable or disable optical character recognition (OCR). When enabled, if you select an image in the \ref mt_content_viewer "content viewer" Autopsy will use OCR to attempt to extract text to be translated. Instructions for installing OCR packages for different languages can be found on the \ref keyword_search_ocr_config "Keyword Search page". + \section mt_file_names Translating File Names You can use machine translation to automatically translate file and folder names, such as the ones seen below: @@ -49,4 +51,12 @@ Then use the drop-down menu on the right to change from "Original Text" to "Tran \image html mt_message_translated.png +If you've enabled OCR as described in the \ref mt_config section above, you can extract and translate text from images. Here is an image containing the beginning of a French poem: + +\image html mt_ocr_image.png + +If you go to the Text tab and then the Translation viewer it will use OCR to read text from the image and then display the translation. + +\image html mt_ocr_result.png + */ \ No newline at end of file diff --git a/thunderbirdparser/nbproject/project.xml b/thunderbirdparser/nbproject/project.xml index 4c32aa38610912759b22fe89d0b5a575eccf7fa8..31276d7838026cfe09db454bb537a66632bc37a7 100644 --- a/thunderbirdparser/nbproject/project.xml +++ b/thunderbirdparser/nbproject/project.xml @@ -44,7 +44,8 @@ <build-prerequisite/> <compile-dependency/> <run-dependency> - <specification-version>1.0</specification-version> + <release-version>1</release-version> + <specification-version>23</specification-version> </run-dependency> </dependency> <dependency> diff --git a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java index 0f9759819f9adc50616ed9f0c7a93ab8b838dd92..9957c52454489d16e866b06e71edbb05280dd3f4 100644 --- a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java @@ -79,7 +79,7 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule { private static final int MBOX_SIZE_TO_SPLIT = 1048576000; private Case currentCase; - + /** * Empty constructor. */ @@ -139,6 +139,10 @@ public ProcessResult process(AbstractFile abstractFile) { boolean isPstFile = PstParser.isPstFile(abstractFile); boolean isVcardFile = VcardParser.isVcardFile(abstractFile); + if (context.fileIngestIsCancelled()) { + return ProcessResult.OK; + } + if (isMbox || isEMLFile || isPstFile || isVcardFile ) { try { communicationArtifactsHelper = new CommunicationArtifactsHelper(currentCase.getSleuthkitCase(), @@ -213,6 +217,9 @@ private ProcessResult processPst(AbstractFile abstractFile) { Iterator<EmailMessage> pstMsgIterator = parser.getEmailMessageIterator(); if (pstMsgIterator != null) { processEmails(parser.getPartialEmailMessages(), pstMsgIterator , abstractFile); + if (context.fileIngestIsCancelled()) { + return ProcessResult.OK; + } } else { // sometimes parser returns ParseResult=OK but there are no messages postErrorMessage( @@ -321,6 +328,9 @@ private ProcessResult processMBox(AbstractFile abstractFile) { } processMboxFile(file, abstractFile, emailFolder); + if (context.fileIngestIsCancelled()) { + return ProcessResult.OK; + } if (file.delete() == false) { logger.log(Level.INFO, "Failed to delete temp file: {0}", file.getName()); //NON-NLS @@ -349,7 +359,9 @@ private ProcessResult processMBox(AbstractFile abstractFile) { if (splitFile.delete() == false) { logger.log(Level.INFO, "Failed to delete temp file: {0}", splitFile); //NON-NLS } - + if (context.fileIngestIsCancelled()) { + return ProcessResult.OK; + } } } @@ -385,6 +397,9 @@ private void processMboxFile(File file, AbstractFile abstractFile, String emailF List<EmailMessage> emails = new ArrayList<>(); if(emailIterator != null) { while(emailIterator.hasNext()) { + if (context.fileIngestIsCancelled()) { + return; + } EmailMessage emailMessage = emailIterator.next(); if(emailMessage != null) { emails.add(emailMessage); @@ -526,6 +541,10 @@ private void processEmails(List<EmailMessage> partialEmailsForThreading, Iterato int msgCnt = 0; while(fullMessageIterator.hasNext()) { + if (context.fileIngestIsCancelled()) { + return; + } + EmailMessage current = fullMessageIterator.next(); if(current == null) { @@ -550,6 +569,9 @@ private void processEmails(List<EmailMessage> partialEmailsForThreading, Iterato if (derivedFiles.isEmpty() == false) { for (AbstractFile derived : derivedFiles) { + if (context.fileIngestIsCancelled()) { + return; + } services.fireModuleContentEvent(new ModuleContentEvent(derived)); } } @@ -675,6 +697,10 @@ private BlackboardArtifact addEmailArtifact(EmailMessage email, AbstractFile abs String senderAddress; senderAddressList.addAll(findEmailAddresess(from)); + if (context.fileIngestIsCancelled()) { + return null; + } + AccountFileInstance senderAccountInstance = null; if (senderAddressList.size() == 1) { @@ -690,13 +716,20 @@ private BlackboardArtifact addEmailArtifact(EmailMessage email, AbstractFile abs logger.log(Level.WARNING, "Failed to find sender address, from = {0}", from); //NON-NLS } + if (context.fileIngestIsCancelled()) { + return null; + } + List<String> recipientAddresses = new ArrayList<>(); recipientAddresses.addAll(findEmailAddresess(to)); recipientAddresses.addAll(findEmailAddresess(cc)); recipientAddresses.addAll(findEmailAddresess(bcc)); List<AccountFileInstance> recipientAccountInstances = new ArrayList<>(); - recipientAddresses.forEach((addr) -> { + for (String addr : recipientAddresses) { + if (context.fileIngestIsCancelled()) { + return null; + } try { AccountFileInstance recipientAccountInstance = currentCase.getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.EMAIL, addr, @@ -706,7 +739,7 @@ private BlackboardArtifact addEmailArtifact(EmailMessage email, AbstractFile abs catch(TskCoreException ex) { logger.log(Level.WARNING, "Failed to create account for email address " + addr, ex); //NON-NLS } - }); + } addArtifactAttribute(headers, ATTRIBUTE_TYPE.TSK_HEADERS, bbattributes); addArtifactAttribute(from, ATTRIBUTE_TYPE.TSK_EMAIL_FROM, bbattributes); @@ -731,12 +764,23 @@ private BlackboardArtifact addEmailArtifact(EmailMessage email, AbstractFile abs try { + if (context.fileIngestIsCancelled()) { + return null; + } bbart = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG); bbart.addAttributes(bbattributes); + if (context.fileIngestIsCancelled()) { + return null; + } + // Add account relationships currentCase.getSleuthkitCase().getCommunicationsManager().addRelationships(senderAccountInstance, recipientAccountInstances, bbart,Relationship.Type.MESSAGE, dateL); + + if (context.fileIngestIsCancelled()) { + return null; + } try { // index the artifact for keyword search