From 82c5e3e96a18603e6965f158a1ff74666f56ca4e Mon Sep 17 00:00:00 2001 From: Alan Davis Date: Thu, 28 Jun 2018 13:25:01 +0100 Subject: [PATCH] REPO-3425 Transformers: Tika based transformers --- .../Dockerfile | 2 +- .../AlfrescoPdfRendererController.java | 12 - .../AlfrescoPdfRendererControllerTest.java | 2 +- alfresco-docker-imagemagick/Dockerfile | 2 +- .../ImageMagickControllerTest.java | 2 +- alfresco-docker-libreoffice/Dockerfile | 2 +- alfresco-docker-tika/.maven-dockerignore | 1 + alfresco-docker-tika/Dockerfile | 20 + alfresco-docker-tika/LICENSES.md | 7 + alfresco-docker-tika/pom.xml | 268 ++++++ .../org/alfresco/transformer/Application.java | 27 + .../java/org/alfresco/transformer/Tika.java | 801 ++++++++++++++++++ .../alfresco/transformer/TikaController.java | 137 +++ .../transformer/TikaOfficeDetectParser.java | 117 +++ .../src/main/resources/quick.pdf | Bin 0 -> 23697 bytes .../resources/templates/transformForm.html | 39 + .../src/main/resources/tika-config.xml | 6 + .../transformer/TikaControllerTest.java | 344 ++++++++ .../transformer/TikaHttpRequestTest.java | 51 ++ .../src/test/resources/quick.doc | Bin 0 -> 19968 bytes .../src/test/resources/quick.docx | Bin 0 -> 10197 bytes .../src/test/resources/quick.msg | Bin 0 -> 28160 bytes .../src/test/resources/quick.pptx | Bin 0 -> 37824 bytes .../src/test/resources/quick.txt | 6 + .../src/test/resources/quick.xslx | Bin 0 -> 8643 bytes .../src/test/resources/quick.zip | Bin 0 -> 47055 bytes .../AbstractTransformerController.java | 84 +- .../src/main/resources/application.properties | 3 +- .../AbstractTransformerControllerTest.java | 71 +- pom.xml | 9 +- scripts/testImages.sh | 39 + 31 files changed, 1997 insertions(+), 55 deletions(-) create mode 100644 alfresco-docker-tika/.maven-dockerignore create mode 100644 alfresco-docker-tika/Dockerfile create mode 100644 alfresco-docker-tika/LICENSES.md create mode 100644 alfresco-docker-tika/pom.xml create mode 100644 alfresco-docker-tika/src/main/java/org/alfresco/transformer/Application.java create mode 100644 alfresco-docker-tika/src/main/java/org/alfresco/transformer/Tika.java create mode 100644 alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaController.java create mode 100644 alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaOfficeDetectParser.java create mode 100644 alfresco-docker-tika/src/main/resources/quick.pdf create mode 100644 alfresco-docker-tika/src/main/resources/templates/transformForm.html create mode 100644 alfresco-docker-tika/src/main/resources/tika-config.xml create mode 100644 alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaControllerTest.java create mode 100644 alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaHttpRequestTest.java create mode 100644 alfresco-docker-tika/src/test/resources/quick.doc create mode 100644 alfresco-docker-tika/src/test/resources/quick.docx create mode 100644 alfresco-docker-tika/src/test/resources/quick.msg create mode 100644 alfresco-docker-tika/src/test/resources/quick.pptx create mode 100644 alfresco-docker-tika/src/test/resources/quick.txt create mode 100644 alfresco-docker-tika/src/test/resources/quick.xslx create mode 100644 alfresco-docker-tika/src/test/resources/quick.zip create mode 100755 scripts/testImages.sh diff --git a/alfresco-docker-alfresco-pdf-renderer/Dockerfile b/alfresco-docker-alfresco-pdf-renderer/Dockerfile index 2824b46c..c2334389 100644 --- a/alfresco-docker-alfresco-pdf-renderer/Dockerfile +++ b/alfresco-docker-alfresco-pdf-renderer/Dockerfile @@ -3,7 +3,7 @@ # The container is only intended to be used with the Alfresco Enterprise editon which is covered by https://www.alfresco.com/legal/agreements and https://www.alfresco.com/terms-use. # alfresco-pdf-renderer uses the PDFium library from Google Inc. See the license at https://pdfium.googlesource.com/pdfium/+/master/LICENSE or in /pdfium.txt. -FROM quay.io/alfresco/alfresco-base-java:9 +FROM alfresco/alfresco-base-java:8 ENV ALFRESCO_PDF_RENDERER_LIB_RPM_URL=https://nexus.alfresco.com/nexus/service/local/repositories/releases/content/org/alfresco/alfresco-pdf-renderer/1.1/alfresco-pdf-renderer-1.1-linux.tgz ENV PDFIUM_LICENSE_FILE=https://github.com/Alfresco/acs-community-packaging/blob/master/distribution/src/main/resources/licenses/3rd-party/pdfium.txt diff --git a/alfresco-docker-alfresco-pdf-renderer/src/main/java/org/alfresco/transformer/AlfrescoPdfRendererController.java b/alfresco-docker-alfresco-pdf-renderer/src/main/java/org/alfresco/transformer/AlfrescoPdfRendererController.java index 06d8d05f..b2fc1ef1 100644 --- a/alfresco-docker-alfresco-pdf-renderer/src/main/java/org/alfresco/transformer/AlfrescoPdfRendererController.java +++ b/alfresco-docker-alfresco-pdf-renderer/src/main/java/org/alfresco/transformer/AlfrescoPdfRendererController.java @@ -155,16 +155,4 @@ public class AlfrescoPdfRendererController extends AbstractTransformerController return createAttachment(targetFilename, targetFile, testDelay); } - - private void executeTransformCommand(String options, File sourceFile, File targetFile, @RequestParam(value = "timeout", required = false) Long timeout) - { - LogEntry.setOptions(options); - - Map properties = new HashMap(5); - properties.put("options", options); - properties.put("source", sourceFile.getAbsolutePath()); - properties.put("target", targetFile.getAbsolutePath()); - - executeTransformCommand(properties, targetFile, timeout); - } } diff --git a/alfresco-docker-alfresco-pdf-renderer/src/test/java/org/alfresco/transformer/AlfrescoPdfRendererControllerTest.java b/alfresco-docker-alfresco-pdf-renderer/src/test/java/org/alfresco/transformer/AlfrescoPdfRendererControllerTest.java index 311b4638..6b2dc12c 100644 --- a/alfresco-docker-alfresco-pdf-renderer/src/test/java/org/alfresco/transformer/AlfrescoPdfRendererControllerTest.java +++ b/alfresco-docker-alfresco-pdf-renderer/src/test/java/org/alfresco/transformer/AlfrescoPdfRendererControllerTest.java @@ -51,7 +51,7 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro @Before public void before() throws IOException { - super.mockTransformCommand(controller, "pdf", "png", "application/pdf"); + super.mockTransformCommand(controller, "pdf", "png", "application/pdf", true); } @Test diff --git a/alfresco-docker-imagemagick/Dockerfile b/alfresco-docker-imagemagick/Dockerfile index 64e644b1..db121c6e 100644 --- a/alfresco-docker-imagemagick/Dockerfile +++ b/alfresco-docker-imagemagick/Dockerfile @@ -3,7 +3,7 @@ # The container is only intended to be used with the Alfresco Enterprise editon which is covered by https://www.alfresco.com/legal/agreements and https://www.alfresco.com/terms-use. # ImageMagick is from ImageMagick Studio LLC. See the license at http://www.imagemagick.org/script/license.php or in /ImageMagick-license.txt. -FROM quay.io/alfresco/alfresco-base-java:9 +FROM alfresco/alfresco-base-java:8 ENV IMAGEMAGICK_RPM_URL=https://nexus.alfresco.com/nexus/service/local/repositories/thirdparty/content/org/imagemagick/imagemagick-distribution/7.0.7-27/imagemagick-distribution-7.0.7-27-linux.rpm ENV IMAGEMAGICK_LIB_RPM_URL=https://nexus.alfresco.com/nexus/service/local/repositories/thirdparty/content/org/imagemagick/imagemagick-distribution/7.0.7-27/imagemagick-distribution-7.0.7-27-libs-linux.rpm diff --git a/alfresco-docker-imagemagick/src/test/java/org/alfresco/transformer/ImageMagickControllerTest.java b/alfresco-docker-imagemagick/src/test/java/org/alfresco/transformer/ImageMagickControllerTest.java index 2d8a6029..5cf5025a 100644 --- a/alfresco-docker-imagemagick/src/test/java/org/alfresco/transformer/ImageMagickControllerTest.java +++ b/alfresco-docker-imagemagick/src/test/java/org/alfresco/transformer/ImageMagickControllerTest.java @@ -51,7 +51,7 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest @Before public void before() throws IOException { - super.mockTransformCommand(controller, "jpg", "png", "image/jpg"); + super.mockTransformCommand(controller, "jpg", "png", "image/jpg", true); } @Test diff --git a/alfresco-docker-libreoffice/Dockerfile b/alfresco-docker-libreoffice/Dockerfile index 4a9d264b..80aa75f7 100644 --- a/alfresco-docker-libreoffice/Dockerfile +++ b/alfresco-docker-libreoffice/Dockerfile @@ -3,7 +3,7 @@ # The container is only intended to be used with the Alfresco Enterprise editon which is covered by https://www.alfresco.com/legal/agreements and https://www.alfresco.com/terms-use. # LibreOffice is from The Document Foundation. See the license at https://www.libreoffice.org/download/license/ or in /libreoffice.txt. -FROM quay.io/alfresco/alfresco-base-java:9 +FROM alfresco/alfresco-base-java:8 ENV LIBREOFFICE_RPM_URL=https://nexus.alfresco.com/nexus/service/local/repositories/thirdparty/content/org/libreoffice/libreoffice-dist/5.4.6/libreoffice-dist-5.4.6-linux.gz ENV LIBREOFFICE_LICENSE_FILE=https://github.com/Alfresco/acs-community-packaging/blob/master/distribution/src/main/resources/licenses/3rd-party/libreoffice.txt diff --git a/alfresco-docker-tika/.maven-dockerignore b/alfresco-docker-tika/.maven-dockerignore new file mode 100644 index 00000000..112bd182 --- /dev/null +++ b/alfresco-docker-tika/.maven-dockerignore @@ -0,0 +1 @@ +target/docker/ \ No newline at end of file diff --git a/alfresco-docker-tika/Dockerfile b/alfresco-docker-tika/Dockerfile new file mode 100644 index 00000000..fb20d99b --- /dev/null +++ b/alfresco-docker-tika/Dockerfile @@ -0,0 +1,20 @@ +# Image provides a container in which to run Tika transformations for Alfresco Enterprise Content Services. + +# The container is only intended to be used with the Alfresco Enterprise editon which is covered by https://www.alfresco.com/legal/agreements and https://www.alfresco.com/terms-use. +# Tika is from Apache. See the license at http://www.apache.org/licenses/LICENSE-2.0. + +FROM alfresco/alfresco-base-java:8 + +ENV APACHE_LICENSE_FILE=https://github.com/Alfresco/acs-community-packaging/blob/master/distribution/src/main/resources/licenses/3rd-party/Apache%202.0.txt + +COPY target/alfresco-docker-tika-${env.project_version}.jar /usr/bin + +RUN ln /usr/bin/alfresco-docker-tika-${env.project_version}.jar /usr/bin/alfresco-docker-tika.jar && \ + yum install -y wget && \ + wget $APACHE_LICENSE_FILE && \ + yum remove -y wget && \ + yum clean all + +EXPOSE 8090 + +ENTRYPOINT java -jar /usr/bin/alfresco-docker-tika.jar diff --git a/alfresco-docker-tika/LICENSES.md b/alfresco-docker-tika/LICENSES.md new file mode 100644 index 00000000..dfdb7c47 --- /dev/null +++ b/alfresco-docker-tika/LICENSES.md @@ -0,0 +1,7 @@ +### Licenses + +* The code in the alfresco-docker-imagemagick project is only intended to be use with the Alfresco Enterprise + Content Repository which is covered by [https://www.alfresco.com/legal/agreements](https://www.alfresco.com/legal/agreements) and [https://www.alfresco.com/terms-use](https://www.alfresco.com/terms-use) +* Tika is from Apache. See the license at http://www.apache.org/licenses/LICENSE-2.0 or the +[Apache 2.0.txt](https://github.com/Alfresco/acs-community-packaging/blob/master/distribution/src/main/resources/licenses/3rd-party/Apache%202.0.txt) +file placed in the root directory of the docker image. diff --git a/alfresco-docker-tika/pom.xml b/alfresco-docker-tika/pom.xml new file mode 100644 index 00000000..96b4c715 --- /dev/null +++ b/alfresco-docker-tika/pom.xml @@ -0,0 +1,268 @@ + + 4.0.0 + alfresco-docker-tika + Alfresco Docker Tika + jar + + + org.alfresco + alfresco-docker-transformers + 1.2-SNAPSHOT + ../pom.xml + + + + alfresco/alfresco-tika + quay.io + 3.17 + + + + + org.alfresco + alfresco-transformer-base + ${project.version} + + + org.alfresco + alfresco-transformer-base + ${project.version} + tests + test-jar + test + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-test + test + + + org.alfresco + alfresco-core + + + org.alfresco + alfresco-data-model + + + + org.slf4j + slf4j-api + 1.7.24 + + + org.slf4j + slf4j-log4j12 + 1.7.25 + + + + + org.apache.tika + tika-core + 1.17-20180201-alfresco-patched + + + org.apache.tika + tika-parsers + 1.17-20180201-alfresco-patched + + + com.tdunning + json + + + + + + + org.apache.poi + poi + ${dependency.poi.version} + + + org.apache.poi + poi-ooxml + ${dependency.poi.version} + + + org.apache.poi + poi-scratchpad + ${dependency.poi.version} + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${dependency.spring-boot.version} + + + + repackage + + + + + + io.fabric8 + fabric8-maven-plugin + ${dependency.fabric8.version} + + + + ${image.name}:${image.tag} + + ${project.basedir}/ + + + + + + + + + + + + enterpriseDocker + + + + io.fabric8 + fabric8-maven-plugin + ${dependency.fabric8.version} + + + build-image + install + + build + + + + + + + + + + internal + + + + io.fabric8 + fabric8-maven-plugin + ${dependency.fabric8.version} + + + + ${image.registry}/${image.name}:${image.tag} + + ${project.basedir}/ + + + + + + + build-push-image + install + + build + push + + + + + + + + + + master + + + + io.fabric8 + fabric8-maven-plugin + ${dependency.fabric8.version} + + + + ${image.registry}/${image.name} + + ${project.basedir}/ + + + + ${image.name} + + ${project.basedir}/ + + + + + + + build-push-image + install + + build + push + + + + + + + + + + release + + + + io.fabric8 + fabric8-maven-plugin + ${dependency.fabric8.version} + + + + ${image.name}:${project.version} + ${image.registry} + + ${project.basedir}/ + + + + ${image.name}:${project.version} + + ${project.basedir}/ + + + + + + + build-push-image + deploy + + build + push + + + + + + + + + diff --git a/alfresco-docker-tika/src/main/java/org/alfresco/transformer/Application.java b/alfresco-docker-tika/src/main/java/org/alfresco/transformer/Application.java new file mode 100644 index 00000000..22cbefc4 --- /dev/null +++ b/alfresco-docker-tika/src/main/java/org/alfresco/transformer/Application.java @@ -0,0 +1,27 @@ +/* + * #%L + * Alfresco Enterprise Repository + * %% + * Copyright (C) 2005 - 2018 Alfresco Software Limited + * %% + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + * #L% + */ +package org.alfresco.transformer; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; + +@SpringBootApplication +@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) +public class Application +{ + public static void main(String[] args) + { + SpringApplication.run(Application.class, args); + } +} diff --git a/alfresco-docker-tika/src/main/java/org/alfresco/transformer/Tika.java b/alfresco-docker-tika/src/main/java/org/alfresco/transformer/Tika.java new file mode 100644 index 00000000..a7091002 --- /dev/null +++ b/alfresco-docker-tika/src/main/java/org/alfresco/transformer/Tika.java @@ -0,0 +1,801 @@ +/* + * #%L + * Alfresco Enterprise Repository + * %% + * Copyright (C) 2005 - 2018 Alfresco Software Limited + * %% + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + * #L% + */ +package org.alfresco.transformer; + +import org.apache.tika.config.TikaConfig; +import org.apache.tika.exception.TikaException; +import org.apache.tika.extractor.DocumentSelector; +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.microsoft.OfficeParser; +import org.apache.tika.parser.microsoft.ooxml.OOXMLParser; +import org.apache.tika.parser.pdf.PDFParser; +import org.apache.tika.parser.pkg.PackageParser; +import org.apache.tika.sax.BodyContentHandler; +import org.apache.tika.sax.ExpandedTitleContentHandler; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; +import java.io.*; +import java.net.URL; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +import static org.alfresco.repo.content.MimetypeMap.*; + +/** + * Stripped down command line Tika transformers. Not actually run as a separate process, but the code fits the patten + * used by transformers that do. + *
+ *
+ *           Archive 0 ms
+ *               1) cpio html [100] unlimited
+ *               2) cpio txt   [50] unlimited
+ *               3) cpio xhtml [100] unlimited
+ *               4) cpio xml  [100] unlimited
+ *               5) jar  html [100] unlimited
+ *               6) jar  txt   [50] unlimited
+ *               7) jar  xhtml [100] unlimited
+ *               8) jar  xml  [100] unlimited
+ *               9) tar  html [100] unlimited
+ *              10) tar  txt   [50] unlimited
+ *              11) tar  xhtml [100] unlimited
+ *              12) tar  xml  [100] unlimited
+ *              13) zip  html [100] unlimited
+ *              14) zip  txt   [50] unlimited
+ *              15) zip  xhtml [100] unlimited
+ *              16) zip  xml  [100] unlimited
+ *           PdfBox 0 ms
+ *               1) pdf  html [110] unlimited
+ *               2) pdf  txt   [50] 25 MB
+ *               3) pdf  xhtml [110] unlimited
+ *               4) pdf  xml  [110] unlimited
+ *           OutlookMsg 0 ms
+ *               1) msg  html [125] unlimited
+ *               2) msg  txt  [125] unlimited
+ *               3) msg  xhtml [125] unlimited
+ *               4) msg  xml  [125] unlimited
+ *           PdfBox 0 ms
+ *               1) pdf  html [110] unlimited
+ *               2) pdf  txt   [50] 25 MB
+ *               3) pdf  xhtml [110] unlimited
+ *               4) pdf  xml  [110] unlimited
+ *           Office 0 ms
+ *               1) doc  html [130] unlimited
+ *               2) doc  txt  [130] unlimited
+ *               3) doc  xhtml [130] unlimited
+ *               4) doc  xml  [130] unlimited
+ *               5) mpp  html [130] unlimited
+ *               6) mpp  txt  [130] unlimited
+ *               7) mpp  xhtml [130] unlimited
+ *               8) mpp  xml  [130] unlimited
+ *               9) msg  html [130] unlimited
+ *              10) msg  txt  [130] unlimited
+ *              11) msg  xhtml [130] unlimited
+ *              12) msg  xml  [130] unlimited
+ *              13) ppt  html [130] unlimited
+ *              14) ppt  txt  [130] unlimited
+ *              15) ppt  xhtml [130] unlimited
+ *              16) ppt  xml  [130] unlimited
+ *              17) vsd  html [130] unlimited
+ *              18) vsd  txt  [130] unlimited
+ *              19) vsd  xhtml [130] unlimited
+ *              20) vsd  xml  [130] unlimited
+ *           Poi 0 ms
+ *               1) xls  csv  [130] unlimited
+ *               2) xls  html [130] unlimited
+ *               3) xls  txt  [130] unlimited
+ *               4) xls  xhtml [130] unlimited
+ *               5) xls  xml  [130] unlimited
+ *               6) xlsx csv  [130] unlimited
+ *               7) xlsx html [130] unlimited
+ *               8) xlsx txt  [130] unlimited
+ *               9) xlsx xhtml [130] unlimited
+ *              10) xlsx xml  [130] unlimited
+ *           OOXML 0 ms
+ *               1) docm html [130] unlimited
+ *               2) docm txt  [130] unlimited
+ *               3) docm xhtml [130] unlimited
+ *               4) docm xml  [130] unlimited
+ *               5) docx html [130] unlimited
+ *               6) docx txt  [130] unlimited
+ *               7) docx xhtml [130] unlimited
+ *               8) docx xml  [130] unlimited
+ *               9) dotm html [130] unlimited
+ *              10) dotm txt  [130] unlimited
+ *              11) dotm xhtml [130] unlimited
+ *              12) dotm xml  [130] unlimited
+ *              13) dotx html [130] unlimited
+ *              14) dotx txt  [130] unlimited
+ *              15) dotx xhtml [130] unlimited
+ *              16) dotx xml  [130] unlimited
+ *              17) potm html [130] unlimited
+ *              18) potm txt  [130] unlimited
+ *              19) potm xhtml [130] unlimited
+ *              20) potm xml  [130] unlimited
+ *              21) potx html [130] unlimited
+ *              22) potx txt  [130] unlimited
+ *              23) potx xhtml [130] unlimited
+ *              24) potx xml  [130] unlimited
+ *              25) ppam html [130] unlimited
+ *              26) ppam txt  [130] unlimited
+ *              27) ppam xhtml [130] unlimited
+ *              28) ppam xml  [130] unlimited
+ *              29) ppsm html [130] unlimited
+ *              30) ppsm txt  [130] unlimited
+ *              31) ppsm xhtml [130] unlimited
+ *              32) ppsm xml  [130] unlimited
+ *              33) ppsx html [130] unlimited
+ *              34) ppsx txt  [130] unlimited
+ *              35) ppsx xhtml [130] unlimited
+ *              36) ppsx xml  [130] unlimited
+ *              37) pptm html [130] unlimited
+ *              38) pptm txt  [130] unlimited
+ *              39) pptm xhtml [130] unlimited
+ *              40) pptm xml  [130] unlimited
+ *              41) pptx html [130] unlimited
+ *              42) pptx txt  [130] unlimited
+ *              43) pptx xhtml [130] unlimited
+ *              44) pptx xml  [130] unlimited
+ *              45) sldm html [130] unlimited
+ *              46) sldm txt  [130] unlimited
+ *              47) sldm xhtml [130] unlimited
+ *              48) sldm xml  [130] unlimited
+ *              49) sldx html [130] unlimited
+ *              50) sldx txt  [130] unlimited
+ *              51) sldx xhtml [130] unlimited
+ *              52) sldx xml  [130] unlimited
+ *              53) xlam html [130] unlimited
+ *              54) xlam txt  [130] unlimited
+ *              55) xlam xhtml [130] unlimited
+ *              56) xlam xml  [130] unlimited
+ *              57) xlsb html [130] unlimited
+ *              58) xlsb txt  [130] unlimited
+ *              59) xlsb xhtml [130] unlimited
+ *              60) xlsb xml  [130] unlimited
+ *              61) xlsm html [130] unlimited
+ *              62) xlsm txt  [130] unlimited
+ *              63) xlsm xhtml [130] unlimited
+ *              64) xlsm xml  [130] unlimited
+ *              65) xlsx html [130] unlimited
+ *              66) xlsx txt  [130] unlimited
+ *              67) xlsx xhtml [130] unlimited
+ *              68) xlsx xml  [130] unlimited
+ *              69) xltm html [130] unlimited
+ *              70) xltm txt  [130] unlimited
+ *              71) xltm xhtml [130] unlimited
+ *              72) xltm xml  [130] unlimited
+ *              73) xltx html [130] unlimited
+ *              74) xltx txt  [130] unlimited
+ *              75) xltx xhtml [130] unlimited
+ *              76) xltx xml  [130] unlimited
+ *           TikaAuto 0 ms
+ *               1) cdf  html [120] unlimited
+ *               2) cdf  txt  [120] unlimited
+ *               3) cdf  xhtml [120] unlimited
+ *               4) cdf  xml  [120] unlimited
+ *               5) cpio html [120] unlimited
+ *               6) cpio txt  [120] unlimited
+ *               7) cpio xhtml [120] unlimited
+ *               8) cpio xml  [120] unlimited
+ *               9) doc  html [120] unlimited
+ *              10) doc  txt  [120] unlimited
+ *              11) doc  xhtml [120] unlimited
+ *              12) doc  xml  [120] unlimited
+ *              13) docm html [120] unlimited
+ *              14) docm txt  [120] unlimited
+ *              15) docm xhtml [120] unlimited
+ *              16) docm xml  [120] unlimited
+ *              17) docx html [120] unlimited
+ *              18) docx txt  [120] unlimited
+ *              19) docx xhtml [120] unlimited
+ *              20) docx xml  [120] unlimited
+ *              21) dotm html [120] unlimited
+ *              22) dotm txt  [120] unlimited
+ *              23) dotm xhtml [120] unlimited
+ *              24) dotm xml  [120] unlimited
+ *              25) dotx html [120] unlimited
+ *              26) dotx txt  [120] unlimited
+ *              27) dotx xhtml [120] unlimited
+ *              28) dotx xml  [120] unlimited
+ *              29) gzip html [120] unlimited
+ *              30) gzip txt  [120] unlimited
+ *              31) gzip xhtml [120] unlimited
+ *              32) gzip xml  [120] unlimited
+ *              33) hdf  html [120] unlimited
+ *              34) hdf  txt  [120] unlimited
+ *              35) hdf  xhtml [120] unlimited
+ *              36) hdf  xml  [120] unlimited
+ *              37) html html [120] unlimited
+ *              38) html txt  [120] unlimited
+ *              39) html xhtml [120] unlimited
+ *              40) html xml  [120] unlimited
+ *              41) jar  html [120] unlimited
+ *              42) jar  txt  [120] unlimited
+ *              43) jar  xhtml [120] unlimited
+ *              44) jar  xml  [120] unlimited
+ *              45) java html [120] unlimited
+ *              46) java txt  [120] unlimited
+ *              47) java xhtml [120] unlimited
+ *              48) java xml  [120] unlimited
+ *              49) key  html [120] unlimited
+ *              50) key  txt  [120] unlimited
+ *              51) key  xhtml [120] unlimited
+ *              52) key  xml  [120] unlimited
+ *              53) mpp  html [120] unlimited
+ *              54) mpp  txt  [120] unlimited
+ *              55) mpp  xhtml [120] unlimited
+ *              56) mpp  xml  [120] unlimited
+ *              57) numbers html [120] unlimited
+ *              58) numbers txt  [120] unlimited
+ *              59) numbers xhtml [120] unlimited
+ *              60) numbers xml  [120] unlimited
+ *              61) odc  html [120] unlimited
+ *              62) odc  txt  [120] unlimited
+ *              63) odc  xhtml [120] unlimited
+ *              64) odc  xml  [120] unlimited
+ *              65) odi  html [120] unlimited
+ *              66) odi  txt  [120] unlimited
+ *              67) odi  xhtml [120] unlimited
+ *              68) odi  xml  [120] unlimited
+ *              69) odm  html [120] unlimited
+ *              70) odm  txt  [120] unlimited
+ *              71) odm  xhtml [120] unlimited
+ *              72) odm  xml  [120] unlimited
+ *              73) odp  html [120] unlimited
+ *              74) odp  txt  [120] unlimited
+ *              75) odp  xhtml [120] unlimited
+ *              76) odp  xml  [120] unlimited
+ *              77) ods  html [120] unlimited
+ *              78) ods  txt  [120] unlimited
+ *              79) ods  xhtml [120] unlimited
+ *              80) ods  xml  [120] unlimited
+ *              81) odt  html [120] unlimited
+ *              82) odt  txt  [120] unlimited
+ *              83) odt  xhtml [120] unlimited
+ *              84) odt  xml  [120] unlimited
+ *              85) ogx  html [120] unlimited
+ *              86) ogx  txt  [120] unlimited
+ *              87) ogx  xhtml [120] unlimited
+ *              88) ogx  xml  [120] unlimited
+ *              89) oth  html [120] unlimited
+ *              90) oth  txt  [120] unlimited
+ *              91) oth  xhtml [120] unlimited
+ *              92) oth  xml  [120] unlimited
+ *              93) otp  html [120] unlimited
+ *              94) otp  txt  [120] unlimited
+ *              95) otp  xhtml [120] unlimited
+ *              96) otp  xml  [120] unlimited
+ *              97) ots  html [120] unlimited
+ *              98) ots  txt  [120] unlimited
+ *              99) ots  xhtml [120] unlimited
+ *             100) ots  xml  [120] unlimited
+ *             101) ott  html [120] unlimited
+ *             102) ott  txt  [120] unlimited
+ *             103) ott  xhtml [120] unlimited
+ *             104) ott  xml  [120] unlimited
+ *             105) pages html [120] unlimited
+ *             106) pages txt  [120] unlimited
+ *             107) pages xhtml [120] unlimited
+ *             108) pages xml  [120] unlimited
+ *             109) pdf  html [120] unlimited
+ *             110) pdf  txt  [120] 25 MB
+ *             111) pdf  xhtml [120] unlimited
+ *             112) pdf  xml  [120] unlimited
+ *             113) potm html [120] unlimited
+ *             114) potm txt  [120] unlimited
+ *             115) potm xhtml [120] unlimited
+ *             116) potm xml  [120] unlimited
+ *             117) potx html [120] unlimited
+ *             118) potx txt  [120] unlimited
+ *             119) potx xhtml [120] unlimited
+ *             120) potx xml  [120] unlimited
+ *             121) ppam html [120] unlimited
+ *             122) ppam txt  [120] unlimited
+ *             123) ppam xhtml [120] unlimited
+ *             124) ppam xml  [120] unlimited
+ *             125) ppsm html [120] unlimited
+ *             126) ppsm txt  [120] unlimited
+ *             127) ppsm xhtml [120] unlimited
+ *             128) ppsm xml  [120] unlimited
+ *             129) ppsx html [120] unlimited
+ *             130) ppsx txt  [120] unlimited
+ *             131) ppsx xhtml [120] unlimited
+ *             132) ppsx xml  [120] unlimited
+ *             133) ppt  html [120] unlimited
+ *             134) ppt  txt  [120] unlimited
+ *             135) ppt  xhtml [120] unlimited
+ *             136) ppt  xml  [120] unlimited
+ *             137) pptm html [120] unlimited
+ *             138) pptm txt  [120] unlimited
+ *             139) pptm xhtml [120] unlimited
+ *             140) pptm xml  [120] unlimited
+ *             141) pptx html [120] unlimited
+ *             142) pptx txt  [120] unlimited
+ *             143) pptx xhtml [120] unlimited
+ *             144) pptx xml  [120] unlimited
+ *             145) rar  html [120] unlimited
+ *             146) rar  txt  [120] unlimited
+ *             147) rar  xhtml [120] unlimited
+ *             148) rar  xml  [120] unlimited
+ *             149) rss  html [120] unlimited
+ *             150) rss  txt  [120] unlimited
+ *             151) rss  xhtml [120] unlimited
+ *             152) rss  xml  [120] unlimited
+ *             153) rtf  html [120] unlimited
+ *             154) rtf  txt  [120] unlimited
+ *             155) rtf  xhtml [120] unlimited
+ *             156) rtf  xml  [120] unlimited
+ *             157) sldm html [120] unlimited
+ *             158) sldm txt  [120] unlimited
+ *             159) sldm xhtml [120] unlimited
+ *             160) sldm xml  [120] unlimited
+ *             161) sldx html [120] unlimited
+ *             162) sldx txt  [120] unlimited
+ *             163) sldx xhtml [120] unlimited
+ *             164) sldx xml  [120] unlimited
+ *             165) sxw  html [120] unlimited
+ *             166) sxw  txt  [120] unlimited
+ *             167) sxw  xhtml [120] unlimited
+ *             168) sxw  xml  [120] unlimited
+ *             169) txt  html [120] unlimited
+ *             170) txt  txt  [120] unlimited
+ *             171) txt  xhtml [120] unlimited
+ *             172) txt  xml  [120] unlimited
+ *             173) vsd  html [120] unlimited
+ *             174) vsd  txt  [120] unlimited
+ *             175) vsd  xhtml [120] unlimited
+ *             176) vsd  xml  [120] unlimited
+ *             177) xhtml html [120] unlimited
+ *             178) xhtml txt  [120] unlimited
+ *             179) xhtml xhtml [120] unlimited
+ *             180) xhtml xml  [120] unlimited
+ *             181) xlam html [120] unlimited
+ *             182) xlam txt  [120] unlimited
+ *             183) xlam xhtml [120] unlimited
+ *             184) xlam xml  [120] unlimited
+ *             185) xls  html [120] unlimited
+ *             186) xls  txt  [120] unlimited
+ *             187) xls  xhtml [120] unlimited
+ *             188) xls  xml  [120] unlimited
+ *             189) xlsb html [120] unlimited
+ *             190) xlsb txt  [120] unlimited
+ *             191) xlsb xhtml [120] unlimited
+ *             192) xlsb xml  [120] unlimited
+ *             193) xlsm html [120] unlimited
+ *             194) xlsm txt  [120] unlimited
+ *             195) xlsm xhtml [120] unlimited
+ *             196) xlsm xml  [120] unlimited
+ *             197) xlsx html [120] unlimited
+ *             198) xlsx txt  [120] unlimited
+ *             199) xlsx xhtml [120] unlimited
+ *             200) xlsx xml  [120] unlimited
+ *             201) xltm html [120] unlimited
+ *             202) xltm txt  [120] unlimited
+ *             203) xltm xhtml [120] unlimited
+ *             204) xltm xml  [120] unlimited
+ *             205) xltx html [120] unlimited
+ *             206) xltx txt  [120] unlimited
+ *             207) xltx xhtml [120] unlimited
+ *             208) xltx xml  [120] unlimited
+ *             209) xml  html [120] unlimited
+ *             210) xml  txt  [120] unlimited
+ *             211) xml  xhtml [120] unlimited
+ *             212) xml  xml  [120] unlimited
+ *             213) z    html [120] unlimited
+ *             214) z    txt  [120] unlimited
+ *             215) z    xhtml [120] unlimited
+ *             216) z    xml  [120] unlimited
+ *           TextMining 0 ms
+ *               1) doc  html [130] unlimited
+ *               2) doc  txt   [50] unlimited
+ *               3) doc  xhtml [130] unlimited
+ *               4) doc  xml  [130] unlimited
+ * 
+ */ +public class Tika +{ + public static final String ARCHIVE = "Archive"; + public static final String OUTLOOK_MSG = "OutlookMsg"; + public static final String PDF_BOX = "PdfBox"; + public static final String POI_OFFICE = "Office"; + public static final String POI = "Poi"; + public static final String POI_OO_XML = "OOXML"; + public static final String TIKA_AUTO = "TikaAuto"; + public static final String TEXT_MINING = "TextMining"; + + public static final List TRANSFORM_NAMES = Arrays.asList( + ARCHIVE, OUTLOOK_MSG, PDF_BOX, POI_OFFICE, POI, POI_OO_XML, TIKA_AUTO, TEXT_MINING); + + public static final String TARGET_MIMETYPE = "--targetMimetype="; + public static final String TARGET_ENCODING = "--targetEncoding="; + public static final String INCLUDE_CONTENTS = "--includeContents"; + + public static final String CSV = "csv"; + public static final String DOC = "doc"; + public static final String DOCX = "docx"; + public static final String HTML = "html"; + public static final String MSG = "msg"; + public static final String PDF = "pdf"; + public static final String PPTX = "pptx"; + public static final String TXT = "txt"; + public static final String XHTML = "xhtml"; + public static final String XSLX = "xslx"; + public static final String XML = "xml"; + public static final String ZIP = "zip"; + + private Parser packageParser = new PackageParser(); + private Parser pdfParser = new PDFParser(); + private Parser officeParser = new OfficeParser(); + private Parser autoDetectParser; + private Parser ooXmlParser = new OOXMLParser(); + private Parser tikaOfficeDetectParser = new TikaOfficeDetectParser(); + + private DocumentSelector pdfBoxEmbededDocumentSelector = new DocumentSelector() + { + private List disabledMediaTypes = Arrays.asList(new String[] {MIMETYPE_IMAGE_JPEG, MIMETYPE_IMAGE_TIFF, MIMETYPE_IMAGE_PNG}); + + @Override + public boolean select(Metadata metadata) + { + String contentType = metadata.get(Metadata.CONTENT_TYPE); + if (contentType == null || contentType.equals("") || disabledMediaTypes == null) + { + return true; + } + return !disabledMediaTypes.contains(contentType); + } + }; + + public Tika() throws TikaException, IOException, SAXException + { + ClassLoader classLoader = getClass().getClassLoader(); + URL tikaConfigXml = classLoader.getResource("tika-config.xml"); + TikaConfig tikaConfig = new TikaConfig(tikaConfigXml); + autoDetectParser = new AutoDetectParser(tikaConfig); + } + + // Method included for developer testing + public static void main(String[] args) + { + long start = System.currentTimeMillis(); + try + { + new Tika().transform(args); + } + catch (IllegalArgumentException e) + { + System.err.println("ERROR "+e.getMessage()); + System.exit(-1); + } + catch (IllegalStateException | TikaException | IOException | SAXException e) + { + System.err.println("ERROR "+e.getMessage()); + e.printStackTrace(); + System.exit(-2); + } + System.out.println("Finished in "+(System.currentTimeMillis()-start)+"ms"); + } + + // Extracts parameters form args + public void transform(String[] args) + { + String transform = null; + String targetMimetype = null; + String targetEncoding = null; + String sourceFilename = null; + String targetFilename = null; + Boolean includeContents = null; + + for (String arg: args) + { + if (arg.startsWith("--")) + { + if (INCLUDE_CONTENTS.startsWith(arg)) + { + getValue(arg, false, includeContents, INCLUDE_CONTENTS); + includeContents = true; + } + else if (arg.startsWith(TARGET_ENCODING)) + { + targetEncoding = getValue(arg, true, targetEncoding, TARGET_ENCODING); + } + else if (arg.startsWith(TARGET_MIMETYPE)) + { + targetMimetype = getValue(arg, true, targetMimetype, TARGET_MIMETYPE); + } + else + { + throw new IllegalArgumentException("Unexpected argument "+arg); + } + } + else + { + if (transform == null) + { + transform = arg; + } + else if (sourceFilename == null) + { + sourceFilename = arg; + } + else if (targetFilename == null) + { + targetFilename = arg; + } + else + { + throw new IllegalArgumentException("Unexpected argument "+arg); + } + } + } + if (targetFilename == null) + { + throw new IllegalArgumentException("Missing arguments"); + } + includeContents = includeContents == null ? false : includeContents; + + transform(transform, includeContents, sourceFilename, targetFilename, targetMimetype, targetEncoding); + } + + private String getValue(String arg, boolean valueExpected, Object value, String optionName) + { + if (value != null) + { + throw new IllegalArgumentException("Duplicate "+optionName); + } + String stringValue = arg.substring(optionName.length()).trim(); + if (!valueExpected && stringValue.length() > 0) + { + throw new IllegalArgumentException("Unexpected value with "+optionName); + } + if (valueExpected && stringValue.length() == 0) + { + throw new IllegalArgumentException("Expected value with "+optionName); + } + return stringValue; + } + + // Adds transform specific values such as parser and documentSelector. + private void transform(String transform, Boolean includeContents, + String sourceFilename, + String targetFilename, String targetMimetype, String targetEncoding) + { + Parser parser = null; + DocumentSelector documentSelector = null; + + switch(transform) + { + case ARCHIVE: + parser = packageParser; + break; + case OUTLOOK_MSG: + case POI_OFFICE: + case TEXT_MINING: + parser = officeParser; + break; + case PDF_BOX: + parser = pdfParser; + documentSelector = pdfBoxEmbededDocumentSelector; + break; + case POI: + parser = tikaOfficeDetectParser; + break; + case POI_OO_XML: + parser = ooXmlParser; + break; + case TIKA_AUTO: + parser = autoDetectParser; + break; + } + + transform(parser, documentSelector, includeContents, sourceFilename, targetFilename, targetMimetype, targetEncoding); + } + + + private void transform(Parser parser, DocumentSelector documentSelector, Boolean includeContents, + String sourceFilename, + String targetFilename, String targetMimetype, String targetEncoding) + { + InputStream is = null; + OutputStream os = null; + Writer ow = null; + + try + { + is = new BufferedInputStream(new FileInputStream(sourceFilename)); + os = new FileOutputStream(targetFilename); + ow = new BufferedWriter(new OutputStreamWriter(os, targetEncoding)); + Metadata metadata = new Metadata(); + ParseContext context = buildParseContext(documentSelector, includeContents); + ContentHandler handler = getContentHandler(targetMimetype, ow); + + parser.parse(is, handler, metadata, context); + } + catch (SAXException | TikaException | IOException e) + { + throw new IllegalStateException(e.getMessage(), e); + } + finally + { + if (is != null) + { + try { is.close(); } catch (Throwable e) {} + } + if (os != null) + { + try { os.close(); } catch (Throwable e) {} + } + if (ow != null) + { + try { ow.close(); } catch (Throwable e) {} + } + } + } + + protected ContentHandler getContentHandler(String targetMimetype, Writer output) + { + try + { + ContentHandler handler; + if (MIMETYPE_TEXT_PLAIN.equals(targetMimetype)) + { + handler = new BodyContentHandler(output); + } + else + { + SAXTransformerFactory factory = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + TransformerHandler transformerHandler = null; + transformerHandler = factory.newTransformerHandler(); + transformerHandler.getTransformer().setOutputProperty(OutputKeys.INDENT, "yes"); + transformerHandler.setResult(new StreamResult(output)); + handler = transformerHandler; + + if (MIMETYPE_HTML.equals(targetMimetype)) + { + transformerHandler.getTransformer().setOutputProperty(OutputKeys.METHOD, HTML); + return new ExpandedTitleContentHandler(transformerHandler); + } + else if (MIMETYPE_XHTML.equals(targetMimetype) || + MIMETYPE_XML.equals(targetMimetype)) + { + transformerHandler.getTransformer().setOutputProperty(OutputKeys.METHOD, XML); + } + else if (MIMETYPE_TEXT_CSV.equals(targetMimetype)) + { + handler = new CsvContentHandler(output); + } + else + { + throw new IllegalArgumentException("Invalid target mimetype " + targetMimetype); + } + } + return handler; + } + catch (TransformerConfigurationException e) + { + throw new IllegalStateException(e.getMessage(), e); + } + } + + /** + * A wrapper around the normal Tika BodyContentHandler for CSV rather encoding than tab separated. + */ + protected static class CsvContentHandler extends BodyContentHandler { + private static final char[] comma = new char[]{ ',' }; + private static final Pattern all_nums = Pattern.compile("[\\d\\.\\-\\+]+"); + + private boolean inCell = false; + private boolean needsComma = false; + + protected CsvContentHandler(Writer output) { + super(output); + } + + @Override + public void ignorableWhitespace(char[] ch, int start, int length) + throws SAXException { + if(length == 1 && ch[0] == '\t') { + // Ignore tabs, as they mess up the CSV output + } else { + super.ignorableWhitespace(ch, start, length); + } + } + + @Override + public void characters(char[] ch, int start, int length) + throws SAXException { + if(inCell) { + StringBuffer t = new StringBuffer(new String(ch,start,length)); + + // Quote if not all numbers + if(all_nums.matcher(t).matches()) + { + super.characters(ch, start, length); + } + else + { + for(int i=t.length()-1; i>=0; i--) { + if(t.charAt(i) == '\"') { + // Double up double quotes + t.insert(i, '\"'); + i--; + } + } + t.insert(0, '\"'); + t.append('\"'); + char[] c = t.toString().toCharArray(); + super.characters(c, 0, c.length); + } + } else { + super.characters(ch, start, length); + } + } + + @Override + public void startElement(String uri, String localName, String name, + Attributes atts) throws SAXException { + if(localName.equals("td")) { + inCell = true; + if(needsComma) { + super.characters(comma, 0, 1); + needsComma = true; + } + } else { + super.startElement(uri, localName, name, atts); + } + } + + @Override + public void endElement(String uri, String localName, String name) + throws SAXException { + if(localName.equals("td")) { + needsComma = true; + inCell = false; + } else { + if(localName.equals("tr")) { + needsComma = false; + } + super.endElement(uri, localName, name); + } + } + } + + protected ParseContext buildParseContext(DocumentSelector documentSelector, Boolean includeContents) + { + ParseContext context = new ParseContext(); + if (documentSelector != null) + { + context.set(DocumentSelector.class, documentSelector); + } + + // pdfParserConfig is never set in the original repo code, so code removed here. + + // If Archive transform + if (includeContents != null) + { + context.set(Parser.class, includeContents ? autoDetectParser : new EmptyParser()); + } + + return context; + } +} diff --git a/alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaController.java b/alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaController.java new file mode 100644 index 00000000..8c365f0c --- /dev/null +++ b/alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaController.java @@ -0,0 +1,137 @@ +/* + * #%L + * Alfresco Enterprise Repository + * %% + * Copyright (C) 2005 - 2018 Alfresco Software Limited + * %% + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + * #L% + */ +package org.alfresco.transformer; + +import org.apache.commons.logging.LogFactory; +import org.apache.tika.exception.TikaException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; +import org.xml.sax.SAXException; + +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.IOException; + +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_TEXT_PLAIN; +import static org.alfresco.transformer.Tika.*; + +/** + * Controller for the Docker based Tika transformers. + * + * Status Codes: + * + * 200 Success + * 400 Bad Request: Invalid target mimetype <mimetype> + * 400 Bad Request: Request parameter <name> is missing (missing mandatory parameter) + * 400 Bad Request: Request parameter <name> is of the wrong type + * 400 Bad Request: Transformer exit code was not 0 (possible problem with the source file) + * 400 Bad Request: The source filename was not supplied + * 500 Internal Server Error: (no message with low level IO problems) + * 500 Internal Server Error: The target filename was not supplied (should not happen as targetExtension is checked) + * 500 Internal Server Error: Transformer version check exit code was not 0 + * 500 Internal Server Error: Transformer version check failed to create any output + * 500 Internal Server Error: Could not read the target file + * 500 Internal Server Error: The target filename was malformed (should not happen because of other checks) + * 500 Internal Server Error: Transformer failed to create an output file (the exit code was 0, so there should be some content) + * 500 Internal Server Error: Filename encoding error + * 507 Insufficient Storage: Failed to store the source file + */ +@Controller +public class TikaController extends AbstractTransformerController +{ + private Tika tika; + + @Autowired + public TikaController() throws TikaException, IOException, SAXException + { + logger = LogFactory.getLog(TikaController.class); + logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------"); + logEnterpriseLicenseMessage(); + logger.info("Tika is from Apache. See the license at http://www.apache.org/licenses/LICENSE-2.0. or in /Apache\\ 2.0.txt"); + logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------"); + + tika = new Tika(); + } + + @Override + protected String getTransformerName() + { + return "Tika"; + } + + @Override + public void callTransform(String... args) + { + tika.transform(args); + } + + @Override + protected String version() + { + return "Tika available"; + } + + @Override + protected ProbeTestTransform getProbeTestTransform() + { + // See the Javadoc on this method and Probes.md for the choice of these values. + // the livenessPercentage is a little large as Tika does tend to suffer from slow transforms that class with a gc. + return new ProbeTestTransform(this, "quick.pdf", "quick.txt", + 60, 16, 400, 10240, 60*30+1, 60*15+20) + { + @Override + protected void executeTransformCommand(File sourceFile, File targetFile) + { + TikaController.this.callTransform(sourceFile, targetFile, PDF_BOX, + TARGET_MIMETYPE+MIMETYPE_TEXT_PLAIN, TARGET_ENCODING+"UTF-8"); + } + }; + } + + @PostMapping("/transform") + public ResponseEntity transform(HttpServletRequest request, + @RequestParam("file") MultipartFile sourceMultipartFile, + @RequestParam("targetExtension") String targetExtension, + @RequestParam("targetMimetype") String targetMimetype, + @RequestParam("targetEncoding") String targetEncoding, + + @RequestParam(value = "timeout", required = false) Long timeout, + @RequestParam(value = "testDelay", required = false) Long testDelay, + + @RequestParam(value = "transform") String transform, + @RequestParam(value="includeContents", required = false) Boolean includeContents) + { + if (!TRANSFORM_NAMES.contains(transform)) + { + throw new TransformException(400, "Invalid transform value"); + } + + String targetFilename = createTargetFileName(sourceMultipartFile, targetExtension); + File sourceFile = createSourceFile(request, sourceMultipartFile); + File targetFile = createTargetFile(request, targetFilename); + // Both files are deleted by TransformInterceptor.afterCompletion + + // TODO Consider streaming the request and response rather than using temporary files + // https://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/streaming-response-body.html + + callTransform(sourceFile, targetFile, transform, + includeContents != null && includeContents ? INCLUDE_CONTENTS : null, + TARGET_MIMETYPE+targetMimetype, TARGET_ENCODING+targetEncoding); + + return createAttachment(targetFilename, targetFile, testDelay); + } +} diff --git a/alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaOfficeDetectParser.java b/alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaOfficeDetectParser.java new file mode 100644 index 00000000..d5607bbb --- /dev/null +++ b/alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaOfficeDetectParser.java @@ -0,0 +1,117 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.transformer; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PushbackInputStream; +import java.util.HashSet; +import java.util.Set; + +import org.apache.poi.poifs.common.POIFSConstants; +import org.apache.poi.util.IOUtils; +import org.apache.tika.exception.TikaException; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.mime.MediaType; +import org.apache.tika.parser.ParseContext; +import org.apache.tika.parser.Parser; +import org.apache.tika.parser.microsoft.OfficeParser; +import org.apache.tika.parser.microsoft.ooxml.OOXMLParser; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +///////// THIS FILE IS A COPY OF THE CODE IN alfresco-repository ///////////// + +/** + * Apache Tika assumes that + * you either know exactly what your content is, or that + * you'll leave it to auto-detection. + * Within Alfresco, we usually do know. However, from time + * to time, we don't know if we have one of the old or one + * of the new office files (eg .xls and .xlsx). + * This class allows automatically selects the appropriate + * old (OLE2) or new (OOXML) Tika parser as required. + * + * @author Nick Burch + */ +public class TikaOfficeDetectParser implements Parser { + private Parser ole2Parser = new OfficeParser(); + private Parser ooxmlParser = new OOXMLParser(); + + public Set getSupportedTypes(ParseContext parseContext) { + Set types = new HashSet(); + types.addAll(ole2Parser.getSupportedTypes(parseContext)); + types.addAll(ooxmlParser.getSupportedTypes(parseContext)); + return types; + } + + public void parse(InputStream stream, + ContentHandler handler, Metadata metadata, + ParseContext parseContext) throws IOException, SAXException, + TikaException + { + byte[] initial4 = new byte[4]; + InputStream wrapped; + // Preserve TikaInputStreams as TikaInputStreams as they require less memory to process + if (stream.markSupported()) + { + stream.mark(initial4.length); + IOUtils.readFully(stream, initial4); + stream.reset(); + wrapped = stream; + } + else + { + PushbackInputStream inp = new PushbackInputStream(stream, 4); + IOUtils.readFully(inp, initial4); + inp.unread(initial4); + wrapped = inp; + } + + // Which is it? + if(initial4[0] == POIFSConstants.OOXML_FILE_HEADER[0] && + initial4[1] == POIFSConstants.OOXML_FILE_HEADER[1] && + initial4[2] == POIFSConstants.OOXML_FILE_HEADER[2] && + initial4[3] == POIFSConstants.OOXML_FILE_HEADER[3]) + { + ooxmlParser.parse(wrapped, handler, metadata, parseContext); + } + else + { + ole2Parser.parse(wrapped, handler, metadata, parseContext); + } + } + + /** + * @deprecated This method will be removed in Apache Tika 1.0. + */ + public void parse(InputStream stream, + ContentHandler handler, Metadata metadata) + throws IOException, SAXException, TikaException + { + parse(stream, handler, metadata, new ParseContext()); + } +} diff --git a/alfresco-docker-tika/src/main/resources/quick.pdf b/alfresco-docker-tika/src/main/resources/quick.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a1779afd8b4d1b7d75456c61900c5cead5444abb GIT binary patch literal 23697 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≺ND&( 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 Pz?x-07<5&PtcCX{dE{yb literal 0 HcmV?d00001 diff --git a/alfresco-docker-tika/src/main/resources/templates/transformForm.html b/alfresco-docker-tika/src/main/resources/templates/transformForm.html new file mode 100644 index 00000000..5e230dbf --- /dev/null +++ b/alfresco-docker-tika/src/main/resources/templates/transformForm.html @@ -0,0 +1,39 @@ + + + +
+

Tika Test Transformations

+
+ + + + + + + + + + + +
transform *
file *
targetExtension *
targetMimetype *
targetEncoding *
includeContents (archive) *
timeout
testDelay
+
+
+ + + + + diff --git a/alfresco-docker-tika/src/main/resources/tika-config.xml b/alfresco-docker-tika/src/main/resources/tika-config.xml new file mode 100644 index 00000000..ef9f6df4 --- /dev/null +++ b/alfresco-docker-tika/src/main/resources/tika-config.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaControllerTest.java b/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaControllerTest.java new file mode 100644 index 00000000..bbf14145 --- /dev/null +++ b/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaControllerTest.java @@ -0,0 +1,344 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2018 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.transformer; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; + +import static org.alfresco.repo.content.MimetypeMap.*; +import static org.alfresco.transformer.Tika.*; +import static org.springframework.test.util.AssertionErrors.assertTrue; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * Test the TikaController without a server. + * Super class includes tests for the AbstractTransformerController. + */ +@RunWith(SpringRunner.class) +@WebMvcTest(TikaController.class) +public class TikaControllerTest extends AbstractTransformerControllerTest +{ + public static final String EXPECTED_XHTML_CONTENT_CONTAINS = "

The quick brown fox jumps over the lazy dog

"; + public static final String EXPECTED_TEXT_CONTENT_CONTAINS = "The quick brown fox jumps over the lazy dog"; + public static final String EXPECTED_MSG_CONTENT_CONTAINS = "Recipients\n" + + "\tmark.rogers@alfresco.com; speedy@quick.com; mrquick@nowhere.com\n" + + "\n" + + "The quick brown fox jumps over the lazy dogs"; + public static final String EXPECTED_CSV_CONTENT_CONTAINS = "\"The\",\"quick\",\"brown\",\"fox\""; + + @SpyBean + private TikaController controller; + + String transform = PDF_BOX; + String targetEncoding = "UTF-8"; + String targetMimetype = MIMETYPE_TEXT_PLAIN; + + private void transform(String transform, String sourceExtension, String targetExtension, + String sourceMimetype, String targetMimetype, + Boolean includeContents, String expectedContentContains) throws Exception + { + // We don't use targetFileBytes as some of the transforms contain different date text based on the os being used. + super.mockTransformCommand(controller, sourceExtension, targetExtension, sourceMimetype, false); + this.transform = transform; + this.targetMimetype = targetMimetype; + + System.out.println("Test "+transform+" "+ sourceExtension +" to "+targetExtension); + MockHttpServletRequestBuilder requestBuilder = includeContents == null + ? mockMvcRequest("/transform", sourceFile, "targetExtension", this.targetExtension) + : mockMvcRequest("/transform", sourceFile, "targetExtension", this.targetExtension, "includeContents", includeContents.toString()); + MvcResult result = mockMvc.perform(requestBuilder) + .andExpect(status().is(200)) + .andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick." + this.targetExtension)). + andReturn(); + String content = result.getResponse().getContentAsString(); + assertTrue("The content did not include \""+expectedContentContains, content.contains(expectedContentContains)); + } + + @Override + // Add extra required parameters to the request. + protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile, String... params) + { + return super.mockMvcRequest(url, sourceFile, params) + .param("transform", transform) + .param("targetEncoding", targetEncoding) + .param("targetMimetype", targetMimetype); + } + + @Test + @Override + public void simpleTransformTest() throws Exception + { + super.mockTransformCommand(controller, PDF, TXT, MIMETYPE_PDF, true); + super.simpleTransformTest(); + } + + @Test + @Override + public void testDelayTest() throws Exception + { + super.mockTransformCommand(controller, PDF, TXT, MIMETYPE_PDF, true); + super.testDelayTest(); + } + + @Test + @Override + public void badExitCodeTest() throws Exception + { + // Ignore the test in super class as the Tika transforms are real rather than mocked up. + // It is the mock that returns a non zero exit code. + } + + @Test + @Override + public void noTargetFileTest() throws Exception + { + // Ignore the test in super class as the Tika transforms are real rather than mocked up. + // It is the mock that returns a zero length file for other transformers, when we supply an invalid targetExtension. + } + + // --- Super class tests (need modified setup) --- + + @Test + @Override + public void dotDotSourceFilenameTest() throws Exception + { + super.mockTransformCommand(controller, PDF, TXT, MIMETYPE_PDF, true); + super.dotDotSourceFilenameTest(); + } + + @Test + @Override + public void noExtensionSourceFilenameTest() throws Exception + { + super.mockTransformCommand(controller, PDF, TXT, MIMETYPE_PDF, true); + super.noExtensionSourceFilenameTest(); + } + + @Test + @Override + public void badSourceFilenameTest() throws Exception + { + super.mockTransformCommand(controller, PDF, TXT, MIMETYPE_PDF, true); + super.badSourceFilenameTest(); + } + + @Test + @Override + public void blankSourceFilenameTest() throws Exception + { + super.mockTransformCommand(controller, PDF, TXT, MIMETYPE_PDF, true); + super.blankSourceFilenameTest(); + } + + @Test + @Override + public void noTargetExtensionTest() throws Exception + { + super.mockTransformCommand(controller, PDF, TXT, MIMETYPE_PDF, true); + super.noTargetExtensionTest(); + } + + @Test + @Override + public void calculateMaxTime() throws Exception + { + super.mockTransformCommand(controller, PDF, TXT, MIMETYPE_PDF, true); + super.calculateMaxTime(); + } + + // --- General Tika tests --- + + @Test + public void badEncodingTest() throws Exception + { + super.mockTransformCommand(controller, PDF, TXT, MIMETYPE_PDF, true); + targetEncoding = "rubbish"; + mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension)) + .andExpect(status().is(500)); + } + + // --- Archive --- + + @Test + public void zipToTextArchiveTest() throws Exception + { + transform(ARCHIVE, ZIP, TXT, MIMETYPE_ZIP, MIMETYPE_TEXT_PLAIN,false, + "quick.html\n" + + "\n" + + "\n" + + "quick.pdf\n" + + "\n" + + "\n"); + } + + @Test + public void zipToTextIncludeArchiveTest() throws Exception + { + transform(ARCHIVE, ZIP, TXT, MIMETYPE_ZIP, MIMETYPE_TEXT_PLAIN,true, + "quick.html\n" + + "\n" + + "\n" + + "The quick brown fox jumps over the lazy dog\n" + + "\n" + + "\n" + + "\n" + + "quick.pdf\n" + + "\n" + + "\n" + + "The quick brown fox jumps over the lazy dog" + + "\n" + + "\n"); + } + + @Test + public void zipToTextExcludeArchiveTest() throws Exception + { + transform(ARCHIVE, ZIP, TXT, MIMETYPE_ZIP, MIMETYPE_TEXT_PLAIN, + false, "\n" + + "folder/subfolder/quick.jpg\n" + + "\n" + + "\n" + + "quick.doc\n" + + "\n" + + "\n" + + "quick.html\n" + + "\n" + + "\n" + + "quick.pdf\n" + + "\n" + + "\n" + + "quick.txt\n" + + "\n" + + "\n" + + "quick.xml\n" + + "\n"); + } + + // --- OutlookMsg --- + + @Test + public void msgToTxtOutlookMsgTest() throws Exception + { + transform(OUTLOOK_MSG, MSG, TXT, MIMETYPE_OUTLOOK_MSG, MIMETYPE_TEXT_PLAIN, null, EXPECTED_MSG_CONTENT_CONTAINS); + } + + // --- PdfBox --- + + @Test + public void pdfToTxtPdfBoxTest() throws Exception + { + transform(PDF_BOX, PDF, TXT, MIMETYPE_PDF, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); + } + + @Test + public void pdfToCsvPdfBoxTest() throws Exception + { + transform(PDF_BOX, PDF, CSV, MIMETYPE_PDF, MIMETYPE_TEXT_CSV, null, EXPECTED_TEXT_CONTENT_CONTAINS); // Yes it is just text + } + + @Test + public void pdfToXmlPdfBoxTest() throws Exception + { + transform(PDF_BOX, PDF, XML, MIMETYPE_PDF, MIMETYPE_XML, null, EXPECTED_XHTML_CONTENT_CONTAINS); // Yes it is just XHTML + } + + @Test + public void pdfToXhtmlPdfBoxTest() throws Exception + { + transform(PDF_BOX, PDF, XHTML, MIMETYPE_PDF, MIMETYPE_XHTML, null, EXPECTED_XHTML_CONTENT_CONTAINS); + } + + @Test + public void pdfToHtmlPdfBoxTest() throws Exception + { + transform(PDF_BOX, PDF, HTML, MIMETYPE_PDF, MIMETYPE_HTML, null, EXPECTED_XHTML_CONTENT_CONTAINS); // Yes it is just XHTML + } + + // --- Office --- + + @Test + public void msgToTxtOfficeTest() throws Exception + { + transform(POI_OFFICE, MSG, TXT, MIMETYPE_OUTLOOK_MSG, MIMETYPE_TEXT_PLAIN, null, EXPECTED_MSG_CONTENT_CONTAINS); + } + + @Test + public void docToTxtOfficeTest() throws Exception + { + transform(POI_OFFICE, DOC, TXT, MIMETYPE_WORD, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); + } + + // --- Poi --- + + @Test + public void xslxToCsvPoiTest() throws Exception + { + transform(POI, XSLX, CSV, MIMETYPE_OPENXML_SPREADSHEET, MIMETYPE_TEXT_CSV, null, EXPECTED_CSV_CONTENT_CONTAINS); + } + + // --- OOXML --- + + @Test + public void docxToTxtOoXmlTest() throws Exception + { + transform(POI_OO_XML, DOCX, TXT, MIMETYPE_OPENXML_WORDPROCESSING, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); + } + + @Test + public void pptxToTxtOoXmlTest() throws Exception + { + transform(POI_OO_XML, PPTX, TXT, MIMETYPE_OPENXML_PRESENTATION, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); + } + + // --- TikaAuto --- + + @Test + public void ppxtToTxtTikaAutoTest() throws Exception + { + transform(TIKA_AUTO, PPTX, TXT, MIMETYPE_OPENXML_PRESENTATION, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); + } + + @Test + public void doctToTxtTikaAutoTest() throws Exception + { + transform(TIKA_AUTO, DOCX, TXT, MIMETYPE_OPENXML_WORDPROCESSING, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); + } + + // --- TextMining --- + + @Test + public void docToTxtTextMiningTest() throws Exception + { + transform(TEXT_MINING, DOC, TXT, MIMETYPE_WORD, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); + } +} diff --git a/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaHttpRequestTest.java b/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaHttpRequestTest.java new file mode 100644 index 00000000..25547e11 --- /dev/null +++ b/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaHttpRequestTest.java @@ -0,0 +1,51 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2018 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.transformer; + +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * Tests TikaController with a server test harness. + */ +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class TikaHttpRequestTest extends AbstractHttpRequestTest +{ + @Override + protected String getTransformerName() + { + return "Tika"; + } + + @Override + protected String getSourceExtension() + { + return "pdf"; + }; +} diff --git a/alfresco-docker-tika/src/test/resources/quick.doc b/alfresco-docker-tika/src/test/resources/quick.doc new file mode 100644 index 0000000000000000000000000000000000000000..eb307fb2182f673a4e48d950b629612925aed126 GIT binary patch literal 19968 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 literal 0 HcmV?d00001 diff --git a/alfresco-docker-tika/src/test/resources/quick.msg b/alfresco-docker-tika/src/test/resources/quick.msg new file mode 100644 index 0000000000000000000000000000000000000000..6ee3750070192fe8b014c0fc1bad1e8944d6d6cd GIT binary patch literal 28160 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 literal 0 HcmV?d00001 diff --git a/alfresco-docker-tika/src/test/resources/quick.pptx b/alfresco-docker-tika/src/test/resources/quick.pptx new file mode 100644 index 0000000000000000000000000000000000000000..666b5d7ea18940ded8a5c598bc0cb1a22a40c869 GIT binary patch literal 37824 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 O;|YHD%n|+L)&BvC1oUM9 literal 0 HcmV?d00001 diff --git a/alfresco-docker-tika/src/test/resources/quick.txt b/alfresco-docker-tika/src/test/resources/quick.txt new file mode 100644 index 00000000..39deeeca --- /dev/null +++ b/alfresco-docker-tika/src/test/resources/quick.txt @@ -0,0 +1,6 @@ + +The quick brown fox jumps over the lazy dog + + + Blank Page + diff --git a/alfresco-docker-tika/src/test/resources/quick.xslx b/alfresco-docker-tika/src/test/resources/quick.xslx new file mode 100644 index 0000000000000000000000000000000000000000..2e1f271ed89954532bba77af998d8ed25f4abf69 GIT binary patch literal 8643 zcmeHMgfaDQjdGkZVte0#0gdwuU(-}}8wT?q}H6o3i91^@tzfaXv&HFp#MAO!;e zAORpy3}hgVFiS_6v9_m^rHdiAhl4#s-Xsbr2Y`ya|DWT3D*|N+(yE_$3FS@{zA%0# zXK`$j!WP=j`$)`zg2j7WTm5Y+sgrAaI~6F1N*VxuuShC)aGfn;uC{hQ0u;k8%Iu#O zrLIOVgMksQ14hPlBh*PIq>piyIajs-U8^;{;TyehG*)c~K5My%t0b2Mj09AHHTXz& zB3?o0;hl*uc<+ep7UGB3)0C{4r&2n=f&GPQqzpC~-I_tCAn^A^?@!Fd(g!rw`JHic zTDqQV${vtf(%86zOdZLmS`GTPI6d7Cibi@|ZaT$##`t`6w-!w99-;)bp)w?~+Q~)_ zxK|Myki?%qAhOB9;`PwC%jOj*DMNHV^xlH5TTc$I%m(+TyQI5l6|Y+q3>~L5+2PoD z^)84zryVT-)ES@TXsX2#=DkePOBUfW8TWo5zj9>9FZ$_Z+~(+<61GC=M|G7fgUd{T z(ZAJ4qdzMtYQl(Gv_`q^cK@93vSc>-^{nCsYR2s)54X~9Q7S7(E%(on=()Z|1E~Kg z1?zNpnU9bo%E%1E0}P-TJ6qbj@NoY;GvxLBlY0L%DHjnph|IQI9lHw6GArlb92Ky0 z3!0P_ni#d|J_2{>>mpwRrB056&;r2bh~eY4K}mzTomE?HdKxnx)lct1($xZH-jmNf z%CjF6!_!uMb{+pi}1(ABR7~#`4B0kvJ3o@wP!w1>(W8>T8y)8X=WMBG&8nRmKXh zco0#P_OMqmknA91l&Jfh$s8?^ws;dQ+zlu7B;kix=&_4DxX9(E4-EjI0$`(f*z^1jcXx=hof!mT_jAGd7xdA8 zLLYhW|L>zYUQMZ;m+Rcpz>#>(4MzF;?zgWFi${2=%P??Rf0s zBU`_rC`<7Om(%4r56hkK%)<7Q^`*k^xuZ0l>b*wkuPZcGZQsW(HeivmWtkasV4r`d zYByas|2{w0T0#{VJ=g5IeySX_(iJ?c9zvxD7xfF*BbJuVvhJF+INe)RAdj_t4jhEC{WM5LyH`yULmspti zwY*WpE9^nn7IS>VrrONF=erI#xci^qoV$AMJa}{Pxm9NcuPk1kLXf&3;YCG6jF-Vs z^!PzPEz5ulS0g_at{31D#n+>8A6~Z;+rB6Ue>V(==3Ohrr4mg29r;4E$oQG5ByY}b zVQ3}>_fxb5gTyMqOjfSsG`c%h$C5OK6_yy$h2IQ@t`y9qq0wti@@`Q{2l^bk^khVH zu9eN7n@+-rKW9EC9ti}kqbmt~l>2l%E5oCcvbvGL`Zc;sL+UVH4Mfe)>XZ4(h4tbwX_SD&CdBTfV6qDKY4#AXaXLW8PA z$Ubu2g^%5O&e6_-`|-;FkkyU-?Z-W={(+&C>m0o=6pM}dOC=BY8D;g8=HH4lsa_lV zAv5)_(eJT-2Z};Q{|Ryw|M%#-z&!0OU4G_ozLts|vd*;-9Mebamd3Y%MV1l_aRVK0 zO~5N0xAQTdqZ_bq`(3U8RnnDsnt*CybMe_Lq@}NgR&pMW%|X)!`N0VY&tk*=jT5WO zs(fI8lP2XZ=^Hk(jgsaMcbPIG&SvgnptC$(fe{Re3y`~eTgqkpkiU1K`NIUmgz_1A zdQMQpD+~N|>*)Z!Tw1R19j%d$XQ^TG#w8sw1xb$B@+1KL~$Rqc)wz<02Mdl;fUDV_2C$1<6}D}JxpW?;L2 z_U!6b#4xe zI?iF6DkNeuwY(pVDhcAQ>hvowA$rbbg=a+`u3O!?oyS0~%+Y9A_$^wNuKIDz+H_pE zV+}1j9_Dq&+o4=W6M`Alc&ZOez_pmd%a2rfP7M`jXWmqQ)1nuL5oZ|f8O&(6uGiCa zO6Fbs?ZmY>8i;;EPFxCdl=4^FxY$@)!d!TMyYT;ntcLJodOM1hnkQzw03pXMDX)CicRW*cDzQ*K=nb z*RB{5aD7oN*|gHT=J|q(Z^MK? zW8`svMi|-=P!y75#L_Eh$kq~*7L7}NE=e^d_%?v{G0y`V$uM2@w$V#Nw#a2mBPFw3 z2CH25Q&6>RlvDE&z8|xR$07Y~QSlF4pG@Iev!|{Z&)7CQwj5~vyyY`+%x5q- zeUf6>H|@~Jy%vFat~Wp4-q8`Ue5c9ozP>TfU8+ZcGa=F;S*=tvwvh&7yVp{bVMJVC z@DSkblz^9K$uFUNVz(jU9)f}GBwo>%CT_K}QlnssLulZ-Z!Z@t9(F&zPHOcY zBu?Tk8$DD@gdnH&uNk{h$kG^q2>@tO|J>;PRxe>TmJXIYzn%Gh&iR&}8U!Is`hj4| zodE`MV5_Ibat)iRPA^xXZg&i!vrSFX)yk6^QS_yrS$=`?>Ah((O4By4{oNtdCRjGB zK}b2;8QHM{_$_6x(g-H?#CV7-({rEe`DJF;qnW_aTp1?dS16*?u)-^}U4nj8)W+NW z<)soeT^w$wd7p>!%v^@T?##sbuHol&4j_?ql|)i{<90BZB|S0h(3G;bSDcZrPo*)m zD&Pr`b_Xgw%5134M9H`nOPk=adIU3rw>N*TgtUyx2%;zSgtEB<{0$}hl|QRW1{tPU z)`Z~00n20@Sg0NXO~Twy5J->^LYaiiI%70`(cCjJjytDJ!B=PIU}`vjG2*%run+6s zBZY&k^*1LCp13)mVSXIrubA9)^{&gvLNS@gQYq(@OFO!fFOMJQe6h96zwKD3QQmZl zdU?c>YLKb=W*BT)EsNhJF_FASJ#OXe-4CaZ`7DyOcQoMEfPn2`TI~0;_*{ca_1yO{ zN%^VNl80t;Fa5v|LX<@jT)_~4&+D`{3Q*`v@%Mt^IML%Jy5W1i+-HCxsh4Dtv1x1; z0luM2+)?rYX8iyN@za!QnbxONBh4{~7%JL`b6$815uR6N*7NIcKeP_N{fJ)<8H}R8 zf?cc+?|-7_;<8@kjtX3AOP=>TUYn$UEt%za@O_`+tA}3u_1P!34;L4n_XzoI7>C1o zvM-Ley2C3aE-#xpS@s~+h_`n%zD>DCp9LsMXspx8 z(JCvc@aHqL#gK=)*`oWUCU4xTaI>#*r*IX$JL(le^Iky#yAK>hPrRD4e?N|6VO2b44N3_moP77o{Qy7WifnxOk!uRTdz zjAVEAY(?5NG+)vViE^4r#%N({L>#~42;7B=$Q+8DqIBM!^-U)3oP9$PASUP}tB)R< zm5Q^i1R7JljI_CM|D2*x)FF&HN48wwfN!9s2j0p8!AqU4;cZQU*839vy2f)JbK|q_ zu9M!In>!^>CG6@9Np*`_-g{R0R&T_;PE`3G#4oJwBJT(uWmB5s?C_-=+w4P$T?r`! z26fgpiZx1^)L`ONNaS(Q1d007HLcn*`70}85wkpPn;y88JTl?2KAQO8j__eBd;;y& zI2}D=(e*(FExt3qRWDB84*~Pq3Y?6@>9fQHP|@Z6zGwPH0xqR@hLww58ozP`5+v&c z!oQ>q1v9K0e(X^Z&9j?u5{5@a)Xi>VX1x3CvB+cylo4kwj;@{Sl_x z_Q@age4|_bvAm$W6{Vp@w79FHHNbGSMPy%-9FE7c(flAbij$j_Eqqu5VJ9>}MfV*# za?I*f7TgI!sZ^RhH6{Nz8&esCf36ijZSkWmyR4Z}T=9hj6S56cRhKDa#GtFOZ|1AGEDIYo@N1M$F+dYp&#lb#-{l;3caH3Y>w_+f}Y2)ik$q#XpBbH@+fue9FMcl<$?0yp5cQ z_q^}=*#O-E%W1CKnoX(qM(D)A@Fq=q4m4XO#D3hGLZ*JFCR)aA)VhWdaX9@o#`jyz zkC@rxX|t|+U$^mUf8Ls!wwxnipCm9d`zS-Cl9#-uF3PfYf-_=u*Q{CF%6J!Mrk=mu zoLm_)p%weuIuy(4@OCM)UG^wN=!daJ}vY*l1e^`+(dYc`=B-FbopmmQTEg{C#Yf_j% z!{KfnHS;EGyDAlPsg>TsDasbDdq9W)d;bBZdAZa=6NP0bXeNqQ5t*W%v` z6Z2c#bEHUKOn}52>F@N&#m3ax(n1U7Z0l(K+rGwrSVIY^mSXL>!*`u9$;h70w8>hf z$^ko`!AuJ>=7t)R6^5S1R_wG9fKqpS)1Q}rh;1+vzJjrU>v?)EkH*%o`rNz56 zVLc+D(hap;Z}Cck`O)*YRX~b-EJM_FJNw5J-`N-Y?hc?D3uA8@b&GgFk3W6vaa^dI z%*3L0kqO;??BkgGR_L|A!2O8J$U;F!F!X7LS#$h|hwx`cxo3RZV403FH(4VXDA7h* zxDDsdlDUKI~4<}s-s-tA?KYw6y)qiZ=4PY1SJx#|2AV69lj(bB1bBa zU&7y`Xl`n6E@NYA>-dvlibtv7w($}Mp9HvL*EDDu7AeGY<7P<_5RO#i0OR9u@)|_A zVJChI-VjP-_7XNSoK&H$COXpUUY7;APnT}9nbL}N;)s+~!DdAhK}7$8JuJS#Ux&HM zX0NV-LKd18m&je&UhcUPXYWwY39@4p3uh}~U&`H$PN4$yEocw())fy)0ImW?pDaD^ z_W9daz+7!`%0>cV3kd`wq(Wr@F;{nnIJxkcL!2#tz5_$vKf)9;asZz=W5_5k>F4>_ z)7we&TAkh6^`QQI{|>y;7;Mz-{u+n@)!iZJP+(p^MBZFQLYQ2MU4@n~<{080Xl4T@DRYBX3h zjHqA&?$O$iliRidq2?`Ce7g7O-~}SI%ULxTlA#BO5?!8EyXSJos(hM$U_S|;AHolW z;;pvA&>Ww^OF^##3TIKy#ucvuvYNN?XQm!_?bPCR70ziWzcu@S1>CA>knmgjC4Gq^5Q6I>?dEZr!SD${p;?pkyarz0y)Bo-1Zax z5!I$nPXB=VC!BvjGUBAe5y%3y8+?WJ`dnTWRDiCh)Lp-oTi|ceV68*fX=bTtW2G`; zJYTIsZ0!vidz0!Jy*9Y4andd;m zfY?G~?i<9Q!gg1+Yij*RVtb1RR|%B5rGxCA*7*BRzU>aIhF0e;^$rI-apvYIMELvm zN2$KocAhKA6rvNRDWhH{N@%`4#++hmYp~4!Y<%=RmJ%Puy5GUfCA*&ck zXf-BcETT?LLGL=^2ZjOQATw3uqKq{gxhfwNU`>S>7Q!FH^oKH(2+|3JGGo4s6PIHIb>f8G9xvSYO z6P0L3T}lIf*weMFG&vI9SL837JhGyUd7gyFW$)7r2(VOISNvL9P*Ay$i}ByLs{cJ> z|GxfB<62$m&kp|FX#2O}&ubtuE&kAUyJ`66uEie>AxK5#zxOb1`njoD|MK(>*^R%U zVBa*pDY^bK7Qy|^_?G~C)AXk3_set-??3S zf=vbippgSnBg5bzPwYYiefJS5Dk{$Zgnay_si~*0oncXyn{)hLB?bebIV&rp0RRAH zXSgLbARq{894_(+8Xyd0CTJ>bP7<~xAn>OAFE1@AjJoK{Rz+2|KOy0f$9}!dzlnEo z*vG#IVxr=MZ>Q1Ev(zF_b%%ailxLLYH(ZZUvv_43O_%te4W|G{nzI>zbD``6Z$-=MH}ufpO5Z7w@H^I{Lukkfd^T<{`~e*j8@6-#Xjih>o{63b`n1- zxtHj}E;4`^w%*on^R!vqnSn98;i?{Cf9Xu}*WIBQB;N2JU?6FfmtOiI3gA;w5dP7?8aUg*|N5B-HuTQm5c{5RO$Ysm)yw=7hp z417Vn4O8^EV_e>3QJ)b^M~z*Wq-7}+G*r|dk3hfi2i$Y-AgJ2>*Or#5~e-F@5`4aL`PI2hL|<6M8G7E4x$V=`41Wv-{5es#O9j_wpT zXd54LCu!QIIVNE9cAWL83v@#o#Q)I!b8)Q)abz-9{^Yd+)P;0R-$$?A3M()Fhi&uU>r|zihVqu zN6|k=DjVwV@*aT#1Qf@4K%HP|0xo{M$kdO|G_Ww?y>MHoyxO7QA!(4x+3kD0IqwUR zxa>-)qkp?Q5-n~jMFsf^DCHkm0JDa}u)A5e=>COwyo^ z88+GML~b@uskHXOPEW=DN+Zv9VF;%4N#+B0~*OUnlfW^KgW>hpzU zFya4#TtX2A{~9{V{j+a&C@x)cQ}Om&1G44pebE#N$k`R-x4FAJ1nk#d*p{Mi{tGrf zOvwhk2=P2`XX#9$S|5@}LUIWJ%_MDT1gU?xVs0OobI!Ys4NBU(#4HBG0pE`LN`Uq}G(z*jh42u{C_f;J8j z+q!6r*gZUMMO+6q+t_|7zt-}SP@_eY0%(6VTkD*l5Y>7H?=s7+Ga0lGWK+x1B3HZnyavB^xuvdfmG7~r1=kF7G(jh{ z7kuQJbx%g<^1z`~$fFBlA=}H%H`tUs6faNC3QMGBE>n9i%I)i$1ca3Ib?4$vi+-j7 zfk-!Zh#a6#A48GfP`7A0wBUAzr@mL?dE#`tZeLIZRK==HO1HUA?%RNRtDt&i=*4qW z;IgF#4G6e&#S== z5#42JhL0;0TK?1X*A;P&u>!^};}rKqNFyFq??s%+9tBQAJjTnTi|zdk03$_O%RLP4 zNyh0i){9)I%-PTf(HOId8ct>6LA|G7B3pg{5-jc0A?~o)VQfn{uE;ucY<_zJCx zJ}o{lS0)yXnQisbfXlGB$ZkW)HG&NLw(y<}@?fFZ?MNdSwL?^R^=;85``vn-h*X_I z;(?{8U-?t^C)lm-djhkA$(~Vg@R@vrU|R|C)an+~oQZrnzu{+)fpb;oTuSU&>Lr$E zP+6VMx)uHjy2_ogN|BH(4ccip)idcM$Xpg`cOdAH`x`FsT#RRIKzI}GvcyCCRZ-an zt5nhtU2p5EAokKNuIYrXXi^*?6c_BhvQew|W8qEuUn z-?u8b*}^ejz1xK-L@bPZ%nKk2;WDisTPsf) zze@l+O!w@ROl<~9v&k~44@kvXb;(F};A!{FkJ%Ajg2*wN<(6L_i|wiBn0H2dSmi#l zg5#b5O-EzKV02kxX=T=6GyqnWpAWu4k{gGGN~p}bDsBtX&sTTZ(3hp_l65>%PyD@0 za4@|6YW6tb={5`Y<3W0o*;r421Ru5$^acOnf=VX69e9Np8V6eB3j`vIv>psxZSwt3FVpzfZ!rQ_aLf;g@yfXq&=tfbZ)E?!I+rwO z@I3e)P-uN#V=3!;`t7P2vAFMQA7VxCagwl98Z{HnISAGzu*sU~yA?{l`9RX)E$+3e zaPvqLd1*sL8lY){jcdPukyXMbS)E)KyEISK`2hegoaRPGncgc#z;O@L#8XEExo>Zc z=5An#_Ed(Yala@Hf_DCpLP&Uqv|Oz@G)!~2Pad5!gf+ii4d>p|zZI5l^& z3_>v!3`kkM=~9A`%#Q3M;n;+>%s~oV!MiC_^R{Idr_*=KtDAHKwz3FU1$c$iYC5P5 zwT2@~ZZz^+)@0`f6% z$%&;y?;qYxUD0p`FPf0?xj&JI!+-1|&B|=Uu_Y(}g@!!>s5ATq<4`x^AWpAM#rQbU zd-uIM1a}lNv4zVW}XnYz!gR(+e>ixf?)mEJUKBqvxjF}~>neS0+}YLthT z098nfxbb>T=vq@OXIHgaY)I`wU`XlUYv5Vf>GyhhX5C#f*Sp)T3B>6vXRARGrqRDZ zv(WZKH4jAS+^!u$Js2$+wL22k-kOs;Q0+v7mHMkqPi4Q)g~{d3S}%%q%_4mVz?iO@ z9-fyvU@T@#ZU4lb`mGpcwW0F>=G{GdIQj%SV@Tx*iEj%l6nEv|qq^CD7 z#^uVM7IN~0)4l9ypb7;=@sD-bToIRxJMZFOXR}YA5gmW(bFRr6Kf1V6=m5r&^v7wb zXB>xcWZxIbxwPnPW`GQ{81g|s#3$WIHiS5AxM@Xcq4#loYkd+QT^F~YxAV`PFBNda zY-X+9;YuB_u){M?#9c zTjKK+Yw_CX2XHL*FEeaea9iu`>IK!e7bYcDQbX_lXqWHF69z}U0B!SHOl3I?=jCZY zFmP*3o1`-eF;OOBH9FYGL+wZmv6>4;V=C;SK0-acLPX_K+DZEP}U9PK^9Y))sSnJ`|=x6j*t zvUuqGnz_{bg-n?I);-^c#p%Q9W>jK$f+r|U!M{5eobFfYlNH%?2w-=9{34l`?EU6s z7dfgmu6cY{rJ7lgVM~tguLlX6ulHS>ixWW z%(3r3C>Ex|Z#Hu<>e854rOn;CgbAe&HV|nV&|*G!Ssp{f&AVK(`7I2lF5kWB;yy~O z3lE{)+y0GW$>`jMCotpo{hH^(HR!VA6`H%DddP47Vdp+R2us>T?P&I!J{V=UkZ$t> zrYPYyIcHaD)`k3KOnE_kTF_N$4)~Q`CWeXBN&E+Yr_&sXm3-?q2j5h>9SdXOx_cZA z`!EdNp1R%Wi9lh~ib^=iN%eW^;^zc$$`Ayb-CuG|xexLyOZIDZw1A*{H1or4$P}m- z2$3G^l$_M8HJm$z;g)PkA1UN(JI~}b29#p+{LFpb={M@gX~l+F(I27rU@tV2*ieI& z-upY$G@%OZzSCPqB&q+gb7i2Qk#Ijex1~ET5sjHywN6`yUVyUVXKi3&JR=i2oq^Y{+OoO_fyWN-}7nDY-&)TP(xvZZS-&IaRqq*KAQ!SI^lauSh{pPV4_;c;FgLo?0 zU{KRzwomdC#YtACop!nxt+o*+)*;D*vs9!h$TW{~hzch=dcXSz;||7|unwiA)Np5S zT(q4tb0A0ZL*e1{*m!aPj490}JSz+ftpQ4t z!Ahw38({|~KVz5B{(-*trJ9I4Vj4ZUC)ODmH>RBa<&%{)l&H8aX}mGqh;V|oHW444 z=i&uP1p*={Y=k^lZJHa6!{Dv;V?Nes&e3av+StH+vlt!y3RYX)g_w+29$O`4&lbn% z&`a=&GKU}86_IPy7QMBRgDvKNHJ!_pQ<)wdY?#l?5Ob`-UJ@5uewHDBP9W>V{HeUj z!K3=;8wCotdhU3clB()!W8ntvC$}UauKs*K-1;W=!Uo)eJ%NMbY(Yr4c%FoRiMmX1 zUCvWqAc^AW!dqO%autdJ>Y8}^k(Ob@c3YaXBy2^l5KMe8pb9^gMok@4BEVLGGoooE z!OnhXzvUZRL=FLZ`PK?--gGnO18WG5%blL`r)r9Q&t_yA zX<&bIoRF0|uOqK2+I3V3E26p63ARLN3L5*DY#VHJvtyfEGI>Exuy9;D$l7lE6p z40i$RHI^ApSWU^!qW783%?;`eAfSM&rgzcD&W*yKc8SpDUf_Cq@9DOr% zv7EL_pFB`vh_Px2fD|5NnTM9LYIEYEh8==WA-6=2w>zt@nf9A1B6XR8sI2+|Y^PGd zY_P@OnaNH-Zy6eaT`I#UR`%juD|#;LIZW%1J^sY)-)2V8OWhX_b5k5rY$@eC@0E7* z)x(p(jo#nHTvF&z$I_ur@c?{3j^!+FmO%yUNc|d0=@1z|^`%U>K&X3%wegZm9_W5O z1nj)sk(BwpXwKNr@6%rV-qO64?XVc`Rl+V9jC*o-KaR(Lfq;<-^!l;enw&#L4z-nK z#&zy$*^W0@1vYx!arAc9pvQM#OMGs(5EWz5=A#J-W4Rp37;ewRXx(=}h~7|n<+mRj!V+0`qhPfO%C?$CXYxD`Dd@yu z9FDs5+SGXFXeXzU_J}Wlw}QufpiWG>$aMZ3QCjdlympv-Cyix@3Kq85^C@}3eqls> zk3~zRV*g>SGoyshRc$71kqQImhTDP2VmDNsS3cvZkf!3Tj?$Yjs^78U6GY~p$~nL| zo(T@SX(0=C3uHmf@Msf=&cF>zYIfF*5%&Y$xMvGVRY*6O>a_KtQZ%phyMMb=Rb$s0 z@4`5I#gHD$m_V3-r@lz;Dk3Zq1BZOd=rtFwHmllLm^rVbYl z8ibgwX%@0ClE&LS^TaR96rd-EA7rpvl%4ayap{JS6UOi|yoF_JcIK4dja`ixTiY^m zzMg@k6TT_J`Sem-anjBqSF!vP)Y$2X$)1KIx)Uv@_(!RUNx}eJqb}ex+(DQZe2O=X z$wXP>LxM`8)M34KRW4gbAj`+UN|Nl%SI?_@Ee_UtK>|O8Huq2S zbQtMb2?O)(Z`u5l&BmU;w;YTtKF>SJ-453<7t-Xz$JkOmg!Z4@*$t#sR(IyWv5L>p?J}% zutzywD!F%mE)HF`>0CdSU=%#37=c`$?}jh@560PZpw?R_OI-Pys2b@EnJNc}6ZTjg zJMXN-{+G$tV3E7#;AhfpLh-Dif!$)gtXk()a%D3)OvA64tjuiP9zRwA+L9MOqJ z&qhXo&?if`rrLTE~Um|!}kpt3Dc(| zOE30b7mKG~)zmXt)Qqo5*G6QLnlsMleMS#zUsYAPFSgQ{ZMyd3J+obIAKI~Nm!|;! zrU<1gt0<|5gnyf;rr-d9vYcHRQxzPF9wL)k7>687Rq}~*mjgi)1e~M9q*s-)-5qA^ zsz}@EJrj#M-%zndksmw#+c^CM833`k6Ia@Y)&>d}9soi!%%Ib0mC@W2wtEDYb-mDE zuRmDYvFw|7ak#Cn)(eJ1ts$@#p>FQkU-@WkG(X3M9D3NHb@rC4mWf`1@Jq{^_^L-c)e0>P z7&L#K-UE$4gC~mF#+txzne0X#Wi0!922JnrmnRsf6tpYPoqyYx|FO`@WJt(StT7t5 zP}B3=KOs^=tLF5Gdw0!JY05^LTQHMN`{k_;*|K z^mW~W@|w0yVW5fzVEcNFFq_D!IPEveY?$xcpsk_1lDRkM<5QFCg~2J2iRO|LE=EZ< zWMbvHqmu7z31x4Gd{1GVGHH$wI5yJ0#(qW`Iz|s!McPCoFI!;X%-Y zPj&){Y9*g+!fGX2IBS5EndMZ4I!(05_gvwLF<5)Ptj0>qr`nE9ui6*Au=*FGU++omq(;-{*FSP>94@QYiQsGtley#gno-WhbS)~IM>Gb??xWQQmmUahUvp&; z(z8KzSD+a#=8pojm-$DxorFzFP-&f%tpI=H-Un-=NucwTVy0698P5$$;l}Wh*X4)_ss$TvgYwm2dV&vi}*=?>iga?KgE{ty>NPDxTea)`m7xbt@?^db<4*AXQ zT*Ec1pY6w=eS(Nvg`R5}PsQ6ffsMPsYk-}X<{w<0>(Lc$M6z|X^Ep~dSG^1Pk#}ZZ zm)p(Rz_S?Uy(>Q*#_`=|isaYG5|<+{Lr=Z)KK^O4{Y#eHqAAytP@?a>N|d7MFd*&l z{u_wvsoo?7Cl`Wh20QpE-DrnAMFXOKvlMr@E5XC&A)Am1S?LiBehY+iHn07LoO!(n z&%fU|JA-4=IRSxJKX~6(s%^z&cT^&WEZH9;<>Xvf2KhM7=plo7l8E*3%e_;BX3MC3 zoU4XB_3WJyrV@(mnY0b|^6MEIYFkqNA_Rv@p&{fK`-m9O$w!{qtM1j?0HJRyLEvY= z)jOp8H(cbNPZM~TqA54t9$}6P7{@p-X+)r18i}C%xga6Spk!C}*JgIbRodSn(jnn3 z54m!$<*296U);3xDAc4sXjs)KC^(j3(a7Q8Fe7Wp%4eq%_q(pCTWKRRZ@jjU$IH2M z3qxqPp-)%jO=qHejM3}PP_B)oXdhFJvs~kG%3)!DqX;=gQJQ59Wu%-7>_LoG?BM25 zb6s6$J+U*S{To|LByTVC?ZWmL&-;9>)R>>PMqMfRVmD&Aj1MN(S;1sz*SHc_Npm;& zQY+*nn}3d)fU#nu{oo85TT0*DV^n&$Vd0f!*Y$Tm@?G%@h6 z^vHaK5eFpdUjOBx!h3u@OPcOTa;p*R_x@*MCd!T_g=jnZI5!h@6(#>hNAPMhpE|&{jJz;-fphnv87-RB!Mg6&F3E zN$OqGtk}nUzlH0Z3nv`?Y3^^!CX>Q42o*=v5svT~=`t<)LTy;(&BJH*rI?+AFr8(?HPGj zm}i}cSV_pRc%?g$A@P47L_Pb`@zLaoZ96N2T4(P7W;A9Hk6wyuu_`Y2}b8?HTlzgwqird1SJ)9O(LHSYm zvg=L;iWN+Yhy)+Eid1zqTn+02`@xOG%Ac7g4(Jx4|`+Kj?RoB4LB zwVjPHlW!@T2~&{-2>N|svkds|k7llNm{;7wBxymgX{pQ{f{)&I6+}&63w9hWC;&Gb ziC<38L|#>Y{z2&y9Py@`_~wgb3Wqv%*YD##$?{U(4!`5)FCDLE9$H&61VORXZ_wK` zKc39DFiy|guN0X9Gm`QCI(`?nTmA7oI7%t(*&9LsL&tDAVI2iLZiMy7Q%yd?Le7vX zQ36MCw3(97Ud9N`3NWgA8F+0}@d>_sb7sHx+!~yo_7qi5?VHe&g+PKZF3_oZE_N& z4kxQDW#O}Bgp8?h+<1airn*sbc_i)irewM`?S2YT{6YYxxUa9TppcMeru{X!FI@A1 zJa&w6>|?09(lq!L=i7Qp;icM@X_c>`;(})V14UFyxk#kkOiQ#JUVK{)j14|doP5oe zx@dG6sQ(04|AgW{R;2$v|05(n;&kA8@QFjLsErWz^8+%Lr=~ z`Ep0Cz3`B+_R0hi$K`%_a#v3hkK^(-1Jw>kp6aPZO1`PUS%k=LDZGfBl2nIo2TPvW&(Vg1qrB*Z-) zu)83{&vima>zFxIE9}lKb7#*!*!SkTj859xZ&pzJlW-x!H4Hk^*y+g26$a!}Oh1hI z^PAz8NNE?fJp&=h7ET#D3f6TbBTuU);;W=(7^S~(N<9PMnq8(P08%{P*4Ng>$~k!#r-CFf`RmnDqElob*(RD$%kMWSwkxXT_YiAk&$}q) z32@zOeAzvr{&-iUgCav#y#Nx_YqZ+P)0pIZyD6_2)Jk-X4i=6?U1`yR{gVT!$|rHF zw-Pg`zr6>4_K5R3lh@r`KLJf6f~vL@AeTYDVF!N69v-`$AFx4RIBn<7lNf>S+)PWJcWPiUs)sb`p4{kiwl)aX2+o6>I9WHtZ`xrj0YvXHO`AD>l zk@=_zi+_%idw{4=&s)da%$0`cUR!D0r8uYk=JlGoL-xixV_eBQTpV+ZR~t~Q3KQDh zIrJLOt#GI?Ff~s1&L~WT<3HKzc1sEs@>M>)UoN2mr>tC}c}f~o zHh(ZbzX+L*XzG!&D>>w`(R*Fw^VnzRECvHaP3TKRc%LQ+p^PtFtB;OIt<>{yfTkia zj;TPMj5<5w-78SWMz-8aLdIBgJ~itYYKq~BaQBrDZmx{21DFVd&EZxz46odd&QDQN zR0s-To@!iO`_@Ac(liOEUSrZ05RvL+)gB^in`1UaNOYg_ZbQAhqoGvq`Z6?Wdsva zr)z~JWQy>~nHTx4`d4b)hovuCUR@HN;e^iuNt$=3Oi}Fz{PqdbHkuB>mLS#sksDSe z4kUj4G@qhnPzBprlh1K7qiEfjcT;j%Q`X+tr0*A6NBgEVC2I7oD-@~lDz={$!iv59 zQU$#f%pwqgGCU8{|6!IS4qxQW2wym|HC;+`ukeJaw{Y#O zn!K*B9~&R%27@vUK)>|mkL(?k&{)Eq1hLk+_QtcHzkN@v`i3hrUY-pR+@Ui_8I~;taN@r+ z(YkQ#yf56@@0~Y8*4j>}utl_!bT|Q^b0u}WBDPRir+CKshS=5NT{w=(875PUh1LiP zOXpylqKNg~yLAk8ytb^IY~ld2*Gu_=gA;HLk4viG8^(U);n|Iv6@}-ckmbh;P`kR! z6AM)Heu|cP)IG}F2xBKfsaVZcQ0zmu;F;I#Hs8YsK2t);!Vhh}dhi)l_O=nqy$$`2 zZ*c!!Y0kc%dwdatt(&xi#d~9|RsN7j#rNvRiSpO}zDZamQ4_@&cMs#HfRbtv9`Z~k z5EkpP++s2WE8}G+z_;vp>5{bH8wcNIiiuOU(3HMg_D+z*!_k%JLA(MGGj$2tDnuqthZC#dy78EgA~XSC?dNj`aiQ}cF;sX})|a&m_#$o^iR4?FhCv zIjUilf+`X5mPOP(_eHmJQowT7{68FOK?TPN(+k&9MhsR-{A?kTl3X2rH@z;eiba0Q zUffZ)jmYlgOzM!TF$T+{kZ@dBs6;d}+^R z603h_Gq4%?(^kWg4RhsnQP~1_Tabn-dpAW7zILPe5!_=a*+kjmFLvdCgTYz58XxVn9*f=%A{No&-~mo8SjT+A7D)S0?5u7bb`O4|p+ zQu=0Dm67JsZNvayihzOWLz#u0#OAjkXEvrgbtRM-KD2cqG&V3J#q4I$^OC&pHh(Zw#Tx(&`KX9Fx2*8K=i?L?Gl>vX37ZmVlpu#}dIL-Jbn^9}mt z4L&)ci+7@Bdzw7y&!ZV?aj+uQwY2ND>o*6+L)DX#Trw{IS!HVN;oi`?tV}^ z65{CvdS6{m^VZ*yif*Lhd1<2*x6GKB-o|cTh(WMb1bHcGi_t7Y+JfWKJOo(zg4}w& zDt#_FSxps|?UA8r`n7f~bNw#!aGtP5rv)x!A;ms>I?(dyC@PUTj+1=|enng5Vj=;|8)iu4Tf6HQDk_V3N`|>% zgA2bBL--VQ+uU_>gXGRCO=riRh|4OlOVb`OWz>7_&tbFT{ymc*C?jHKP{hO+VWTO&k+EQppC%v(E7 zck|_Z1Ke->`zE)d(>U^oE8bgShdSqDXAmE~zc7-Xh@{2PNtb#VEno#zlID>>B*c<1 zbACFd7xx=AN>!)Te+t}!S&@hq<=>TXX~jWV{WaMqR`e@x?UXo*HXxUGQ)RiE3?lRV^tX!KOO zUhyx<((WlHhEiB58hy`nbi6WiDI1Y}KXZR;*>e4i7k&EAsX&4K56&a*M3G7b6HRg)w@#v(+5A`(3+@-W7N{?F4k#Q8~4nDa{fKdjCG8 zHPjGOHw#n|ueOIqbqG-^Zayv=_258Z{60;pv8+bc zqr0b4Chm3H_6uq6KDCwy7n$-&-CalKCG>`)biD?701sK!*@2$Pqzej120XcQwee0v zefcrM!pih)zQfVJqGax(q3NaI54gFj!9z?N-#U{eR#pY$UG`ngr>Qlov72tXV~7ho z#ZC{r&7Dm=PU)n@1Rb-KYtwOy6Ymp|jMRlDK$yj`%~nNRcC3DCdG31q@*A61*umfI z&d3l5@u^lC6q>u~N=P-g^YtxJle{}O2!gwNmr-b%PAURqKh4Jb>agf(0Kf3;-RIN|F(?Y54A{HJR@R+P2H_p@|YXZ({*=$|e_0!jxa zhmH1}fgiGO-K%8mBRE)=+g#Hew^R)xbP0Ovo;L;ItxJlB; zQm3&xq7SBui?vKtY3x*&n;&rGI|T5II7hJoSvE?XZvzWINjL#K)qqVIy>NW++{4hYpOQFQ-$XDF%JXDOn8w>k^Dqob zE7=W>YQY-pC_e(fYcK1A8)|!V8BO)}s>@Dp5j%#xJFoA9tJg(vXQgzC_rvDw*UYIi zQ>@G?y5G9ophY=uWZgg|#%tR~#L9vtGKH8o7EE6vR~0eq1jxK=naK3`)lVs|-Yj?v zmU9XAYhe~S+FIcX^F#qI<)5(R3?e2+WYSq7hP?5n*i?Bb#dMgNPSfiK8AFQ~O(G@* zt0~2<#Rlj-leTB9!lKeet+OEb6dl={X9S}CyrXd2iNBJ9ourb!bP);dEQaMXdjtZ` zc`bS>Wq1maAmaYVpIS^!QByLvux%`gV|1xK*C`->Rm=TyO7rg^M1+bAK$xr|Fk*? zA>;gj4Qzp5d`BWN{{B}B*;Iw{Qaou{522MlBukrK-4in5Ov$F~L`CkMK9OCuqF-`E zH8Jbz?vSZ2GY|M1*Gr0?lM_R0RdWp9;kGx%!vy~Ca*tkwCEma`6XM0q|a zI;eu$NR_fN^!6?9t1p|CvXx8+gv~tlUXdm+l%*K0J^!nIR-==3DG5Kd|2Aa1F)HAL z8(^7@#K36VS$8zU70-h(e9DL@0wi}hv3RyBf!?kk@9COITTs|x97pok_C1N-Mn*zu zgs^>0ti3s+&Jp(Byc(qc2s3-+VZS%QOR4n&RoQGsgRSQvC3WR=3(Y^@-n>|9S?O{I zMH`V?7N=?@+wcVF@TJwVn|(1c=PlkW-gEphAr~K@;7HbLX6Ozb^#zr~<_x47AsxaN zMEgx2$0qz8weaOsvz@N=y9xycT)>WXQiElZgE; ze)9W8fAdow|E~?skB`7l`CsYb3g(OC+jNd>_>zuPoSO@)as_DtmjvQ1$5hIwE&&|kQNlY0La>iYaslSY#O zd!x%~`v-kM8>qUt*;FO!9>GR=hXA=c3Z(~Xb$5VO7yRJo;c)2R!UQBwy%XOV`&ZrKrLcZ- zHB(PON42(<2=w0#^fnhqyM`dcnupL(_fEGdsxyrg1(4s(2S)FV6hyOM8Q@<{ z^Lh<@>PZq+I`Lfu%xmG(?Vpx@--KBdA+MGxdKl*rTwK+X zzo=T)h=%jJgn}cMTSej0eV;Svvxbkrm5y`0k_fOB4CeLw;Gn(ZW`8C` z+)SDVfs_(A3i?)1s6v@Z$5`Tz;bYp#R_;w5-uzq2OQ}W{dMZi21&nH6>P@srwvUG( zOR}dUd>5vFjOM;Zxj+4_V7h`HSKH{>E@1x5fCWko=eg=-VLSCnrs}kX>mgeH1GnO! zV$E0R*w+~R>-rL?g4#X77NJlhb6j@gbiTw3(obPJPFuQLP_4znB$U+P9o|3Ds@1DY zTdokFWF#+PLy`H#b`%p5ccvQU8e?!t8drvdE&|epp7y=avyC(ZDGPSJoSft)3LEr% z#$N{v+jd5@ZJ(I?eewL52IY+#F!Dt(D!q|zV`UtoTd>NSy5H?wf>OHScgHSenX75k z09!L}8Mv$jj*%p(7Iqs2&>PtI1OAI|24OIrKPM106$H^oOOKZ z`AV_na^@+(hhU`~u+L0GH2qnXLs-+}VAPAh!z zI>uJ9p`P&Aet0KHZLyf^mS)r^_d7`aQQ#6Z`G%IahZx>fA8UAbGp&R^u?7xldiiTe zU!%6QDxagY^I`dD?=%b+@^aK>m(xD_2O+JM)o~qOeFd_S&tikHS(;+V??%RDci60( zs#Div z&I&wiV>`%|h;E~>5ESZoYaj+FSiL}=pmA-vuedhJ0Pg6eTyiN7g&*_YBx}lJ?E_(e zT6_9GRZYZBg^!ns9VYEbRao$fH&KzjRdIu4NX5uc`t>bk{WKotyLmkAKhTo54w*K2Ue(tf*Y8D7>>xL*z1G&^`pX?BRQ$zER`6+i2HPwmjTuVb*5AmK%2T~f zPk90rC-RbMvKD)Zd`VqCxVngQXgNkJ_QPwetJchtdGmlaheM@(5`>{o6bvQp1JL7x z6$?YBg1uAn#w$;7TAxPbD zF`&AcYKElTf=OA^Jpd;rj7P;Lo+*=>!IkUEeS27D+fQy1)aL#-%Rvds(ua_RI0_>S z)`ct(UA3P~%iW7FXTn@-sO@r05M%*yDYY}E030!%pdYjc{espOJ7-ZwO|c-FD7?T_ z5Yv|FL(RHVd? zWT)$gduzBdygiooMp#Re;`3s@HYL5&nAfO-LSdNfP5ho}3o?PQNt7Gvj0yrJ&Kz^I`;X?Q5xBd4H#xB)l<7#&+14a zqH-PMgkPvJy2=PYjG3F9*4wIY&-uE8{DfCY-O^;7XxP)IM-~(=F2w2pS>BgT-vLU} zLh^T&7QVW3eAt%h(uk=m7}w^3ebLkAL>_ZXS;t=SF2Pr4xolAUxz9j91TB;JM9%J3 zHCeLwOo{L<<8UB*HtW>Ck$awu?NgXeJ{?3_tVit4uI>XOTR7$5>;?xBk z9@LFuFwZO~A#XV%X=ud(<28>owDd=xr-6&i(+@T|+e6ccG?{XJGAQmDhGODR+Pck) z7MkcEg@mPIJMr&gw?r0S92f2PYS7#_&g3<0W%H5ZPzErI`pSiNOn2XEaB?IImoB@#AHxLKPOT17kw*7$OE8yyrC;eeG>s{h ze8tg<=!1FEv-C*!LJoe}&fBq0AT>Xb4Ni;2>3&i$^wWY~{-@AGx*fmlm9 z^gKUWZ-f>`(Oe|P=^n!CI?2A!=rHZQU1O4MSe?Lg(d1{~m6(apHU>^pm*}Sc6`byP za%1JFM`%Xq=4>YMv7S7!xWJe4JcagIji@c-Z_x1{5l`1%6o?S3EK3-3mdS3=Cp?#1 z(-rcEh;FoEM$C{1mBrS!pv2*&u%b)LW^s!d$>sDcJMuV@y!DxDcK9J;cr*dn#5r&E zvITPYnHStvG=i?hcrvV_;wGheHQqV%Jw05z#m=Zwypi*1QUtD> z-qfhuCi6EvNQIFg-JGAna^~Q@k5M=I6Jh8yV>Anf6WLEXT#?0m)}goERJG-8hW7S~ z@^zzh_mBJi+BUnSem6RCk>51}C^Q(8Zyy9$T+7tA65ia+Os=JvXX7#KJFq4}W(2Qx*f=an zWpcPi(<5b|f97?ZmGdH?g|?~1hm1FzcT_wRjOgik!`go0tKI5auI~ClosZJI$t8Fk z#&u5itw*+iG#j@guQ2Mr3bXdiHD1+h-*U7Cn(4gb6;N1AgB6MMu6aPbozo~{4_?x7 za)jdEy>dZMvjD_Cs-xQt&FFE`a$PM34aab14(+Nku$c~)6^lU{25L@-R}oA3 z@$GOce$QEg0MTR!aa>bp72Z9zi5DEWnpv0UrFL zEGs%;tUPf+f5cjMrkMoQAmEYLfgltyP^8qGC2k!t>$T(6F96bFykoZ0tn#$iin!Jy z=$wN(YMkm4tBTS%HEW~rv1MxfTQ8WYv#Vja4PttWM}u*9KQc74a=a^;Sc<##97oFa z01|1`eDU54owxVcQNSMigi`<4TD-w(_dVd+v|v_V(HdB-tKVYVOl#q3Ae;oI-H*IX zA=hv+N~3xt`LXrYCb~0Y&tMe`vbDfd3%8y*`{XgzA8p=aB(+qux3Z)9kAC~LVPGj@ z4Qy*{+^{i!)#v-;WwNTFyb}?RyJ{XV(I@BPw=?gxew<@%%9AX14Yhii_i$$_)Tu5{ zReebOinhOJhJlj^*lFcXTg)NtD&UC@R@2ZLyad8i{~MiiZ9i^-pAywN*3G5)@sSd@ z-00KauAlE=^s4ogZIp-}NJ;*ZQJBAq*}cn$_GA(tB0!z*&**yHBM;n6}r;)lh)v>x{Dn z!(veXnDOqYJdu_VRUCT}m{nzD)e4 z)NGsvKUBwcZBE;$X4#BnQ}1ys4aO6{=Tsa{i(TkXsxcj#X=jo`i5ya02|hBJCh>kx zyUn@aQ-oTRh9_CeeZOj&&$ZZH$iqLEt4XR2&{vSQ~z>aD~?eTwKrlGy()*7 z1v(2nrM&Od^;w5aq>|;?ysYFsqCRx0J<2xElD9v}3lf-(_z>3emRg5i!O;3!e~wOV z-^IV3TyEM0*f!D`OG}*J`j)^41if-}Gbmh`koBC~$$SGUgr?}LxiN&N^LUAjiPOlm z;<}1T*OI`9yjw{x+bD#>qMa8=MvS=HLl1C%b*+~=a4$uW*e5qs=BkYPU5nZA#rrAL z_f=i@lDnA(MG!alv)q9m6?;Nn@A8li%PkHOI*(-;?T$-+^v07Xyue?7O#x{nhDX0v z6jH`Dsj(4y^O!@g^iUB+|Q9acraTTo0;HE z4>+a=^K?-UJM^8(vnYj}73-M99pE#)Jj|$M-a2|5^^BuTPAU`B~+H3#-N%?UHvVu`ysNY zb9QJpe0YwfCLum}d&3(|rl zE2XhXz|kWb%zMP;luf+!%`2xsW3=mqupz@DD+tPNY!Ie7b(Pr)Jd4`lKMo&TJM$RO zf3=nOA(+|)1l`qwAtMFt6j386ffg3ghuP+{O8C8AgI}gFg>R;hLv!>8gEowQ{{VU_ z&)N(90LG&F3iNAh@jbtcqX_eoJXuqBJpJxoqxvleSklbjD>GzlVnXWDzcU81MG_*6 z4z;V<9F?UXW6ta#^N;TGD-_QaZWaVy?`F55GL}CJ?&Uu9u2|)OByoH9CTdt6Qc=&H zC_ePn-%1`B=r3OE1Ls&L+yzx)=*gWf&iklFJ$)%E#v7B7lR|Oe1`@KnC3eDZiAX#i zZV)JH_qwQi;IMFp-!}-yV0s6~9!h8$(1JEfKlcMpC*Mv!BB^-!!#>*@$LGnfs|@?T z)uBuhH-!8w>qAdXEAvKQ+B>ASR0h|k(W$N)W{J??_^?nYoj|()Ou*$nxKOgouUTcF zHW^ju6ib&?Q(++kS5}c_vsd9u(!>u6V2As9lnOgomcVz&8(o-v^A+>cTZ%*0`M;jg zi#k|sLQ_6vm}&5~#Zz+RG~qB1g#igX@mOryM>@NHS!uJT}naf`o6cRSC-;Q_*sRJ7+^>sW>K;PB|cpTIpgF{%hl_f|h6hy{_4$KfD!0Fu`yS#$w z4=|OuyH`akQ&<@_0}@dm$vd#~4fJ&^6I%ArdDWP@lObnQex1j*xNz8ygK+p{GO`F%^LOVU@A-z~ zDIrC|;;G}VNDhVVna0TzUsmnHbLAIA#9DXLDK`_AhV4&`46CXNj5u1B#-LxO+1`X6 zV);2!2N%DN!D{-|o|~lyD2wwTYf+FJAG)IX9_RymGvhXzAyc-T(isMsNh>N#OGON2 zjTOTkf6S%aC~$Hcgy28=>542!ABQ)MoI#_qEuCe^-ZIQ1SKLn+VV(a0YBIJ83pTOW zY8-4Wp74i#FG+8l%oyt}d-V>p{zR6ja@Q5fwsd$?>E5BIS=#FkXZu%+txP-?KopE;8pP8L5ZoT&5*;d-Txxe%1? zM2a+`_|Y(LYy}i&pOP1${t^4UueXse6AmR<`RP86LfLA01LNl^Bb+t75~3&Wm5`W$ zEE#!dR79)jjEaNhuAgD^&F;oc7SQ1#cgqp=ep=s8->6tSvtgPYkX84UAy7wGVck3j z_iIu`LkBhgM(1M`%fQVS398Gwh+~yss-rD8u!e_0|3s&Xi9rxyYqpgl<2kNcZZ|7O zAAIGhZO$ENGEz{H5j4r($CXdS*1+vph<{C1)uUr>GQmQhEc&feI zgI~+&_MD0(cSb=OrKFjQe42f%R9V1ZOdPIqX8y zkOjzh1Z-f$=(k&F8yYpLA3cr@4&5e3(0WF$TYXC@G2{k!+?o3?Z4B2El)0mz8*=)| z<)PTL4$VrycnF-@My`=z^QYmO;nFnRXbM_Q2=gq_9wDmfcIWK&qXLql6A^hw?C>4Q&0xpO-o8=`I>kn~bt*j4{VqBK=2W*QbDXrv7uGD{U% zxI3?&3VOEDd+qGv7@RDMr)8o^(s+$)sd5dBV}loetdlwTPB#i|rdn)>;v@~33{4k` zLn2p8XwHW?v-cB$S7fhl5CAXt z*DnX<)v7_XjG47byL_hOm0nsig-3>42-iFB{njc4?j_t%y~f9-0d~*%YDyuvppjG^ zURqjO^FzW~nnb#5Gb+mvP| z^Aq*)*dB+}4k4}Ye5Hj*zv0u8(v_$$pOtZ_UO2uZ5l3YvSPk+Qs(NWT0NwP{Kjd;1 z7SISC{=B{5WGs5?K59}i4Xp%K;;!qO5RLUuRwFwN)7rs6>KoZS>PXo$69b6riYie1 znfitK#LY)y@wWdKhx_MF%S~a2nZ|XPu=YN^4E$hC(&I`vr}?b+3N$e2$hepmPfCg1p47W3%z z3$5V_Cz+?>xw3f_4g+PUfFf?tmmM60-l`4l3o+d;Azc8=vFY!}e8zQF&rUMe96M^O zj#5e$Tv#NHV{MyvI!44l2Fx0yqA5wiIHy;}mbe@hHRGm67*Jmx#ET^AU}=<37#H#q zI(1Xv<;AqCa6@3S+!gmne^-CME0dIgR?&(g-cfQKB)&t?_vn*U-XY1Xd;fhUbHRzMy&L z5tTPLLR8NR43MZ#Be4?L&-p`g7~9gf~#q{<;l zS8&lqWkkR0E5)`DIp6&3Ppt5^mq^SRe9%TY z4_RZra9Z5)o~l7#^^!X(VSrqPtpCz9LJ)Ca3;s|l?tg;+yY^B0U2JpPu`RxAa&0dM zy?0wszl*~xF-9kd%e@3EKflnpTzeTAI&6GIv3sHm%LSbYd%BxROQSI7t!)D|o!qkM zq~cua7W)9Au;A^`U(sZxC^Ya$ok?zqUi^#`-S@kW4a4Hmy573VBi^YngM$xNsd7f! zf-Aw0jdz#jT3y5+6?W&+Mydwr1U7)OPSh-RX2{nqFA6{OAv(~Db8(eT%_&?O3)zV2 z8Pa+~O=^eVutuzq@dYQ;!T^Itg0pnZ+EGa_QUKjxtC-2Qla9G#DM$x_RB30- z&=d)6Wd;V7FqDNJh~ve~e@|KI0oHZ-&E{hM#+_P$9^eP;pL)MtiC!CZ}; zz*|0XjOXm2Bey(4IKTK;03#*)Y>=2TW&TaVp5kJ4VtHPC1*IV?7UT@Bt-YDgJ`s(h zFjhO=VsLRX^m1#2t|+(lyK(suXbGA0PP~Skdr8J?u)~aZ&DGr1if1saDsBd?F&Elv zqBvbTyO`c{^q7noh-_}x!r7AxPU5H4MSp))?`1xw;D@Y>tS{fV$H!l<2gG}QTZ+31 zp9OeYAj}I`wUx(I4_(E*n5LY6sftAaU9r}P0b_Q%C8$CmJ{s5!SB|=IGgczf8O>SE z+5OY#Tm9c>RqekDwiKPo^ypIcLunSQ!hm-T?<8JXYMIPt%N0b6Kxz7rxwU4@HKqJ( z>ZAUjM}Jo;d~ltfqeFvMO*9hdjkp*5H4q8QO2c_Yh8?ghPUL3E0C8N$u@Ym=C#HHZ>Eh9uK6 zigplw@PnSLgLeN8T5Cvc?OD{F_NoW%26aA=n?AV5!`C~H7g1`~VT-O;Kr@eB-6Yb{ zL@ISVg+cQ14FmT)%-z)UWnq>(8}Do+o8ZMM7Ul&Btme(8^%#{1N|ISwQw0G0ej<2~ zddXz>syieOP9}z;&`Ih%Ty=(8hBRBeTt@C-Pu~qdBw(MtHKo~9li@cjdcQ5R#nXpE z?nXos(~^(J)&yybEN$>;mTX5K|DOd&7{?Hso50~%yzN=$!Q8Ns)4OjSyd_kE^{JQl zaIYw``Cr3*5-gdodq%=ZigeyY7*LeQuqJrQ1 zi2($WG$fI*5!180P46Y)6Au5<|J%J!a6HO4iZmbjK}A65{`^C&N5(GuGn=UTyQvcS z=@QF6?;Q7Z>58cl1pIz2K#Q)fEe*V{A8?^G!~0#v>Fupnx zX~rZD?wst^jk`;ygrGb{wy`+Voh?9qm!C&4Nxs&AZ+AS>_VuH%+fvJ1$kE|BnW}zP zYP_xw0a%E?(juS0XRI@QMu$N0^;`Q~lkF@xdN{#MG}a*DKT<@2DbaMw;K!5XY7oou zV(P1PqBg!y<-EeH%v&S$#CM~69%!=9wu;#xfFr);?$*30iZI7ZcE-6M#|?Yxge#S5 zB0wc{Ge+}F5r3Oihk*fddy@9XO)ZN|gs{H)7ZL;PY_9F>v1iQWAAFe2gn{c|Mx!6U ztYIVeHkKZC_X`uN`ttmpKC8Ka!3u(t_Fm4BbCJEquYtTvbbpRjvw}t^RP3r6jelYU zWfq#`t)>Dg(9-XKIQUqNGzLx1luKH-oc#JRn*{%=*jCIt<9a6HWIc2{#&)B$-Z@E! z{F6ibPryH*0p`iv5-omUE$yihdL{E6`GtmyCHBU~$0xMeKhji>JO_@D6P!fwm{nBM zhtx)kiBZmUw)j@1R`(?Tb2Ksfq_*D&b5zuRx$P)T&5)WY_WZUawNV$akkA&;b(`|R3{WzjY9-_nb+{}JdM-YDu;aCI^Su=HPr0F55%OC5Y_B1~JVLp&WN?5{QI$guIFg95%zJH;2skmnQo+{5ChP|=1?=P!*NboMjG3%||K>U!Ww9Zp5 znwh*`Q8{PCM;hYpGWsUUt@H!uhWSf$B8_==euEwa_%u-1OjGe#`~ zEx5$rwlbMzaJ&vKlWB3P_RX{AH#=K3eKh(PI`)yY1ZxX9^UDUZ zJb{RE8t-w5PH$}^1x49M2_(UJbciHX9}*Xd&9Q-GqZ3Y}^lb9AX9^ zA!U4DB-W{afY>}9xWIYUL~c8(plG9}eXHqUx+@9>j=|?(OtGXD<@rr|^`dSWX-B;7 z{j%Kg8@M}D+}!HcKIf_i^~?;>4(TDImfA{B#LW&74|w_Zsn#PriEOkMgfztiO4T|# zYlx|bAcYZN-Ab0h;|+ehA+3He?HyzM$I80E{s5Vm8PHj!Jai}MjX6DL^$o#O_i^!W z<=&_?JK3kMGhKAVn?rCr8l_q}VIwrPSBCC8L@T#AZAtL==ARb4mt!~IpWyX29+Gt$ z6C(P0TD5t|cg}b6%yDP+>;NvW$*;eU+~uIS6Rz%yc)IC~A;}PO0zviGT${i`OJ$E(q{y9)er7c*RDE@2nfSEqIY1Plkn0 zYA?pi7HQ1Hzc%rr-Hq9aesW34_~0%1wWvr|DXWJx3HX`&Ey#ki%^b_t*_!dn^i!d* zzjn1`Rlb)`U2;g`JRT5EXLeN0($S7;aZ+}DaLaId213G(^=Xc1!{16u@z%cb)7$iP zpDF>Ysv8iUJ)0?p9EYsy4pBBEL@A=CXC8-m?3flct6WMLWuYjpl!{t;$1DP2-FPL{ zK%3dj1E_~*)U2^8d{ZxJad8$qmla7`mYcQd%{pG!xByzHa*~7Kf^<#wW7XQz@qElr z1_+9D<-$Rg8?}U;-RjtDk%#6bfAgrnL$x6Kv|3F?cNbHTX>uao*BDtXwHVrsqozl& zf~9^{dc%Lkx2tRANC-FNROQ}l>%o7%_+QS@tD!C=U_NlJtJE^b3AZ7G(Dbg}&$5Hb zGzv+`7beFvr1<5c1O-pu$vLMSwt^EDGfldvEh|5DUz|#z6m_OaOEQb|+uqoOECWN_ zS^5Lc@THd5-vrrKMB7+j=zR^6W41=JXj6NtiAbY*PLFA9`l9B@KG98)xKusuWL>R9H_}FdQ&nxWfN3T7x{NJ1 z!R{CcJ=}|Gag(uJcFcKkRaBgCz5{AIu&R^xJCz{<+rH`sx#DJ==_*mzwrh{8jMQJ! z%d&p1e0Cq2*{FL1o68w09rR^+w&9@y3+sK|?Qh~hiDSX(VxDu9vT8xT&heZg)nYV0 zoN7F_aJ6fA@>2am{EZUD7pQimCI%zlg8#`x7Ywdw2p2*_?n<9;4gI0lnyD^|Qib#T&-7pX`D_ zqP-|#YM{gAfVU_(p}iA4&#RU0ZY3?-&ewA0w7hLuSd-52A{zq_bx!z-q{!sdUl%UZ zqhQljU|_xE!iq^AA+jT#1w4n9f!+lr@*3m~{Q`RdVsnF0XFm;wA>WSjqgG!5i`Xqx|< zL}P4c^gl^7H`-R#$|5Mgw>x5PQX!xX%F691^Q6fo`0tX#NR||$kpYzVQf)V_J2$tx zCS6)I44N@_{}c;FCB%h`B1Xk3<0B&kB>MSA`3wJjlaPMS;rS1X7gnE5Pw&{;bv+08 z$9*)K&24*RGsQWX-E}ZEjm6G#e~gMb`2|B)9SnSUBm5S!2bFJjKmbN5Z-036&M82L zKVtq-em}kvR9C`#1}HW0(nV7Tfc3HhNQ+r@v-moXETGy#0|xF&22;F&YmuzP&N2dh zd`CMB!Q~?FQNf_NJG7(Z=@1tvjEvFsQ-!}#-X8nyf`o?ODX%G=v=E2!LS#L97Jk#h z*GCL?dGq(jKdePx<{h|leQy7&^NrsEBkxoT0aO?;2NQ4tKD(L{<5K7n0?sn+2VWLoEY=eq~G)n)m|&Po{xFBUN{)JInc{&m-_vx&Zsfcct9GZ&xNW%JH6NW+bR=vnnzL-+%Ca9b zd!kREd+=;nWl;qMhnPW(v8mo3FN8@r=a4IgHqwf?heFcCS`eo1^bHX&RZ-yA0;GnR zK(a$@_0ea1=Q7PiU(zXkSNe?My>u4o`lLFo;* zSH>@r1>QTvaSnbzEX2D9gYwef^Y*_3Af$Zhi&<<-hy}mIHU<{iDSc`Q#iKQ zPS?ZqO{)v*Wc`sJGy)9@i+;G?U2wEqeN1_m#etG}(V3Yvntwxg&-Z!^So9dG+a%JSvFuX15!roqw5rn-!M;x9pi%Ce@p7{TwwZP$VgpItO2CM@_OmvGH_LqD)KIymLvx|5FYb_PN<~k4d5< zPfs@!WqN#0wnl2_JvxBY9Tt0U*PFQX#dsqZ-C{vfaQvNiVFW(2eE2=v8==pdG(w*R zRInG%+fvzhj%}5w+tr#JcVx3s(sY=MYA2{puSRc_Id=$sneX`oFONsh+~Q`=NLT8G z(~5;IJ`zcX-A(dVqQiRRU5Lz*UaVH+$(tb z?r=|BA*NhO(Zqu{u4ooz+Ct38H?5hD5yH)L6k|8-pc&+09&eMO>RO|>4P1?@Xk0>^ zSA#CsMoMMeO|cme@IH$kq>jS~2SGk=_qM=smB3H=htQ~N^Z#qL$N$;k{(ZjZ-n$f} z{fE`)d)*GZ{+mAN4+TvH%00ZXAV0z5zljnFUI>r`|t7|O9cMJ z|2~+-H_jOr`^_0ZbD(^+!|4^iXFfU>086f^d+Um)W?g>;M#fhUaj*2IsFp&LutpG32K2+m?V_rA?jE4zn78@o|L#Cg z``5<~Hq_@1O`f)ot8bs?1pHoTQ=4D+ z&t0Q^j8sV9e+CT>k#U#xV+sBrrcU;MXV_5xuVI@z+gSfk$4*HYunnSz3BBVE8R>wi zS(Js=F0Ei=w%7q~9}cOOm_`CNk?X@RZc&uuBAtEvX)W?}Xq{zTLB8Y!1~?H%@JuMk zzgv)Aq4FZ28*#vZ*u0TH5mcj4dk5Xb6(X)MJz|+_aNp#+dzv8;rCu4!#jn_e&IX#p zo%If>TYyD$F9b-OMDs(N->z^JvdwXKRz6{uoFnKvVPnRCht--A`n~@aoSGIGb7s-Fs~VnI2+6ecEr`+B{6^1_nM@XvPH?{V%Sq0c~{w1 z`u;7h_NOjy(K!PI+lHx^#N=7%cA0Bo7=OxS+?5rw$h=25^2Z}zywT1 zIPyDiO-P8%#DLro)WAZBhsRJ5p#Gk*9%g!@=IMu}~*##BA zk#_q#!0PLiJVB!Tm@RRZH#z_MB2iTOagR*aQ?XG#9FrX88KEiFwwEfZ_q zp)KqHpfNHmthck1K@AZOS5vtAxm92ai-TKe}< zW85K&gP|NXlgj@_x6Ox)%w?| z{`&W3__s7DJv}%wGVio*dE)4{_4G2d@=~g{(bYA!BpnwouHHbtI{%L% zSh?HSiX4Pf(`XMjo*w}d33*6@nrk4SABY?Vdh#?51*cg9cerzo3D^feGl!TbbOV=zy{7z_ciaP*Dt< zTgT~vSG$^Y9N41@wYt-)etX&BLBtXmVd5BK)V{oH_mgMgX)IaNSeWB|cb7D_NM_C^ z!C#t~z`~Y!GsiRLj{@grmtQ!)ufSqnA0+8nKD14VY)WYVe8i|a_Pyox{gh$7 zCGhv2wED`;iYupOZKdf)J$ru7_17j(j?I!O5UAz8Qc5wd-ux$A# zKmvGHkNR-M;h?R=7rrt*O3Mz@p-ZXN2{De45Rqn{&YvvQo%=Ev2qU#vAp4nHk;&YR z|8g8%G2#w*2`f~CU~>`P8*xH{e)svi1V^=9Nl42y-^%>4p^$p5$@J_n#_GS*VkCecQ^O3VVlMJI}>SOcN;pt zpwyrXP!lrRES2#!i466NP+mtA5=Sn)2_Ddr*S7c4jenF`V4F2j%H&^LO}L;yrc!%3 zEvM8%{a@KoMIF^JnPzOb5F+Ce1U(nZ=j~w$1~q9IKLQ){7U^Kkcqax3K2mWyYVI+} zMsf`s5&hE8Z!;Go*CNZAKsnADvMN;r$JuW54o)M{^_rNTv1_ibqX#{jk*>2coW?Gk z?>GMqWY&^h4VLW#_$jorS@WlH4M9b2!WIgWES~zoSVzG4DX;^H0E?Z|C4*Zdmb~O$ zZ(Jc>MMIdM+SB0v%sI3JQ+Yjl81zS)QDefA$!Z9BExMb-u^2nwwtyIrGYAVonxr#L zxSiZF`u2#i-l$#RowoWZ%;yn!QV{TX=qp%9D6&x)kfFtR&5L6@DlZ{_d}@%oR`0|G z-IUuVTR+w$nde75gFi4fz9>D4OV}v*;&W0zog)hPUn}j;G&8f&0_!%Jh*@yn#*Sl@ znE&0?HJJ|;8Te?|7Rl)_Eo~Bah!O9lQE$KS5dKp16vY76H`YLSA;ZElQ55aB2-`xI zzC2xU5+fDalNTqP-Ri6K9D>`|7rAS**mP|^T@t4(n&S~YMX^)C_!LZfiYu}1?+h$E z7a~2}G7!am0o5T@vOUe@N$ea}ldJMATfx{s94&DWJ9xZgfcP;VDV-zUJYIGI>BK^M z*}u_E47Td-i$W#EF~>0w1uK-+@0^C6j;$ZQXjtjqvRh}0CDJlEM!zxZjsaAxQhV-2 z4C`mz!;O7U4BcAXYP@os>QPPvU%EbHobBjNR%~Ycu_7E;g#9^1K&CKCiOAM(Yo&=QhOEfL?+-x4&V;XoYpA_as-Y zkH_!9KLKRp=Vsq1_VIiU1)TBOH8%^i%-e>y*&j7~*dQW{O(5Tx5>(Y5iXtqBle%-{ zKVOy`hM4chTVVr{VKT;xh%Zy{kJA|Ye{Ab@r+dw>y6)X|zgkJ?55v>+lh-ABD~ zkNG}`38502n#kuBP9gQO`>tc6jxQE+DUrBwK@6>7>|m&b6#)QA0^+|0T%b;vR97IA z9~|)totq%IOhDDzi&1E&NdNu#^;k#7QQBCZAmS*j8oXyYcD}o!mo!Orf5G1zLD|im z8oEDr5!%Dh!_JS@wGQ{i=X|)Mx)19+Mu3HSbwr-C9PyvE{PB%t)K2PRMqr;AeB%Yw zrgt>=m><+9e_cj0dOHp5L=k*vG4!Sam@U;PJpqC4-oPN(PItdrEwVQBX%k?_lL z3zGeJL?>eCF`gpiMFq5PiEe*wJ8+E4?M0;T2aiuAGx(==yjuMf_E_}xzSp$Fw9Rba zzj`9yrE&GR%a{qK9v&ky!lLlifKns(^aU}27D|Mzm@nRL zQ72EMf#>U#YeqIs0-q}>FIi9HRbr-fVjPQrkO&udM`vqG1GLG;`ts_;bQFk9ug|na zr>Fw!`Cdr4DvH3Q|E5%BVCqHEQz@HrJHtgC;<3tuq36O&d=vB%pO)j11Eu^%5n-zG zwzEvgeWa{>&Z)7RWmln=w5$j;R_4`mbh?Ep2G^zH`x}B%I9+bV4M4Xx1*&w?{%Vd_ zuxIkB@RsXR!RWo%U&2=)Ll_OzlfDfbrIQt;*MK*j336Je zW8jH8pvu-6T?~}QFNGOSqKZ-mC7|Mp^WY4wB_n8xEKB> z%CLt;=TV%oj2t);Du+<4g`SFr6kopFBQ}DFD0YqhYC*>RHK3dQ2Pa!g|0r34aAP7QR=**VMsdq*+VI-6Np2qv<+nMCor;flxpifZ()N!V@Ku8h+HTLdcq+i}MmVFfNi5|eB? zhT?}yf!)(hag2<@jcj%i(Amud32Vf%LRuU(=0Fr&cjAHeKd;B^^(8zY`g19(APSVE zuxd`ggT<$*K_-IDCMQcrEJTaNhiNcL^)mcK)8^h2z-JTHax{YE*haCSWNCLAMXaXw zSA^3tb>Vvg?QJY7=+2z3fG_olLthB7U<=VfE-}iMW<2_vMAB>Dw|wy3as2t z8BHT9-`)SwI-?>e$7RQ3q@-eIc~5_mv%s1ielmu4N9z*@If2Hk2fEy@hfb!HPVho< z*QCIxP#SLgp(b5%jSGt8KMz|_1alx*VYE&%9_AlHGS+Qjw`w=?26Vj2a3?rg>ZL3>eE(TKEjF4Ov-hkl8>K~lD(fF>Kx1Y#cWkw23ehUfnBVylhshbkxe!jqPYU>=T0Lqh&6nol>?>HSXX@qV3_lT?4&}ziQU}vxQbD!gP=xwmrv5dtrV3h(Pkq@?GTH&%18{njvQAm(-)xB`2w+lWk*u1S)(2Xj@ zMj3M8I#&uu-p3}y|BF)ZNDKhez!dJAa&*R+SAFw39)7VAjyJ5jVrKzBPT~rq1tR_A zG7Yz7A^6#Obj)w?@j#|}O-ca-8@O7KvEpkMFu+q}1I|v50Lp`ZD@@uz}%4Jv#vC`L!+y0g?BH|4q8NbMvl-4 zWE6w<6tD(_s6R2F!9T{?Q_m~r6?|^>+w#j%tb;~b=>i}l0Rjn%i}Y=Q)^MK6{bzC_ zr0*F6sM}deOqUd0Vw2`e1Pk>lTQvrqiA^M4RhrL3u&@{@&?{N$k5j4kTWk8v&heg z?j9fMyl3)*`|^e&3s-prg<_!(6H~xWWTj7xgDX*-nYE*eZx@-Fw%WheJI@PY^kZ}M z1j3%8Ct~|dejw$C)155u!T43U=dDh>J8`kFKACCI(E3?gOO`^eNNom=(=qLb=R>94 z?0N*mCKt&wOdB{JOP83G-2_y|ot*0mmwQ{TCl|}-`D!=FCRclJLpqg)8y}}Ypw39^ zS?OyCs@#E-(Zl~`{ps!z1*J{4r@U8>q|=U_MKqq&6BNPSgSLW>(RsWNoNwgb{Nl0C zO7^k+?fuJWJS$)FF%}B};lxHBOd2wNOT%GWxG&pOKj;5O|5 z0vD4K?m1M?ETI-@F}w3MvL$Bx|7h$TgGA}JMa#17+Eum7wr$(CZQHhO+ji};ZQC|` zpYz`B`<>T)qdPKI#>zh3FM(#a3HHl5J0~BFQsZ*I zf?lVVeM2a?Lsa`8w9-rscr-rRFCPlRC($>ko}Ws|@gSPqe!mn$Cy{sSSroc-XboG7 zM(xiV4%c9bjP8rfzM{KZtZ|2XNng?qqlvlkhHR>`%>3l6vWkQ5&6Bj&1~~ELS~Yr* zJ}brETEb0XJtuQuWO&R;BroH^6mg#Dm%95CWA@qfrdi*!9J}U5LL9=hC8;8$sAvr6 z*}c8}z#OqHkL4D-jAWU_JtC5xpjJ>AoVQ*>CXeP%Qu{5Fc-?~asiM>*loIzL?NnJ z$?n01*~MRexFF|_?hl1qH;^|y$fUp`67Bmx~@ZGp`XeX_ORWf zH z=&7IL)K$iPlTE3T?ll@eJ7saX{`UNQ-VAsrbBS}K?iJ%ZY&}#hg9e;x0}E2MaDU&G z7RWk}=rWB*X_igUAtgt-?Q`4|ue?Q<6Jzr+|2`&1I^SI$A9TF?*kE;hJ9$-rl4|$< zQ)B4$5#3q9X*`%cUnPS*p7|vpIKQX}lQNPH6{xl)-xQ;L#+WQdE78X;sU?T4Yg#_b z@jVMEjt#bbKw@0Jqb^!(|^Fs<*Y~%Q)ts42! z$DJ-R;Iv4eb1vt+-8erAc#?ex9r0RQk1kQ1?0&b+2o-_qD;ff7l3E&qe#NsnC#yL3 z7y1|pJ#i~pV;|X&6uxYJMzX2VB5`F1x9W;RmLVoK1RNZDC;pAHdwfSJRKJYTU|CaM zTJe&!1x<5RBL5-r=*E6 z5|dL?Qbi&IpvkGQM_G-Q5&!h@sTU^5OH78Yp=)rOL2TuSxiFz07Ze&w695LN!j#PX ziC?m;vxY`?Lw3|upQ3c;R}2$DNn&3fDIDnRGwrXAL}4jVH!G}5BeO=^qoH>OOoi(| zCsvD0u4+^_{6Rp4zkG1hy>Z53u8k1AvvD^-#dq)6$=%FDAH^F(X0|*Nc-^a_B6>Kwwci61OMR z1+*gpYdGVwRQS%zkS|&C32L}jix0Q%jYm411y3N@>U&okJ(CC%t+OvKcGHRk59T#T=`3Mv9-z0l71VkaYZ^P;#FM z*v-4kxtEYf3R`0cudyf{w>d1BrOs23m2y#34X8Es5-(2viGM+Mp+YvLd{u##c1?p! z=2^Z@$KB?7NpDjvY^as-U5T3@5?PA2&_74at?O^A)>+}(=)K;4)%-}+d9oVD2Amk` zb~m3@XW~coCU`sT6ujk&@>Z!NJsMXH)(I)yKQ?NAxPU*rbKvZ9draZ&cVqr&GGg44 zxVf|YadpF=lb8A+x&SFZ%ty^Kw*iPKpC`xsX?`+CjIyvN(N;*dI*Ih9K-~zuQR5vu zK&ie6g1J}6dLT4XhVui0TL#Cu{)s^?+(3n_Le8h4AtLgdW)&5!DpR%^Tc4T^Lx7hu z9Y9QBKI7|BfK!x4<+c;F&59qID+2*iid9(8PcXnD&?f{Ts1!CM{cp)Wh*qFCEYJ$i zPs%Ffd{1NES2xpPe9HBjxJR%hXA6JBWur_62ks!j8LO{?7Bk@@e5F1!?m~VYyxh>V zTfmlnh5}wi^_5O*M(H99O#0Yq6z6R-&();?Stt8C3F}Jy&Xp0T?V~E6qjnFz5mgLz zf3=Q!moIm#t|1kDmpxXban!(Q!$eBuj+SI+^4YEwdeJw<3kvmxf-VaKO_Fqv++&^A z&|bV^M$y$KTWi>zaFqs??=5O3ROU*8ZqRNrVPHeLDCTY^Lh1%*w8=Pupanx8s4-)p z-K7|&G`VDp*jQnI7T?z^QVIq;Uu|)oOtvkCJ=Qw$LUe33JG&PMe~} z#~!O&7Lz4cJDywfcPiA?GxQhUjM*KWcl4EI_w-BP=)jA3qdTuVKPr#dCPDu!p&;+TN* zP@?@+25F6G2$oHzmHP(N%}~KRZl=o%^o8q1;=^&|GgftGi*=;!W=YcvLTj5WNvhc= zSkV)gsee-GAmykl!A1jRZ%9@NooWnApIjaFSm)cAeWPrp_yy!K)#uc^>SOB_Ym4L$ zvSI0>0Oh5q9k|I;YK6nSheDl#0Y^wuJ>Hs@&7H-*hK)V1ds%?XJp%hsa#K`O6ZYqX zL01ooj{R1`Rlt=2H=RhnxczKv!%wz%(v|>{)6jf&2yE=WF{aEm>XORPDqBjj`!@u> zmXDIpAhzZJoAiE9h#wpr4O$mio;qOwsRA3s1v`@s28R|~m{P7`5GQJRjBQ(r&#izh z)*Du?2E5KTKhp7*E{~=JY(X;7iDA`)R(!q97uk^P7k3kzZrGmS{PFj5lnp4sjt=Xi zEat>(R_kAoFvy~zDnR)Tap-QrkiY0*-BW;ZX|iM&`uEpuKdz7(nW&huAt;`|d9A1^ z7F=b_5gOK=!Tv;}wrGwW!0i1Q4}tBdAmpU%DH+N|tQjT*Dte&q8m*>p;V8II5Hhn! z&u?qA+*EYiiyqSdvY3;S{p$&OMd{K#yr?D#4yc1GL1w@%b467zS13y<1)GVEIcIzt zzg0@Nq+s7{XlSYR8X9)Cb^8;aUMadE^0&8iS|KyQ##?J&#Tuk^reNkF88}!3(>B0X zMKS#si)!i}fueuZ^Fk}AurdR8;6Ytk68d>P3C0Ho)S{W8?A4_62I$4{K%|+|c36M8 zaC&*A3+)MvcE$6zRZm~|Nz-8@VPc|>#!l5s_)Up)`Zr~<1M@|K6tOG}7{Lq0Bhn{1 z$P9X{Jh-MUUCRucou__ESEOA(36Y|n;U2QIriZVv=6j8ykmr-CwVC;7-EcuvFCK-( zTjh<#{!oP0i(Y-^m65qw@x|0QZ6enj4k4U&pf0*)r|}x9NnLM&&;1RtK59vPbfHfI z+{ulhx6IGI2Zk3ibsYjV^3wGtS?&$a2Q-E0AU*wSB+OpA7EvFXS|G3oBgh}~l8I3bk7^i?jyE>4znBEgo=KJ9R5nBskxEbEk zGL&x+o}-u2+ZxZVLcH|8mWb?X9-&N02!Ju#(K{JEax*EKRiYO`6i+_Dxb7 zEiBwqSrhEm0Kgj7?|$c0GX~eT4M0^SFxUVpCLdqAw0aJ`q^&hJacqk{w>^x#mO2|f zOh6ZKpw2p0l1T;-GQE5S*I4W5QkICiq`R^M31IIyq767xK8hFnc;d73(jvmrU{AE#Iy75?;XnTA zhi8wQAve1b ze1|dJ)r_?Qz+mLukN?&Jddi8|E5iIEisjp2hb zFJdL|W@CseXd#}6<-+!3?ugZ0Etxu9Df`!SkxB(HsIPI?6IG`%C@Jrl$S{b`YPgO6 zE{-g&vw48bFY6!6v{NL(Fp@7d*pHXeGu3T8y;;KUzQ+HC&?%smT=OL5g3*tELIVOn zQ-%A%!zGJDY_r89kehTl<=Wa${1;iZb>Q_2@5fsoyYxTR= znz%B(SMi*3t^2$|$w{+^dT!>Giz!g*#3SbYE&8h@HMhB zduSDd^y%&jFd}^|oG7aEGF=02o!07yyvnMHhLeD5?9iwHom5i3=93kU#ngJv@%Ou< zO&&vMUH7Xh)7c#gfhqQPnu=RUjK5y#S7_vkfzQXnHOAhV#=78b$jK72_jXJD!tYv+ zcd~|yAjL28PO3V$a7%ec%{jJ>s2uMQV2o@A1Drq9G-T(j!@1l#4Y8Ru&Nju1_Ycxn z4&Ys`_xi;{Qsm1YDBQZrUdtJf;A8YH z90)XJDJ)VgbX;*XEd>Q-g@fxxUY)1P>RAIJ+;r596iV+Mxb@NOO-ikPmovucdZ#M) zWQO|@Iu@K7NlK@kl zsOJ!tYwo~yFj{yfEnkngGsi+}#B>GN;~u$vOpfqq@>5Ult$H)ovzdVKa* zEbX7jo-)M$9uY~=2Uku^p)hcYu=^s=jB}xntSuIYlcoIBvGf8E#ts7kwRv7SQeSR1 zF5gX^+=pCufg-8JWd^~vLb4TG`Gx3E|NTc08`t>@Z{ zQo_go^H%DMUzhZ1B_!v$oDr_0q641lYLTkofy0uis?;ON1c@?N_2OE8OW{%{-^|%V zDsiwHzG47GfL1;%BWe=di&guj<$GNC$PLx&)L;r7#`Rg`ak9Ip3_P|gv_qu0MEy`g zn{?JS%C*g(Q>N*ZaH}~YG>{O91S%H<{*(QXMNyBOA9k!%RG8>xGdGkY)iY_E5s~hD zP$3w*K^niW6p3pXd~5X_JETj-Y}trEp5vCoZw$aKqlcIr13@z+tyPI+t~iSz7WGV#w{%Q;_@0PtjB4K_0SUO&xD;I>xp{_YRS`CZ zOcAM8x;kiAR3>e%i{uT2K2Tkb9VMPHN4BQGu85mTv73~sK)XcYrj?XYjklkJxRS&h zwogNVIKMPGIZ@&=;?5_4BXE50qIl`XBisKov0d0n-L(3rBfPp-WitZ3CpG?|N!2sk zb?e&e1!$+_F1I#NWE@&z3np))kCTyB7 z!e0cMJ{hE&`d}$VZ3TGYf@t_kAa3u^PU+XRAuiQZvDj~7kuLl&_j5qCmeaB`lJ||h-i-M%kcwD>nv1)AU^aMrCh-1*_m76Y=jURTQ1Wn}x5nP@l;27=6$;hN zQYkXQ&4c+TGsRDFS=4_LjwX!thr=0Uf!OH@AY)sFg2Rw%WleR`_-HoQJFOTh0QU*{ z62Fp=8|i-S(m3lp3b*csYY~U&A`0>uXY0R=dOW9cq-Sh>6t!gVWqIM)|1E^YW6RLS zPCoufuAq>%C5c^}&bl?HQ18H*D7l%M8Mrw*R5_F&-M8L%&BPdn2+tlSI!Ao?;`fBZ zAy^6ymv-0ltm&xjqMeRA@an7T4{&^O4es?Qt9ZRndeLu0`v zM;Q$yNyIT!=Nu_JVy+USGOdki5Ley8J@eSNoB~gJFE1L8MgDVH%aQB?7>+~MP47WW z@4NlvoHRLYfae5@p~9q&0#qiqTYTCFz~ZSfuH;jT~9%nyt@ww zVgeh|(*X-3Wi6&I^A$$s(C*u9Yv4!a>z(6{F=EZ3T*V{k<HXnPYRD2-vS!Df7R zykYwQ!`utg#a1z~KUD-2K|@EOcF3`CKiTE>)8O4^-&B&Rz4k&fKC$fS-t>muMNc8@ zhWnvyEQwIdP9UWv4QDL^;ug_6?$GgmABxc`SblzeDVeM9rlg|%hP`YI`vw|TG@maf zs_7gD>zgH-%^QGjrlQ#^1FJP2uEndMiYkn9hD0)+O2562@Myn?4`=E`7z<+-^C`i` z5(RxemdFV!a8_#<{EXGE4x*SZ=@B}J=hbLtB!He0zLIYU{cb>A@)jT)v z<*j}ik7YvO>Xsp}6qOyuHAB4C=glmWLQ=f+lWJyhuY=kVMb}64v8;q$g0c;Qd5V7Y zY0~zLwO+Kez(H*vW?vs?_>7xE&FER^Q{$?hnV3s=Rrj+_)ZYX3gk~`neR6!l^!oU= znY%Up+$ENx3#dh>0EYIHzC_CW&ZP2{U-%UV*1fmrew^$9Y`)VJJY;;yzCY=5(XC1d z@~qK(v?bIi*+HYWf;(gJ*Z}I07<+XDxYk@c3%OnUdZ3DpX}g~Jt;iOLM@w6XH!hS( z9K+0IQj}xjpI;~^7a+xBN55k77>;L=$&VbxKa3tG;z&%*3ahCh0SOtiaU+Xw<_7@U zuN=o?9Ag2J0qDn$2&)b+vsz}*06AlK1yi0I#3V~ZZ<;?Q(fL2bS>NNeEN)M75pe0@o_q z2GS06DLD#>$@$eEZ7>NTK(Vi+R!d(E5E#;0|4dz7+|C$u{yg$6l_4ty$aj(f$)< z72~$h>5bqGq!>=!5gF(^=a>m*wXk>Q*x-;WS7>pgVtI6OMa=YVF$`{9^-^`N)nPT= zEmM*PEZ16e*$70u5_(m?u||2k#v(J7w-9#!s1@+;KQ!b2yn|$ z3e+w%11z?pYdr~eUZqk>gd<%O6>!!{c(RVD0%O!hEzp7m2-n_Tv8f~TXlc!_1 zT!!pJ^!|fP5D`LX1NSy)!K{e5*@;YVUxjeO7i+iba*|vi#r% zEaY;bBS=~vS%Y5*W&3KYa93X+<8h;fbe1$GH3*@0dQ4wtl8l1h zLM|$CJEU+NQmlg9W)2Tw+5D1b;hiXD?~&lWo21AWVT7{~qKPt`Ko)4|c9D7FJPR3y z@F(!&A&00<`qPXeEQHt$(t(m`1@j_z%F*GZ^RHc_1j;f5u{KT0!34r=@+Au`NG zhWZBfYEX88qMz%>b_*6rE`T2|JCg+FP&IV{&+10#CSuj%@YDK@)K2lqr!=8N()`v2 z-Y5M@GAxjKhRc}>yFr9I`gt0Fs%HTp<5@s%+jf~0vvLpDAb-eOq1xnln*gXFyrOx( zhc4?!y`tamev|^4el{_y-$d>I7NeJLq7JEvJ9$#u9GMR)AhGV3_V*0L&A3M4?k+?~ zpfd;DFsja9qc{vG=p_2s&S3A(K7$4wGU@X7JI@a`G=~eb5W_kuU}2Q=lm)ZtEmiPXh(!0*rdtG3|n`L2qb`KCtZCd+xR!Id~6 z%2wJqq-`L}&p*?O>+1+;DHpbYkn|Q%D~vzSBf>T)ZKG}!H5tddn%`O!D%Nfh!RM@k zlTB*pojb2NC`Pj0irB%4gWZ6PnDFnnyu7xx5xmUDj`~C@q!Db&9X!#ts*Og&|60Bug>VV358Q}*Lrz8$RfQBw( zjM)~&dZ3_(JTmcnQ=jsdTGS?+-``^yJA+{jBxQ&y*+{u6`TXoWaZjmNDsd+I0?zm#&x>cc}Ks--507@qsZ z7Tu~APi_t&VXY`)C7yO`z_q@TRy#kpva2;Le%=!8`%~7nLH88TUIpJ?Qm+A6r&c9( z`=K8~o~xWvAx3*!A`YJ#=RT@Y!_~2kH|=dRTjn&(UG3GHrdH;~QgqEbbK-Cc-zQ2& z1w;^0%`j8IT|VVD!EVL7^j0_3E140AIp&S#779Aj@KNI^wt=?2 z-D6yYyu3Bcjgw4$m|Lfcj1@@r+q(23qY2FvG0Dn`(feAr74KkGxr{UpPjEvDg;=cUm? zTH(qbRz(-LS;|hnzR&I10|{ zsBkA5REax^iOlr3&*lA6>CAUeF@IyItfO?Hst?v07>;0DH;Mo6pUro)@8}l^hvH>n z`PNwT&k^GSn#SzfpymI33b+C#KV% zGR4LHr|uJ4s+|GUXqWD%aP#E`_Kn~7EL&1&m3b16Rk&{7gm!JtCm3@kY|O)IS|j}X zwJw6>EPuP^Iuhu#N$F2_d31=OPU2&7oYQRvqy|MxuHB3S(~<~+Lh@!#Gw+^KiJYXV zolw|i1q;GFTfDXnO|SM1fPRl-D9-G<8xAS(&o(z>u01@0Rf^Tp-d{M84*?pinQPeay*AR`J59Hi3H9S{DS+9Q|ACnLgmyemzJtpA) zaqc$JjQu!Qqz%=)d9X{`C_a$xR(_X5_T|)>?ii_pve(JsF!4wFZE4&=At)#rzOV&%_IPxKH{LhuY%)lL;{swYo3-9gWm86C)j zXi_TEMpV%(fF=;&>?O}Wo%|DZVrN;^vp0jBmzWVaa;~4sdwJrbj2MF1mhV*w>-Mpf zOnhywRxNLGTL`6c59acFcohZ&mN*AIB7XZC?PYTr=yLx_crh_R8_tj47Ww78fUKfw zJlC5GnxIYT;+~*jsr%Pu)x=|%(%jgzt&?H<+O)7JI0qmPk9aRqy6|{-JqSYgxvT2r zpN;+p5qh0ZMXQr&uO0*`sGfz>eZc&+rLTPAG4fn`14-Lox?I|IJ@WxkMv+`aDC(C{ zYx-|?ypBu14N>JUzmmq7uk%@i4P$IrA|Km_fY+LvdsQ6Koi#_TZ1*6tZD*P=HGD=iIekzip|U1een*g zd@C$_JuLMkS%){F{OrBFg2IUhR*clfkARdC6e19OOmDh|Pl&L1e`!*Ai1H_F`#_*C zquQfsK#MXt>E8Kz2b-?+T;!<*h!X@}OfwTP2-W0P;}YZ3MOb>>oF#epnzWy18F{X< zY}|@9t}jtO-Hp1v_x8IgWGoeM`6duv+`1Zv=4~Sp&!FPIS$6cdfGUquPt~T65tgP< zYkS7vM+oE5&rAfDrpz)9aQzIt9pj9rf-iT?Y!zz5>zvcXkMjSh-;m6)`nPEUzZ(zc zB8`G5i9fsv3L+lS8j!P=NfBYSL2{fhKRTQO>ZUOmh)PD}R|zszsTzdP;h(jWguSzXUMHz|KlQ=ml~vJn#3E z-neagFd1hKE_~NyuW=qc2Z`OxrMVfBz%vO>(m^b#e)+EN{S1@;%2?p*h#hZ31}(%4 zB6`b9<3*CqhAyQAr&lJAi<;D4RlFhi?TqH;2;_3)^})w+Jwfs`{1E`=uil|2fM4zs z;_OdyX3uOMX_9IYSj!Eb=8!sGniD`j^JEj6<)fk1jO7FC&~7O^Lef`&)?#$ZY%gZ6v3j60}l&o@JoL1R_z z{hO_d;98`ObS7Pkf7Z>pA&`_V924|Xl5)@M| zAx8)Kly6VE70fjJ7am_l7>!gc?rz@|cl)qHj{j?CI8jT_Aalu}E^G`HXq8CEuF#sC ze@PEap@B5JRu}5A7?GA3asdDf!lgCWDtBPH3|c6WxrUGh4RtLJHVe=E+h$R6QoY*F zXMqoDr$G$4RSb#<+)yHhKQR@`!X^>OAt?yyqaOqePPp|hwZtvyxI(*)@t}E!qj}3V zMmM?Z=aZnE_!uP?UUm_YYLrR)0}oi^Mha<8NE|K!UQme@o%>wbJ`ENoOcxzFgGv(g zJv>m*Xf*|W99l38G9}KnL@>$UPMP2_AQS)zLL7&cmwxN>A!KZsC7eF~(HazD=(Xxl zUXjrmxLNHecyHoRjp9;qE`TK&a5dwgJf(mJIiS~rI7rd=J={bU?LGS1j98YRUXBp%X*4%CJ8)Pz|+02M2% z)@ohxD`|!67|7}5%-A$pVyA*${d{!a)RNu;ws$yy+hYW&v;JzSR~fvS1N_PXfCL&@ zQ1_L85@&wTP$fi@KiLzh1 zHn@rybueFglJIDj(qNWaQeEncK0h#4yRf;Uc&b3Ld^@`jnvCTWbg0j^jxypYHwu8T zY3qeRY%|4Qms4)5*>sD3qHa(P-|XFz9Xh4BlKbPqGzam{dO9Cx4y0{!uu-3)T9S=W zf|z1B5nVVyAgn3GIK-?H{;p$@Ka7yRVF07d3<4}2A-lw`i+N`dUZ{@KfevUK7B=LN znH99-cB9(3^m+fawU5-%;J7OsV2%|9*ZH5;AMzFWr>qw|3*_g!RB%m zAm2UDo=nkjpG9>DTkLxopUvTm4KAe>^%gv3s5BCxwr}n9XvNrA9WNq5rtn(fbyQDg zYGG+BVU2+B%*lsZ9$xaeu>FKneQpljfu!_Xtm4G7*@(A5QQmr@d^I zh9G)!0NBr7YJJoA7mmA(N`rt0>7iAuW5^pACo(^Z_r?SXV5ppoyrdj*4U?2)Sy0=} z6pmu#)UR7_mA{Q-Vqq9n?1daup5(4>t`PgY#lL($P8PGBQ-)D_F)+LW`MUNLIdXI* z7r_VaTG=2bqr>bug4hITXEuIeggx^lMSu8(@>Y?d#LUPY1?KGYOmv45y$C@@)Q5=; zOr2c?Bt4_~zb!bv?#`m^M#|4~flqr2(qRxseXhK+ef&hlHaapie%A`Ij`+gH0pnb1 z4^4i%OKP%raIpOd{z#5ut$h)OL;QH23gK*KRZnIeO>vZ=j z*E4)khW}!h$WT{T>-hHk&=nY3nv}^-i#+?gGfJt+h-T38gJ|=^t8kw6!(2Q)KK=ZI z{JkQXR1a?;fasC3d7kSe3>ya}6iS?rms;ej*dTz`L1Zo;%`y>UWtbIF%N6ReOX%?< z?AN|I-7x3G@wE!UTxp$(tu#9U?Fl(z&blj0Z0Rh5Len-q?JuV`_W=A$ea4D#MG86; zvQiU}Wi(JKRBnnkNMdCJmL@Z>@hN&+qx0TmNEOASC>(l^C-d(nm@CWhNW=&Nb8}40 z)}%sRixpp7NErl!Gh9`bxmNEE0&Yu6IxCiw zYO&Hcau5mD44N3O7}GR50W0&=ca)*S6NQ+2Im6kr(5#4hIRu>03D+ zTkjgMUY_qG@m3*K4D=E4St5+TfuXUeg({l@5UW6-`~9MAUzQyc!_Dd*^laR2yltPS zGHth=X2{Zmvuj^m;D6_OGCv(E>F?S&{(P@pe=etn2f{m=6@7kAU6i{X#iCnoz?;@u zoPZC%to+@iqp_0iJ>}B)>+tCRexA6nrSvSl>GFMdcd~Ud-No9`mQy#!o#{QS>x^bg zzK~ZfLbJ9Ca22xn=0^T1Lsr$`k{Dy2V)S3f+j{J7OLk({Sr^AaV_ZJ2L7RAI zSp0+KpF2ONFnW22%p@LHjW_=c*NZ3ak!7`~fzshf5JDZhRFNnS;m+&e^$<1~D|*H} znZmA484e``unnLhSbR=OiA^D}D%G3eR5PnwE2vFF!Iw+qPE1}jxY|V5LN+|i0vZJ^7*{dN31Y7&ZqUaSWe%UPap6H!6oN<}7xKY7D5c06zc~H5h>#~^ z0r}2RVW@0c!I2$L$T0xHsGMz0&aq{Wk}ZvzC7kriS2`$wH$)**D&du4bF?2x2p7x? z#KISU%L+;aos-NL685*>X2`ACtW<|WHf{U-p&APeK8&`6zTV#g1ZNni^yD0;311Pa z0rq~){z5ixA_IDXrvCnk#>5|DLFv#29>I}w9~gL-`fa3Bmlaprd=ZoyP%!~ewR4(U zC%HB#tnmKL<4mkk=uAO#NL?hGs0c-@iBanZ8F2A12nm;2A+A;s_^z%UH&z?|?+8YN zCHPsXRhv-CydDyk<$=+QJcDTPsW94DqG>|z(n42=m>?t9u+>$&Z-3rqv8sZ{wx0~C z9AKzRhD(o}6NYa7aPd93(~tu|aIRpf7JW6$bf144Q1W<|Bm)Hj0H($M|Cv0T+?@VT zlLt-|H{1XnOt34_^({>wHG+ZOA&~jOH=nqqf}lPnUXTZ(nm=TCv?Nh$|CPbS%|}iu zrv8L`mx$3sH@^al+FgkQnX8dJG|l22fOg5joLdu~8pF87+*)4+#R^Di8;R1m3={hZ z94P*@1A{jSr2Rr_>HX|bdcJ_05h~U|)WKxGG7GDD^bRYMs3g6-)@VlKoc9v%=fch( zYAyVO%bmE3{he=2jvxNh0rIBr;8`dhSh_4>x4hKQ#*cq%+hPvAtGfT%OfLQoIZ0rU z|1WKu+y7Gn!yQeJ6hMa{>}k^WC-(~ViVEqJ3-C8y0%~DhB@vmM2P0aF?{?RVbYm2- z4%bkgfqCy1q8i5&zlUV$a~nH?fy4e*-av{<%;KW4Jle1&Yb+HxEda?~!uj*K+jM^C z0oR$P-5hAEyO)p|5C6EET`sDQr{Y%>cExuw?Z1R93=tZPUVp=n{r4>Z0-*v!{ha{- z6b2V_{d@AiPv8JB|8>cC#s9CViLI59u>-BL8U%oA!k%Qn-ytXY-+;3J1AzD+0OtP& zI652r1LgA<6ZwCm{`-Oc(~$S;AE+XKr~fz9|I*}H*qQz-yyCySk>9KTJG}p9{!`)u z`5#R9zaGASnD+i>#6NvDQ2&AGv-vN?|8oEQ&y0Vrr2h=#)%L#_|MuYg&xn5};(sCr t8vhIN?*;fjBmS8P|A`oG`Y*)4^Y@s~g4hR4sy!l^O{};JUtz7^B literal 0 HcmV?d00001 diff --git a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/AbstractTransformerController.java b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/AbstractTransformerController.java index 68dc895f..75da9fd0 100644 --- a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/AbstractTransformerController.java +++ b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/AbstractTransformerController.java @@ -51,8 +51,7 @@ import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.nio.file.Files; import java.nio.file.StandardCopyOption; -import java.util.Collection; -import java.util.Map; +import java.util.*; /** *

Abstract Controller, provides structure and helper methods to sub-class transformer controllers.

@@ -376,6 +375,87 @@ public abstract class AbstractTransformerController } } + public void callTransform(File sourceFile, File targetFile, String... args) throws TransformException + { + args = buildArgs(sourceFile, targetFile, args); + try + { + callTransform(args); + } + catch (IllegalArgumentException e) + { + throw new TransformException(400, getMessage(e)); + } + catch (Exception e) + { + throw new TransformException(500, getMessage(e)); + } + if (!targetFile.exists() || targetFile.length() == 0) + { + throw new TransformException(500, "Transformer failed to create an output file"); + } + } + + private String getMessage(Exception e) + { + return e.getMessage() == null ? e.getClass().getSimpleName(): e.getMessage(); + } + + protected void callTransform(String[] args) + { + // Overridden when the transform is done in the JVM rather than in an external command. + } + + protected String[] buildArgs(File sourceFile, File targetFile, String[] args) + { + ArrayList methodArgs = new ArrayList<>(args.length+2); + StringJoiner sj = new StringJoiner(" "); + for (String arg: args) + { + addArg(methodArgs, sj, arg); + } + + addFileArg(methodArgs, sj, sourceFile); + addFileArg(methodArgs, sj, targetFile); + + LogEntry.setOptions(sj.toString()); + + return methodArgs.toArray(new String[methodArgs.size()]); + } + + private void addArg(ArrayList methodArgs, StringJoiner sj, String arg) + { + if (arg != null) + { + sj.add(arg); + methodArgs.add(arg); + } + } + + private void addFileArg(ArrayList methodArgs, StringJoiner sj, File arg) + { + if (arg != null) + { + String path = arg.getAbsolutePath(); + int i = path.lastIndexOf('.'); + String ext = i == -1 ? "???" : path.substring(i+1); + sj.add(ext); + methodArgs.add(path); + } + } + + protected void executeTransformCommand(String options, File sourceFile, File targetFile, Long timeout) + { + LogEntry.setOptions(options); + + Map properties = new HashMap(5); + properties.put("options", options); + properties.put("source", sourceFile.getAbsolutePath()); + properties.put("target", targetFile.getAbsolutePath()); + + executeTransformCommand(properties, targetFile, timeout); + } + public void executeTransformCommand(Map properties, File targetFile, Long timeout) { timeout = timeout != null && timeout > 0 ? timeout : 0; diff --git a/alfresco-transformer-base/src/main/resources/application.properties b/alfresco-transformer-base/src/main/resources/application.properties index 995b06b0..ca637b84 100644 --- a/alfresco-transformer-base/src/main/resources/application.properties +++ b/alfresco-transformer-base/src/main/resources/application.properties @@ -6,4 +6,5 @@ server.port = 8090 logging.level.org.alfresco.transformer.LibreOfficeController=debug logging.level.org.alfresco.transformer.JodConverterSharedInstance=debug logging.level.org.alfresco.transformer.AlfrescoPdfRendererController=debug -logging.level.org.alfresco.transformer.ImageMagickController=debug \ No newline at end of file +logging.level.org.alfresco.transformer.ImageMagickController=debug +logging.level.org.alfresco.transformer.TikaController=debug \ No newline at end of file diff --git a/alfresco-transformer-base/src/test/java/org/alfresco/transformer/AbstractTransformerControllerTest.java b/alfresco-transformer-base/src/test/java/org/alfresco/transformer/AbstractTransformerControllerTest.java index a2b58814..5c619442 100644 --- a/alfresco-transformer-base/src/test/java/org/alfresco/transformer/AbstractTransformerControllerTest.java +++ b/alfresco-transformer-base/src/test/java/org/alfresco/transformer/AbstractTransformerControllerTest.java @@ -33,12 +33,10 @@ import org.mockito.stubbing.Answer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; +import java.io.*; import java.net.URL; import java.nio.channels.FileChannel; import java.nio.file.Files; @@ -83,7 +81,9 @@ public abstract class AbstractTransformerControllerTest protected AbstractTransformerController controller; // Called by sub class - public void mockTransformCommand(AbstractTransformerController controller, String sourceExtension, String targetExtension, String sourceMimetype) throws IOException + public void mockTransformCommand(AbstractTransformerController controller, String sourceExtension, + String targetExtension, String sourceMimetype, + boolean readTargetFileBytes) throws IOException { this.controller = controller; this.sourceExtension = sourceExtension; @@ -92,8 +92,8 @@ public abstract class AbstractTransformerControllerTest expectedOptions = null; expectedSourceSuffix = null; - expectedSourceFileBytes = Files.readAllBytes(getTestFile("quick."+sourceExtension, true).toPath()); - expectedTargetFileBytes = Files.readAllBytes(getTestFile("quick."+targetExtension, true).toPath()); + expectedSourceFileBytes = readTestFile(sourceExtension); + expectedTargetFileBytes = readTargetFileBytes ? readTestFile(targetExtension) : null; sourceFile = new MockMultipartFile("file", "quick."+sourceExtension, sourceMimetype, expectedSourceFileBytes); controller.setTransformCommand(mockTransformCommand); @@ -159,6 +159,11 @@ public abstract class AbstractTransformerControllerTest when(mockExecutionResult.getStdOut()).thenReturn("STDOUT"); } + protected byte[] readTestFile(String extension) throws IOException + { + return Files.readAllBytes(getTestFile("quick."+extension, true).toPath()); + } + protected File getTestFile(String testFilename, boolean required) throws IOException { ClassLoader classLoader = getClass().getClassLoader(); @@ -170,12 +175,26 @@ public abstract class AbstractTransformerControllerTest return testFileUrl == null ? null : new File(testFileUrl.getFile()); } + protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile, String... params) + { + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.fileUpload("/transform").file(sourceFile); + + if (params.length % 2 != 0) + { + throw new IllegalArgumentException("each param should have a name and value."); + } + for (int i=0; i2.0.8 3.5.37 1.5.12.RELEASE - 7.2 + 7.3 + 8.8 3.0.1.1 1.2.3 ${project.version} @@ -27,6 +28,7 @@ alfresco-transformer-base + alfresco-docker-tika alfresco-docker-alfresco-pdf-renderer alfresco-docker-imagemagick alfresco-docker-libreoffice @@ -68,6 +70,11 @@ alfresco-core ${dependency.alfresco-core.version} + + org.alfresco + alfresco-data-model + ${dependency.alfresco-data-model.version} + org.alfresco alfresco-jodconverter-core diff --git a/scripts/testImages.sh b/scripts/testImages.sh new file mode 100755 index 00000000..4f316f13 --- /dev/null +++ b/scripts/testImages.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# For each transform project, check the live probe in each docker image works. +set -e + +docker images +echo + +transformers=`ls | grep alfresco-docker- | sed 's/alfresco-docker-\(.*\)/\1/'` +for transformer in $transformers +do + echo + echo === $transformer === + repo=`docker images | awk '{print $1}' | grep $transformer | sort -u` + echo docker run --rm -d -p 8090:8090 --name $transformer $repo:$tag + docker run --rm -d -p 8090:8090 --name $transformer $repo:$tag >/dev/null + + WAIT_INTERVAL=1 + COUNTER=0 + TIMEOUT=30 + t0=`date +%s` + echo -n "Waiting for $transformer to start " + until $(curl --output /dev/null --silent --fail http://localhost:8090/live) || [ "$COUNTER" -eq "$TIMEOUT" ]; do + printf '.' + sleep $WAIT_INTERVAL + COUNTER=$(($COUNTER+$WAIT_INTERVAL)) + done + t1=`date +%s` + delta=$(($t1 - $t0)) + + docker stop $transformer > /dev/null + + if (("$COUNTER" < "$TIMEOUT")) ; then + echo " started in $delta seconds" + else + echo " did not start after $delta seconds" + exit 1 + fi +done +echo