From bb187dc00f1012b31097f71b41b53f0ab17ef317 Mon Sep 17 00:00:00 2001 From: CezarLeahu <35226487+CezarLeahu@users.noreply.github.com> Date: Tue, 20 Aug 2019 10:05:39 +0300 Subject: [PATCH] ATS-488 : Remove alfresco-core dependency (#90) - remove *alfresco-core* dependency - remove *alfresco-data-model* dependency - replace _TempFileProvider_ with local implementation - duplicate _RuntimeExec_ and _ExecParameterTokenizer_ from alfresco-core - partially duplicate _MimetypeMap_ from alfresco-data-model --- alfresco-docker-alfresco-pdf-renderer/pom.xml | 15 - .../src/license/THIRD-PARTY.properties | 34 - .../executors/PdfRendererCommandExecutor.java | 1 - .../AlfrescoPdfRendererControllerTest.java | 4 +- alfresco-docker-imagemagick/pom.xml | 15 - .../src/license/THIRD-PARTY.properties | 34 - .../executors/ImageMagickCommandExecutor.java | 1 - .../ImageMagickControllerTest.java | 5 +- alfresco-docker-libreoffice/pom.xml | 15 - .../src/license/THIRD-PARTY.properties | 34 - .../executors/JodConverterSharedInstance.java | 3 +- .../LibreOfficeControllerTest.java | 4 +- alfresco-docker-tika/pom.xml | 20 - .../src/license/THIRD-PARTY.properties | 25 +- .../alfresco/transformer/TikaController.java | 2 +- .../alfresco/transformer/executors/Tika.java | 16 +- .../transformer/TikaControllerTest.java | 26 +- alfresco-docker-transform-misc/pom.xml | 15 - .../src/license/THIRD-PARTY.properties | 36 - .../AppleIWorksContentTransformer.java | 5 +- .../OOXMLThumbnailContentTransformer.java | 3 +- .../transformers/SelectingTransformer.java | 3 +- .../TextToPdfContentTransformer.java | 5 +- .../transformer/MiscControllerTest.java | 3 +- alfresco-transformer-base/pom.xml | 15 - .../AbstractTransformerController.java | 4 +- .../executors/AbstractCommandExecutor.java | 3 +- .../executors/ExecParameterTokenizer.java | 360 +++++++ .../transformer/executors/RuntimeExec.java | 986 ++++++++++++++++++ .../alfresco/transformer/fs/FileManager.java | 41 +- .../probes/ProbeTestTransform.java | 6 +- .../transformer/util/MimetypeMap.java | 165 +++ pom.xml | 22 - 33 files changed, 1597 insertions(+), 329 deletions(-) delete mode 100644 alfresco-docker-alfresco-pdf-renderer/src/license/THIRD-PARTY.properties delete mode 100644 alfresco-docker-imagemagick/src/license/THIRD-PARTY.properties delete mode 100644 alfresco-docker-libreoffice/src/license/THIRD-PARTY.properties delete mode 100644 alfresco-docker-transform-misc/src/license/THIRD-PARTY.properties create mode 100644 alfresco-transformer-base/src/main/java/org/alfresco/transformer/executors/ExecParameterTokenizer.java create mode 100644 alfresco-transformer-base/src/main/java/org/alfresco/transformer/executors/RuntimeExec.java create mode 100644 alfresco-transformer-base/src/main/java/org/alfresco/transformer/util/MimetypeMap.java diff --git a/alfresco-docker-alfresco-pdf-renderer/pom.xml b/alfresco-docker-alfresco-pdf-renderer/pom.xml index 65c02b4b..9d88786f 100644 --- a/alfresco-docker-alfresco-pdf-renderer/pom.xml +++ b/alfresco-docker-alfresco-pdf-renderer/pom.xml @@ -46,24 +46,9 @@ - - org.alfresco - alfresco-core - - - - dom4j - dom4j - - - org.dom4j dom4j - 2.1.1 diff --git a/alfresco-docker-alfresco-pdf-renderer/src/license/THIRD-PARTY.properties b/alfresco-docker-alfresco-pdf-renderer/src/license/THIRD-PARTY.properties deleted file mode 100644 index 9e3a8812..00000000 --- a/alfresco-docker-alfresco-pdf-renderer/src/license/THIRD-PARTY.properties +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by org.codehaus.mojo.license.AddThirdPartyMojo -#------------------------------------------------------------------------------- -# Already used licenses in project : -# - Apache 2 -# - Apache 2.0 -# - Apache License 2.0 -# - Apache License, Version 2.0 -# - Apache License, version 2.0 -# - BSD 3-clause New License -# - CDDL + GPLv2 with classpath exception -# - CDDL 1.1 -# - CDDL+GPL License -# - CDDL/GPLv2+CE -# - Eclipse Distribution License - v 1.0 -# - Eclipse Public License - v 1.0 -# - GNU Lesser General Public License -# - GNU Lesser General Public License v2.1 -# - GPL2 w/ CPE -# - MIT License -# - MIT license -# - Public Domain, per Creative Commons CC0 -# - Sun Binary Code License Agreement -# - The Apache License, Version 2.0 -# - The Apache Software License, Version 2.0 -# - The JSON License -# - The MIT License -#------------------------------------------------------------------------------- -# Please fill the missing licenses for dependencies : -# -# -#Tue Jul 09 13:35:12 EEST 2019 -javax.transaction--jta--1.1=Sun Binary Code License Agreement -commons-httpclient--commons-httpclient--3.1-HTTPCLIENT-1265=Apache License 2.0 -org.codehaus.guessencoding--guessencoding--1.4=Apache License 2.0 diff --git a/alfresco-docker-alfresco-pdf-renderer/src/main/java/org/alfresco/transformer/executors/PdfRendererCommandExecutor.java b/alfresco-docker-alfresco-pdf-renderer/src/main/java/org/alfresco/transformer/executors/PdfRendererCommandExecutor.java index c79900ed..90ad4509 100644 --- a/alfresco-docker-alfresco-pdf-renderer/src/main/java/org/alfresco/transformer/executors/PdfRendererCommandExecutor.java +++ b/alfresco-docker-alfresco-pdf-renderer/src/main/java/org/alfresco/transformer/executors/PdfRendererCommandExecutor.java @@ -29,7 +29,6 @@ package org.alfresco.transformer.executors; import java.util.HashMap; import java.util.Map; -import org.alfresco.util.exec.RuntimeExec; import org.springframework.stereotype.Component; /** 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 3c21840a..cc8b49c6 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 @@ -26,6 +26,7 @@ */ package org.alfresco.transformer; +import static org.alfresco.transformer.executors.RuntimeExec.ExecutionResult; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -58,10 +59,9 @@ import java.util.UUID; import org.alfresco.transform.client.model.TransformReply; import org.alfresco.transform.client.model.TransformRequest; import org.alfresco.transformer.executors.PdfRendererCommandExecutor; +import org.alfresco.transformer.executors.RuntimeExec; import org.alfresco.transformer.model.FileRefEntity; import org.alfresco.transformer.model.FileRefResponse; -import org.alfresco.util.exec.RuntimeExec; -import org.alfresco.util.exec.RuntimeExec.ExecutionResult; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/alfresco-docker-imagemagick/pom.xml b/alfresco-docker-imagemagick/pom.xml index b965292e..7c5bb5a1 100644 --- a/alfresco-docker-imagemagick/pom.xml +++ b/alfresco-docker-imagemagick/pom.xml @@ -46,24 +46,9 @@ - - org.alfresco - alfresco-core - - - - dom4j - dom4j - - - org.dom4j dom4j - 2.1.1 diff --git a/alfresco-docker-imagemagick/src/license/THIRD-PARTY.properties b/alfresco-docker-imagemagick/src/license/THIRD-PARTY.properties deleted file mode 100644 index eeeb7e0b..00000000 --- a/alfresco-docker-imagemagick/src/license/THIRD-PARTY.properties +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by org.codehaus.mojo.license.AddThirdPartyMojo -#------------------------------------------------------------------------------- -# Already used licenses in project : -# - Apache 2 -# - Apache 2.0 -# - Apache License 2.0 -# - Apache License, Version 2.0 -# - Apache License, version 2.0 -# - BSD 3-clause New License -# - CDDL + GPLv2 with classpath exception -# - CDDL 1.1 -# - CDDL+GPL License -# - CDDL/GPLv2+CE -# - Eclipse Distribution License - v 1.0 -# - Eclipse Public License - v 1.0 -# - GNU Lesser General Public License -# - GNU Lesser General Public License v2.1 -# - GPL2 w/ CPE -# - MIT License -# - MIT license -# - Public Domain, per Creative Commons CC0 -# - Sun Binary Code License Agreement -# - The Apache License, Version 2.0 -# - The Apache Software License, Version 2.0 -# - The JSON License -# - The MIT License -#------------------------------------------------------------------------------- -# Please fill the missing licenses for dependencies : -# -# -#Tue Jul 09 13:35:40 EEST 2019 -javax.transaction--jta--1.1=Sun Binary Code License Agreement -commons-httpclient--commons-httpclient--3.1-HTTPCLIENT-1265=Apache License 2.0 -org.codehaus.guessencoding--guessencoding--1.4=Apache License 2.0 diff --git a/alfresco-docker-imagemagick/src/main/java/org/alfresco/transformer/executors/ImageMagickCommandExecutor.java b/alfresco-docker-imagemagick/src/main/java/org/alfresco/transformer/executors/ImageMagickCommandExecutor.java index f6329d6a..a0971997 100644 --- a/alfresco-docker-imagemagick/src/main/java/org/alfresco/transformer/executors/ImageMagickCommandExecutor.java +++ b/alfresco-docker-imagemagick/src/main/java/org/alfresco/transformer/executors/ImageMagickCommandExecutor.java @@ -29,7 +29,6 @@ package org.alfresco.transformer.executors; import java.util.HashMap; import java.util.Map; -import org.alfresco.util.exec.RuntimeExec; import org.springframework.stereotype.Component; /** 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 e3244f2a..201464fd 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 @@ -26,6 +26,7 @@ */ package org.alfresco.transformer; +import static org.alfresco.transformer.executors.RuntimeExec.ExecutionResult; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -57,9 +58,9 @@ import java.util.UUID; import org.alfresco.transform.client.model.TransformReply; import org.alfresco.transform.client.model.TransformRequest; import org.alfresco.transformer.executors.ImageMagickCommandExecutor; +import org.alfresco.transformer.executors.RuntimeExec; import org.alfresco.transformer.model.FileRefEntity; import org.alfresco.transformer.model.FileRefResponse; -import org.alfresco.util.exec.RuntimeExec; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -85,7 +86,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; public class ImageMagickControllerTest extends AbstractTransformerControllerTest { @Mock - private RuntimeExec.ExecutionResult mockExecutionResult; + private ExecutionResult mockExecutionResult; @Mock private RuntimeExec mockTransformCommand; diff --git a/alfresco-docker-libreoffice/pom.xml b/alfresco-docker-libreoffice/pom.xml index 68df9f89..94296a85 100644 --- a/alfresco-docker-libreoffice/pom.xml +++ b/alfresco-docker-libreoffice/pom.xml @@ -46,24 +46,9 @@ - - org.alfresco - alfresco-core - - - - dom4j - dom4j - - - org.dom4j dom4j - 2.1.1 diff --git a/alfresco-docker-libreoffice/src/license/THIRD-PARTY.properties b/alfresco-docker-libreoffice/src/license/THIRD-PARTY.properties deleted file mode 100644 index 52c90861..00000000 --- a/alfresco-docker-libreoffice/src/license/THIRD-PARTY.properties +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by org.codehaus.mojo.license.AddThirdPartyMojo -#------------------------------------------------------------------------------- -# Already used licenses in project : -# - Apache 2 -# - Apache 2.0 -# - Apache License 2.0 -# - Apache License, Version 2.0 -# - Apache License, version 2.0 -# - BSD 3-clause New License -# - CDDL + GPLv2 with classpath exception -# - CDDL 1.1 -# - CDDL+GPL License -# - CDDL/GPLv2+CE -# - Eclipse Distribution License - v 1.0 -# - Eclipse Public License - v 1.0 -# - GNU Lesser General Public License -# - GNU Lesser General Public License v2.1 -# - GPL2 w/ CPE -# - MIT License -# - MIT license -# - Public Domain, per Creative Commons CC0 -# - Sun Binary Code License Agreement -# - The Apache License, Version 2.0 -# - The Apache Software License, Version 2.0 -# - The JSON License -# - The MIT License -#------------------------------------------------------------------------------- -# Please fill the missing licenses for dependencies : -# -# -#Tue Jul 09 13:36:53 EEST 2019 -javax.transaction--jta--1.1=Sun Binary Code License Agreement -commons-httpclient--commons-httpclient--3.1-HTTPCLIENT-1265=Apache License 2.0 -org.codehaus.guessencoding--guessencoding--1.4=Apache License 2.0 diff --git a/alfresco-docker-libreoffice/src/main/java/org/alfresco/transformer/executors/JodConverterSharedInstance.java b/alfresco-docker-libreoffice/src/main/java/org/alfresco/transformer/executors/JodConverterSharedInstance.java index d4f44fcc..e6c4579f 100644 --- a/alfresco-docker-libreoffice/src/main/java/org/alfresco/transformer/executors/JodConverterSharedInstance.java +++ b/alfresco-docker-libreoffice/src/main/java/org/alfresco/transformer/executors/JodConverterSharedInstance.java @@ -37,7 +37,6 @@ import java.util.StringTokenizer; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; -import org.alfresco.error.AlfrescoRuntimeException; import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration; import org.artofsolving.jodconverter.office.OfficeException; import org.artofsolving.jodconverter.office.OfficeManager; @@ -163,7 +162,7 @@ public class JodConverterSharedInstance implements JodConverter File tmp = new File(templateProfileDir); if (!tmp.isDirectory()) { - throw new AlfrescoRuntimeException( + throw new RuntimeException( "OpenOffice template profile directory " + templateProfileDir + " does not exist."); } this.templateProfileDir = tmp; diff --git a/alfresco-docker-libreoffice/src/test/java/org/alfresco/transformer/LibreOfficeControllerTest.java b/alfresco-docker-libreoffice/src/test/java/org/alfresco/transformer/LibreOfficeControllerTest.java index d6bc3827..6c457721 100644 --- a/alfresco-docker-libreoffice/src/test/java/org/alfresco/transformer/LibreOfficeControllerTest.java +++ b/alfresco-docker-libreoffice/src/test/java/org/alfresco/transformer/LibreOfficeControllerTest.java @@ -26,6 +26,7 @@ */ package org.alfresco.transformer; +import static org.alfresco.transformer.executors.RuntimeExec.ExecutionResult; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -56,7 +57,6 @@ import org.alfresco.transform.client.model.TransformRequest; import org.alfresco.transformer.executors.LibreOfficeJavaExecutor; import org.alfresco.transformer.model.FileRefEntity; import org.alfresco.transformer.model.FileRefResponse; -import org.alfresco.util.exec.RuntimeExec; import org.artofsolving.jodconverter.office.OfficeException; import org.junit.Before; import org.junit.Test; @@ -81,7 +81,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; public class LibreOfficeControllerTest extends AbstractTransformerControllerTest { @Mock - private RuntimeExec.ExecutionResult mockExecutionResult; + private ExecutionResult mockExecutionResult; @SpyBean private LibreOfficeJavaExecutor javaExecutor; diff --git a/alfresco-docker-tika/pom.xml b/alfresco-docker-tika/pom.xml index 2e50e7f2..7e3abd4b 100644 --- a/alfresco-docker-tika/pom.xml +++ b/alfresco-docker-tika/pom.xml @@ -47,29 +47,9 @@ - - org.alfresco - alfresco-core - - - - dom4j - dom4j - - - org.dom4j dom4j - 2.1.1 - - - - org.alfresco - alfresco-data-model diff --git a/alfresco-docker-tika/src/license/THIRD-PARTY.properties b/alfresco-docker-tika/src/license/THIRD-PARTY.properties index bea04d22..ccb5f496 100644 --- a/alfresco-docker-tika/src/license/THIRD-PARTY.properties +++ b/alfresco-docker-tika/src/license/THIRD-PARTY.properties @@ -2,8 +2,6 @@ #------------------------------------------------------------------------------- # Already used licenses in project : # - (MIT-style) netCDF C library license -# - Apache 1.1 -# - Apache 2 # - Apache 2.0 # - Apache License 2.0 # - Apache License v2.0 @@ -13,21 +11,14 @@ # - BSD # - BSD 3-clause New License # - BSD License -# - BSD licence # - Bouncy Castle Licence # - CDDL + GPLv2 with classpath exception -# - CDDL 1.1 -# - CDDL+GPL License # - CDDL, v1.0 -# - CDDL/GPLv2+CE -# - COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 -# - CPL # - EPL 2.0 -# - Eclipse Distribution License - v 1.0 # - Eclipse Public License - v 1.0 -# - GNU General Public Library +# - Eclipse Public License, Version 1.0 # - GNU Lesser General Public License -# - GNU Lesser General Public License v2.1 +# - GNU Lesser General Public License, Version 2.1 # - GPL2 w/ CPE # - LGPL, v2.1 or later # - LGPL, version 2.1 @@ -42,24 +33,14 @@ # - Public Domain, per Creative Commons CC0 # - Similar to Apache License but with the acknowledgment clause removed # - Specification License -# - Sun Binary Code License Agreement # - The Apache License, Version 2.0 # - The Apache Software License, Version 2.0 # - The BSD License -# - The JSON License # - The MIT License -# - The SAX License -# - The W3C License # - UnRar License #------------------------------------------------------------------------------- # Please fill the missing licenses for dependencies : # # -#Tue Jul 09 13:34:27 EEST 2019 -org.acegisecurity--acegi-security--0.8.2_patched=Apache License 2.0 +#Mon Aug 19 18:06:38 EEST 2019 net.jcip--jcip-annotations--1.0=Public -xerces--xercesImpl--2.11.0-alfresco-patched-20180402=Apache License 2.0 -javax.transaction--jta--1.1=Sun Binary Code License Agreement -commons-httpclient--commons-httpclient--3.1-HTTPCLIENT-1265=Apache License 2.0 -xpp3--xpp3--1.1.3_8=Apache 1.1 -org.codehaus.guessencoding--guessencoding--1.4=Apache License 2.0 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 index dcf0393e..8c1c6f44 100644 --- a/alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaController.java +++ b/alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaController.java @@ -26,7 +26,6 @@ */ package org.alfresco.transformer; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_TEXT_PLAIN; import static org.alfresco.transformer.executors.Tika.INCLUDE_CONTENTS; import static org.alfresco.transformer.executors.Tika.NOT_EXTRACT_BOOKMARKS_TEXT; import static org.alfresco.transformer.executors.Tika.PDF_BOX; @@ -37,6 +36,7 @@ import static org.alfresco.transformer.fs.FileManager.createAttachment; import static org.alfresco.transformer.fs.FileManager.createSourceFile; import static org.alfresco.transformer.fs.FileManager.createTargetFile; import static org.alfresco.transformer.fs.FileManager.createTargetFileName; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_TEXT_PLAIN; import static org.alfresco.transformer.util.Util.stringToBoolean; import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.OK; diff --git a/alfresco-docker-tika/src/main/java/org/alfresco/transformer/executors/Tika.java b/alfresco-docker-tika/src/main/java/org/alfresco/transformer/executors/Tika.java index 9ea1b3de..4c910ee7 100644 --- a/alfresco-docker-tika/src/main/java/org/alfresco/transformer/executors/Tika.java +++ b/alfresco-docker-tika/src/main/java/org/alfresco/transformer/executors/Tika.java @@ -26,14 +26,14 @@ */ package org.alfresco.transformer.executors; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_HTML; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_IMAGE_JPEG; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_IMAGE_PNG; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_IMAGE_TIFF; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_TEXT_CSV; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_TEXT_PLAIN; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_XHTML; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_XML; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_HTML; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_IMAGE_JPEG; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_IMAGE_PNG; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_IMAGE_TIFF; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_TEXT_CSV; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_TEXT_PLAIN; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_XHTML; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_XML; import java.io.BufferedInputStream; import java.io.BufferedWriter; 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 index 38a642d7..ce54ce97 100644 --- a/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaControllerTest.java +++ b/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaControllerTest.java @@ -26,18 +26,6 @@ */ package org.alfresco.transformer; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_HTML; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_OPENXML_PRESENTATION; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_OUTLOOK_MSG; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_PDF; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_TEXT_CSV; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_TEXT_PLAIN; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_WORD; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_XHTML; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_XML; -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_ZIP; import static org.alfresco.transformer.executors.Tika.ARCHIVE; import static org.alfresco.transformer.executors.Tika.CSV; import static org.alfresco.transformer.executors.Tika.DOC; @@ -58,6 +46,18 @@ import static org.alfresco.transformer.executors.Tika.XHTML; import static org.alfresco.transformer.executors.Tika.XML; import static org.alfresco.transformer.executors.Tika.XSLX; import static org.alfresco.transformer.executors.Tika.ZIP; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_HTML; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_OPENXML_PRESENTATION; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_OUTLOOK_MSG; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_PDF; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_TEXT_CSV; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_TEXT_PLAIN; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_WORD; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_XHTML; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_XML; +import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_ZIP; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -87,10 +87,10 @@ import java.util.UUID; import org.alfresco.transform.client.model.TransformReply; import org.alfresco.transform.client.model.TransformRequest; +import org.alfresco.transformer.executors.RuntimeExec; import org.alfresco.transformer.executors.TikaJavaExecutor; import org.alfresco.transformer.model.FileRefEntity; import org.alfresco.transformer.model.FileRefResponse; -import org.alfresco.util.exec.RuntimeExec; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/alfresco-docker-transform-misc/pom.xml b/alfresco-docker-transform-misc/pom.xml index 59e7ebef..df824b5a 100644 --- a/alfresco-docker-transform-misc/pom.xml +++ b/alfresco-docker-transform-misc/pom.xml @@ -48,24 +48,9 @@ - - org.alfresco - alfresco-core - - - - dom4j - dom4j - - - org.dom4j dom4j - 2.1.1 diff --git a/alfresco-docker-transform-misc/src/license/THIRD-PARTY.properties b/alfresco-docker-transform-misc/src/license/THIRD-PARTY.properties deleted file mode 100644 index 2ce17de2..00000000 --- a/alfresco-docker-transform-misc/src/license/THIRD-PARTY.properties +++ /dev/null @@ -1,36 +0,0 @@ -# Generated by org.codehaus.mojo.license.AddThirdPartyMojo -#------------------------------------------------------------------------------- -# Already used licenses in project : -# - Apache 2 -# - Apache 2.0 -# - Apache License 2.0 -# - Apache License, Version 2.0 -# - Apache License, version 2.0 -# - BSD 3-clause New License -# - BSD License -# - CDDL + GPLv2 with classpath exception -# - CDDL 1.1 -# - CDDL+GPL License -# - CDDL/GPLv2+CE -# - Common Public License -# - Eclipse Distribution License - v 1.0 -# - Eclipse Public License - v 1.0 -# - GNU Lesser General Public License -# - GNU Lesser General Public License v2.1 -# - GPL2 w/ CPE -# - MIT License -# - MIT license -# - Public Domain, per Creative Commons CC0 -# - Sun Binary Code License Agreement -# - The Apache License, Version 2.0 -# - The Apache Software License, Version 2.0 -# - The JSON License -# - The MIT License -#------------------------------------------------------------------------------- -# Please fill the missing licenses for dependencies : -# -# -#Tue Jul 09 13:38:31 EEST 2019 -javax.transaction--jta--1.1=Sun Binary Code License Agreement -commons-httpclient--commons-httpclient--3.1-HTTPCLIENT-1265=Apache License 2.0 -org.codehaus.guessencoding--guessencoding--1.4=Apache License 2.0 diff --git a/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/AppleIWorksContentTransformer.java b/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/AppleIWorksContentTransformer.java index 2c4ddadc..c572fe01 100644 --- a/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/AppleIWorksContentTransformer.java +++ b/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/AppleIWorksContentTransformer.java @@ -40,7 +40,6 @@ import java.nio.file.StandardCopyOption; import java.util.List; import java.util.Map; -import org.alfresco.error.AlfrescoRuntimeException; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.slf4j.Logger; @@ -113,13 +112,13 @@ public class AppleIWorksContentTransformer implements SelectableTransformer if (!found) { - throw new AlfrescoRuntimeException( + throw new RuntimeException( "The source " + sourceMimetype + " file did not contain a " + targetMimetype + " preview"); } } catch (IOException e) { - throw new AlfrescoRuntimeException( + throw new RuntimeException( "Unable to transform " + sourceMimetype + " file. It should have been a zip format file.", e); } diff --git a/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/OOXMLThumbnailContentTransformer.java b/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/OOXMLThumbnailContentTransformer.java index 0a39709d..44f858dc 100644 --- a/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/OOXMLThumbnailContentTransformer.java +++ b/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/OOXMLThumbnailContentTransformer.java @@ -55,7 +55,6 @@ import java.nio.file.StandardCopyOption; import java.util.List; import java.util.Map; -import org.alfresco.error.AlfrescoRuntimeException; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; @@ -148,7 +147,7 @@ public class OOXMLThumbnailContentTransformer implements SelectableTransformer } catch (IOException e) { - throw new AlfrescoRuntimeException("Unable to transform file.", e); + throw new RuntimeException("Unable to transform file.", e); } } diff --git a/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/SelectingTransformer.java b/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/SelectingTransformer.java index ffd1760a..1b47cfb7 100644 --- a/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/SelectingTransformer.java +++ b/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/SelectingTransformer.java @@ -34,7 +34,6 @@ import java.util.List; import java.util.Map; import java.util.StringJoiner; -import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.transform.exceptions.TransformException; import org.alfresco.transformer.logging.LogEntry; import org.slf4j.Logger; @@ -117,7 +116,7 @@ public class SelectingTransformer return transformer; } } - throw new AlfrescoRuntimeException( + throw new RuntimeException( "Could not select a transformer for sourceMimetype=" + sourceMimetype + " targetMimetype=" + targetMimetype); } diff --git a/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/TextToPdfContentTransformer.java b/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/TextToPdfContentTransformer.java index dd05b91b..bf577184 100644 --- a/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/TextToPdfContentTransformer.java +++ b/alfresco-docker-transform-misc/src/main/java/org/alfresco/transformer/transformers/TextToPdfContentTransformer.java @@ -46,7 +46,6 @@ import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; -import org.alfresco.error.AlfrescoRuntimeException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; @@ -86,7 +85,7 @@ public class TextToPdfContentTransformer implements SelectableTransformer } catch (Throwable e) { - throw new AlfrescoRuntimeException( + throw new RuntimeException( "Unable to set Standard Font for PDF generation: " + fontName, e); } } @@ -99,7 +98,7 @@ public class TextToPdfContentTransformer implements SelectableTransformer } catch (Throwable e) { - throw new AlfrescoRuntimeException( + throw new RuntimeException( "Unable to set Font Size for PDF generation: " + fontSize); } } diff --git a/alfresco-docker-transform-misc/src/test/java/org/alfresco/transformer/MiscControllerTest.java b/alfresco-docker-transform-misc/src/test/java/org/alfresco/transformer/MiscControllerTest.java index 1babb128..cbb8a19c 100644 --- a/alfresco-docker-transform-misc/src/test/java/org/alfresco/transformer/MiscControllerTest.java +++ b/alfresco-docker-transform-misc/src/test/java/org/alfresco/transformer/MiscControllerTest.java @@ -45,7 +45,6 @@ import java.io.IOException; import java.io.StringWriter; import java.io.UnsupportedEncodingException; -import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.transform.client.model.TransformRequest; import org.alfresco.transformer.transformers.SelectingTransformer; import org.apache.pdfbox.pdmodel.PDDocument; @@ -165,7 +164,7 @@ public class MiscControllerTest extends AbstractTransformerControllerTest } catch (UnsupportedEncodingException e) { - throw new AlfrescoRuntimeException("Encoding not recognised", e); + throw new RuntimeException("Encoding not recognised", e); } MvcResult result = sendText("txt", diff --git a/alfresco-transformer-base/pom.xml b/alfresco-transformer-base/pom.xml index dc8eadb4..6d553d9f 100644 --- a/alfresco-transformer-base/pom.xml +++ b/alfresco-transformer-base/pom.xml @@ -40,24 +40,9 @@ - - org.alfresco - alfresco-core - - - - dom4j - dom4j - - - org.dom4j dom4j - 2.1.1 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 aff695fd..7a3e618c 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 @@ -27,6 +27,7 @@ package org.alfresco.transformer; import static java.util.stream.Collectors.joining; +import static org.alfresco.transformer.fs.FileManager.TempFileProvider.createTempFile; import static org.alfresco.transformer.fs.FileManager.buildFile; import static org.alfresco.transformer.fs.FileManager.createTargetFileName; import static org.alfresco.transformer.fs.FileManager.deleteFile; @@ -51,7 +52,6 @@ import org.alfresco.transform.exceptions.TransformException; import org.alfresco.transformer.clients.AlfrescoSharedFileStoreClient; import org.alfresco.transformer.logging.LogEntry; import org.alfresco.transformer.model.FileRefResponse; -import org.alfresco.util.TempFileProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -324,7 +324,7 @@ public abstract class AbstractTransformerController implements TransformControll logger.warn(message); throw new TransformException(BAD_REQUEST.value(), message); } - File file = TempFileProvider.createTempFile("source_", "." + extension); + final File file = createTempFile("source_", "." + extension); logger.debug("Read source content {} length={} contentType={}", sourceReference, size, contentType); diff --git a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/executors/AbstractCommandExecutor.java b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/executors/AbstractCommandExecutor.java index b4c04f2f..013dccc6 100644 --- a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/executors/AbstractCommandExecutor.java +++ b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/executors/AbstractCommandExecutor.java @@ -26,6 +26,7 @@ */ package org.alfresco.transformer.executors; +import static org.alfresco.transformer.executors.RuntimeExec.ExecutionResult; import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; @@ -33,8 +34,6 @@ import java.io.File; import java.util.Map; import org.alfresco.transform.exceptions.TransformException; -import org.alfresco.util.exec.RuntimeExec; -import org.alfresco.util.exec.RuntimeExec.ExecutionResult; /** * diff --git a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/executors/ExecParameterTokenizer.java b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/executors/ExecParameterTokenizer.java new file mode 100644 index 00000000..5060b396 --- /dev/null +++ b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/executors/ExecParameterTokenizer.java @@ -0,0 +1,360 @@ +/* + * #%L + * Alfresco Transform Core + * %% + * Copyright (C) 2005 - 2019 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.executors; + +import static java.util.Collections.singletonList; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.StringTokenizer; + +/** + * DUPLICATED FROM *alfresco-core*. + * + * This class is used to tokenize strings used as parameters for {@link RuntimeExec} objects. + * Examples of such strings are as follows (ImageMagick-like parameters): + * + * The first is the simple case which would be parsed into Strings as follows: + * "-font", "Helvetica", "-pointsize", "50" + *

+ * The second is more complex in that it includes a quoted parameter, which would be parsed as a single String: + * "-font", "Helvetica", "-pointsize", "50", "circle 100,100 150,150" + * Note however that the quotation characters will be stripped from the token. + *

+ * The third shows an example with embedded quotation marks, which would parse to: + * "-font", "Helvetica", "-pointsize", "50", "gravity south fill black text 0,12 'CopyRight'" + * In this case, the embedded quotation marks (which must be different from those surrounding the parameter) + * are preserved in the extracted token. + *

+ * The class does not understand escaped quotes such as p1 p2 "a b c \"hello\" d" p4 + * + * @author Neil Mc Erlean + * @since 3.4.2 + */ +public class ExecParameterTokenizer +{ + /** + * The string to be tokenized. + */ + private final String str; + + /** + * The list of tokens, which will take account of quoted sections. + */ + private List tokens; + + public ExecParameterTokenizer(String str) + { + this.str = str; + } + + /** + * This method returns the tokens in a parameter string. + * Any tokens not contained within single or double quotes will be tokenized in the normal + * way i.e. by using whitespace separators and the standard StringTokenizer algorithm. + * Any tokens which are contained within single or double quotes will be returned as single + * String instances and will have their quote marks removed. + *

+ * See above for examples. + * + * @throws NullPointerException if the string to be tokenized was null. + */ + public List getAllTokens() + { + if (this.str == null) + { + throw new NullPointerException("Illegal null string cannot be tokenized."); + } + + if (tokens == null) + { + tokens = new ArrayList<>(); + + // Preserve original behaviour from RuntimeExec. + if (str.indexOf('\'') == -1 && str.indexOf('"') == -1) + { + // Contains no quotes. + for (StringTokenizer standardTokenizer = new StringTokenizer( + str); standardTokenizer.hasMoreTokens(); ) + { + tokens.add(standardTokenizer.nextToken()); + } + } + else + { + // There are either single or double quotes or both. + // So we need to identify the quoted regions within the string. + List> quotedRegions = new ArrayList<>(); + + for (Pair next = identifyNextQuotedRegion(str, 0); next != null; ) + { + quotedRegions.add(next); + next = identifyNextQuotedRegion(str, next.getSecond() + 1); + } + + // Now we've got a List of index pairs identifying the quoted regions. + // We need to get substrings of quoted and unquoted blocks, whilst maintaining order. + List substrings = getSubstrings(str, quotedRegions); + + for (Substring r : substrings) + { + tokens.addAll(r.getTokens()); + } + } + } + + return this.tokens; + } + + /** + * The substrings will be a list of quoted and unquoted substrings. + * The unquoted ones need to be further tokenized in the normal way. + * The quoted ones must not be tokenized, but need their quotes stripped off. + */ + private List getSubstrings(String str, + List> quotedRegionIndices) + { + List result = new ArrayList<>(); + + int cursorPosition = 0; + for (Pair nextQuotedRegionIndices : quotedRegionIndices) + { + if (cursorPosition < nextQuotedRegionIndices.getFirst()) + { + int startIndexOfNextQuotedRegion = nextQuotedRegionIndices.getFirst() - 1; + result.add(new UnquotedSubstring( + str.substring(cursorPosition, startIndexOfNextQuotedRegion))); + } + result.add(new QuotedSubstring(str.substring(nextQuotedRegionIndices.getFirst(), + nextQuotedRegionIndices.getSecond()))); + cursorPosition = nextQuotedRegionIndices.getSecond(); + } + + // We've processed all the quoted regions, but there may be a final unquoted region + if (cursorPosition < str.length() - 1) + { + result.add(new UnquotedSubstring(str.substring(cursorPosition, str.length() - 1))); + } + + return result; + } + + private Pair identifyNextQuotedRegion(String str, int startingIndex) + { + int indexOfNextSingleQuote = str.indexOf('\'', startingIndex); + int indexOfNextDoubleQuote = str.indexOf('"', startingIndex); + + if (indexOfNextSingleQuote == -1 && indexOfNextDoubleQuote == -1) + { + // If there are no more quoted regions + return null; + } + else if (indexOfNextSingleQuote > -1 && indexOfNextDoubleQuote > -1) + { + // If there are both single and double quotes in the remainder of the string + // Then select the closest quote. + int indexOfNextQuote = Math.min(indexOfNextSingleQuote, indexOfNextDoubleQuote); + char quoteChar = str.charAt(indexOfNextQuote); + + return findIndexOfClosingQuote(str, indexOfNextQuote, quoteChar); + } + else + { + // Only one of the quote characters is present. + + int indexOfNextQuote = Math.max(indexOfNextSingleQuote, indexOfNextDoubleQuote); + char quoteChar = str.charAt(indexOfNextQuote); + + return findIndexOfClosingQuote(str, indexOfNextQuote, quoteChar); + } + } + + private Pair findIndexOfClosingQuote(String str, int indexOfStartingQuote, + char quoteChar) + { + // So we know which type of quote char we're dealing with. Either ' or ". + // Now we need to find the closing quote. + int indexAfterClosingQuote = str.indexOf(quoteChar, + indexOfStartingQuote + 1) + 1; // + 1 to search after opening quote. + 1 to give result including closing quote. + + if (indexAfterClosingQuote == 0) // -1 + 1 + { + // If no closing quote. + throw new IllegalArgumentException("No closing " + quoteChar + "quote in" + str); + } + + return new Pair<>(indexOfStartingQuote, indexAfterClosingQuote); + } + + /** + * Utility interface for a substring in a parameter string. + */ + public interface Substring + { + /** + * Gets all the tokens in a parameter string. + */ + List getTokens(); + } + + /** + * A substring that is not surrounded by (single or double) quotes. + */ + public class UnquotedSubstring implements Substring + { + private final String regionString; + + public UnquotedSubstring(String str) + { + this.regionString = str; + } + + public List getTokens() + { + StringTokenizer t = new StringTokenizer(regionString); + List result = new ArrayList<>(); + while (t.hasMoreTokens()) + { + result.add(t.nextToken()); + } + return result; + } + + public String toString() + { + return UnquotedSubstring.class.getSimpleName() + ": '" + regionString + '\''; + } + } + + /** + * A substring that is surrounded by (single or double) quotes. + */ + public class QuotedSubstring implements Substring + { + private final String regionString; + + public QuotedSubstring(String str) + { + this.regionString = str; + } + + public List getTokens() + { + String stringWithoutQuotes = regionString.substring(1, regionString.length() - 1); + return singletonList(stringWithoutQuotes); + } + + public String toString() + { + return QuotedSubstring.class.getSimpleName() + ": '" + regionString + '\''; + } + } + + public static final class Pair implements Serializable + { + private static final long serialVersionUID = -7406248421185630612L; + + /** + * The first member of the pair. + */ + private F first; + + /** + * The second member of the pair. + */ + private S second; + + /** + * Make a new one. + * + * @param first The first member. + * @param second The second member. + */ + public Pair(F first, S second) + { + this.first = first; + this.second = second; + } + + /** + * Get the first member of the tuple. + * + * @return The first member. + */ + public final F getFirst() + { + return first; + } + + /** + * Get the second member of the tuple. + * + * @return The second member. + */ + public final S getSecond() + { + return second; + } + + public final void setFirst(F first) + { + this.first = first; + } + + public final void setSecond(S second) + { + this.second = second; + } + + @Override public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Pair pair = (Pair) o; + return Objects.equals(first, pair.first) && + Objects.equals(second, pair.second); + } + + @Override public int hashCode() + { + return Objects.hash(first, second); + } + + @Override + public String toString() + { + return "(" + first + ", " + second + ")"; + } + } +} + diff --git a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/executors/RuntimeExec.java b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/executors/RuntimeExec.java new file mode 100644 index 00000000..ef170478 --- /dev/null +++ b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/executors/RuntimeExec.java @@ -0,0 +1,986 @@ +/* + * #%L + * Alfresco Transform Core + * %% + * Copyright (C) 2005 - 2019 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.executors; + +import static java.util.Collections.emptyMap; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.Timer; +import java.util.TimerTask; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * DUPLICATED FROM *alfresco-core*. + * + * This acts as a session similar to the java.lang.Process, but + * logs the system standard and error streams. + *

+ * The bean can be configured to execute a command directly, or be given a map + * of commands keyed by the os.name Java system property. In this map, + * the default key that is used when no match is found is the + * {@link #KEY_OS_DEFAULT *} key. + *

+ * Use the {@link #setProcessDirectory(String) processDirectory} property to change the default location + * from which the command executes. The process's environment can be configured using the + * {@link #setProcessProperties(Map) processProperties} property. + *

+ * Commands may use placeholders, e.g. + *


+ *    find
+ *    -name
+ *    ${filename}
+ * 
+ * The filename property will be substituted for any supplied value prior to + * each execution of the command. Currently, no checks are made to get or check the + * properties contained within the command string. It is up to the client code to + * dynamically extract the properties required if the required properties are not + * known up front. + *

+ * Sometimes, a variable may contain several arguments. . In this case, the arguments + * need to be tokenized using a standard StringTokenizer. To force tokenization + * of a value, use: + *


+ *    SPLIT:${userArgs}
+ * 
+ * You should not use this just to split up arguments that are known to require tokenization + * up front. The SPLIT: directive works for the entire argument and will not do anything + * if it is not at the beginning of the argument. Do not use SPLIT: to break up arguments + * that are fixed, so avoid doing this: + *

+ *    SPLIT:ls -lih
+ * 
+ * Instead, break the command up explicitly: + *

+ *    ls
+ *    -lih
+ * 
+ * + * Tokenization of quoted parameter values is handled by ExecParameterTokenizer, which + * describes the support in more detail. + * + * @author Derek Hulley + */ +public class RuntimeExec +{ + private static final Logger logger = LoggerFactory.getLogger(RuntimeExec.class); + + /** + * the key to use when specifying a command for any other OS: * + */ + private static final String KEY_OS_DEFAULT = "*"; + + private static final String KEY_OS_NAME = "os.name"; + private static final int BUFFER_SIZE = 1024; + private static final String VAR_OPEN = "${"; + private static final String VAR_CLOSE = "}"; + private static final String DIRECTIVE_SPLIT = "SPLIT:"; + + private String[] command; + private Charset charset = Charset.defaultCharset(); + private boolean waitForCompletion = true; + private Map defaultProperties = emptyMap(); + private String[] processProperties; + private File processDirectory; + private final Set errCodes; + private final Timer timer = new Timer(true); + + /** + * Default constructor. Initialize this instance by setting individual properties. + */ + public RuntimeExec() + { + // set default error codes + errCodes = new HashSet<>(2); + errCodes.add(1); + errCodes.add(2); + } + + public String toString() + { + final StringBuilder sb = new StringBuilder(256); + sb.append("RuntimeExec:\n").append(" command: "); + if (command == null) + { + // command is 'null', so there's nothing to toString + sb.append("'null'\n"); + } + else + { + for (String cmdStr : command) + { + sb.append(cmdStr).append(" "); + } + sb.append("\n"); + } + sb.append(" env props: ").append(Arrays.toString(processProperties)).append("\n") + .append(" dir: ").append(processDirectory).append("\n") + .append(" os: ").append(System.getProperty(KEY_OS_NAME)).append("\n"); + return sb.toString(); + } + + /** + * Set the command to execute regardless of operating system + * + * @param command an array of strings representing the command (first entry) and arguments + * @since 3.0 + */ + public void setCommand(String[] command) + { + this.command = command; + } + + /** + * Sets the assumed charset of OUT and ERR streams generated by the executed command. + * This defaults to the system default charset: {@link Charset#defaultCharset()}. + * + * @param charsetCode a supported character set code + * @throws UnsupportedCharsetException if the characterset code is not recognised by Java + */ + public void setCharset(String charsetCode) + { + this.charset = Charset.forName(charsetCode); + } + + /** + * Set whether to wait for completion of the command or not. If there is no wait for completion, + * then the return value of out and err buffers cannot be relied upon as the + * command may still be in progress. Failure is therefore not possible unless the calling thread + * waits for execution. + * + * @param waitForCompletion true (default) is to wait for the command to exit, + * or false to just return an exit code of 0 and whatever + * output is available at that point. + * @since 2.1 + */ + public void setWaitForCompletion(boolean waitForCompletion) + { + this.waitForCompletion = waitForCompletion; + } + + /** + * Supply a choice of commands to execute based on a mapping from the os.name system + * property to the command to execute. The {@link #KEY_OS_DEFAULT *} key can be used + * to get a command where there is not direct match to the operating system key. + *

+ * Each command is an array of strings, the first of which represents the command and all subsequent + * entries in the array represent the arguments. All elements of the array will be checked for + * the presence of any substitution parameters (e.g. '{dir}'). The parameters can be set using the + * {@link #setDefaultProperties(Map) defaults} or by passing the substitution values into the + * {@link #execute(Map)} command. + *

+ * If parameters passed may be multiple arguments, or if the values provided in the map are themselves + * collections of arguments (not recommended), then prefix the value with SPLIT: to ensure that + * the value is tokenized before being passed to the command. Any values that are not split, will be + * passed to the command as single arguments. For example:
+ * 'SPLIT: dir . ..' becomes 'dir', '.' and '..'.
+ * 'SPLIT: dir ${path}' (if path is '. ..') becomes 'dir', '.' and '..'.
+ * The splitting occurs post-subtitution. Where the arguments are known, it is advisable to avoid + * SPLIT:. + * + * @param commandsByOS a map of command string arrays, keyed by operating system names + * @see #setDefaultProperties(Map) + * @since 3.0 + */ + public void setCommandsAndArguments(Map commandsByOS) + { + // get the current OS + String serverOs = System.getProperty(KEY_OS_NAME); + // attempt to find a match + String[] command = commandsByOS.get(serverOs); + if (command == null) + { + // go through the commands keys, looking for one that matches by regular expression matching + for (String osName : commandsByOS.keySet()) + { + // Ignore * options. It is dealt with later. + if (osName.equals(KEY_OS_DEFAULT)) + { + continue; + } + // Do regex match + if (serverOs.matches(osName)) + { + command = commandsByOS.get(osName); + break; + } + } + // if there is still no command, then check for the wildcard + if (command == null) + { + command = commandsByOS.get(KEY_OS_DEFAULT); + } + } + // check + if (command == null) + { + throw new RuntimeException( + "No command found for OS " + serverOs + " or '" + KEY_OS_DEFAULT + "': \n" + + " commands: " + commandsByOS); + } + this.command = command; + } + + /** + * Supply a choice of commands to execute based on a mapping from the os.name system + * property to the command to execute. The {@link #KEY_OS_DEFAULT *} key can be used + * to get a command where there is not direct match to the operating system key. + * + * @param commandsByOS a map of command string keyed by operating system names + * @deprecated Use {@link #setCommandsAndArguments(Map)} + */ + public void setCommandMap(Map commandsByOS) + { + // This is deprecated, so issue a warning + logger.warn( + "The bean RuntimeExec property 'commandMap' has been deprecated;" + + " use 'commandsAndArguments' instead. See https://issues.alfresco.com/jira/browse/ETHREEOH-579."); + Map fixed = new LinkedHashMap<>(); + for (Map.Entry entry : commandsByOS.entrySet()) + { + String os = entry.getKey(); + String unparsedCmd = entry.getValue(); + StringTokenizer tokenizer = new StringTokenizer(unparsedCmd); + String[] cmd = new String[tokenizer.countTokens()]; + for (int i = 0; i < cmd.length; i++) + { + cmd[i] = tokenizer.nextToken(); + } + fixed.put(os, cmd); + } + setCommandsAndArguments(fixed); + } + + /** + * Set the default command-line properties to use when executing the command. + * These are properties that substitute variables defined in the command string itself. + * Properties supplied during execution will overwrite the default properties. + *

+ * null properties will be treated as an empty string for substitution + * purposes. + * + * @param defaultProperties property values + */ + public void setDefaultProperties(Map defaultProperties) + { + this.defaultProperties = defaultProperties; + } + + /** + * Set additional runtime properties (environment properties) that will used + * by the executing process. + *

+ * Any keys or properties that start and end with ${...} will be removed on the assumption + * that these are unset properties. null values are translated to empty strings. + * All keys and values are trimmed of leading and trailing whitespace. + * + * @param processProperties Runtime process properties + * @see Runtime#exec(String, String[], java.io.File) + */ + public void setProcessProperties(Map processProperties) + { + ArrayList processPropList = new ArrayList<>(processProperties.size()); + boolean hasPath = false; + String systemPath = System.getenv("PATH"); + for (Map.Entry entry : processProperties.entrySet()) + { + String key = entry.getKey(); + String value = entry.getValue(); + if (key == null) + { + continue; + } + if (value == null) + { + value = ""; + } + key = key.trim(); + value = value.trim(); + if (key.startsWith(VAR_OPEN) && key.endsWith(VAR_CLOSE)) + { + continue; + } + if (value.startsWith(VAR_OPEN) && value.endsWith(VAR_CLOSE)) + { + continue; + } + // If a path is specified, prepend it to the existing path + if (key.equals("PATH")) + { + if (systemPath != null && systemPath.length() > 0) + { + processPropList.add(key + "=" + value + File.pathSeparator + systemPath); + } + else + { + processPropList.add(key + "=" + value); + } + hasPath = true; + } + else + { + processPropList.add(key + "=" + value); + } + } + // If a path was not specified, inherit the current one + if (!hasPath && systemPath != null && systemPath.length() > 0) + { + processPropList.add("PATH=" + systemPath); + } + this.processProperties = processPropList.toArray(new String[0]); + } + + /** + * Adds a property to existed processProperties. + * Property should not be null or empty. + * If property with the same value already exists then no change is made. + * If property exists with a different value then old value is replaced with the new one. + * + * @param name - property name + * @param value - property value + */ + public void setProcessProperty(String name, String value) + { + boolean set = false; + + if (name == null || value == null) + { + return; + } + + name = name.trim(); + value = value.trim(); + + if (name.isEmpty() || value.isEmpty()) + { + return; + } + + String property = name + "=" + value; + + for (String prop : this.processProperties) + { + if (prop.equals(property)) + { + set = true; + break; + } + + if (prop.startsWith(name)) + { + String oldValue = prop.split("=")[1]; + prop.replace(oldValue, value); + set = true; + } + } + + if (!set) + { + String[] existedProperties = this.processProperties; + int epl = existedProperties.length; + String[] newProperties = Arrays.copyOf(existedProperties, epl + 1); + newProperties[epl] = property; + this.processProperties = newProperties; + } + } + + /** + * Set the runtime location from which the command is executed. + *

+ * If the value is an unsubsititued variable (${...}) then it is ignored. + * If the location is not visible at the time of setting, a warning is issued only. + * + * @param processDirectory the runtime location from which to execute the command + */ + public void setProcessDirectory(String processDirectory) + { + if (processDirectory.startsWith(VAR_OPEN) && processDirectory.endsWith(VAR_CLOSE)) + { + this.processDirectory = null; + } + else + { + this.processDirectory = new File(processDirectory); + if (!this.processDirectory.exists()) + { + logger.warn( + "The runtime process directory is not visible when setting property " + + "'processDirectory': \n{}", this); + } + } + } + + /** + * A comma or space separated list of values that, if returned by the executed command, + * indicate an error value. This defaults to "1, 2". + * + * @param errCodesStr the error codes for the execution + */ + public void setErrorCodes(String errCodesStr) + { + errCodes.clear(); + StringTokenizer tokenizer = new StringTokenizer(errCodesStr, " ,"); + while (tokenizer.hasMoreElements()) + { + String errCodeStr = tokenizer.nextToken(); + // attempt to convert it to an integer + try + { + int errCode = Integer.parseInt(errCodeStr); + this.errCodes.add(errCode); + } + catch (NumberFormatException e) + { + throw new RuntimeException( + "Property 'errorCodes' must be comma-separated list of integers: " + errCodesStr); + } + } + } + + /** + * Executes the command using the default properties + * + * @see #execute(Map) + */ + public ExecutionResult execute() + { + return execute(defaultProperties); + } + + /** + * Executes the statement that this instance was constructed with. + * + * @param properties the properties that the command might be executed with. + * null properties will be treated as an empty string for substitution + * purposes. + * @return Returns the full execution results + */ + public ExecutionResult execute(Map properties) + { + return execute(properties, -1); + } + + /** + * Executes the statement that this instance was constructed with an optional + * timeout after which the command is asked to + * + * @param properties the properties that the command might be executed with. + * null properties will be treated as an empty string for substitution + * purposes. + * @param timeoutMs a timeout after which {@link Process#destroy()} is called. + * ignored if less than or equal to zero. Note this method does not guarantee + * to terminate the process (it is not a kill -9). + * @return Returns the full execution results + */ + public ExecutionResult execute(Map properties, final long timeoutMs) + { + int defaultFailureExitValue = errCodes.size() > 0 ? ((Integer) errCodes.toArray()[0]) : 1; + + // check that the command has been set + if (command == null) + { + throw new RuntimeException("Runtime command has not been set: \n" + this); + } + + // create the properties + Runtime runtime = Runtime.getRuntime(); + Process process; + String[] commandToExecute = null; + try + { + // execute the command with full property replacement + commandToExecute = getCommand(properties); + final Process thisProcess = runtime.exec(commandToExecute, processProperties, + processDirectory); + process = thisProcess; + if (timeoutMs > 0) + { + final String[] command = commandToExecute; + timer.schedule(new TimerTask() + { + @Override + public void run() + { + // Only try to kill the process if it is still running + try + { + thisProcess.exitValue(); + } + catch (IllegalThreadStateException stillRunning) + { + logger.debug( + "Process has taken too long ({} seconds). Killing process {}", + timeoutMs / 1000, Arrays.deepToString(command)); + } + } + }, timeoutMs); + } + } + catch (IOException e) + { + // The process could not be executed here, so just drop out with an appropriate error state + String execOut = ""; + String execErr = e.getMessage(); + ExecutionResult result = new ExecutionResult(null, commandToExecute, errCodes, + defaultFailureExitValue, execOut, execErr); + logFullEnvironmentDump(result); + return result; + } + + // create the stream gobblers + InputStreamReaderThread stdOutGobbler = new InputStreamReaderThread( + process.getInputStream(), charset); + InputStreamReaderThread stdErrGobbler = new InputStreamReaderThread( + process.getErrorStream(), charset); + + // start gobbling + stdOutGobbler.start(); + stdErrGobbler.start(); + + // wait for the process to finish + int exitValue = 0; + try + { + if (waitForCompletion) + { + exitValue = process.waitFor(); + } + } + catch (InterruptedException e) + { + // process was interrupted - generate an error message + stdErrGobbler.addToBuffer(e.toString()); + exitValue = defaultFailureExitValue; + } + + if (waitForCompletion) + { + // ensure that the stream gobblers get to finish + stdOutGobbler.waitForCompletion(); + stdErrGobbler.waitForCompletion(); + } + + // get the stream values + String execOut = stdOutGobbler.getBuffer(); + String execErr = stdErrGobbler.getBuffer(); + + // construct the return value + ExecutionResult result = new ExecutionResult(process, commandToExecute, errCodes, exitValue, + execOut, execErr); + + // done + logFullEnvironmentDump(result); + return result; + } + + /** + * Dump the full environment in debug mode + */ + private void logFullEnvironmentDump(ExecutionResult result) + { + if (logger.isTraceEnabled()) + { + StringBuilder sb = new StringBuilder(); + sb.append(result); + + // Environment variables modified by Alfresco + if (processProperties != null && processProperties.length > 0) + { + sb.append("\n modified environment: "); + for (String property : processProperties) + { + sb.append("\n "); + sb.append(property); + } + } + + // Dump the full environment + sb.append("\n existing environment: "); + Map envVariables = System.getenv(); + for (Map.Entry entry : envVariables.entrySet()) + { + String name = entry.getKey(); + String value = entry.getValue(); + sb.append("\n "); + sb.append(name).append("=").append(value); + } + + logger.trace(sb.toString()); + } + logger.debug("Result: " + result.toString()); + + // close output stream (connected to input stream of native subprocess) + } + + /** + * @return Returns the command that will be executed if no additional properties + * were to be supplied + */ + public String[] getCommand() + { + return getCommand(defaultProperties); + } + + /** + * Get the command that will be executed post substitution. + *

+ * null properties will be treated as an empty string for substitution + * purposes. + * + * @param properties the properties that the command might be executed with + * @return Returns the command that will be executed should the additional properties + * be supplied + */ + public String[] getCommand(Map properties) + { + Map execProperties; + if (properties == defaultProperties) + { + // we are just using the default properties + execProperties = defaultProperties; + } + else + { + execProperties = new HashMap<>(defaultProperties); + // overlay the supplied properties + execProperties.putAll(properties); + } + // Perform the substitution for each element of the command + ArrayList adjustedCommandElements = new ArrayList<>(20); + for (String s : command) + { + StringBuilder sb = new StringBuilder(s); + for (Map.Entry entry : execProperties.entrySet()) + { + String key = entry.getKey(); + String value = entry.getValue(); + // ignore null + if (value == null) + { + value = ""; + } + // progressively replace the property in the command + key = (VAR_OPEN + key + VAR_CLOSE); + int index = sb.indexOf(key); + while (index > -1) + { + // replace + sb.replace(index, index + key.length(), value); + // get the next one + index = sb.indexOf(key, index + 1); + } + } + String adjustedValue = sb.toString(); + // Now SPLIT: it + if (adjustedValue.startsWith(DIRECTIVE_SPLIT)) + { + String unsplitAdjustedValue = sb.substring(DIRECTIVE_SPLIT.length()); + + // There may be quoted arguments here (see ALF-7482) + ExecParameterTokenizer quoteAwareTokenizer = new ExecParameterTokenizer( + unsplitAdjustedValue); + List tokens = quoteAwareTokenizer.getAllTokens(); + adjustedCommandElements.addAll(tokens); + } + else + { + adjustedCommandElements.add(adjustedValue); + } + } + // done + return adjustedCommandElements.toArray(new String[0]); + } + + /** + * Object to carry the results of an execution to the caller. + * + * @author Derek Hulley + */ + public static class ExecutionResult + { + private final Process process; + private final String[] command; + private final Set errCodes; + private final int exitValue; + private final String stdOut; + private final String stdErr; + + /** + * @param process the process attached to Java - null is allowed + */ + private ExecutionResult( + final Process process, + final String[] command, + final Set errCodes, + final int exitValue, + final String stdOut, + final String stdErr) + { + this.process = process; + this.command = command; + this.errCodes = errCodes; + this.exitValue = exitValue; + this.stdOut = stdOut; + this.stdErr = stdErr; + } + + @Override + public String toString() + { + String out = stdOut.length() > 250 ? stdOut.substring(0, 250) : stdOut; + String err = stdErr.length() > 250 ? stdErr.substring(0, 250) : stdErr; + + StringBuilder sb = new StringBuilder(128); + sb.append("Execution result: \n") + .append(" os: ").append(System.getProperty(KEY_OS_NAME)).append("\n") + .append(" command: "); + appendCommand(sb, command).append("\n") + .append(" succeeded: ").append(getSuccess()).append("\n") + .append(" exit code: ").append(exitValue).append("\n") + .append(" out: ").append(out).append("\n") + .append(" err: ").append(err); + return sb.toString(); + } + + /** + * Appends the command in a form that make running from the command line simpler. + * It is not a real attempt at making a command given all the operating system + * and shell options, but makes copy, paste and edit a bit simpler. + */ + private StringBuilder appendCommand(StringBuilder sb, String[] command) + { + boolean arg = false; + for (String element : command) + { + if (element == null) + { + continue; + } + + if (arg) + { + sb.append(' '); + } + else + { + arg = true; + } + + boolean escape = element.indexOf(' ') != -1 || element.indexOf('>') != -1; + if (escape) + { + sb.append("\""); + } + sb.append(element); + if (escape) + { + sb.append("\""); + } + } + return sb; + } + + /** + * A helper method to force a kill of the process that generated this result. This is + * useful in cases where the process started is not expected to exit, or doesn't exit + * quickly. If the {@linkplain RuntimeExec#setWaitForCompletion(boolean) "wait for completion"} + * flag is false then the process may still be running when this result is returned. + * + * @return true if the process was killed, otherwise false + */ + public boolean killProcess() + { + if (process == null) + { + return true; + } + try + { + process.destroy(); + return true; + } + catch (Throwable e) + { + logger.warn(e.getMessage()); + return false; + } + } + + /** + * @param exitValue the command exit value + * @return Returns true if the code is a listed failure code + * @see #setErrorCodes(String) + */ + private boolean isFailureCode(int exitValue) + { + return errCodes.contains(exitValue); + } + + /** + * @return Returns true if the command was deemed to be successful according to the + * failure codes returned by the execution. + */ + public boolean getSuccess() + { + return !isFailureCode(exitValue); + } + + public int getExitValue() + { + return exitValue; + } + + public String getStdOut() + { + return stdOut; + } + + public String getStdErr() + { + return stdErr; + } + } + + /** + * Gobbles an InputStream and writes it into a + * StringBuffer + *

+ * The reading of the input stream is buffered. + */ + public static class InputStreamReaderThread extends Thread + { + private final InputStream is; + private final Charset charset; + private final StringBuffer buffer; // we require the synchronization + private boolean completed; + + /** + * @param is an input stream to read - it will be wrapped in a buffer + * for reading + */ + public InputStreamReaderThread(InputStream is, Charset charset) + { + super(); + setDaemon(true); // must not hold up the VM if it is terminating + this.is = is; + this.charset = charset; + this.buffer = new StringBuffer(BUFFER_SIZE); + this.completed = false; + } + + public synchronized void run() + { + completed = false; + + byte[] bytes = new byte[BUFFER_SIZE]; + try (InputStream tempIs = new BufferedInputStream(is, BUFFER_SIZE)) + { + int count = -2; + while (count != -1) + { + // do we have something previously read? + if (count > 0) + { + String toWrite = new String(bytes, 0, count, charset.name()); + buffer.append(toWrite); + } + // read the next set of bytes + count = tempIs.read(bytes); + } + // done + } + catch (IOException e) + { + throw new RuntimeException("Unable to read stream", e); + } + finally + { + // The thread has finished consuming the stream + completed = true; + // Notify waiters + this.notifyAll(); // Note: Method is synchronized + } + } + + /** + * Waits for the run to complete. + *

+ * Remember to start the thread first + */ + public synchronized void waitForCompletion() + { + while (!completed) + { + try + { + // release our lock and wait a bit + this.wait(1000L); // 200 ms + } + catch (InterruptedException ignore) + { + } + } + } + + /** + * @param msg the message to add to the buffer + */ + public void addToBuffer(String msg) + { + buffer.append(msg); + } + + public boolean isComplete() + { + return completed; + } + + /** + * @return Returns the current state of the buffer + */ + public String getBuffer() + { + return buffer.toString(); + } + } +} + diff --git a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/fs/FileManager.java b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/fs/FileManager.java index ba27fc05..746897b1 100644 --- a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/fs/FileManager.java +++ b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/fs/FileManager.java @@ -44,7 +44,6 @@ import javax.servlet.http.HttpServletRequest; import org.alfresco.transform.exceptions.TransformException; import org.alfresco.transformer.logging.LogEntry; -import org.alfresco.util.TempFileProvider; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.http.HttpHeaders; @@ -241,4 +240,44 @@ public class FileManager return ResponseEntity.ok().header(CONTENT_DISPOSITION, "attachment; filename*= UTF-8''" + targetFilename).body(targetResource); } + + /** + * TempFileProvider - Duplicated and adapted from alfresco-core. + */ + public static class TempFileProvider + { + public static File createTempFile(final String prefix, final String suffix) + { + final File directory = getTempDir(); + try + { + return File.createTempFile(prefix, suffix, directory); + } + catch (IOException e) + { + throw new RuntimeException( + "Failed to created temp file: \n prefix: " + prefix + + "\n suffix: " + suffix + "\n directory: " + directory, e); + } + } + + private static File getTempDir() + { + final String dirName = "Alfresco"; + final String systemTempDirPath = System.getProperty("java.io.tmpdir"); + if (systemTempDirPath == null) + { + throw new RuntimeException("System property not available: java.io.tmpdir"); + } + + final File systemTempDir = new File(systemTempDirPath); + final File tempDir = new File(systemTempDir, dirName); + if (!tempDir.exists() && !tempDir.mkdirs() && !tempDir.exists()) + { + throw new RuntimeException("Failed to create temp directory: " + tempDir); + } + + return tempDir; + } + } } diff --git a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/probes/ProbeTestTransform.java b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/probes/ProbeTestTransform.java index 3e4b3779..b6bfd431 100644 --- a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/probes/ProbeTestTransform.java +++ b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/probes/ProbeTestTransform.java @@ -28,6 +28,7 @@ package org.alfresco.transformer.probes; import static org.alfresco.transformer.fs.FileManager.SOURCE_FILE; import static org.alfresco.transformer.fs.FileManager.TARGET_FILE; +import static org.alfresco.transformer.fs.FileManager.TempFileProvider.createTempFile; import static org.springframework.http.HttpStatus.INSUFFICIENT_STORAGE; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; import static org.springframework.http.HttpStatus.OK; @@ -46,7 +47,6 @@ import javax.servlet.http.HttpServletRequest; import org.alfresco.transform.exceptions.TransformException; import org.alfresco.transformer.AbstractTransformerController; import org.alfresco.transformer.logging.LogEntry; -import org.alfresco.util.TempFileProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -263,7 +263,7 @@ public abstract class ProbeTestTransform private File getSourceFile(HttpServletRequest request, boolean isLiveProbe) { incrementTransformerCount(); - File sourceFile = TempFileProvider.createTempFile("source_", "_" + sourceFilename); + File sourceFile = createTempFile("source_", "_" + sourceFilename); request.setAttribute(SOURCE_FILE, sourceFile); try (InputStream inputStream = this.getClass().getResourceAsStream('/' + sourceFilename)) { @@ -281,7 +281,7 @@ public abstract class ProbeTestTransform private File getTargetFile(HttpServletRequest request) { - File targetFile = TempFileProvider.createTempFile("target_", "_" + targetFilename); + File targetFile = createTempFile("target_", "_" + targetFilename); request.setAttribute(TARGET_FILE, targetFile); LogEntry.setTarget(targetFilename); return targetFile; diff --git a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/util/MimetypeMap.java b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/util/MimetypeMap.java new file mode 100644 index 00000000..6e414670 --- /dev/null +++ b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/util/MimetypeMap.java @@ -0,0 +1,165 @@ +/* + * #%L + * Alfresco Transform Core + * %% + * Copyright (C) 2005 - 2019 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.util; + +/** + * Partially duplicated from *alfresco-data-model*. + */ +public interface MimetypeMap +{ + String PREFIX_APPLICATION = "application/"; + String PREFIX_AUDIO = "audio/"; + String PREFIX_IMAGE = "image/"; + String PREFIX_MESSAGE = "message/"; + String PREFIX_MODEL = "model/"; + String PREFIX_MULTIPART = "multipart/"; + String PREFIX_TEXT = "text/"; + String PREFIX_VIDEO = "video/"; + String EXTENSION_BINARY = "bin"; + String MACOS_RESOURCE_FORK_FILE_NAME_PREFIX = "._"; + String MIMETYPE_MULTIPART_ALTERNATIVE = "multipart/alternative"; + String MIMETYPE_TEXT_PLAIN = "text/plain"; + String MIMETYPE_TEXT_MEDIAWIKI = "text/mediawiki"; + String MIMETYPE_TEXT_CSS = "text/css"; + String MIMETYPE_TEXT_CSV = "text/csv"; + String MIMETYPE_TEXT_JAVASCRIPT = "text/javascript"; + String MIMETYPE_XML = "text/xml"; + String MIMETYPE_HTML = "text/html"; + String MIMETYPE_XHTML = "application/xhtml+xml"; + String MIMETYPE_PDF = "application/pdf"; + String MIMETYPE_JSON = "application/json"; + String MIMETYPE_WORD = "application/msword"; + String MIMETYPE_EXCEL = "application/vnd.ms-excel"; + String MIMETYPE_BINARY = "application/octet-stream"; + String MIMETYPE_PPT = "application/vnd.ms-powerpoint"; + String MIMETYPE_APP_DWG = "application/dwg"; + String MIMETYPE_IMG_DWG = "image/vnd.dwg"; + String MIMETYPE_VIDEO_AVI = "video/x-msvideo"; + String MIMETYPE_VIDEO_QUICKTIME = "video/quicktime"; + String MIMETYPE_VIDEO_WMV = "video/x-ms-wmv"; + String MIMETYPE_VIDEO_3GP = "video/3gpp"; + String MIMETYPE_VIDEO_3GP2 = "video/3gpp2"; + String MIMETYPE_DITA = "application/dita+xml"; + String MIMETYPE_FLASH = "application/x-shockwave-flash"; + String MIMETYPE_VIDEO_FLV = "video/x-flv"; + String MIMETYPE_APPLICATION_FLA = "application/x-fla"; + String MIMETYPE_VIDEO_MPG = "video/mpeg"; + String MIMETYPE_VIDEO_MP4 = "video/mp4"; + String MIMETYPE_IMAGE_GIF = "image/gif"; + String MIMETYPE_IMAGE_JPEG = "image/jpeg"; + String MIMETYPE_IMAGE_RGB = "image/x-rgb"; + String MIMETYPE_IMAGE_SVG = "image/svg+xml"; + String MIMETYPE_IMAGE_PNG = "image/png"; + String MIMETYPE_IMAGE_TIFF = "image/tiff"; + String MIMETYPE_IMAGE_RAW_DNG = "image/x-raw-adobe"; + String MIMETYPE_IMAGE_RAW_3FR = "image/x-raw-hasselblad"; + String MIMETYPE_IMAGE_RAW_RAF = "image/x-raw-fuji"; + String MIMETYPE_IMAGE_RAW_CR2 = "image/x-raw-canon"; + String MIMETYPE_IMAGE_RAW_K25 = "image/x-raw-kodak"; + String MIMETYPE_IMAGE_RAW_MRW = "image/x-raw-minolta"; + String MIMETYPE_IMAGE_RAW_NEF = "image/x-raw-nikon"; + String MIMETYPE_IMAGE_RAW_ORF = "image/x-raw-olympus"; + String MIMETYPE_IMAGE_RAW_PEF = "image/x-raw-pentax"; + String MIMETYPE_IMAGE_RAW_ARW = "image/x-raw-sony"; + String MIMETYPE_IMAGE_RAW_X3F = "image/x-raw-sigma"; + String MIMETYPE_IMAGE_RAW_RW2 = "image/x-raw-panasonic"; + String MIMETYPE_IMAGE_RAW_RWL = "image/x-raw-leica"; + String MIMETYPE_IMAGE_RAW_R3D = "image/x-raw-red"; + String MIMETYPE_IMAGE_DWT = "image/x-dwt"; + String MIMETYPE_APPLICATION_EPS = "application/eps"; + String MIMETYPE_APPLICATION_PS = "application/postscript"; + String MIMETYPE_JAVASCRIPT = "application/x-javascript"; + String MIMETYPE_ZIP = "application/zip"; + String MIMETYPE_OPENSEARCH_DESCRIPTION = "application/opensearchdescription+xml"; + String MIMETYPE_ATOM = "application/atom+xml"; + String MIMETYPE_RSS = "application/rss+xml"; + String MIMETYPE_RFC822 = "message/rfc822"; + String MIMETYPE_OUTLOOK_MSG = "application/vnd.ms-outlook"; + String MIMETYPE_VISIO = "application/vnd.visio"; + String MIMETYPE_VISIO_2013 = "application/vnd.visio2013"; + String MIMETYPE_APPLICATION_ILLUSTRATOR = "application/illustrator"; + String MIMETYPE_APPLICATION_PHOTOSHOP = "image/vnd.adobe.photoshop"; + String MIMETYPE_ENCRYPTED_OFFICE = "application/x-tika-ooxml-protected"; + String MIMETYPE_OPENDOCUMENT_TEXT = "application/vnd.oasis.opendocument.text"; + String MIMETYPE_OPENDOCUMENT_TEXT_TEMPLATE = "application/vnd.oasis.opendocument.text-template"; + String MIMETYPE_OPENDOCUMENT_GRAPHICS = "application/vnd.oasis.opendocument.graphics"; + String MIMETYPE_OPENDOCUMENT_GRAPHICS_TEMPLATE = "application/vnd.oasis.opendocument.graphics-template"; + String MIMETYPE_OPENDOCUMENT_PRESENTATION = "application/vnd.oasis.opendocument.presentation"; + String MIMETYPE_OPENDOCUMENT_PRESENTATION_TEMPLATE = "application/vnd.oasis.opendocument.presentation-template"; + String MIMETYPE_OPENDOCUMENT_SPREADSHEET = "application/vnd.oasis.opendocument.spreadsheet"; + String MIMETYPE_OPENDOCUMENT_SPREADSHEET_TEMPLATE = "application/vnd.oasis.opendocument.spreadsheet-template"; + String MIMETYPE_OPENDOCUMENT_CHART = "application/vnd.oasis.opendocument.chart"; + String MIMETYPE_OPENDOCUMENT_CHART_TEMPLATE = "applicationvnd.oasis.opendocument.chart-template"; + String MIMETYPE_OPENDOCUMENT_IMAGE = "application/vnd.oasis.opendocument.image"; + String MIMETYPE_OPENDOCUMENT_IMAGE_TEMPLATE = "applicationvnd.oasis.opendocument.image-template"; + String MIMETYPE_OPENDOCUMENT_FORMULA = "application/vnd.oasis.opendocument.formula"; + String MIMETYPE_OPENDOCUMENT_FORMULA_TEMPLATE = "applicationvnd.oasis.opendocument.formula-template"; + String MIMETYPE_OPENDOCUMENT_TEXT_MASTER = "application/vnd.oasis.opendocument.text-master"; + String MIMETYPE_OPENDOCUMENT_TEXT_WEB = "application/vnd.oasis.opendocument.text-web"; + String MIMETYPE_OPENDOCUMENT_DATABASE = "application/vnd.oasis.opendocument.database"; + String MIMETYPE_OPENOFFICE1_WRITER = "application/vnd.sun.xml.writer"; + String MIMETYPE_OPENOFFICE1_CALC = "application/vnd.sun.xml.calc"; + String MIMETYPE_OPENOFFICE1_DRAW = "application/vnd.sun.xml.draw"; + String MIMETYPE_OPENOFFICE1_IMPRESS = "application/vnd.sun.xml.impress"; + String MIMETYPE_OPENXML_WORDPROCESSING = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; + String MIMETYPE_OPENXML_WORDPROCESSING_MACRO = "application/vnd.ms-word.document.macroenabled.12"; + String MIMETYPE_OPENXML_WORD_TEMPLATE = "application/vnd.openxmlformats-officedocument.wordprocessingml.template"; + String MIMETYPE_OPENXML_WORD_TEMPLATE_MACRO = "application/vnd.ms-word.template.macroenabled.12"; + String MIMETYPE_OPENXML_SPREADSHEET = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + String MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE = "application/vnd.openxmlformats-officedocument.spreadsheetml.template"; + String MIMETYPE_OPENXML_SPREADSHEET_MACRO = "application/vnd.ms-excel.sheet.macroenabled.12"; + String MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE_MACRO = "application/vnd.ms-excel.template.macroenabled.12"; + String MIMETYPE_OPENXML_SPREADSHEET_ADDIN_MACRO = "application/vnd.ms-excel.addin.macroenabled.12"; + String MIMETYPE_OPENXML_SPREADSHEET_BINARY_MACRO = "application/vnd.ms-excel.sheet.binary.macroenabled.12"; + String MIMETYPE_OPENXML_PRESENTATION = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; + String MIMETYPE_OPENXML_PRESENTATION_MACRO = "application/vnd.ms-powerpoint.presentation.macroenabled.12"; + String MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW = "application/vnd.openxmlformats-officedocument.presentationml.slideshow"; + String MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW_MACRO = "application/vnd.ms-powerpoint.slideshow.macroenabled.12"; + String MIMETYPE_OPENXML_PRESENTATION_TEMPLATE = "application/vnd.openxmlformats-officedocument.presentationml.template"; + String MIMETYPE_OPENXML_PRESENTATION_TEMPLATE_MACRO = "application/vnd.ms-powerpoint.template.macroenabled.12"; + String MIMETYPE_OPENXML_PRESENTATION_ADDIN = "application/vnd.ms-powerpoint.addin.macroenabled.12"; + String MIMETYPE_OPENXML_PRESENTATION_SLIDE = "application/vnd.openxmlformats-officedocument.presentationml.slide"; + String MIMETYPE_OPENXML_PRESENTATION_SLIDE_MACRO = "application/vnd.ms-powerpoint.slide.macroenabled.12"; + String MIMETYPE_STAROFFICE5_DRAW = "application/vnd.stardivision.draw"; + String MIMETYPE_STAROFFICE5_CALC = "application/vnd.stardivision.calc"; + String MIMETYPE_STAROFFICE5_IMPRESS = "application/vnd.stardivision.impress"; + String MIMETYPE_STAROFFICE5_IMPRESS_PACKED = "application/vnd.stardivision.impress-packed"; + String MIMETYPE_STAROFFICE5_CHART = "application/vnd.stardivision.chart"; + String MIMETYPE_STAROFFICE5_WRITER = "application/vnd.stardivision.writer"; + String MIMETYPE_STAROFFICE5_WRITER_GLOBAL = "application/vnd.stardivision.writer-global"; + String MIMETYPE_STAROFFICE5_MATH = "application/vnd.stardivision.math"; + String MIMETYPE_IWORK_KEYNOTE = "application/vnd.apple.keynote"; + String MIMETYPE_IWORK_NUMBERS = "application/vnd.apple.numbers"; + String MIMETYPE_IWORK_PAGES = "application/vnd.apple.pages"; + String MIMETYPE_APPLEFILE = "application/applefile"; + String MIMETYPE_WORDPERFECT = "application/wordperfect"; + String MIMETYPE_MP3 = "audio/mpeg"; + String MIMETYPE_AUDIO_MP4 = "audio/mp4"; + String MIMETYPE_VORBIS = "audio/vorbis"; + String MIMETYPE_FLAC = "audio/x-flac"; + String MIMETYPE_ACP = "application/acp"; +} diff --git a/pom.xml b/pom.xml index 8cb657b7..6648c256 100644 --- a/pom.xml +++ b/pom.xml @@ -21,8 +21,6 @@ latest 2.0.16 - 7.17 - 8.39 3.0.1.1 ${project.version} 1.0.2.3 @@ -50,31 +48,11 @@ - - org.alfresco - alfresco-core - ${dependency.alfresco-core.version} - - - - dom4j - dom4j - - - org.dom4j dom4j 2.1.1 - - org.alfresco - alfresco-data-model - ${dependency.alfresco-data-model.version} - org.alfresco alfresco-jodconverter-core