HXENG-64 refactor ATS (#657)

Refactor to clean up packages in the t-model and to introduce a simpler to implement t-engine base.

The new t-engines (tika, imagemagick, libreoffice, pdfrenderer, misc, aio, aspose) and t-router may be used in combination with older components as the API between the content Repo and between components has not changed. As far as possible the same artifacts are created (the -boot projects no longer exist). They may be used with older ACS repo versions.

The main changes to look for are:
* The introduction of TransformEngine and CustomTransformer interfaces to be implemented.
* The removal in t-engines and t-router of the Controller, Application, test template page, Controller tests and application config, as this is all now done by the t-engine base package.
* The t-router now extends the t-engine base, which also reduced the amount of duplicate code.
* The t-engine base provides the test page, which includes drop downs of known transform options. The t-router is able to use pipeline and failover transformers. This was not possible to do previously as the router had no test UI.
* Resources including licenses are automatically included in the all-in-one t-engine, from the individual t-engines. They just need to be added as dependencies in the pom. 
* The ugly code in the all-in-one t-engine and misc t-engine to pick transformers has gone, as they are now just selected by the transformRegistry.
* The way t-engines respond to http or message queue transform requests has been combined (eliminates the similar but different code that existed before).
* The t-engine base now uses InputStream and OutputStream rather than Files by default. As a result it will be simpler to avoid writing content to a temporary location.
* A number of the Tika and Misc CustomTransforms no longer use Files.
* The original t-engine base still exists so customers can continue to create custom t-engines the way they have done previously. the project has just been moved into a folder called deprecated.
* The folder structure has changed. The long "alfresco-transform-..." names have given way to shorter easier to read and type names.
* The t-engine project structure now has a single project rather than two. 
* The previous config values still exist, but there are now a new set for config values for in files with names that don't misleadingly imply they only contain pipeline of routing information. 
* The concept of 'routing' has much less emphasis in class names as the code just uses the transformRegistry. 
* TransformerConfig may now be read as json or yaml. The restrictions about what could be specified in yaml has gone.
* T-engines and t-router may use transform config from files. Previously it was just the t-router.
* The POC code to do with graphs of possible routes has been removed.
* All master branch changes have been merged in.
* The concept of a single transform request which results in multiple responses (e.g. images from a video) has been added to the core processing of requests in the t-engine base.
* Many SonarCloud linter fixes.
This commit is contained in:
Alan Davis 2022-09-14 13:40:19 +01:00 committed by GitHub
parent ea83ef9ebc
commit babe26b0ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
652 changed files with 19479 additions and 18195 deletions

View File

@ -16,42 +16,42 @@ updates:
registries: registries:
- maven-alfresco-internal - maven-alfresco-internal
- package-ecosystem: docker - package-ecosystem: docker
directory: "/alfresco-transform-core-aio/alfresco-transform-core-aio-boot" directory: "/engines/aio"
schedule: schedule:
interval: daily interval: daily
time: "22:00" time: "22:00"
timezone: Europe/London timezone: Europe/London
open-pull-requests-limit: 99 open-pull-requests-limit: 99
- package-ecosystem: docker - package-ecosystem: docker
directory: "/alfresco-transform-libreoffice/alfresco-transform-libreoffice-boot" directory: "/engines/libreoffice"
schedule: schedule:
interval: daily interval: daily
time: "22:00" time: "22:00"
timezone: Europe/London timezone: Europe/London
open-pull-requests-limit: 99 open-pull-requests-limit: 99
- package-ecosystem: docker - package-ecosystem: docker
directory: "/alfresco-transform-imagemagick/alfresco-transform-imagemagick-boot" directory: "/engines/imagemagick"
schedule: schedule:
interval: daily interval: daily
time: "22:00" time: "22:00"
timezone: Europe/London timezone: Europe/London
open-pull-requests-limit: 99 open-pull-requests-limit: 99
- package-ecosystem: docker - package-ecosystem: docker
directory: "/alfresco-transform-misc/alfresco-transform-misc-boot" directory: "/engines/misc"
schedule: schedule:
interval: daily interval: daily
time: "22:00" time: "22:00"
timezone: Europe/London timezone: Europe/London
open-pull-requests-limit: 99 open-pull-requests-limit: 99
- package-ecosystem: docker - package-ecosystem: docker
directory: "/alfresco-transform-tika/alfresco-transform-tika-boot" directory: "/engines/tika"
schedule: schedule:
interval: daily interval: daily
time: "22:00" time: "22:00"
timezone: Europe/London timezone: Europe/London
open-pull-requests-limit: 99 open-pull-requests-limit: 99
- package-ecosystem: docker - package-ecosystem: docker
directory: "/alfresco-transform-pdf-renderer/alfresco-transform-pdf-renderer-boot" directory: "/engines/pdfrenderer"
schedule: schedule:
interval: daily interval: daily
time: "22:00" time: "22:00"

View File

@ -79,6 +79,6 @@ jobs:
- name: "Release" - name: "Release"
stage: release stage: release
if: commit_message ~= /\[release\]/ AND branch ~= /^(master|SP\/.+|HF\/.+)$/ if: commit_message ~= /\[release\]/ AND branch ~= /^(master|ATS-0000_refactor_packages|SP\/.+|HF\/.+)$/
before_script: travis_wait bash _ci/cache_artifacts.sh before_script: travis_wait bash _ci/cache_artifacts.sh
script: travis_wait 55 bash _ci/release.sh script: travis_wait 55 bash _ci/release.sh

View File

@ -3,28 +3,27 @@
Contains the common transformer (T-Engine) code, plus a few implementations. Contains the common transformer (T-Engine) code, plus a few implementations.
> When upgrading to 3.0.0, you will find that a number of classes in the alfresco-transform-model
have moved. See the [alfresco-transform-model README](https://github.com/Alfresco/alfresco-transform-core/blob/master/model/README.md)
### Sub-projects ### Sub-projects
* `alfresco-transform-model` - library packaged as a jar file which contains the data model of json * `model` - library packaged as a jar file which contains the data model of json
configuration files and messages sent between clients, T-Engines and T-Router. Also contains code to configuration files and messages sent between clients, T-Engines and T-Router. Also contains code to
work out which transform should be used for a combination of configuration files; see the sub-project's to combine and then work out which transform to use for a combination of source and target mimetypes
[README](https://github.com/Alfresco/alfresco-transform-core/blob/master/alfresco-transform-model/README.md) and transform options.
* `alfresco-transformer-base` - library packaged as a jar file which contains code that is common * `engines/base` - contains code common to t-engines, packaged as a jar.
to all the transformers; see the sub-project's [README](https://github.com/Alfresco/alfresco-transform-core/blob/master/engines/base/README.md)
[README](https://github.com/Alfresco/alfresco-transform-core/blob/master/alfresco-transformer-base/README.md) * `engines/<name>` - multiple T-Engines, which extend the `engines/base`; each one builds a SpringBoot jar
* `alfresco-transform-<name>` - multiple T-Engines; each one of them builds both a SpringBoot fat jar
and a [Docker image](https://github.com/Alfresco/alfresco-transform-core#docker) and a [Docker image](https://github.com/Alfresco/alfresco-transform-core#docker)
* `deprecated/alfresco-base-t-engine` - The original t-engine base, which may still be used,
but has been replaced by the simpler `engines/base`.
### Documentation ### Documentation
In addition to the subprojects (such as `alfresco-transformer-base` README above) some additional documentation can be found in: * `docs` - provides additional documentation.
* [this project's docs](docs) folder
* [ACS Packaging docs](https://github.com/Alfresco/acs-packaging/tree/master/docs) folder * [ACS Packaging docs](https://github.com/Alfresco/acs-packaging/tree/master/docs) folder
* If you're interested in the Alfresco Transform Service (ATS) see https://docs.alfresco.com/transform/concepts/transformservice-overview.html
Note: if you're interested in the Alfresco Transform Service (ATS) that is part of the enterprise Alfresco Content Services (ACS) please see:
* https://docs.alfresco.com/transform/concepts/transformservice-overview.html
### Building and testing ### Building and testing
@ -49,7 +48,7 @@ The artifacts can be obtained by:
<dependency> <dependency>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-transformer-base</artifactId> <artifactId>alfresco-base-t-engine</artifactId>
<version>version</version> <version>version</version>
</dependency> </dependency>
``` ```
@ -67,7 +66,7 @@ The core T-Engine images are available on Docker Hub.
Either as a single Core AIO (All-In-One) T-Engine: Either as a single Core AIO (All-In-One) T-Engine:
* [alfresco/alfresco-transform-core-aio](https://hub.docker.com/r/alfresco/alfresco-transform-core-aio) * [alfresco/alfresco-transform-core-aio](https://hub.docker.com/r/alfresco/alfresco-transform-core-aio)
Or as set of individual T-Engines: Or as a set of individual T-Engines:
* [alfresco/alfresco-imagemagick](https://hub.docker.com/r/alfresco/alfresco-imagemagick) * [alfresco/alfresco-imagemagick](https://hub.docker.com/r/alfresco/alfresco-imagemagick)
* [alfresco/alfresco-pdf-renderer](https://hub.docker.com/r/alfresco/alfresco-pdf-renderer) * [alfresco/alfresco-pdf-renderer](https://hub.docker.com/r/alfresco/alfresco-pdf-renderer)
* [alfresco/alfresco-libreoffice](https://hub.docker.com/r/alfresco/alfresco-libreoffice) * [alfresco/alfresco-libreoffice](https://hub.docker.com/r/alfresco/alfresco-libreoffice)

5
_ci/buildAndTestAll.sh Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -x
mvn -U -Dmaven.wagon.http.pool=false clean install -DadditionalOption=-Xdoclint:none -Dmaven.javadoc.skip=true -Dparent.core.deploy.skip=true -Dtransformer.base.deploy.skip=true -Plocal,docker-it-setup

View File

@ -16,7 +16,7 @@ else
echo "Downloading LibreOffice distribution..." echo "Downloading LibreOffice distribution..."
curl -s -S ${LIBREOFFICE_RPM_URL} -o "${HOME}/artifacts/libreoffice-dist-${LIBREOFFICE_VERSION}-linux.gz" curl -s -S ${LIBREOFFICE_RPM_URL} -o "${HOME}/artifacts/libreoffice-dist-${LIBREOFFICE_VERSION}-linux.gz"
fi fi
cp "${HOME}/artifacts/libreoffice-dist-${LIBREOFFICE_VERSION}-linux.gz" alfresco-transform-libreoffice/alfresco-transform-libreoffice-boot cp "${HOME}/artifacts/libreoffice-dist-${LIBREOFFICE_VERSION}-linux.gz" engines/libreoffice
popd popd

View File

@ -11,7 +11,7 @@ pushd "$(dirname "${BASH_SOURCE[0]}")/../"
# If the branch is "master" and the commit is not a Pull Request then deploy the JAR SNAPSHOT artifacts # If the branch is "master" and the commit is not a Pull Request then deploy the JAR SNAPSHOT artifacts
[ "${TRAVIS_PULL_REQUEST}" = "false" ] && [ "${TRAVIS_BRANCH}" = "master" ] && DEPLOY="deploy" || DEPLOY="verify" [ "${TRAVIS_PULL_REQUEST}" = "false" ] && [ "${TRAVIS_BRANCH}" = "master" ] && DEPLOY="deploy" || DEPLOY="verify"
# Do not deploy snapshots for alfresco-transform-core and alfresco-transformer-base # Do not deploy snapshots for alfresco-transform-core, alfresco-transformer-base and alfresco-base-t-engine
mvn -B -U -Dmaven.wagon.http.pool=false \ mvn -B -U -Dmaven.wagon.http.pool=false \
clean ${DEPLOY} \ clean ${DEPLOY} \
-DadditionalOption=-Xdoclint:none -Dmaven.javadoc.skip=true \ -DadditionalOption=-Xdoclint:none -Dmaven.javadoc.skip=true \

View File

@ -1,122 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import org.alfresco.transform.client.model.config.TransformConfig;
import org.alfresco.transform.exceptions.TransformException;
import org.alfresco.transformer.executors.Transformer;
import org.alfresco.transformer.probes.ProbeTestTransform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestParam;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_HTML;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
import static org.alfresco.transform.client.model.config.CoreVersionDecorator.setOrClearCoreVersion;
import static org.alfresco.transform.client.util.RequestParamMap.CONFIG_VERSION_DEFAULT;
import static org.alfresco.transformer.util.RequestParamMap.CONFIG_VERSION;
import static org.alfresco.transformer.util.RequestParamMap.SOURCE_ENCODING;
import static org.alfresco.transformer.util.RequestParamMap.TRANSFORM_NAME_PARAMETER;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.OK;
@Controller
public class AIOController extends AbstractTransformerController
{
private static final Logger logger = LoggerFactory.getLogger(AIOController.class);
@Autowired
private AIOTransformRegistry transformRegistry;
@Override
public String getTransformerName()
{
return "All in One Transformer";
}
@Override
public String version()
{
return getTransformerName() + " available";
}
@Override
public ProbeTestTransform getProbeTestTransform()
{
return new ProbeTestTransform(this, "quick.html", "quick.txt",
119, 30, 150, 1024,
60 * 2 + 1, 60 * 2)
{
@Override
protected void executeTransformCommand(File sourceFile, File targetFile)
{
Map<String, String> parameters = new HashMap<>();
parameters.put(SOURCE_ENCODING, "UTF-8");
transformImpl("html", MIMETYPE_HTML, MIMETYPE_TEXT_PLAIN, parameters, sourceFile, targetFile);
}
};
}
@Override
public ResponseEntity<TransformConfig> info(
@RequestParam(value = CONFIG_VERSION, defaultValue = CONFIG_VERSION_DEFAULT) int configVersion)
{
logger.info("GET Transform Config version: " + configVersion);
TransformConfig transformConfig = transformRegistry.getTransformConfig();
transformConfig = setOrClearCoreVersion(transformConfig, configVersion);
return new ResponseEntity<>(transformConfig, OK);
}
@Override
public void transformImpl(String transformName, String sourceMimetype, String targetMimetype,
Map<String, String> transformOptions, File sourceFile, File targetFile)
{
logger.debug("Processing transform with: transformName; '{}', sourceFile '{}', targetFile '{}', transformOptions" +
" {}", transformName, sourceFile, targetFile, transformOptions);
Transformer transformer = transformRegistry.getByTransformName(transformName);
if (transformer == null)
{
throw new TransformException(INTERNAL_SERVER_ERROR.value(), "No transformer mapping for - transform:"
+ transformName + " sourceMimetype:" + sourceMimetype + " targetMimetype:" + targetMimetype);
}
if (logger.isDebugEnabled())
{
logger.debug("Performing transform with name '{}' using transformer with id '{}'.", transformName, transformer.getTransformerId());
}
transformer.transformExtractOrEmbed(transformName, sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile);
}
}

View File

@ -1,123 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import org.alfresco.transform.client.registry.TransformServiceRegistry;
import org.alfresco.transformer.executors.ImageMagickCommandExecutor;
import org.alfresco.transformer.executors.LibreOfficeJavaExecutor;
import org.alfresco.transformer.executors.PdfRendererCommandExecutor;
import org.alfresco.transformer.executors.TikaJavaExecutor;
import org.alfresco.transformer.executors.Transformer;
import org.alfresco.transformer.transformers.SelectingTransformer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Configuration
public class AIOCustomConfig
{
@Value("${transform.core.libreoffice.path}")
private String libreofficePath;
@Value("${transform.core.libreoffice.maxTasksPerProcess}")
private String libreofficeMaxTasksPerProcess;
@Value("${transform.core.libreoffice.timeout}")
private String libreofficeTimeout;
@Value("${transform.core.libreoffice.portNumbers}")
private String libreofficePortNumbers;
@Value("${transform.core.libreoffice.templateProfileDir}")
private String libreofficeTemplateProfileDir;
@Value("${transform.core.libreoffice.isEnabled}")
private String libreofficeIsEnabled;
@Value("${transform.core.pdfrenderer.exe}")
private String pdfRendererPath;
@Value("${transform.core.imagemagick.exe}")
private String imageMagickExePath;
@Value("${transform.core.imagemagick.dyn}")
private String imageMagickDynPath;
@Value("${transform.core.imagemagick.root}")
private String imageMagickRootPath;
@Value("${transform.core.imagemagick.coders}")
private String imageMagickCodersPath;
@Value("${transform.core.imagemagick.config}")
private String imageMagickConfigPath;
@Value("${transform.core.tika.pdfBox.notExtractBookmarksTextDefault:false}")
private boolean notExtractBookmarksTextDefault;
@Value("${transform.core.version}")
private String coreVersion;
/**
*
* @return Override the TransformRegistryImpl used in {@link AbstractTransformerController}
*/
@Bean
@Primary
public TransformServiceRegistry aioTransformRegistry() throws Exception
{
AIOTransformRegistry aioTransformRegistry = new AIOTransformRegistry();
aioTransformRegistry.setCoreVersion(coreVersion);
// T-Engines are sorted by name so they are combined in the same order as in the T-Router
// and Content Repository with individual T-Engines. See TransformersConfigRegistry#retrieveRemoteConfig and
// LocalTransformServiceRegistry#getTEngineUrlsSortedByName.
for (Transformer tEngine : getTEnginesSortedByName())
{
aioTransformRegistry.registerTransformer(tEngine); // now a poor name - should be combineTransformers
}
aioTransformRegistry.registerCombinedTransformers();
return aioTransformRegistry;
}
List<Transformer> getTEnginesSortedByName()
{
return Stream.of(new SelectingTransformer(),
new TikaJavaExecutor(notExtractBookmarksTextDefault),
new ImageMagickCommandExecutor(imageMagickExePath, imageMagickDynPath, imageMagickRootPath, imageMagickCodersPath, imageMagickConfigPath),
new LibreOfficeJavaExecutor(libreofficePath, libreofficeMaxTasksPerProcess, libreofficeTimeout, libreofficePortNumbers, libreofficeTemplateProfileDir, libreofficeIsEnabled),
new PdfRendererCommandExecutor(pdfRendererPath))
.sorted(Comparator.comparing(Transformer::getTransformerId))
.collect(Collectors.toList());
}
}

View File

@ -1,85 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2020 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import io.micrometer.core.instrument.MeterRegistry;
import org.alfresco.transformer.executors.ImageMagickCommandExecutor;
import org.alfresco.transformer.executors.LibreOfficeJavaExecutor;
import org.alfresco.transformer.executors.PdfRendererCommandExecutor;
import org.alfresco.transformer.executors.TikaJavaExecutor;
import org.alfresco.transformer.transformers.SelectingTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
import java.util.Arrays;
import static org.alfresco.transformer.logging.StandardMessages.LICENCE;
@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class Application
{
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Value("${container.name}")
private String containerName;
@Bean
MeterRegistryCustomizer<MeterRegistry> metricsCommonTags()
{
return registry -> registry.config().commonTags("containerName", containerName);
}
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
@EventListener(ApplicationReadyEvent.class)
public void startup()
{
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
Arrays.stream(LICENCE.split("\\n")).forEach(logger::info);
logger.info(ImageMagickCommandExecutor.LICENCE);
logger.info(LibreOfficeJavaExecutor.LICENCE);
Arrays.stream(TikaJavaExecutor.LICENCE.split("\\n")).forEach(logger::info);
logger.info(PdfRendererCommandExecutor.LICENCE);
Arrays.stream(SelectingTransformer.LICENCE.split("\\n")).forEach(logger::info);
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
logger.info("Starting application components... Done");
}
}

View File

@ -1 +0,0 @@
#logging.level.org.alfresco.transformer.metadataExtractors=debug

View File

@ -1,131 +0,0 @@
<html xmlns:th="http://www.thymeleaf.org">
<style>
.transfomer {
display: inline-block;
padding-right: 20px;
}
</style>
<body>
<div>
<h1>All in One Transformer Test Transformation</h1>
</div>
<div>
<a href="/log">Log entries</a>
</div>
<div class="transfomer">
<h2>Tika Test Transformations</h2>
<form method="POST" enctype="multipart/form-data" action="/transform">
<table>
<tr><td><div style="text-align:right">file *</div></td><td><input type="file" name="file" /></td></tr>
<tr><td><div style="text-align:right">sourceMimetype *</div></td><td><input type="text" name="sourceMimetype" required="required" value="application/msword" /></td></tr>
<tr><td><div style="text-align:right">targetMimetype *</div></td><td><input type="text" name="targetMimetype" required="required" value="text/plain" /></td></tr>
<tr><td><div style="text-align:right">sourceExtension </div></td><td><input type="text" name="sourceExtension" value="" /></td></tr>
<tr><td><div style="text-align:right">targetExtension *</div></td><td><input type="text" name="targetExtension" required="required" value="txt" /></td></tr>
<tr><td><div style="text-align:right">timeout</div></td><td><input type="text" name="timeout" value="" /></td></tr>
<tr><td><div style="text-align:right">testDelay</div></td><td><input type="text" name="testDelay" value="" /></td></tr>
<tr><td><div style="text-align:right">targetEncoding</div></td><td><input type="text" name="targetEncoding" value="UTF-8" /></td></tr>
<tr><td><div style="text-align:right">includeContents (archive) *</div></td><td><input type="checkbox" name="includeContents" value="true" /></td></tr>
<tr><td><div style="text-align:right">notExtractBookmarksText</div></td><td><input type="checkbox" name="notExtractBookmarksText" value="true" /></td></tr>
<tr><td></td><td><input type="submit" value="Transform" /></td></tr>
</table>
</form>
</div>
<div class="transfomer">
<h2>LibreOffice Test Transformation</h2>
<form method="POST" enctype="multipart/form-data" action="/transform">
<table>
<tr><td><div style="text-align:right">file *</div></td><td><input type="file" required="required" name="file" /></td></tr>
<tr><td><div style="text-align:right">sourceMimetype *</div></td><td><input type="text" name="sourceMimetype" required="required" value="text/html" /></td></tr>
<tr><td><div style="text-align:right">targetMimetype *</div></td><td><input type="text" name="targetMimetype" required="required" value="text/plain" /></td></tr>
<tr><td><div style="text-align:right">sourceExtension </div></td><td><input type="text" name="sourceExtension" value="" /></td></tr>
<tr><td><div style="text-align:right">targetExtension *</div></td><td><input type="text" name="targetExtension" required="required" value="png" /></td></tr>
<tr><td><div style="text-align:right">timeout</div></td><td><input type="text" name="timeout" value="" /></td></tr>
<tr><td><div style="text-align:right">testDelay</div></td><td><input type="text" name="testDelay" value="" /></td></tr>
<tr><td></td><td><input type="submit" value="Transform" /></td></tr>
</table>
</form>
</div>
<div class="transfomer">
<h2>Alfresco PDF Renderer Test Transformation</h2>
<form method="POST" enctype="multipart/form-data" action="/transform">
<table>
<tr><td><div style="text-align:right">file *</div></td><td><input type="file" required="required" name="file" /></td></tr>
<tr><td><div style="text-align:right">sourceMimetype *</div></td><td><input type="text" name="sourceMimetype" required="required" value="" /></td></tr>
<tr><td><div style="text-align:right">targetMimetype *</div></td><td><input type="text" name="targetMimetype" required="required" value="" /></td></tr>
<tr><td><div style="text-align:right">sourceExtension </div></td><td><input type="text" name="sourceExtension" value="" /></td></tr>
<tr><td><div style="text-align:right">targetExtension *</div></td><td><input type="text" name="targetExtension" required="required" value="" /></td></tr>
<tr><td><div style="text-align:right">timeout</div></td><td><input type="text" name="timeout" value="" /></td></tr>
<tr><td><div style="text-align:right">testDelay</div></td><td><input type="text" name="testDelay" value="" /></td></tr>
<tr><td><div style="text-align:right">page</div></td><td><input type="text" name="page" value="" /></td></tr>
<tr><td><div style="text-align:right">width</div></td><td><input type="text" name="width" value="" /></td></tr>
<tr><td><div style="text-align:right">height</div></td><td><input type="text" name="height" value="" /></td></tr>
<tr><td><div style="text-align:right">allowPdfEnlargement</div></td><td><input type="checkbox" name="allowPdfEnlargement" value="true" /></td></tr>
<tr><td><div style="text-align:right">maintainPdfAspectRatio</div></td><td><input type="checkbox" name="maintainPdfAspectRatio" value="true" /></td></tr>
<tr><td></td><td><input type="submit" value="Transform" /></td></tr>
</table>
</form>
</div>
<div class="transfomer">
<h2>Miscellaneous Transformers Test Transformation</h2>
<form method="POST" enctype="multipart/form-data" action="/transform">
<table>
<tr><td><div style="text-align:right">file *</div></td><td><input type="file" name="file" /></td></tr>
<tr><td><div style="text-align:right">sourceMimetype *</div></td><td><input type="text" name="sourceMimetype" required="required" value="text/html" /></td></tr>
<tr><td><div style="text-align:right">targetMimetype *</div></td><td><input type="text" name="targetMimetype" required="required" value="text/plain" /></td></tr>
<tr><td><div style="text-align:right">sourceExtension </div></td><td><input type="text" name="sourceExtension" value="" /></td></tr>
<tr><td><div style="text-align:right">targetExtension *</div></td><td><input type="text" name="targetExtension" required="required" value="" /></td></tr>
<tr><td><div style="text-align:right">timeout</div></td><td><input type="text" name="timeout" value="" /></td></tr>
<tr><td><div style="text-align:right">testDelay</div></td><td><input type="text" name="testDelay" value="" /></td></tr>
<tr><td><div style="text-align:right">sourceEncoding</div></td><td><input type="text" name="sourceEncoding" value="" /></td></tr>
<tr><td><div style="text-align:right">targetEncoding</div></td><td><input type="text" name="targetEncoding" value="" /></td></tr>
<tr><td></td><td><input type="submit" value="Transform" /></td></tr>
</table>
</form>
</div>
<div style="display: inline-block;">
<h2>ImageMagick Test Transformation</h2>
<form method="POST" enctype="multipart/form-data" action="/transform">
<table>
<tr><td><div style="text-align:right">file *</div></td><td><input type="file" name="file" /></td></tr>
<tr><td><div style="text-align:right">sourceMimetype *</div></td><td><input type="text" name="sourceMimetype" required="required" value="text/html" /></td></tr>
<tr><td><div style="text-align:right">targetMimetype *</div></td><td><input type="text" name="targetMimetype" required="required" value="text/plain" /></td></tr>
<tr><td><div style="text-align:right">sourceExtension </div></td><td><input type="text" name="sourceExtension" value="" /></td></tr>
<tr><td><div style="text-align:right">targetExtension *</div></td><td><input type="text" name="targetExtension" required="required" value="" /></td></tr>
<tr><td><div style="text-align:right">timeout</div></td><td><input type="text" name="timeout" value="" /></td></tr>
<tr><td><div style="text-align:right">testDelay</div></td><td><input type="text" name="testDelay" value="" /></td></tr>
<tr><td><div style="text-align:right">startPage</div></td><td><input type="text" name="startPage" /></td></tr>
<tr><td><div style="text-align:right">endPage</div></td><td><input type="text" name="endPage" /></td></tr>
<tr><td><div style="text-align:right">alphaRemove</div></td><td><input type="text" name="alphaRemove" /></td></tr>
<tr><td><div style="text-align:right">autoOrient</div></td><td><input type="text" name="autoOrient" /></td></tr>
<tr><td><div style="text-align:right">cropGravity</div></td><td><input type="text" name="cropGravity" value="North, NorthEast...Center"/></td></tr>
<tr><td><div style="text-align:right">cropWidth</div></td><td><input type="text" name="cropWidth" /></td></tr>
<tr><td><div style="text-align:right">cropHeight</div></td><td><input type="text" name="cropHeight" /></td></tr>
<tr><td><div style="text-align:right">cropPercentage</div></td><td><input type="checkbox" name="cropPercentage" value="true" /></td></tr>
<tr><td><div style="text-align:right">cropXOffset</div></td><td><input type="text" name="cropXOffset" /></td></tr>
<tr><td><div style="text-align:right">cropYOffset</div></td><td><input type="text" name="cropYOffset" /></td></tr>
<tr><td><div style="text-align:right">thumbnail</div></td><td><input type="checkbox" name="thumbnail" value="true" /></td></tr>
<tr><td><div style="text-align:right">resizeWidth</div></td><td><input type="text" name="resizeWidth" value="" /></td></tr>
<tr><td><div style="text-align:right">resizeHeight</div></td><td><input type="text" name="resizeHeight" value="" /></td></tr>
<tr><td><div style="text-align:right">resizePercentage</div></td><td><input type="checkbox" name="resizePercentage" value="true" /></td></tr>
<tr><td><div style="text-align:right">allowEnlargement</div></td><td><input type="checkbox" name="allowEnlargement" value="true" /></td></tr>
<tr><td><div style="text-align:right">maintainAspectRatio</div></td><td><input type="checkbox" name="maintainAspectRatio" value="true" /></td></tr>
<tr><td></td><td><input type="submit" value="Transform" /></td></tr>
</table>
</form>
</div>
</body>
</html>

View File

@ -1,141 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2021 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.util.Map;
import org.alfresco.transformer.executors.Transformer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
/**
* Test the AIOController ImageMagick transforms without a server.
* Super class includes tests for the AbstractTransformerController.
*/
@WebMvcTest(AIOController.class)
@Import(AIOCustomConfig.class)
public class AIOControllerImageMagickTest extends ImageMagickControllerTest
{
// All tests contained in ImageMagickControllerTest
@Autowired
AIOTransformRegistry transformRegistry;
@BeforeEach @Override
public void before() throws IOException
{
ReflectionTestUtils.setField(commandExecutor, "transformCommand", mockTransformCommand);
ReflectionTestUtils.setField(commandExecutor, "checkCommand", mockCheckCommand);
//Need to wire in the mocked commandExecutor into the controller...
Map<String,Transformer> transformers = transformRegistry.getTransformerEngineMapping();
transformers.replace("imagemagick", commandExecutor);
mockTransformCommand("jpg", "png", "image/jpeg", true);
}
@Override
protected AbstractTransformerController getController()
{
return controller;
}
@Override
protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile,
String... params)
{
final MockHttpServletRequestBuilder builder = super.mockMvcRequest(url, sourceFile, params)
.param("targetMimetype", targetMimetype)
.param("sourceMimetype", sourceMimetype);
return builder;
}
@Test
public void testTestValidity()
{
// just test that we are actually testing against the AIOController (instead of MiscController)
assertTrue(controller instanceof AIOController, "Wrong controller wired for test");
}
@Test
@Override
public void noTargetFileTest()
{
// Ignore the test in super class as the AIO transforms will not be selected .
// It is the mock that returns a zero length file for other transformers, when we supply an invalid targetExtension.
}
@Test
@Override
public void testGetTransformConfigInfo()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetTransformConfigInfoExcludingCoreVersion()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithDuplicates()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithEmptyTransformOptions()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithNoTransformOptions()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
}

View File

@ -1,119 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2021 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Map;
import org.alfresco.transformer.executors.LibreOfficeJavaExecutor;
import org.alfresco.transformer.executors.Transformer;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
@WebMvcTest(AIOController.class)
@Import(AIOCustomConfig.class)
/**
* Test the AIOController without a server.
* Super class includes tests for the LibreOfficeController and AbstractTransformerController.
*/
public class AIOControllerLibreOfficeTest extends LibreOfficeControllerTest
{
//Tests contained in LibreOfficeControllerTest
@Test
public void testTestValidity()
{
// just test that we are actually testing against the AIOController (instead of MiscController)
assertTrue(controller instanceof AIOController,"Wrong controller wired for test");
}
@Autowired
AIOTransformRegistry transformRegistry;
@Override
// Used by the super class to mock the javaExecutor, a different implementation is required here
protected void setJavaExecutor(AbstractTransformerController controller, LibreOfficeJavaExecutor javaExecutor)
{
//Need to wire in the mocked javaExecutor into the controller...
Map<String,Transformer> transformers = transformRegistry.getTransformerEngineMapping();
transformers.replace("libreoffice", javaExecutor);
// No need to set the transform registry to the controller as it is @Autowired in
}
@Override
protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile,
String... params)
{
final MockHttpServletRequestBuilder builder = super.mockMvcRequest(url, sourceFile, params)
.param("targetMimetype", targetMimetype)
.param("sourceMimetype", sourceMimetype);
return builder;
}
@Test
@Override
public void testGetTransformConfigInfo()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetTransformConfigInfoExcludingCoreVersion()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithDuplicates()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithEmptyTransformOptions()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithNoTransformOptions()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
}

View File

@ -1,85 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2021 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
@WebMvcTest(AIOController.class)
@Import(AIOCustomConfig.class)
public class AIOControllerMiscTest extends MiscControllerTest
{
//Tests contained in MiscControllerTest
@Test
public void testTestValidity()
{
// just test that we are actually testing against the AIOController (instead of MiscController)
assertTrue(controller instanceof AIOController, "Wrong controller wired for test");
}
@Test
@Override
public void testGetTransformConfigInfo()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetTransformConfigInfoExcludingCoreVersion()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithDuplicates()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithEmptyTransformOptions()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithNoTransformOptions()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
}

View File

@ -1,119 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2021 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Map;
import org.alfresco.transformer.executors.Transformer;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
@WebMvcTest(AIOController.class)
@Import(AIOCustomConfig.class)
/**
* Test the AIOController PDF Renderer transforms without a server.
* Super class includes tests for the AbstractTransformerController.
*/
public class AIOControllerPdfRendererTest extends AlfrescoPdfRendererControllerTest
{
@Autowired
AIOTransformRegistry transformRegistry;
@Override
protected void setFields()
{
ReflectionTestUtils.setField(commandExecutor, "transformCommand", mockTransformCommand);
ReflectionTestUtils.setField(commandExecutor, "checkCommand", mockCheckCommand);
//Need to wire in the mocked commandExecutor into the controller...
Map<String,Transformer> transformers = transformRegistry.getTransformerEngineMapping();
transformers.replace("pdfrenderer", commandExecutor);
}
@Override
protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile,
String... params)
{
final MockHttpServletRequestBuilder builder = super.mockMvcRequest(url, sourceFile, params)
.param("targetMimetype", targetMimetype)
.param("sourceMimetype", sourceMimetype);
return builder;
}
@Test
public void testTestValidity()
{
// just test that we are actually testing against the AIOController (instead of MiscController)
assertTrue(controller instanceof AIOController, "Wrong controller wired for test");
}
@Test
@Override
public void testGetTransformConfigInfo()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetTransformConfigInfoExcludingCoreVersion()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithDuplicates()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithEmptyTransformOptions()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithNoTransformOptions()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
}

View File

@ -1,93 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import java.io.IOException;
import org.alfresco.transform.client.model.TransformRequest;
import org.alfresco.transform.client.model.config.TransformConfig;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.http.ResponseEntity;
import static org.alfresco.transform.client.util.RequestParamMap.CONFIG_VERSION_DEFAULT;
import static org.alfresco.transform.client.util.RequestParamMap.CONFIG_VERSION_LATEST;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
@WebMvcTest(AIOController.class)
@Import(AIOCustomConfig.class)
public class AIOControllerTest //extends AbstractTransformerControllerTest
{
@Value("${transform.core.version}")
private String coreVersion;
@Autowired
AIOController aioController;
//@Override
protected void mockTransformCommand(String sourceExtension, String targetExtension, String sourceMimetype,
boolean readTargetFileBytes) throws IOException {
// TODO Auto-generated method stub
}
//@Override
protected AbstractTransformerController getController() {
// TODO Auto-generated method stub
return null;
}
//@Override
protected void updateTransformRequestWithSpecificOptions(TransformRequest transformRequest) {
// TODO Auto-generated method stub
}
@Test
public void emptyTest()
{
ResponseEntity<TransformConfig> responseEntity = aioController.info(Integer.valueOf(CONFIG_VERSION_DEFAULT));
responseEntity.getBody().getTransformers().forEach(transformer -> {
assertNull(transformer.getCoreVersion(), transformer.getTransformerName() +
" should have had a null coreValue but was " + transformer.getCoreVersion());
});
}
@Test
public void emptyTestWithLatestVersion()
{
ResponseEntity<TransformConfig> responseEntity = aioController.info(CONFIG_VERSION_LATEST);
responseEntity.getBody().getTransformers().forEach(transformer -> {
assertNotNull(transformer.getCoreVersion(), transformer.getTransformerName() +
" should have had a coreValue but was null. Should have been " + coreVersion);
});
}
}

View File

@ -1,99 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2021 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
@WebMvcTest(AIOController.class)
@Import(AIOCustomConfig.class)
/**
* Test the AIOController Tika transforms without a server.
* Super class includes tests for the AbstractTransformerController.
*/
public class AIOControllerTikaTest extends TikaControllerTest
{
// All tests contained in TikaControllerTest
@Test
public void testTestValidity()
{
// just test that we are actually testing against the AIOController (instead of MiscController)
assertTrue(controller instanceof AIOController,"Wrong controller wired for test");
}
@Test
@Override
public void testGetTransformConfigInfo()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetTransformConfigInfoExcludingCoreVersion()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithDuplicates()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithEmptyTransformOptions()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void testGetInfoFromConfigWithNoTransformOptions()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
}
@Test
@Override
public void xlsxEmbedTest()
{
// Ignore the test in super class as the way the AIO transformer provides config is fundamentally different.
// It uses the real class path rather than the test one.
}
}

View File

@ -1,53 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2021 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import java.util.StringJoiner;
import static org.junit.jupiter.api.Assertions.*;
@WebMvcTest(AIOController.class)
@Import(AIOCustomConfig.class)
class AIOCustomConfigTest
{
@Autowired
AIOCustomConfig aioCustomConfig;
@Test
void testGetTEnginesSortedByName()
{
// T-Engine config must be read in a predictable order (alphabetically on T-Engine name) as they may override each other.
StringJoiner sortedTEngines = new StringJoiner(",");
aioCustomConfig.getTEnginesSortedByName().stream().forEach(tEngine -> sortedTEngines.add(tEngine.getTransformerId()));
assertEquals("imagemagick,libreoffice,misc,pdfrenderer,tika", sortedTEngines.toString());
}
}

View File

@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfresco-transform-core-aio</artifactId>
<name>Alfresco Core All-In-One Transformer</name>
<parent>
<artifactId>alfresco-transform-core</artifactId>
<groupId>org.alfresco</groupId>
<version>2.7.0-A2-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-transformer-base</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-transform-misc</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-transform-tika</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-transform-pdf-renderer</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-transform-libreoffice</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-transform-imagemagick</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,184 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.alfresco.transform.client.model.config.TransformConfig;
import org.alfresco.transform.client.registry.AbstractTransformRegistry;
import org.alfresco.transform.client.registry.CombinedTransformConfig;
import org.alfresco.transform.client.registry.TransformCache;
import org.alfresco.transformer.executors.Transformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.alfresco.transform.client.model.config.CoreVersionDecorator.setCoreVersionOnSingleStepTransformers;
/**
* AIOTransformRegistry manages all of the sub transformers registered to it and provides aggregated TransformConfig.
*/
public class AIOTransformRegistry extends AbstractTransformRegistry
{
private static final Logger log = LoggerFactory.getLogger(AIOTransformRegistry.class);
private static final String ENGINE_CONFIG_LOCATION_POSTFIX = "_engine_config.json";
private String coreVersion;
private CombinedTransformConfig combinedTransformConfig = new CombinedTransformConfig();
// Holds the structures used by AbstractTransformRegistry to look up what is supported.
// Unlike other sub classes this class does not extend Data or replace it at run time.
private TransformCache data = new TransformCache();
private ObjectMapper jsonObjectMapper = new ObjectMapper();
// Represents the mapping between a transform and a transformer, multiple mappings can point to the same transformer.
private Map<String, Transformer> transformerEngineMapping = new HashMap();
public void setCoreVersion(String coreVersion)
{
this.coreVersion = coreVersion;
}
/**
* Adds a transformer's (T-Engine) config to the configuration and creates a map of transforms to the T-Engine.
* The name of this method is now misleading as the registry of transforms takes place in
* {@link #registerCombinedTransformers()} .
* @param tEngine The transformer implementation, this could be a single transformer
* or a transformer managing multiple sub transformers. The transformer's configuration file will
* be read based on the {@link Transformer#getTransformerId()} value.
*/
public void registerTransformer(final Transformer tEngine) throws Exception
{
// Load config for the transformer
String location = getTransformConfigLocation(tEngine);
TransformConfig transformConfig = loadTransformConfig(location);
setCoreVersionOnSingleStepTransformers(transformConfig, coreVersion);
String transformerId = tEngine.getTransformerId();
combinedTransformConfig.addTransformConfig(transformConfig, location, transformerId, this);
// Map all of the transforms defined in the config to this Transformer implementation
for (org.alfresco.transform.client.model.config.Transformer transformerConfig : transformConfig.getTransformers())
{
String transformerName = transformerConfig.getTransformerName();
// A later tEngine 'might' override one that has already been defined. That is fine.
Transformer originalTEngine = transformerEngineMapping.get(transformerName);
if (originalTEngine != null)
{
log.debug("Overriding transform with name: '{}' originally defined in '{}'.", transformerName, originalTEngine.getTransformerId());
}
transformerEngineMapping.put(transformerName, tEngine);
log.debug("Registered transform with name: '{}' defined in '{}'.", transformerName, transformerId);
}
}
public void registerCombinedTransformers()
{
combinedTransformConfig.combineTransformerConfig(this);
combinedTransformConfig.registerCombinedTransformers(this);
}
/**
*
* @param transformName The transform name as it appears in TransformConfig.
* @return The transformer implementation mapped to the transform name.
*/
public Transformer getByTransformName(final String transformName)
{
return getTransformerEngineMapping().get(transformName);
}
/**
*
* @return The aggregated config of all the registered transformers
*/
public TransformConfig getTransformConfig()
{
return combinedTransformConfig.buildTransformConfig();
}
protected String getTransformConfigLocation(final Transformer transformer)
{
String location = transformer.getTransformerId() + ENGINE_CONFIG_LOCATION_POSTFIX;
return location;
}
protected TransformConfig loadTransformConfig(final String name) throws Exception
{
if (getClass().getClassLoader().getResource(name) == null)
{
throw new Exception("Configuration '" + name + "' does not exist on the classpath.");
}
try (InputStream is = getClass().getClassLoader().getResourceAsStream(name);
Reader reader = new InputStreamReader(is, UTF_8))
{
return jsonObjectMapper.readValue(reader, TransformConfig.class);
}
catch (IOException e)
{
throw new Exception("Could not read '" + name + "' from the classpath.", e);
}
}
Map<String, Transformer> getTransformerEngineMapping()
{
return transformerEngineMapping;
}
void setTransformerEngineMapping(Map<String, Transformer> transformerEngineMapping)
{
this.transformerEngineMapping = transformerEngineMapping;
}
@Override
public TransformCache getData()
{
return data;
}
@Override
protected void logError(String msg)
{
log.error(msg);
}
@Override
protected void logWarn(String msg)
{
log.warn(msg);
}
}

View File

@ -1,324 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.alfresco.transform.client.model.config.TransformConfig;
import org.alfresco.transformer.executors.TikaJavaExecutor;
import org.alfresco.transformer.executors.Transformer;
import org.alfresco.transformer.transformers.SelectingTransformer;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.alfresco.transformer.util.RequestParamMap.PAGE_LIMIT;
import static org.alfresco.transformer.util.RequestParamMap.TRANSFORM_NAME_PARAMETER;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class AIOTransformRegistryTest
{
private static final String SOURCE_MIMETYPE = "text/html";
private static final String TARGET_MIMETYPE = "text/plain";
String SOURCE_ENCODING = "sourceEncoding";
AIOTransformRegistry aioTransformerRegistry = new AIOTransformRegistry();
ObjectMapper objectMapper = new ObjectMapper();
@BeforeEach
public void before() throws Exception
{
aioTransformerRegistry.registerTransformer(new SelectingTransformer());
aioTransformerRegistry.registerTransformer(new TikaJavaExecutor());
aioTransformerRegistry.registerCombinedTransformers();
}
private void writeToFile(File file, String content, String encoding) throws Exception
{
try (OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream(file), encoding))
{
ow.append(content);
}
}
private String readFromFile(File file, final String encoding) throws Exception
{
return new String(Files.readAllBytes(file.toPath()), encoding);
}
private TransformConfig loadConfig(String s) throws Exception
{
return objectMapper.readValue(new ClassPathResource(s).getFile(), TransformConfig.class);
}
@Test
public void testConfigAggregation() throws Exception
{
List<String> expectedTransformNames = Arrays.asList("html", "string", "appleIWorks", "textToPdf", "rfc822",
"Archive", "OutlookMsg", "PdfBox", "Office", "Poi", "OOXML", "TikaAuto", "TextMining");
List<String> expectedTransformOptionNames = Arrays.asList("tikaOptions", "archiveOptions", "pdfboxOptions",
"textToPdfOptions", "stringOptions", "metadataOptions");
TransformConfig miscConfig = loadConfig("misc_engine_config.json");
TransformConfig tikaConfig = loadConfig("tika_engine_config.json");
// check correct number of transformers
assertEquals(
miscConfig.getTransformers().size() + tikaConfig.getTransformers().size(),
aioTransformerRegistry.getTransformConfig().getTransformers().size(),
"Number of expected transformers");
List<String> actualTransformerNames = aioTransformerRegistry.getTransformConfig().getTransformers()
.stream().map(t -> t.getTransformerName()).collect(Collectors.toList());
// check all transformers are there
for(String transformNames : expectedTransformNames)
{
assertTrue(actualTransformerNames.contains(transformNames),"Expected transformer missing.");
}
// check correct number of options
long distinctOptionCount = Stream.concat(
miscConfig.getTransformOptions().keySet().stream(),
tikaConfig.getTransformOptions().keySet().stream()).distinct().count();
assertEquals(
distinctOptionCount,
aioTransformerRegistry.getTransformConfig().getTransformOptions().size(),
"Number of expected transformers");
Set<String> actualOptionNames = aioTransformerRegistry.getTransformConfig().getTransformOptions().keySet();
// check all options are there
for (String optionName : expectedTransformOptionNames)
{
assertTrue(actualOptionNames.contains(optionName), "Expected transform option missing:"+optionName);
}
}
@Test
public void testTransformerMapping()
{
List<String> tikaTransforms = Arrays.asList("Archive", "OutlookMsg", "PdfBox", "Office", "Poi", "OOXML", "TikaAuto", "TextMining");
List<String> miscTransforms = Arrays.asList("html", "string", "appleIWorks", "textToPdf", "rfc822");
for (String transform : tikaTransforms)
{
String actualId = aioTransformerRegistry.getByTransformName(transform).getTransformerId();
assertEquals("tika", actualId, "Wrong mapping for transform "+transform);
}
for (String transform : miscTransforms)
{
String actualId = aioTransformerRegistry.getByTransformName(transform).getTransformerId();
assertEquals("misc", actualId, "Wrong mapping for transform "+transform);
}
}
// Test copied from Misc (HtmlParserContentTransformerTest) See ATS-712 aioTransformerRegistry - html
@Test
public void testMiscHtml() throws Exception
{
final String NEWLINE = System.getProperty("line.separator");
final String TITLE = "Testing!";
final String TEXT_P1 = "This is some text in English";
final String TEXT_P2 = "This is more text in English";
final String TEXT_P3 = "C'est en Fran\u00e7ais et Espa\u00f1ol";
String partA = "<html><head><title>" + TITLE + "</title></head>" + NEWLINE;
String partB = "<body><p>" + TEXT_P1 + "</p>" + NEWLINE +
"<p>" + TEXT_P2 + "</p>" + NEWLINE +
"<p>" + TEXT_P3 + "</p>" + NEWLINE;
String partC = "</body></html>";
final String expected = TITLE + NEWLINE + TEXT_P1 + NEWLINE + TEXT_P2 + NEWLINE + TEXT_P3 + NEWLINE;
File tmpS = null;
File tmpD = null;
try
{
// Content set to ISO 8859-1
tmpS = File.createTempFile("AlfrescoTestSource_", ".html");
writeToFile(tmpS, partA + partB + partC, "ISO-8859-1");
tmpD = File.createTempFile("AlfrescoTestTarget_", ".txt");
Map<String, String> parameters = new HashMap<>();
parameters.put(SOURCE_ENCODING, "ISO-8859-1");
Transformer transformer = aioTransformerRegistry.getByTransformName("html");
transformer.transformExtractOrEmbed("html", SOURCE_MIMETYPE, TARGET_MIMETYPE, parameters, tmpS, tmpD);
assertEquals(expected, readFromFile(tmpD, "UTF-8"));
tmpS.delete();
tmpD.delete();
// Content set to UTF-8
tmpS = File.createTempFile("AlfrescoTestSource_", ".html");
writeToFile(tmpS, partA + partB + partC, "UTF-8");
tmpD = File.createTempFile("AlfrescoTestTarget_", ".txt");
parameters = new HashMap<>();
parameters.put(SOURCE_ENCODING, "UTF-8");
transformer.transformExtractOrEmbed("html", SOURCE_MIMETYPE, TARGET_MIMETYPE, parameters, tmpS, tmpD);
assertEquals(expected, readFromFile(tmpD, "UTF-8"));
tmpS.delete();
tmpD.delete();
// Content set to UTF-16
tmpS = File.createTempFile("AlfrescoTestSource_", ".html");
writeToFile(tmpS, partA + partB + partC, "UTF-16");
tmpD = File.createTempFile("AlfrescoTestTarget_", ".txt");
parameters = new HashMap<>();
parameters.put(SOURCE_ENCODING, "UTF-16");
transformer.transformExtractOrEmbed("html", SOURCE_MIMETYPE, TARGET_MIMETYPE, parameters, tmpS, tmpD);
assertEquals(expected, readFromFile(tmpD, "UTF-8"));
tmpS.delete();
tmpD.delete();
// Note - since HTML Parser 2.0 META tags specifying the
// document encoding will ONLY be respected if the original
// content type was set to ISO-8859-1.
//
// This means there is now only one test which we can perform
// to ensure that this now-limited overriding of the encoding
// takes effect.
// Content set to ISO 8859-1, meta set to UTF-8
tmpS = File.createTempFile("AlfrescoTestSource_", ".html");
String str = partA +
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">" +
partB + partC;
writeToFile(tmpS, str, "UTF-8");
tmpD = File.createTempFile("AlfrescoTestTarget_", ".txt");
parameters = new HashMap<>();
parameters.put(SOURCE_ENCODING, "ISO-8859-1");
transformer.transformExtractOrEmbed("html", SOURCE_MIMETYPE, TARGET_MIMETYPE, parameters, tmpS, tmpD);
assertEquals(expected, readFromFile(tmpD, "UTF-8"));
tmpS.delete();
tmpD.delete();
// Note - we can't test UTF-16 with only a meta encoding,
// because without that the parser won't know about the
// 2 byte format so won't be able to identify the meta tag
}
finally
{
if (tmpS != null && tmpS.exists()) tmpS.delete();
if (tmpD != null && tmpD.exists()) tmpD.delete();
}
}
// Test copied from Misc (TextToPdfContentTransformerTest) See ATS-712 aioTransformerRegistry - pdf
@Test
public void testMiscPdf() throws Exception
{
transformTextAndCheckPageLength(-1);
}
private void transformTextAndCheckPageLength(int pageLimit) throws Exception
{
int pageLength = 32;
int lines = (pageLength + 10) * ((pageLimit > 0) ? pageLimit : 1);
StringBuilder sb = new StringBuilder();
String checkText = null;
int cutoff = pageLimit * pageLength;
for (int i = 1; i <= lines; i++)
{
sb.append(Integer.toString(i));
sb.append(" I must not talk in class or feed my homework to my cat.\n");
if (i == cutoff)
checkText = sb.toString();
}
sb.append("\nBart\n");
String text = sb.toString();
checkText = (checkText == null) ? clean(text) : clean(checkText);
transformTextAndCheck(text, "UTF-8", checkText, String.valueOf(pageLimit));
}
private void transformTextAndCheck(String text, String encoding, String checkText,
String pageLimit) throws Exception
{
// Get a reader for the text
File sourceFile = File.createTempFile("AlfrescoTestSource_", ".txt");
writeToFile(sourceFile, text, encoding);
// And a temp writer
File targetFile = File.createTempFile("AlfrescoTestTarget_", ".pdf");
// Transform to PDF
Map<String, String> parameters = new HashMap<>();
parameters.put(PAGE_LIMIT, pageLimit);
Transformer transformer = aioTransformerRegistry.getByTransformName("textToPdf");
transformer.transformExtractOrEmbed("textToPdf", "text/plain", "application/pdf", parameters, sourceFile, targetFile);
// Read back in the PDF and check it
PDDocument doc = PDDocument.load(targetFile);
PDFTextStripper textStripper = new PDFTextStripper();
StringWriter textWriter = new StringWriter();
textStripper.writeText(doc, textWriter);
doc.close();
String roundTrip = clean(textWriter.toString());
assertEquals(
checkText, roundTrip,
"Incorrect text in PDF when starting from text in " + encoding
);
sourceFile.delete();
targetFile.delete();
}
private String clean(String text)
{
text = text.replaceAll("\\s+\\r", "");
text = text.replaceAll("\\s+\\n", "");
text = text.replaceAll("\\r", "");
text = text.replaceAll("\\n", "");
return text;
}
}

View File

@ -1,131 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import org.alfresco.transformer.executors.ImageMagickCommandExecutor;
import org.alfresco.transformer.probes.ProbeTestTransform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import javax.annotation.PostConstruct;
import java.io.File;
import java.util.Collections;
import java.util.Map;
/**
* Controller for the Docker based ImageMagick transformer.
*
*
* Status Codes:
*
* 200 Success
* 400 Bad Request: Invalid cropGravity value (North, NorthEast, East, SouthEast, South, SouthWest, West, NorthWest, Center)
* 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 ImageMagickController extends AbstractTransformerController
{
private static final Logger logger = LoggerFactory.getLogger(ImageMagickController.class);
@Value("${transform.core.imagemagick.exe}")
private String EXE;
@Value("${transform.core.imagemagick.dyn}")
private String DYN;
@Value("${transform.core.imagemagick.root}")
private String ROOT;
@Value("${transform.core.imagemagick.coders}")
private String CODERS;
@Value("${transform.core.imagemagick.config}")
private String CONFIG;
ImageMagickCommandExecutor commandExecutor;
@PostConstruct
private void init()
{
commandExecutor = new ImageMagickCommandExecutor(EXE, DYN, ROOT, CODERS, CONFIG);
}
@Override
public String getTransformerName()
{
return "ImageMagick";
}
@Override
public String version()
{
return commandExecutor.version();
}
@Override
public ProbeTestTransform getProbeTestTransform()
{
// See the Javadoc on this method and Probes.md for the choice of these values.
return new ProbeTestTransform(this, "quick.jpg", "quick.png",
35593, 1024, 150, 1024, 60 * 15 + 1, 60 * 15)
{
@Override
protected void executeTransformCommand(File sourceFile, File targetFile)
{
transformImpl(null, null, null, Collections.emptyMap(), sourceFile, targetFile);
}
};
}
@Override
protected String getTransformerName(final File sourceFile, final String sourceMimetype,
final String targetMimetype, final Map<String, String> transformOptions)
{
return null; // does not matter what value is returned, as it is not used because there is only one.
}
@Override
public void transformImpl(String transformName, String sourceMimetype, String targetMimetype,
Map<String, String> transformOptions, File sourceFile, File targetFile)
{
commandExecutor.transformExtractOrEmbed(transformName, sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile);
}
}

View File

@ -1,107 +0,0 @@
The authoritative ImageMagick license can be found at
https://imagemagick.org/script/license.php and ImageMagick notices at
https://raw.githubusercontent.com/ImageMagick/ImageMagick/main/NOTICE.
Before we get to the text of the license, lets just review what the license says in simple terms:
It allows you to:
* freely download and use ImageMagick software, in whole or in part, for personal, company internal, or commercial purposes;
* use ImageMagick software in packages or distributions that you create;
* link against a library under a different license;
* link code under a different license against a library under this license;
* merge code into a work under a different license;
* extend patent grants to any code using code under this license;
* and extend patent protection.
It forbids you to:
* redistribute any piece of ImageMagick-originated software without proper attribution;
* use any marks owned by ImageMagick Studio LLC in any way that might state or imply that ImageMagick Studio LLC endorses your distribution;
* use any marks owned by ImageMagick Studio LLC in any way that might state or imply that you created the ImageMagick software in question.
It requires you to:
* include a copy of the license in any redistribution you may make that includes ImageMagick software;
* provide clear attribution to ImageMagick Studio LLC for any distributions that include ImageMagick software.
It does not require you to:
* include the source of the ImageMagick software itself, or of any modifications you may have made to it, in any redistribution you may assemble that includes it;
* submit changes that you make to the software back to the ImageMagick Studio LLC (though such feedback is encouraged).
A few other clarifications include:
* ImageMagick is freely available without charge;
* you may include ImageMagick on a DVD as long as you comply with the terms of the license;
* you can give modified code away for free or sell it under the terms of the ImageMagick license or distribute the result under a different license, but you need to acknowledge the use of the ImageMagick software;
* the license is compatible with the GPL V3.
* when exporting the ImageMagick software, review its export classification.
Terms and Conditions for Use, Reproduction, and Distribution
The legally binding and authoritative terms and conditions for use, reproduction, and distribution of ImageMagick follow:
Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization dedicated to making software imaging solutions freely available.
1. Definitions.
License shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
Legal Entity shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, control means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
You (or Your) shall mean an individual or Legal Entity exercising permissions granted by this License.
Source form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
Object form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
Work shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
Derivative Works shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
Contribution shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as Not a Contribution.
Contributor shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
* You must give any other recipients of the Work or Derivative Works a copy of this License; and
* You must cause any modified files to carry prominent notices stating that You changed the files; and
* You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
* If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
How to Apply the License to your Work
To apply the ImageMagick License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information (don't include the brackets). The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the ImageMagick License (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy
of the License at
https://imagemagick.org/script/license.php
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.

View File

@ -1,43 +0,0 @@
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div>
<h2>ImageMagick Test Transformation</h2>
<form method="POST" enctype="multipart/form-data" action="/transform">
<table>
<tr><td><div style="text-align:right">file *</div></td><td><input type="file" name="file" /></td></tr>
<tr><td><div style="text-align:right">targetExtension *</div></td><td><input type="text" name="targetExtension" value="" /></td></tr>
<tr><td><div style="text-align:right">timeout</div></td><td><input type="text" name="timeout" value="" /></td></tr>
<tr><td><div style="text-align:right">testDelay</div></td><td><input type="text" name="testDelay" value="" /></td></tr>
<tr><td><div style="text-align:right">startPage</div></td><td><input type="text" name="startPage" /></td></tr>
<tr><td><div style="text-align:right">endPage</div></td><td><input type="text" name="endPage" /></td></tr>
<tr><td><div style="text-align:right">alphaRemove</div></td><td><input type="text" name="alphaRemove" /></td></tr>
<tr><td><div style="text-align:right">autoOrient</div></td><td><input type="text" name="autoOrient" /></td></tr>
<tr><td><div style="text-align:right">cropGravity</div></td><td><input type="text" name="cropGravity" />North, NorthEast...Center</td></tr>
<tr><td><div style="text-align:right">cropWidth</div></td><td><input type="text" name="cropWidth" /></td></tr>
<tr><td><div style="text-align:right">cropHeight</div></td><td><input type="text" name="cropHeight" /></td></tr>
<tr><td><div style="text-align:right">cropPercentage</div></td><td><input type="checkbox" name="cropPercentage" value="true" /></td></tr>
<tr><td><div style="text-align:right">cropXOffset</div></td><td><input type="text" name="cropXOffset" /></td></tr>
<tr><td><div style="text-align:right">cropYOffset</div></td><td><input type="text" name="cropYOffset" /></td></tr>
<tr><td><div style="text-align:right">thumbnail</div></td><td><input type="checkbox" name="thumbnail" value="true" /></td></tr>
<tr><td><div style="text-align:right">resizeWidth</div></td><td><input type="text" name="resizeWidth" value="" /></td></tr>
<tr><td><div style="text-align:right">resizeHeight</div></td><td><input type="text" name="resizeHeight" value="" /></td></tr>
<tr><td><div style="text-align:right">resizePercentage</div></td><td><input type="checkbox" name="resizePercentage" value="true" /></td></tr>
<tr><td><div style="text-align:right">allowEnlargement</div></td><td><input type="checkbox" name="allowEnlargement" value="true" /></td></tr>
<tr><td><div style="text-align:right">maintainAspectRatio</div></td><td><input type="checkbox" name="maintainAspectRatio" value="true" /></td></tr>
<tr><td></td><td><input type="submit" value="Transform" /></td></tr>
</table>
</form>
</div>
<div>
<a href="/log">Log entries</a>
</div>
</body>
</html>

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfresco-transform-imagemagick</artifactId>
<name>Alfresco ImageMagick Transformer</name>
<parent>
<artifactId>alfresco-transform-core</artifactId>
<groupId>org.alfresco</groupId>
<version>2.7.0-A2-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-transformer-base</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,80 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2020 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import io.micrometer.core.instrument.MeterRegistry;
import org.alfresco.transformer.executors.LibreOfficeJavaExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
import java.util.Arrays;
import static org.alfresco.transformer.logging.StandardMessages.LICENCE;
@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class Application
{
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Value("${container.name}")
private String containerName;
@Bean
MeterRegistryCustomizer<MeterRegistry> metricsCommonTags()
{
return registry -> registry.config().commonTags("containerName", containerName);
}
// To run the LibreOffice T-Engine from the command line on a Mac, you generally need to
// install LibreOffice and add: -Dtransform.core.libreoffice.path=/Applications/LibreOffice.app/Contents/
// to the start up command.
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
@EventListener(ApplicationReadyEvent.class)
public void startup()
{
logger.info("-------------------------------------------------------------------------------------------------------------------------------------------------------");
Arrays.stream(LICENCE.split("\\n")).forEach(logger::info);
logger.info(LibreOfficeJavaExecutor.LICENCE);
logger.info("-------------------------------------------------------------------------------------------------------------------------------------------------------");
logger.info("Starting application components... Done");
}
}

View File

@ -1,133 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import org.alfresco.transformer.executors.LibreOfficeJavaExecutor;
import org.alfresco.transformer.probes.ProbeTestTransform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import javax.annotation.PostConstruct;
import java.io.File;
import java.util.Collections;
import java.util.Map;
/**
* Controller for the Docker based LibreOffice transformer.
*
* Status Codes:
*
* 200 Success
* 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 LibreOfficeController extends AbstractTransformerController
{
private static final Logger logger = LoggerFactory.getLogger(LibreOfficeController.class);
@Value("${transform.core.libreoffice.path}")
private String execPath;
@Value("${transform.core.libreoffice.maxTasksPerProcess}")
private String maxTasksPerProcess;
@Value("${transform.core.libreoffice.timeout}")
private String timeout;
@Value("${transform.core.libreoffice.portNumbers}")
private String portNumbers;
@Value("${transform.core.libreoffice.templateProfileDir}")
private String templateProfileDir;
@Value("${transform.core.libreoffice.isEnabled}")
private String isEnabled;
LibreOfficeJavaExecutor javaExecutor;
@PostConstruct
private void init()
{
javaExecutor = new LibreOfficeJavaExecutor(execPath, maxTasksPerProcess, timeout, portNumbers, templateProfileDir, isEnabled);
}
@Override
public String getTransformerName()
{
return "LibreOffice";
}
@Override
public String version()
{
return "LibreOffice available";
}
@Override
public ProbeTestTransform getProbeTestTransform()
{
// See the Javadoc on this method and Probes.md for the choice of these values.
return new ProbeTestTransform(this, "quick.doc", "quick.pdf",
11817, 1024, 150, 10240, 60 * 30 + 1, 60 * 15 + 20)
{
@Override
protected void executeTransformCommand(File sourceFile, File targetFile)
{
transformImpl(null, null, null, Collections.emptyMap(), sourceFile, targetFile);
javaExecutor.call(sourceFile, targetFile);
}
};
}
@Override
protected String getTransformerName(final File sourceFile, final String sourceMimetype,
final String targetMimetype, final Map<String, String> transformOptions)
{
return null; // does not matter what value is returned, as it is not used because there is only one.
}
@Override
public void transformImpl(String transformName, String sourceMimetype, String targetMimetype,
Map<String, String> transformOptions, File sourceFile, File targetFile)
{
javaExecutor.transformExtractOrEmbed(transformName, sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile);
}
}

View File

@ -1 +0,0 @@
#logging.level.org.alfresco.transformer.LibreOfficeController=debug

View File

@ -1,25 +0,0 @@
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div>
<h2>LibreOffice Test Transformation</h2>
<form method="POST" enctype="multipart/form-data" action="/transform">
<table>
<tr><td><div style="text-align:right">file *</div></td><td><input type="file" name="file" /></td></tr>
<tr><td><div style="text-align:right">sourceMimetype *</div></td><td><input type="text" name="sourceMimetype" value="" /></td></tr>
<tr><td><div style="text-align:right">targetMimetype</div></td><td><input type="text" name="targetMimetype" value="" /></td></tr>
<tr><td><div style="text-align:right">targetExtension *</div></td><td><input type="text" name="targetExtension" value="" /></td></tr>
<tr><td><div style="text-align:right">timeout</div></td><td><input type="text" name="timeout" value="" /></td></tr>
<tr><td><div style="text-align:right">testDelay</div></td><td><input type="text" name="testDelay" value="" /></td></tr>
<tr><td></td><td><input type="submit" value="Transform" /></td></tr>
</table>
</form>
</div>
<div>
<a href="/log">Log entries</a>
</div>
</body>
</html>

View File

@ -1,46 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfresco-transform-libreoffice</artifactId>
<name>Alfresco LibreOffice Transformer</name>
<parent>
<artifactId>alfresco-transform-core</artifactId>
<groupId>org.alfresco</groupId>
<version>2.7.0-A2-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-transformer-base</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-jodconverter-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,77 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2020 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import io.micrometer.core.instrument.MeterRegistry;
import org.alfresco.transformer.transformers.SelectingTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
import java.util.Arrays;
import static org.alfresco.transformer.logging.StandardMessages.LICENCE;
@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class Application
{
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Value("${container.name}")
private String containerName;
@Bean
MeterRegistryCustomizer<MeterRegistry> metricsCommonTags()
{
return registry -> registry.config().commonTags("containerName", containerName);
}
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
@EventListener(ApplicationReadyEvent.class)
public void startup()
{
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
Arrays.stream(LICENCE.split("\\n")).forEach(logger::info);
Arrays.stream(SelectingTransformer.LICENCE.split("\\n")).forEach(logger::info);
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
logger.info("Starting application components... Done");
}
}

View File

@ -1,88 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import org.alfresco.transformer.probes.ProbeTestTransform;
import org.alfresco.transformer.transformers.SelectingTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_HTML;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
import static org.alfresco.transformer.util.RequestParamMap.SOURCE_ENCODING;
import static org.alfresco.transformer.util.RequestParamMap.TRANSFORM_NAME_PARAMETER;
@Controller
public class MiscController extends AbstractTransformerController
{
private static final Logger logger = LoggerFactory.getLogger(MiscController.class);
private SelectingTransformer transformer = new SelectingTransformer();
@Override
public String getTransformerName()
{
return "Miscellaneous Transformers";
}
@Override
public String version()
{
return getTransformerName() + " available";
}
@Override
public ProbeTestTransform getProbeTestTransform()
{
// HtmlParserContentTransformer html -> text
// See the Javadoc on this method and Probes.md for the choice of these values.
return new ProbeTestTransform(this, "quick.html", "quick.txt",
119, 30, 150, 1024,
60 * 2 + 1, 60 * 2)
{
@Override
protected void executeTransformCommand(File sourceFile, File targetFile)
{
Map<String, String> parameters = new HashMap<>();
parameters.put(SOURCE_ENCODING, "UTF-8");
transformImpl("html", MIMETYPE_HTML, MIMETYPE_TEXT_PLAIN, parameters, sourceFile, targetFile);
}
};
}
@Override
public void transformImpl(String transformName, String sourceMimetype, String targetMimetype,
Map<String, String> transformOptions, File sourceFile, File targetFile)
{
transformer.transformExtractOrEmbed(transformName, sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile);
}
}

View File

@ -1,7 +0,0 @@
queue:
engineRequestQueue: ${TRANSFORM_ENGINE_REQUEST_QUEUE:org.alfresco.transform.engine.misc.acs}
transform:
core:
version: @project.version@
config:
location: classpath:misc_engine_config.json

View File

@ -1,29 +0,0 @@
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div>
<h2>Miscellaneous Transformers Test Transformation</h2>
<form method="POST" enctype="multipart/form-data" action="/transform">
<table>
<tr><td><div style="text-align:right">file *</div></td><td><input type="file" name="file" /></td></tr>
<tr><td><div style="text-align:right">sourceExtension *</div></td><td><input type="text" name="sourceExtension" value="" /></td></tr>
<tr><td><div style="text-align:right">targetExtension *</div></td><td><input type="text" name="targetExtension" value="" /></td></tr>
<tr><td><div style="text-align:right">sourceMimetype *</div></td><td><input type="text" name="sourceMimetype" value="" /></td></tr>
<tr><td><div style="text-align:right">targetMimetype *</div></td><td><input type="text" name="targetMimetype" value="" /></td></tr>
<tr><td><div style="text-align:right">sourceEncoding *</div></td><td><input type="text" name="sourceEncoding" value="" /></td></tr>
<tr><td><div style="text-align:right">targetEncoding *</div></td><td><input type="text" name="targetEncoding" value="" /></td></tr>
<tr><td><div style="text-align:right">timeout</div></td><td><input type="text" name="timeout" value="" /></td></tr>
<tr><td><div style="text-align:right">testDelay</div></td><td><input type="text" name="testDelay" value="" /></td></tr>
<tr><td></td><td><input type="submit" value="Transform" /></td></tr>
</table>
</form>
</div>
<div>
<a href="/log">Log entries</a>
</div>
</body>
</html>

View File

@ -1,96 +0,0 @@
{
"transformOptions": {
"textToPdfOptions": [
{"value": {"name": "pageLimit"}}
],
"stringOptions": [
{"value": {"name": "targetEncoding"}}
],
"metadataOptions": [
{"value": {"name": "extractMapping"}}
]
},
"transformers": [
{
"transformerName": "html",
"supportedSourceAndTargetList": [
{"sourceMediaType": "text/html", "targetMediaType": "text/plain"}
],
"transformOptions": [
]
},
{
"transformerName": "string",
"supportedSourceAndTargetList": [
{"sourceMediaType": "text/plain", "targetMediaType": "text/plain"},
{"sourceMediaType": "text/mediawiki", "targetMediaType": "text/plain"},
{"sourceMediaType": "text/css", "targetMediaType": "text/plain"},
{"sourceMediaType": "text/csv", "targetMediaType": "text/plain"},
{"sourceMediaType": "text/xml", "targetMediaType": "text/plain"},
{"sourceMediaType": "text/html", "priority": 55, "targetMediaType": "text/plain"},
{"sourceMediaType": "text/richtext", "targetMediaType": "text/plain"},
{"sourceMediaType": "text/sgml", "targetMediaType": "text/plain"},
{"sourceMediaType": "text/tab-separated-values", "targetMediaType": "text/plain"},
{"sourceMediaType": "text/x-setext", "targetMediaType": "text/plain"},
{"sourceMediaType": "text/x-java-source", "targetMediaType": "text/plain"},
{"sourceMediaType": "text/x-jsp", "targetMediaType": "text/plain"},
{"sourceMediaType": "text/x-markdown", "targetMediaType": "text/plain"},
{"sourceMediaType": "text/calendar", "targetMediaType": "text/plain"},
{"sourceMediaType": "application/x-javascript", "targetMediaType": "text/plain"},
{"sourceMediaType": "application/dita+xml", "targetMediaType": "text/plain"}
],
"transformOptions": [
"stringOptions"
]
},
{
"transformerName": "appleIWorks",
"supportedSourceAndTargetList": [
{"sourceMediaType": "application/vnd.apple.keynote", "targetMediaType": "image/jpeg"},
{"sourceMediaType": "application/vnd.apple.numbers", "targetMediaType": "image/jpeg"},
{"sourceMediaType": "application/vnd.apple.pages", "targetMediaType": "image/jpeg"}
],
"transformOptions": [
]
},
{
"transformerName": "textToPdf",
"supportedSourceAndTargetList": [
{"sourceMediaType": "text/plain", "priority": 55, "targetMediaType": "application/pdf"},
{"sourceMediaType": "text/csv", "targetMediaType": "application/pdf"},
{"sourceMediaType": "application/dita+xml", "targetMediaType": "application/pdf"},
{"sourceMediaType": "text/xml", "targetMediaType": "application/pdf"}
],
"transformOptions": [
"textToPdfOptions"
]
},
{
"transformerName": "rfc822",
"supportedSourceAndTargetList": [
{"sourceMediaType": "message/rfc822", "targetMediaType": "text/plain"}
],
"transformOptions": [
]
},
{
"transformerName": "HtmlMetadataExtractor",
"supportedSourceAndTargetList": [
{"sourceMediaType": "text/html", "targetMediaType": "alfresco-metadata-extract"},
{"sourceMediaType": "application/xhtml+xml", "targetMediaType": "alfresco-metadata-extract"}
],
"transformOptions": [
"metadataOptions"
]
},
{
"transformerName": "RFC822MetadataExtractor",
"supportedSourceAndTargetList": [
{"sourceMediaType": "message/rfc822", "targetMediaType": "alfresco-metadata-extract"}
],
"transformOptions": [
"metadataOptions"
]
}
]
}

View File

@ -1,86 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfresco-transform-misc</artifactId>
<name>Alfresco Miscellaneous Transformer</name>
<parent>
<artifactId>alfresco-transform-core</artifactId>
<groupId>org.alfresco</groupId>
<version>2.7.0-A2-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-transformer-base</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
</dependency>
<!-- HtmlParserContentTransformer -->
<dependency>
<groupId>org.htmlparser</groupId>
<artifactId>htmlparser</artifactId>
<version>2.1</version>
</dependency>
<!-- AppleIWorksContentTransformer -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
</dependency>
<!-- TextToPdfContentTransformer -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>2.0.26</version>
</dependency>
<!-- OOXMLThumbnailContentTransformer -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${dependency.poi.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>${dependency.ooxml-schemas.version}</version>
</dependency>
<!-- EMLTransformer -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,195 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005-2020 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer.metadataExtractors;
import org.alfresco.transformer.transformers.SelectableTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.mail.Header;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import javax.mail.internet.MimeUtility;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Metadata extractor for RFC822 mime emails.
*
* Configuration: (see HtmlMetadataExtractor_metadata_extract.properties and misc_engine_config.json)
*
* <pre>
* <b>messageFrom:</b> -- imap:messageFrom, cm:originator
* <b>messageTo:</b> -- imap:messageTo
* <b>messageCc:</b> -- imap:messageCc
* <b>messageSubject:</b> -- imap:messageSubject, cm:title, cm:description, cm:subjectline
* <b>messageSent:</b> -- imap:dateSent, cm:sentdate
* <b>messageReceived:</b> -- imap:dateReceived
* <b>All {@link Header#getName() header names}:</b>
* <b>Thread-Index:</b> -- imap:threadIndex
* <b>Message-ID:</b> -- imap:messageId
* </pre>
*
* @author Derek Hulley
* @author adavis
*/
public class RFC822MetadataExtractor extends AbstractMetadataExtractor implements SelectableTransformer
{
private static final Logger logger = LoggerFactory.getLogger(HtmlMetadataExtractor.class);
protected static final String KEY_MESSAGE_FROM = "messageFrom";
protected static final String KEY_MESSAGE_TO = "messageTo";
protected static final String KEY_MESSAGE_CC = "messageCc";
protected static final String KEY_MESSAGE_SUBJECT = "messageSubject";
protected static final String KEY_MESSAGE_SENT = "messageSent";
protected static final String KEY_MESSAGE_RECEIVED = "messageReceived";
public RFC822MetadataExtractor()
{
super(logger);
}
@Override
public void extractMetadata(String sourceMimetype, String targetMimetype, Map<String, String> transformOptions,
File sourceFile, File targetFile) throws Exception
{
extractMetadata(sourceMimetype, transformOptions, sourceFile, targetFile);
}
@Override
public Map<String, Serializable> extractMetadata(String sourceMimetype, Map<String, String> transformOptions,
File sourceFile) throws Exception
{
final Map<String, Serializable> rawProperties = new HashMap<>();
try (InputStream is = new FileInputStream(sourceFile))
{
MimeMessage mimeMessage = new MimeMessage(null, is);
if (mimeMessage != null)
{
/**
* Extract RFC822 values that doesn't match to headers and need to be encoded.
* Or those special fields that require some code to extract data
*/
String tmp = InternetAddress.toString(mimeMessage.getFrom());
tmp = tmp != null ? MimeUtility.decodeText(tmp) : null;
putRawValue(KEY_MESSAGE_FROM, tmp, rawProperties);
tmp = InternetAddress.toString(mimeMessage.getRecipients(RecipientType.TO));
tmp = tmp != null ? MimeUtility.decodeText(tmp) : null;
putRawValue(KEY_MESSAGE_TO, tmp, rawProperties);
tmp = InternetAddress.toString(mimeMessage.getRecipients(RecipientType.CC));
tmp = tmp != null ? MimeUtility.decodeText(tmp) : null;
putRawValue(KEY_MESSAGE_CC, tmp, rawProperties);
putRawValue(KEY_MESSAGE_SENT, mimeMessage.getSentDate(), rawProperties);
/**
* Received field from RFC 822
*
* "Received" ":" ; one per relay
* ["from" domain] ; sending host
* ["by" domain] ; receiving host
* ["via" atom] ; physical path
* ("with" atom) ; link/mail protocol
* ["id" msg-id] ; receiver msg id
* ["for" addr-spec] ; initial form
* ";" date-time ; time received
*/
Date rxDate = mimeMessage.getReceivedDate();
if(rxDate != null)
{
// The email implementation extracted the received date for us.
putRawValue(KEY_MESSAGE_RECEIVED, rxDate, rawProperties);
}
else
{
// the email implementation did not parse the received date for us.
String[] rx = mimeMessage.getHeader("received");
if(rx != null && rx.length > 0)
{
String lastReceived = rx[0];
lastReceived = MimeUtility.unfold(lastReceived);
int x = lastReceived.lastIndexOf(';');
if(x > 0)
{
String dateStr = lastReceived.substring(x + 1).trim();
putRawValue(KEY_MESSAGE_RECEIVED, dateStr, rawProperties);
}
}
}
String[] subj = mimeMessage.getHeader("Subject");
if (subj != null && subj.length > 0)
{
String decodedSubject = subj[0];
try
{
decodedSubject = MimeUtility.decodeText(decodedSubject);
}
catch (UnsupportedEncodingException e)
{
logger.warn(e.toString());
}
putRawValue(KEY_MESSAGE_SUBJECT, decodedSubject, rawProperties);
}
/*
* Extract values from all header fields, including extension fields "X-"
*/
Set<String> keys = getExtractMapping().keySet();
@SuppressWarnings("unchecked")
Enumeration<Header> headers = mimeMessage.getAllHeaders();
while (headers.hasMoreElements())
{
Header header = (Header) headers.nextElement();
if (keys.contains(header.getName()))
{
tmp = header.getValue();
tmp = tmp != null ? MimeUtility.decodeText(tmp) : null;
putRawValue(header.getName(), tmp, rawProperties);
}
}
}
}
return rawProperties;
}
}

View File

@ -1,114 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2020 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer.transformers;
import com.google.common.collect.ImmutableMap;
import org.alfresco.transformer.executors.Transformer;
import org.alfresco.transformer.logging.LogEntry;
import org.alfresco.transformer.metadataExtractors.HtmlMetadataExtractor;
import org.alfresco.transformer.metadataExtractors.RFC822MetadataExtractor;
import java.io.File;
import java.util.Map;
import java.util.StringJoiner;
import static org.alfresco.transformer.util.RequestParamMap.TRANSFORM_NAME_PARAMETER;
/**
* The SelectingTransformer selects a registered {@link SelectableTransformer}
* and delegates the transformation to its implementation.
*
* @author eknizat
*/
public class SelectingTransformer implements Transformer
{
private static final String ID = "misc";
public static final String LICENCE =
"This transformer uses libraries from Apache. See the license at http://www.apache.org/licenses/LICENSE-2.0. or in /Apache\\\\ 2.0.txt\\n" +
"Additional libraries used:\n" +
"* htmlparser http://htmlparser.sourceforge.net/license.html";
private final Map<String, SelectableTransformer> transformers = ImmutableMap
.<String, SelectableTransformer>builder()
.put("appleIWorks", new AppleIWorksContentTransformer())
.put("html", new HtmlParserContentTransformer())
.put("string", new StringExtractingContentTransformer())
.put("textToPdf", new TextToPdfContentTransformer())
.put("rfc822", new EMLTransformer())
.put("ooXmlThumbnail", new OOXMLThumbnailContentTransformer())
.put("HtmlMetadataExtractor", new HtmlMetadataExtractor())
.put("RFC822MetadataExtractor", new RFC822MetadataExtractor())
.build();
@Override
public String getTransformerId()
{
return ID;
}
@Override
public void transform(String transformName, String sourceMimetype, String targetMimetype,
Map<String, String> transformOptions,
File sourceFile, File targetFile) throws Exception
{
final SelectableTransformer transformer = transformers.get(transformName);
logOptions(sourceFile, targetFile, transformOptions);
transformer.transform(sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile);
}
public void extractMetadata(String transformName, String sourceMimetype, String targetMimetype,
Map<String, String> transformOptions,
File sourceFile, File targetFile) throws Exception
{
final SelectableTransformer transformer = transformers.get(transformName);
logOptions(sourceFile, targetFile, transformOptions);
transformer.extractMetadata(sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile);
}
private static void logOptions(File sourceFile, File targetFile, Map<String, String> parameters)
{
StringJoiner sj = new StringJoiner(" ");
parameters.forEach((k, v) ->
{
if (!TRANSFORM_NAME_PARAMETER.equals(k))
{
sj.add("--" + k + "=" + v);
}
}); // keeping the existing style used in other T-Engines
sj.add(getExtension(sourceFile));
sj.add(getExtension(targetFile));
LogEntry.setOptions(sj.toString());
}
private static String getExtension(File file)
{
final String name = file.getName();
int i = name.lastIndexOf('.');
return i == -1 ? "???" : name.substring(i + 1);
}
}

View File

@ -1,4 +0,0 @@
# alfresco-transform-model
Alfresco Transform Model - Contains the data model of json configuration files
and messages sent between clients, T-Engines and T-Router. Also contains code to
work out which transform should be used for a combination of configuration files.

View File

@ -1,364 +0,0 @@
/*
* #%L
* Alfresco Transform Model
* %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited
* %%
* This program 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.
*
* This program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* #L%
*/
package org.alfresco.transform.client.model;
import static java.util.Arrays.stream;
import static java.util.Collections.unmodifiableSet;
import static java.util.stream.Collectors.toSet;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Objects;
import java.util.Set;
/**
* Mimetype
* <p>
* The same mimetypes defined in org.alfresco.repo.content.MimetypeMap
*/
public class Mimetype
{
//region Prefixes
public static final String PREFIX_APPLICATION = "application/";
public static final String PREFIX_AUDIO = "audio/";
public static final String PREFIX_IMAGE = "image/";
public static final String PREFIX_MESSAGE = "message/";
public static final String PREFIX_MODEL = "model/";
public static final String PREFIX_MULTIPART = "multipart/";
public static final String PREFIX_TEXT = "text/";
public static final String PREFIX_VIDEO = "video/";
public static final String EXTENSION_BINARY = "bin";
public static final String MACOS_RESOURCE_FORK_FILE_NAME_PREFIX = "._";
//endregion
//region Misc
public static final String MIMETYPE_MULTIPART_ALTERNATIVE = "multipart/alternative";
public static final String MIMETYPE_TEXT_PLAIN = "text/plain";
public static final String MIMETYPE_TEXT_MEDIAWIKI = "text/mediawiki";
public static final String MIMETYPE_TEXT_CSS = "text/css";
public static final String MIMETYPE_TEXT_CSV = "text/csv";
public static final String MIMETYPE_TEXT_JAVASCRIPT = "text/javascript";
public static final String MIMETYPE_XML = "text/xml";
public static final String MIMETYPE_HTML = "text/html";
public static final String MIMETYPE_XHTML = "application/xhtml+xml";
public static final String MIMETYPE_PDF = "application/pdf";
public static final String MIMETYPE_JSON = "application/json";
public static final String MIMETYPE_WORD = "application/msword";
public static final String MIMETYPE_EXCEL = "application/vnd.ms-excel";
public static final String MIMETYPE_BINARY = "application/octet-stream";
public static final String MIMETYPE_PPT = "application/vnd.ms-powerpoint";
public static final String MIMETYPE_APP_DWG = "application/dwg";
public static final String MIMETYPE_IMG_DWG = "image/vnd.dwg";
public static final String MIMETYPE_VIDEO_AVI = "video/x-msvideo";
public static final String MIMETYPE_VIDEO_QUICKTIME = "video/quicktime";
public static final String MIMETYPE_VIDEO_WMV = "video/x-ms-wmv";
public static final String MIMETYPE_VIDEO_3GP = "video/3gpp";
public static final String MIMETYPE_VIDEO_3GP2 = "video/3gpp2";
public static final String MIMETYPE_DITA = "application/dita+xml";
//endregion
//region Flash
public static final String MIMETYPE_FLASH = "application/x-shockwave-flash";
public static final String MIMETYPE_VIDEO_FLV = "video/x-flv";
public static final String MIMETYPE_APPLICATION_FLA = "application/x-fla";
public static final String MIMETYPE_VIDEO_MPG = "video/mpeg";
public static final String MIMETYPE_VIDEO_MP4 = "video/mp4";
public static final String MIMETYPE_IMAGE_GIF = "image/gif";
public static final String MIMETYPE_IMAGE_JPEG = "image/jpeg";
public static final String MIMETYPE_IMAGE_RGB = "image/x-rgb";
public static final String MIMETYPE_IMAGE_SVG = "image/svg+xml";
public static final String MIMETYPE_IMAGE_PNG = "image/png";
public static final String MIMETYPE_IMAGE_TIFF = "image/tiff";
public static final String MIMETYPE_IMAGE_RAW_DNG = "image/x-raw-adobe";
public static final String MIMETYPE_IMAGE_RAW_3FR = "image/x-raw-hasselblad";
public static final String MIMETYPE_IMAGE_RAW_RAF = "image/x-raw-fuji";
public static final String MIMETYPE_IMAGE_RAW_CR2 = "image/x-raw-canon";
public static final String MIMETYPE_IMAGE_RAW_K25 = "image/x-raw-kodak";
public static final String MIMETYPE_IMAGE_RAW_MRW = "image/x-raw-minolta";
public static final String MIMETYPE_IMAGE_RAW_NEF = "image/x-raw-nikon";
public static final String MIMETYPE_IMAGE_RAW_ORF = "image/x-raw-olympus";
public static final String MIMETYPE_IMAGE_RAW_PEF = "image/x-raw-pentax";
public static final String MIMETYPE_IMAGE_RAW_ARW = "image/x-raw-sony";
public static final String MIMETYPE_IMAGE_RAW_X3F = "image/x-raw-sigma";
public static final String MIMETYPE_IMAGE_RAW_RW2 = "image/x-raw-panasonic";
public static final String MIMETYPE_IMAGE_RAW_RWL = "image/x-raw-leica";
public static final String MIMETYPE_IMAGE_RAW_R3D = "image/x-raw-red";
public static final String MIMETYPE_IMAGE_DWT = "image/x-dwt";
public static final String MIMETYPE_APPLICATION_EPS = "application/eps";
public static final String MIMETYPE_APPLICATION_PS = "application/postscript";
public static final String MIMETYPE_JAVASCRIPT = "application/x-javascript";
public static final String MIMETYPE_ZIP = "application/zip";
public static final String MIMETYPE_OPENSEARCH_DESCRIPTION = "application/opensearchdescription+xml";
public static final String MIMETYPE_ATOM = "application/atom+xml";
public static final String MIMETYPE_RSS = "application/rss+xml";
public static final String MIMETYPE_RFC822 = "message/rfc822";
public static final String MIMETYPE_OUTLOOK_MSG = "application/vnd.ms-outlook";
public static final String MIMETYPE_VISIO = "application/vnd.visio";
public static final String MIMETYPE_VISIO_2013 = "application/vnd.visio2013";
//endregion
//region Adobe
public static final String MIMETYPE_APPLICATION_ILLUSTRATOR = "application/illustrator";
public static final String MIMETYPE_APPLICATION_PHOTOSHOP = "image/vnd.adobe.photoshop";
//endregion
//region Encrypted office document
public static final String MIMETYPE_ENCRYPTED_OFFICE = "application/x-tika-ooxml-protected";
//endregion
//region Open Document
public static final String MIMETYPE_OPENDOCUMENT_TEXT = "application/vnd.oasis.opendocument.text";
public static final String MIMETYPE_OPENDOCUMENT_TEXT_TEMPLATE = "application/vnd.oasis.opendocument.text-template";
public static final String MIMETYPE_OPENDOCUMENT_GRAPHICS = "application/vnd.oasis.opendocument.graphics";
public static final String MIMETYPE_OPENDOCUMENT_GRAPHICS_TEMPLATE = "application/vnd.oasis.opendocument.graphics-template";
public static final String MIMETYPE_OPENDOCUMENT_PRESENTATION = "application/vnd.oasis.opendocument.presentation";
public static final String MIMETYPE_OPENDOCUMENT_PRESENTATION_TEMPLATE = "application/vnd.oasis.opendocument.presentation-template";
public static final String MIMETYPE_OPENDOCUMENT_SPREADSHEET = "application/vnd.oasis.opendocument.spreadsheet";
public static final String MIMETYPE_OPENDOCUMENT_SPREADSHEET_TEMPLATE = "application/vnd.oasis.opendocument.spreadsheet-template";
public static final String MIMETYPE_OPENDOCUMENT_CHART = "application/vnd.oasis.opendocument.chart";
public static final String MIMETYPE_OPENDOCUMENT_CHART_TEMPLATE = "applicationvnd.oasis.opendocument.chart-template";
public static final String MIMETYPE_OPENDOCUMENT_IMAGE = "application/vnd.oasis.opendocument.image";
public static final String MIMETYPE_OPENDOCUMENT_IMAGE_TEMPLATE = "applicationvnd.oasis.opendocument.image-template";
public static final String MIMETYPE_OPENDOCUMENT_FORMULA = "application/vnd.oasis.opendocument.formula";
public static final String MIMETYPE_OPENDOCUMENT_FORMULA_TEMPLATE = "applicationvnd.oasis.opendocument.formula-template";
public static final String MIMETYPE_OPENDOCUMENT_TEXT_MASTER = "application/vnd.oasis.opendocument.text-master";
public static final String MIMETYPE_OPENDOCUMENT_TEXT_WEB = "application/vnd.oasis.opendocument.text-web";
public static final String MIMETYPE_OPENDOCUMENT_DATABASE = "application/vnd.oasis.opendocument.database";
//endregion
//region Open Office
public static final String MIMETYPE_OPENOFFICE1_WRITER = "application/vnd.sun.xml.writer";
public static final String MIMETYPE_OPENOFFICE1_CALC = "application/vnd.sun.xml.calc";
public static final String MIMETYPE_OPENOFFICE1_DRAW = "application/vnd.sun.xml.draw";
public static final String MIMETYPE_OPENOFFICE1_IMPRESS = "application/vnd.sun.xml.impress";
//endregion
//region Open XML
public static final String MIMETYPE_OPENXML_WORDPROCESSING = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
public static final String MIMETYPE_OPENXML_WORDPROCESSING_MACRO = "application/vnd.ms-word.document.macroenabled.12";
public static final String MIMETYPE_OPENXML_WORD_TEMPLATE = "application/vnd.openxmlformats-officedocument.wordprocessingml.template";
public static final String MIMETYPE_OPENXML_WORD_TEMPLATE_MACRO = "application/vnd.ms-word.template.macroenabled.12";
public static final String MIMETYPE_OPENXML_SPREADSHEET = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
public static final String MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE = "application/vnd.openxmlformats-officedocument.spreadsheetml.template";
public static final String MIMETYPE_OPENXML_SPREADSHEET_MACRO = "application/vnd.ms-excel.sheet.macroenabled.12";
public static final String MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE_MACRO = "application/vnd.ms-excel.template.macroenabled.12";
public static final String MIMETYPE_OPENXML_SPREADSHEET_ADDIN_MACRO = "application/vnd.ms-excel.addin.macroenabled.12";
public static final String MIMETYPE_OPENXML_SPREADSHEET_BINARY_MACRO = "application/vnd.ms-excel.sheet.binary.macroenabled.12";
public static final String MIMETYPE_OPENXML_PRESENTATION = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
public static final String MIMETYPE_OPENXML_PRESENTATION_MACRO = "application/vnd.ms-powerpoint.presentation.macroenabled.12";
public static final String MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW = "application/vnd.openxmlformats-officedocument.presentationml.slideshow";
public static final String MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW_MACRO = "application/vnd.ms-powerpoint.slideshow.macroenabled.12";
public static final String MIMETYPE_OPENXML_PRESENTATION_TEMPLATE = "application/vnd.openxmlformats-officedocument.presentationml.template";
public static final String MIMETYPE_OPENXML_PRESENTATION_TEMPLATE_MACRO = "application/vnd.ms-powerpoint.template.macroenabled.12";
public static final String MIMETYPE_OPENXML_PRESENTATION_ADDIN = "application/vnd.ms-powerpoint.addin.macroenabled.12";
public static final String MIMETYPE_OPENXML_PRESENTATION_SLIDE = "application/vnd.openxmlformats-officedocument.presentationml.slide";
public static final String MIMETYPE_OPENXML_PRESENTATION_SLIDE_MACRO = "application/vnd.ms-powerpoint.slide.macroenabled.12";
//endregion
//region Star Office
public static final String MIMETYPE_STAROFFICE5_DRAW = "application/vnd.stardivision.draw";
public static final String MIMETYPE_STAROFFICE5_CALC = "application/vnd.stardivision.calc";
public static final String MIMETYPE_STAROFFICE5_IMPRESS = "application/vnd.stardivision.impress";
public static final String MIMETYPE_STAROFFICE5_IMPRESS_PACKED = "application/vnd.stardivision.impress-packed";
public static final String MIMETYPE_STAROFFICE5_CHART = "application/vnd.stardivision.chart";
public static final String MIMETYPE_STAROFFICE5_WRITER = "application/vnd.stardivision.writer";
public static final String MIMETYPE_STAROFFICE5_WRITER_GLOBAL = "application/vnd.stardivision.writer-global";
public static final String MIMETYPE_STAROFFICE5_MATH = "application/vnd.stardivision.math";
//endregion
//region Apple iWorks
public static final String MIMETYPE_IWORK_KEYNOTE = "application/vnd.apple.keynote";
public static final String MIMETYPE_IWORK_NUMBERS = "application/vnd.apple.numbers";
public static final String MIMETYPE_IWORK_PAGES = "application/vnd.apple.pages";
//endregion
//region MACOS
public static final String MIMETYPE_APPLEFILE = "application/applefile";
//endregion
//region WordPerfect
public static final String MIMETYPE_WORDPERFECT = "application/wordperfect";
//endregion
//region Audio
public static final String MIMETYPE_MP3 = "audio/mpeg";
public static final String MIMETYPE_AUDIO_MP4 = "audio/mp4";
public static final String MIMETYPE_VORBIS = "audio/vorbis";
public static final String MIMETYPE_FLAC = "audio/x-flac";
//endregion
//region Alfresco
public static final String MIMETYPE_ACP = "application/acp";
//region other
public static final String MIMETYPE_PBM = "image/x-portable-bitmap";
public static final String MIMETYPE_PNM = "image/x-portable-anymap";
public static final String MIMETYPE_XBM = "image/x-xbitmap";
public static final String MIMETYPE_XPM = "image/x-xpixmap";
public static final String MIMETYPE_Z = "application/x-compress";
public static final String MIMETYPE_PPM = "image/x-portable-pixmap";
public static final String MIMETYPE_TAR = "application/x-tar";
public static final String MIMETYPE_OGG = "application/ogg";
//endregion
private static final Set<String> ALL_MIMETYPES;
static
{
ALL_MIMETYPES = unmodifiableSet(stream(Mimetype.class.getDeclaredFields())
.filter(f -> Modifier.isPublic(f.getModifiers()))
.filter(f -> Modifier.isStatic(f.getModifiers()))
.filter(f -> Modifier.isFinal(f.getModifiers()))
.filter(f -> f.getType().isAssignableFrom(String.class))
.filter(f -> f.getName().startsWith("MIMETYPE_"))
.peek(f -> f.setAccessible(true))
.map(Mimetype::getFieldValue)
.filter(Objects::nonNull)
.collect(toSet()));
}
private static String getFieldValue(final Field f)
{
try
{
return (String) f.get(null);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
public static Set<String> matchMimetypes(final String regex)
{
return unmodifiableSet(ALL_MIMETYPES
.stream()
.filter(t -> t.matches(regex))
.collect(toSet()));
}
}

View File

@ -1,97 +0,0 @@
/*
* #%L
* Alfresco Transform Model
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This program 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.
*
* This program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* #L%
*/
package org.alfresco.transform.router;
import java.util.StringJoiner;
import java.util.stream.Stream;
/**
* The client data supplied and echoed back to content repository (the client). May be modified to include
* TransformerDebug.
*/
class RepositoryClientData
{
private static final String CLIENT_DATA_SEPARATOR = "\u23D0";
public static final String DEBUG_SEPARATOR = "\u23D1";
private static final String REPO_ID = "Repo";
private static final String DEBUG = "debug:";
private final String[] split;
public RepositoryClientData(String clientData)
{
split = clientData == null ? null : clientData.split(CLIENT_DATA_SEPARATOR);
}
private boolean isRepositoryClientData()
{
return split != null && split.length == 10 && split[0].startsWith(REPO_ID);
}
public String getAcsVersion()
{
return isRepositoryClientData() ? split[0].substring(REPO_ID.length()) : "";
}
public int getRequestId()
{
try
{
return isRepositoryClientData() ? Integer.parseInt(split[6]) : -1;
}
catch (NumberFormatException e)
{
return -1;
}
}
public String getRenditionName()
{
return isRepositoryClientData() ? split[2] : "";
}
public void appendDebug(String message)
{
if (isDebugRequested())
{
split[9] += DEBUG_SEPARATOR+ message;
}
}
public boolean isDebugRequested()
{
return isRepositoryClientData() && split[9].startsWith(DEBUG);
}
@Override
public String toString()
{
if (split == null)
{
return null;
}
StringJoiner sj = new StringJoiner(CLIENT_DATA_SEPARATOR);
Stream.of(split).forEach(element -> sj.add(element));
return sj.toString();
}
}

View File

@ -1,118 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import org.alfresco.transformer.executors.PdfRendererCommandExecutor;
import org.alfresco.transformer.probes.ProbeTestTransform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import javax.annotation.PostConstruct;
import java.io.File;
import java.util.Collections;
import java.util.Map;
/**
* Controller for the Docker based alfresco-pdf-renderer transformer.
*
* Status Codes:
*
* 200 Success
* 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 AlfrescoPdfRendererController extends AbstractTransformerController
{
private static final Logger logger = LoggerFactory.getLogger(
AlfrescoPdfRendererController.class);
@Value("${transform.core.pdfrenderer.exe}")
private String execPath;
PdfRendererCommandExecutor commandExecutor;
@PostConstruct
private void init()
{
commandExecutor = new PdfRendererCommandExecutor(execPath);
}
@Override
public String getTransformerName()
{
return "Alfresco PDF Renderer";
}
@Override
public String version()
{
return commandExecutor.version();
}
@Override
public ProbeTestTransform getProbeTestTransform()
{
// See the Javadoc on this method and Probes.md for the choice of these values.
return new ProbeTestTransform(this, "quick.pdf", "quick.png",
7455, 1024, 150, 10240, 60 * 20 + 1, 60 * 15 - 15)
{
@Override
protected void executeTransformCommand(File sourceFile, File targetFile)
{
transformImpl(null, null, null, Collections.emptyMap(), sourceFile, targetFile);
}
};
}
@Override
protected String getTransformerName(final File sourceFile, final String sourceMimetype,
final String targetMimetype, final Map<String, String> transformOptions)
{
return null; // does not matter what value is returned, as it is not used because there is only one.
}
@Override
public void transformImpl(String transformName, String sourceMimetype, String targetMimetype,
Map<String, String> transformOptions, File sourceFile, File targetFile)
{
commandExecutor.transformExtractOrEmbed(transformName, sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile);
}
}

View File

@ -1,77 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2020 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import io.micrometer.core.instrument.MeterRegistry;
import org.alfresco.transformer.executors.PdfRendererCommandExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
import java.util.Arrays;
import static org.alfresco.transformer.logging.StandardMessages.LICENCE;
@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class Application
{
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Value("${container.name}")
private String containerName;
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags()
{
return registry -> registry.config().commonTags("containerName", containerName);
}
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
@EventListener(ApplicationReadyEvent.class)
public void startup()
{
logger.info("-----------------------------------------------------------------------------------------------------------------------------------------------------------");
Arrays.stream(LICENCE.split("\\n")).forEach(logger::info);
logger.info(PdfRendererCommandExecutor.LICENCE);
logger.info("-----------------------------------------------------------------------------------------------------------------------------------------------------------");
logger.info("Starting application components... Done");
}
}

View File

@ -1,27 +0,0 @@
// Copyright 2014 PDFium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,30 +0,0 @@
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div>
<h2>Alfresco PDF Renderer Test Transformation</h2>
<form method="POST" enctype="multipart/form-data" action="/transform">
<table>
<tr><td><div style="text-align:right">file *</div></td><td><input type="file" name="file" /></td></tr>
<tr><td><div style="text-align:right">targetExtension *</div></td><td><input type="text" name="targetExtension" value="" /></td></tr>
<tr><td><div style="text-align:right">timeout</div></td><td><input type="text" name="timeout" value="" /></td></tr>
<tr><td><div style="text-align:right">testDelay</div></td><td><input type="text" name="testDelay" value="" /></td></tr>
<tr><td><div style="text-align:right">page</div></td><td><input type="text" name="page" value="" /></td></tr>
<tr><td><div style="text-align:right">width</div></td><td><input type="text" name="width" value="" /></td></tr>
<tr><td><div style="text-align:right">height</div></td><td><input type="text" name="height" value="" /></td></tr>
<tr><td><div style="text-align:right">allowPdfEnlargement</div></td><td><input type="checkbox" name="allowPdfEnlargement" value="true" /></td></tr>
<tr><td><div style="text-align:right">maintainPdfAspectRatio</div></td><td><input type="checkbox" name="maintainPdfAspectRatio" value="true" /></td></tr>
<tr><td></td><td><input type="submit" value="Transform" /></td></tr>
</table>
</form>
</div>
<div>
<a href="/log">Log entries</a>
</div>
</body>
</html>

View File

@ -1,49 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2021 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
/**
* Tests AlfrescoPdfRendererController with a server test harness.
*/
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class AlfrescoPdfRendererHttpRequestTest extends AbstractHttpRequestTest
{
@Override
protected String getTransformerName()
{
return "Alfresco PDF Renderer";
}
@Override
protected String getSourceExtension()
{
return "pdf";
}
}

View File

@ -1,4 +0,0 @@
### Licenses
* The alfresco-pdf-renderer transformer uses the PDFium library from Google Inc. See [https://pdfium.googlesource.com/pdfium/+/master/LICENSE](https://pdfium.googlesource.com/pdfium/+/master/LICENSE)
or the [pdfium.txt](../alfresco-transform-pdf-renderer-boot/src/main/resources/licenses/3rd-party/pdfium.txt) file placed in the root directory of the docker image.

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfresco-transform-pdf-renderer</artifactId>
<name>Alfresco Pdf Renderer Transformer</name>
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-transform-core</artifactId>
<version>2.7.0-A2-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-transformer-base</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,77 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2020 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import io.micrometer.core.instrument.MeterRegistry;
import org.alfresco.transformer.executors.TikaJavaExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
import java.util.Arrays;
import static org.alfresco.transformer.logging.StandardMessages.LICENCE;
@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class Application
{
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Value("${container.name}")
private String containerName;
@Bean
MeterRegistryCustomizer<MeterRegistry> metricsCommonTags()
{
return registry -> registry.config().commonTags("containerName", containerName);
}
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
@EventListener(ApplicationReadyEvent.class)
public void startup()
{
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
Arrays.stream(LICENCE.split("\\n")).forEach(logger::info);
Arrays.stream(TikaJavaExecutor.LICENCE.split("\\n")).forEach(logger::info);
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
logger.info("Starting application components... Done");
}
}

View File

@ -1,111 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import org.alfresco.transformer.executors.TikaJavaExecutor;
import org.alfresco.transformer.probes.ProbeTestTransform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import static org.alfresco.transformer.executors.Tika.PDF_BOX;
import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_PDF;
import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_TEXT_PLAIN;
/**
* 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 static final Logger logger = LoggerFactory.getLogger(TikaController.class);
private TikaJavaExecutor javaExecutor;
public TikaController(@Value("${transform.core.tika.pdfBox.notExtractBookmarksTextDefault:false}") boolean notExtractBookmarksTextDefault)
{
javaExecutor= new TikaJavaExecutor(notExtractBookmarksTextDefault);
}
@Override
public String getTransformerName()
{
return "Tika";
}
@Override
public String version()
{
return "Tika available";
}
@Override
public 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)
{
transformImpl(PDF_BOX, MIMETYPE_PDF, MIMETYPE_TEXT_PLAIN, new HashMap<>(), sourceFile, targetFile);
}
};
}
@Override
public void transformImpl(String transformName, String sourceMimetype, String targetMimetype,
Map<String, String> transformOptions, File sourceFile, File targetFile)
{
javaExecutor.transformExtractOrEmbed(transformName, sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile);
}
}

View File

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,127 +0,0 @@
The "Artistic License"
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.
Definitions:
"Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes
of the Copyright Holder as specified below.
"Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Reasonable copying fee" is whatever you can justify on the
basis of media cost, duplication charges, time of people involved,
and so on. (You will not be required to justify it to the
Copyright Holder, but only to the computing community at large
as a market that must bear the fee.)
"Freely Available" means that no fee is charged for the item
itself, though there may be fees involved in handling the item.
It also means that recipients of the item may redistribute it
under the same conditions they received it.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain or from the Copyright Holder. A Package
modified in such a way shall still be considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or
an equivalent medium, or placing the modifications on a major archive
site such as uunet.uu.net, or by allowing the Copyright Holder to include
your modifications in the Standard Version of the Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that clearly
documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where
to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) give non-standard executables non-standard names, and clearly
document the differences in manual pages (or equivalent), together
with instructions on where to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
5. You may charge a reasonable copying fee for any distribution of this
Package. You may charge any fee you choose for support of this
Package. You may not charge a fee for this Package itself. However,
you may distribute this Package in aggregate with other (possibly
commercial) programs as part of a larger (possibly commercial) software
distribution provided that you do not advertise this Package as a
product of your own. You may embed this Package's interpreter within
an executable of yours (by linking); this shall be construed as a mere
form of aggregation, provided that the complete Standard Version of the
interpreter is so embedded.
6. The scripts and library files supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package. If such scripts or library files are aggregated with this
Package via the so-called "undump" or "unexec" methods of producing a
binary executable image, then distribution of such an image shall
neither be construed as a distribution of this Package nor shall it
fall under the restrictions of Paragraphs 3 and 4, provided that you do
not represent such an executable image as a Standard Version of this
Package.
7. C subroutines (or comparably compiled subroutines in other
languages) supplied by you and linked into this Package in order to
emulate subroutines and variables of the language defined by this
Package shall not be considered part of this Package, but are the
equivalent of input as in Paragraph 6, provided these subroutines do
not change the language in any way that would cause it to fail the
regression tests for the language.
8. Aggregation of this Package with a commercial distribution is always
permitted provided that the use of this Package is embedded; that is,
when no overt attempt is made to make this Package's interfaces visible
to the end user of the commercial distribution. Such use shall not be
construed as a distribution of this Package.
9. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End

View File

@ -1,28 +0,0 @@
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div>
<h2>Tika Test Transformations</h2>
<form method="POST" enctype="multipart/form-data" action="/transform">
<table>
<tr><td><div style="text-align:right">file *</div></td><td><input type="file" name="file" /></td></tr>
<tr><td><div style="text-align:right">Direct Url</div></td><td><input type="text" name="directAccessUrl"/></td></tr>
<tr><td><div style="text-align:right">sourceMimetype *</div></td><td><input type="text" name="sourceMimetype" value="application/msword" /></td></tr>
<tr><td><div style="text-align:right">targetExtension *</div></td><td><input type="text" name="targetExtension" value="txt" /></td></tr>
<tr><td><div style="text-align:right">targetMimetype *</div></td><td><input type="text" name="targetMimetype" value="text/plain" /></td></tr>
<tr><td><div style="text-align:right">targetEncoding *</div></td><td><input type="text" name="targetEncoding" value="UTF-8" /></td></tr>
<tr><td><div style="text-align:right">includeContents (archive) *</div></td><td><input type="checkbox" name="includeContents" value="true" /></td></tr>
<tr><td><div style="text-align:right">timeout</div></td><td><input type="text" name="timeout" value="" /></td></tr>
<tr><td><div style="text-align:right">testDelay</div></td><td><input type="text" name="testDelay" value="" /></td></tr>
<tr><td><div style="text-align:right">notExtractBookmarksText</div></td><td><input type="checkbox" name="notExtractBookmarksText" value="true" /></td></tr>
<tr><td></td><td><input type="submit" value="Transform" /></td></tr>
</table>
</form>
</div>
<div>
<a href="/log">Log entries</a>
</div>
</body>
</html>

View File

@ -1,73 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.util.LinkedMultiValueMap;
/**
* Tests TikaController with a server test harness.
*/
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class TikaHttpRequestTest extends AbstractHttpRequestTest
{
@Override
protected String getTransformerName()
{
return "Tika";
}
@Override
protected String getSourceExtension()
{
return "pdf";
}
// Override method as Tika requires sourceMimetype
// If not provided then sourceMimetype request parameter error will be thrown.
@Override
protected void assertTransformError(boolean addFile,
String errorMessage,
LinkedMultiValueMap<String, Object> additionalParams)
{
LinkedMultiValueMap<String, Object> parameters = new LinkedMultiValueMap<>();
parameters.add("sourceMimetype", "application/pdf");
if (additionalParams != null)
{
parameters.addAll(additionalParams);
}
super.assertTransformError(addFile, errorMessage, parameters);
}
}

View File

@ -1,17 +0,0 @@
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
<title>The quick brown fox jumps over the lazy dog</title>
<meta name="author" content="Nevin Nollop">
<meta name="keywords" content="Pangram, fox, dog">
<meta name="description" content="Gym class featuring a brown fox and lazy dog">
</head>
<body lang=EN-US>
The quick brown fox jumps over the lazy dog
</body>
</html>

View File

@ -1,4 +0,0 @@
### Licenses
* Tika is from Apache. See the licence at http://www.apache.org/licenses/LICENSE-2.0 or the [Apache 2.0.txt](../alfresco-transform-tika-boot/src/main/resources/licenses/3rd-party/Apache%202.0.txt) file placed in the root directory of the docker image.
* Exiftool is from Phil Harvey. See licence at https://exiftool.org/#license and Perl at https://dev.perl.org/licenses/ (https://dev.perl.org/licenses/artistic.html) or [Perl Artistic License.txt](../alfresco-transform-tika-boot/src/main/resources/licenses/3rd-party/Perl-Artistic-License.txt) file placed in the root directory of the docker image.

View File

@ -1,125 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfresco-transform-tika</artifactId>
<name>Alfresco Tika Transformer</name>
<parent>
<artifactId>alfresco-transform-core</artifactId>
<groupId>org.alfresco</groupId>
<version>2.7.0-A2-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-transformer-base</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Tika -->
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>${dependency.tika.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers-standard-package</artifactId>
<version>${dependency.tika.version}</version>
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk15on</artifactId>
</exclusion>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Needed for correct date/time formats -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.11.0</version>
</dependency>
<!-- for Apache Tika Parsers - eg. encrypted PDF -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<!-- Apache POI -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${dependency.poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${dependency.poi.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>${dependency.ooxml-schemas.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>${dependency.poi.version}</version>
</dependency>
<!-- Apache PDFBox -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,876 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2020 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer.executors;
import com.google.common.collect.ImmutableList;
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.pdf.PDFParserConfig;
import org.apache.tika.parser.pkg.PackageParser;
import org.apache.tika.sax.BodyContentHandler;
import org.apache.tika.sax.ExpandedTitleContentHandler;
import org.slf4j.Logger;
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.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.util.List;
import java.util.regex.Pattern;
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;
/**
* Stripped down command line Tika transformers. Not actually run as a separate process, but the code fits the patten
* used by transformers that do.
* <pre>
*
* 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
* </pre>
*/
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<String> TRANSFORM_NAMES = ImmutableList.of(
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 NOT_EXTRACT_BOOKMARKS_TEXT = "--notExtractBookmarksText";
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 final Parser packageParser = new PackageParser();
private final Parser pdfParser = new PDFParser();
private final Parser officeParser = new OfficeParser();
private final Parser autoDetectParser;
private final Parser ooXmlParser = new OOXMLParser();
private final Parser tikaOfficeDetectParser = new TikaOfficeDetectParser();
private final PDFParserConfig pdfParserConfig = new PDFParserConfig();
public static final DocumentSelector pdfBoxEmbededDocumentSelector = new DocumentSelector()
{
private final List<String> disabledMediaTypes = ImmutableList.of(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
{
TikaConfig tikaConfig = readTikaConfig();
autoDetectParser = new AutoDetectParser(tikaConfig);
}
public static TikaConfig readTikaConfig(Logger logger)
{
try
{
return readTikaConfig();
}
catch (Exception e)
{
logger.error("Failed to read tika-config.xml", e);
return null;
}
}
private static TikaConfig readTikaConfig() throws TikaException, IOException, SAXException
{
ClassLoader classLoader = Tika.class.getClassLoader();
URL tikaConfigXml = classLoader.getResource("tika-config.xml");
return new TikaConfig(tikaConfigXml);
}
// 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;
Boolean notExtractBookmarksText = 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 if (arg.startsWith(NOT_EXTRACT_BOOKMARKS_TEXT))
{
getValue(arg, false, notExtractBookmarksText, NOT_EXTRACT_BOOKMARKS_TEXT);
notExtractBookmarksText = true;
}
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;
notExtractBookmarksText = notExtractBookmarksText == null ? false : notExtractBookmarksText;
transform(transform, includeContents, notExtractBookmarksText, 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,
Boolean notExtractBookmarksText,
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, notExtractBookmarksText,
sourceFilename, targetFilename, targetMimetype, targetEncoding);
}
private void transform(Parser parser, DocumentSelector documentSelector,
Boolean includeContents,
Boolean notExtractBookmarksText,
String sourceFilename,
String targetFilename, String targetMimetype, String targetEncoding)
{
try (InputStream is = new BufferedInputStream(new FileInputStream(sourceFilename));
OutputStream os = new FileOutputStream(targetFilename);
Writer ow = new BufferedWriter(new OutputStreamWriter(os, targetEncoding)))
{
Metadata metadata = new Metadata();
ParseContext context = buildParseContext(documentSelector, includeContents,
notExtractBookmarksText);
ContentHandler handler = getContentHandler(targetMimetype, ow);
parser.parse(is, handler, metadata, context);
}
catch (SAXException | TikaException | IOException e)
{
throw new IllegalStateException(e.getMessage(), e);
}
}
private 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;
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);
}
}
}
private ParseContext buildParseContext(DocumentSelector documentSelector,
Boolean includeContents, Boolean notExtractBookmarksText)
{
ParseContext context = new ParseContext();
if (documentSelector != null)
{
context.set(DocumentSelector.class, documentSelector);
}
if (notExtractBookmarksText.equals(true))
{
pdfParserConfig.setExtractBookmarksText(false);
// pdfParserConfig is set to override default settings
context.set(PDFParserConfig.class, pdfParserConfig);
}
// If Archive transform
if (includeContents != null)
{
context.set(Parser.class, includeContents ? autoDetectParser : new EmptyParser());
}
return context;
}
}

View File

@ -1,204 +0,0 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2021 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer.executors;
import com.google.common.collect.ImmutableMap;
import org.alfresco.transformer.logging.LogEntry;
import org.alfresco.transformer.metadataExtractors.AbstractTikaMetadataExtractor;
import org.alfresco.transformer.metadataExtractors.DWGMetadataExtractor;
import org.alfresco.transformer.metadataExtractors.MP3MetadataExtractor;
import org.alfresco.transformer.metadataExtractors.MailMetadataExtractor;
import org.alfresco.transformer.metadataExtractors.OfficeMetadataExtractor;
import org.alfresco.transformer.metadataExtractors.OpenDocumentMetadataExtractor;
import org.alfresco.transformer.metadataExtractors.PdfBoxMetadataExtractor;
import org.alfresco.transformer.metadataExtractors.PoiMetadataExtractor;
import org.alfresco.transformer.metadataExtractors.TikaAudioMetadataExtractor;
import org.alfresco.transformer.metadataExtractors.TikaAutoMetadataExtractor;
import org.alfresco.transformer.metadataExtractors.IPTCMetadataExtractor;
import org.alfresco.transformer.util.RequestParamMap;
import org.apache.tika.exception.TikaException;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import java.util.StringJoiner;
import static java.lang.Boolean.parseBoolean;
import static org.alfresco.transformer.executors.Tika.INCLUDE_CONTENTS;
import static org.alfresco.transformer.executors.Tika.TARGET_ENCODING;
import static org.alfresco.transformer.executors.Tika.TARGET_MIMETYPE;
/**
* JavaExecutor implementation for running TIKA transformations. It loads the
* transformation logic in the same JVM (check {@link Tika}).
*/
public class TikaJavaExecutor implements JavaExecutor
{
private boolean notExtractBookmarksTextDefault;
private static final String ID = "tika";
public static final String LICENCE =
"This transformer uses Tika from Apache. See the license at http://www.apache.org/licenses/LICENSE-2.0. or in /Apache\\ 2.0.txt\n" +
"This transformer uses ExifTool by Phil Harvey. See license at https://exiftool.org/#license. or in /Perl-Artistic-License.txt";
private final Tika tika;
private final Map<String, AbstractTikaMetadataExtractor> metadataExtractor = ImmutableMap
.<String, AbstractTikaMetadataExtractor>builder()
.put("DWGMetadataExtractor", new DWGMetadataExtractor())
.put("MailMetadataExtractor", new MailMetadataExtractor())
.put("MP3MetadataExtractor", new MP3MetadataExtractor())
.put("OfficeMetadataExtractor", new OfficeMetadataExtractor())
.put("OpenDocumentMetadataExtractor", new OpenDocumentMetadataExtractor())
.put("PdfBoxMetadataExtractor", new PdfBoxMetadataExtractor())
.put("PoiMetadataExtractor", new PoiMetadataExtractor())
.put("TikaAudioMetadataExtractor", new TikaAudioMetadataExtractor())
.put("TikaAutoMetadataExtractor", new TikaAutoMetadataExtractor())
.put("IPTCMetadataExtractor", new IPTCMetadataExtractor())
.build();
private final Map<String, AbstractTikaMetadataExtractor> metadataEmbedder = ImmutableMap
.<String, AbstractTikaMetadataExtractor>builder()
.put("SamplePoiMetadataEmbedder", new PoiMetadataExtractor())
.build();
public TikaJavaExecutor(boolean notExtractBookmarksTextDefault)
{
this.notExtractBookmarksTextDefault = notExtractBookmarksTextDefault;
try
{
tika = new Tika();
}
catch (SAXException | IOException | TikaException e)
{
throw new RuntimeException("Unable to instantiate Tika: " + e.getMessage());
}
}
public TikaJavaExecutor()
{
this(false);
}
@Override
public String getTransformerId()
{
return ID;
}
@Override
public void transform(String transformName, String sourceMimetype, String targetMimetype,
Map<String, String> transformOptions, File sourceFile, File targetFile)
throws Exception
{
final boolean includeContents = parseBoolean(
transformOptions.getOrDefault(RequestParamMap.INCLUDE_CONTENTS, "false"));
final boolean notExtractBookmarksText = parseBoolean(
transformOptions.getOrDefault(RequestParamMap.NOT_EXTRACT_BOOKMARKS_TEXT, String.valueOf(notExtractBookmarksTextDefault)));
final String targetEncoding = transformOptions.getOrDefault("targetEncoding", "UTF-8");
if(transformOptions.get(RequestParamMap.NOT_EXTRACT_BOOKMARKS_TEXT)==null && notExtractBookmarksTextDefault)
{
LoggerFactory.getLogger(TikaJavaExecutor.class).trace(
"notExtractBookmarksText default value has been overridden to {}",
notExtractBookmarksTextDefault);
}
call(sourceFile, targetFile, transformName,
includeContents ? INCLUDE_CONTENTS : null,
notExtractBookmarksText ? Tika.NOT_EXTRACT_BOOKMARKS_TEXT : null,
TARGET_MIMETYPE + targetMimetype, TARGET_ENCODING + targetEncoding);
}
@Override
public void call(File sourceFile, File targetFile, String... args)
{
args = buildArgs(sourceFile, targetFile, args);
tika.transform(args);
}
private static String[] buildArgs(File sourceFile, File targetFile, String[] args)
{
ArrayList<String> 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[0]);
}
private static void addArg(ArrayList<String> methodArgs, StringJoiner sj, String arg)
{
if (arg != null)
{
sj.add(arg);
methodArgs.add(arg);
}
}
private static void addFileArg(ArrayList<String> 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);
}
}
public void extractMetadata(String transformName, String sourceMimetype, String targetMimetype,
Map<String, String> transformOptions, File sourceFile, File targetFile)
throws Exception
{
AbstractTikaMetadataExtractor metadataExtractor = this.metadataExtractor.get(transformName);
metadataExtractor.extractMetadata(sourceMimetype, transformOptions, sourceFile, targetFile);
}
/**
* @deprecated The content repository's TikaPoweredMetadataExtracter provides no non test implementations.
* This code exists in case there are custom implementations, that need to be converted to T-Engines.
* It is simply a copy and paste from the content repository and has received limited testing.
*/
@Override
@SuppressWarnings("deprecation" )
public void embedMetadata(String transformName, String sourceMimetype, String targetMimetype,
Map<String, String> transformOptions, File sourceFile, File targetFile)
throws Exception
{
AbstractTikaMetadataExtractor metadataExtractor = this.metadataEmbedder.get(transformName);
metadataExtractor.embedMetadata(sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile);
}
}

View File

@ -1,7 +1,14 @@
# Common code for Transform Engines # Common code for Transform Engines (Deprecated)
This project contains code that is common between all the ACS T-Engine transformers that run as Spring Boot process (optionally within their own This project holds the original code that was common to all ACS T-Engine transformers. Although
Docker containers). It performs common actions such as logging, throttling requests and handling the streaming of content to and from the container. it is still possible to create T-Engines this way, the newer `engine/base` project provides a
simpler way to do it.
> When upgrading to 3.0.0, you will find that a number of classes in the alfresco-transform-model
have moved. See the [alfresco-transform-model README](https://github.com/Alfresco/alfresco-transform-core/blob/master/model/README.md)
This project provides a base Spring Boot process (optionally within their own Docker containers).
It performs common actions such as logging, throttling requests and handling the streaming of content to and from the container.
For more details on build a custom T-Engine, please refer to the current docs in ACS Packaging, including: For more details on build a custom T-Engine, please refer to the current docs in ACS Packaging, including:
@ -49,7 +56,7 @@ src/main/java/org/alfresco/transformer/Application.java
~~~ ~~~
* *TransformerName*Controller.java - A [Spring Boot](https://projects.spring.io/spring-boot/) Controller that * *TransformerName*Controller.java - A [Spring Boot](https://projects.spring.io/spring-boot/) Controller that
extends AbstractTransformerController to handel requests. It implements a few methods including *transformImpl* extends TransformController to handle requests. It implements a few methods including *transformImpl*
which is intended to perform the actual transform. Generally the transform is done in a sub class of which is intended to perform the actual transform. Generally the transform is done in a sub class of
*JavaExecutor*, when a Java library is being used or *AbstractCommandExecutor*, when an external process is used. *JavaExecutor*, when a Java library is being used or *AbstractCommandExecutor*, when an external process is used.
Both are sub interfaces of *Transformer*. Both are sub interfaces of *Transformer*.
@ -57,7 +64,7 @@ src/main/java/org/alfresco/transformer/Application.java
~~~ ~~~
... ...
@Controller @Controller
public class TransformerNameController extends AbstractTransformerController public class TransformerNameController extends TransformController
{ {
private static final Logger logger = LoggerFactory.getLogger(TransformerNameController.class); private static final Logger logger = LoggerFactory.getLogger(TransformerNameController.class);
@ -149,7 +156,7 @@ public class Application
} }
~~~ ~~~
Transform requests are handled by the *AbstractTransformerController*, but are either: Transform requests are handled by the *TransformController*, but are either:
* POST requests (a direct http request from a client) where the transform options are passed as parameters, the source is supplied as a multipart file and * POST requests (a direct http request from a client) where the transform options are passed as parameters, the source is supplied as a multipart file and
the response is a file download. the response is a file download.
* POST request (a request via a message queue) where the transform options are supplied as JSON and the response is also JSON. * POST request (a request via a message queue) where the transform options are supplied as JSON and the response is also JSON.

View File

@ -1,15 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>alfresco-transformer-base</artifactId>
<name>- Deprecated Base</name>
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-transform-core</artifactId> <artifactId>alfresco-transform-core</artifactId>
<version>2.7.0-A2-SNAPSHOT</version> <version>3.0.0-HXP-A10-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent> </parent>
<artifactId>alfresco-transformer-base</artifactId>
<properties> <properties>
<transformer.base.deploy.skip>false</transformer.base.deploy.skip> <transformer.base.deploy.skip>false</transformer.base.deploy.skip>
</properties> </properties>

View File

@ -26,14 +26,14 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import org.alfresco.transform.common.TransformerDebug;
import org.alfresco.transform.client.model.InternalContext; import org.alfresco.transform.client.model.InternalContext;
import org.alfresco.transform.client.model.TransformReply; import org.alfresco.transform.client.model.TransformReply;
import org.alfresco.transform.client.model.TransformRequest; import org.alfresco.transform.client.model.TransformRequest;
import org.alfresco.transform.client.model.TransformRequestValidator; import org.alfresco.transform.messages.TransformRequestValidator;
import org.alfresco.transform.client.model.config.TransformConfig; import org.alfresco.transform.config.TransformConfig;
import org.alfresco.transform.client.registry.TransformServiceRegistry; import org.alfresco.transform.registry.TransformServiceRegistry;
import org.alfresco.transform.exceptions.TransformException; import org.alfresco.transform.exceptions.TransformException;
import org.alfresco.transform.router.TransformerDebug;
import org.alfresco.transformer.clients.AlfrescoSharedFileStoreClient; import org.alfresco.transformer.clients.AlfrescoSharedFileStoreClient;
import org.alfresco.transformer.logging.LogEntry; import org.alfresco.transformer.logging.LogEntry;
import org.alfresco.transformer.model.FileRefResponse; import org.alfresco.transformer.model.FileRefResponse;
@ -67,12 +67,12 @@ import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.joining;
import static org.alfresco.transform.client.model.config.CoreVersionDecorator.setOrClearCoreVersion; import static org.alfresco.transform.config.CoreVersionDecorator.setOrClearCoreVersion;
import static org.alfresco.transform.client.util.RequestParamMap.DIRECT_ACCESS_URL; import static org.alfresco.transform.common.RequestParamMap.DIRECT_ACCESS_URL;
import static org.alfresco.transform.client.util.RequestParamMap.CONFIG_VERSION; import static org.alfresco.transform.common.RequestParamMap.CONFIG_VERSION;
import static org.alfresco.transform.client.util.RequestParamMap.CONFIG_VERSION_DEFAULT; import static org.alfresco.transform.common.RequestParamMap.CONFIG_VERSION_DEFAULT;
import static org.alfresco.transform.client.util.RequestParamMap.ENDPOINT_TRANSFORM; import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM;
import static org.alfresco.transform.client.util.RequestParamMap.ENDPOINT_TRANSFORM_CONFIG; import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM_CONFIG;
import static org.alfresco.transformer.fs.FileManager.TempFileProvider.createTempFile; import static org.alfresco.transformer.fs.FileManager.TempFileProvider.createTempFile;
import static org.alfresco.transformer.fs.FileManager.buildFile; import static org.alfresco.transformer.fs.FileManager.buildFile;
import static org.alfresco.transformer.fs.FileManager.createAttachment; import static org.alfresco.transformer.fs.FileManager.createAttachment;
@ -99,6 +99,8 @@ import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
import static org.springframework.util.StringUtils.getFilenameExtension; import static org.springframework.util.StringUtils.getFilenameExtension;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* <p>Abstract Controller, provides structure and helper methods to sub-class transformer controllers. Sub classes * <p>Abstract Controller, provides structure and helper methods to sub-class transformer controllers. Sub classes
* should implement {@link #transformImpl(String, String, String, Map, File, File)} and unimplemented methods from * should implement {@link #transformImpl(String, String, String, Map, File, File)} and unimplemented methods from
* {@link TransformController}.</p> * {@link TransformController}.</p>
@ -128,6 +130,7 @@ import static org.springframework.util.StringUtils.getFilenameExtension;
* <p>Provides methods to help super classes perform /transform requests. Also responses to /version, /ready and /live * <p>Provides methods to help super classes perform /transform requests. Also responses to /version, /ready and /live
* requests.</p> * requests.</p>
*/ */
@Deprecated
public abstract class AbstractTransformerController implements TransformController public abstract class AbstractTransformerController implements TransformController
{ {
private static final Logger logger = LoggerFactory.getLogger( private static final Logger logger = LoggerFactory.getLogger(
@ -188,7 +191,7 @@ public abstract class AbstractTransformerController implements TransformControll
{ {
if (sourceMultipartFile == null) if (sourceMultipartFile == null)
{ {
throw new TransformException(BAD_REQUEST.value(), "Required request part 'file' is not present"); throw new TransformException(BAD_REQUEST, "Required request part 'file' is not present");
} }
sourceFile = createSourceFile(request, sourceMultipartFile); sourceFile = createSourceFile(request, sourceMultipartFile);
sourceFilename = sourceMultipartFile.getOriginalFilename(); sourceFilename = sourceMultipartFile.getOriginalFilename();
@ -236,11 +239,11 @@ public abstract class AbstractTransformerController implements TransformControll
} }
catch (IllegalArgumentException e) catch (IllegalArgumentException e)
{ {
throw new TransformException(BAD_REQUEST.value(), "Direct Access Url is invalid.", e); throw new TransformException(BAD_REQUEST, "Direct Access Url is invalid.", e);
} }
catch (IOException e) catch (IOException e)
{ {
throw new TransformException(BAD_REQUEST.value(), "Direct Access Url not found.", e); throw new TransformException(BAD_REQUEST, "Direct Access Url not found.", e);
} }
return sourceFile; return sourceFile;
@ -481,7 +484,7 @@ public abstract class AbstractTransformerController implements TransformControll
String message = "Source file with reference: " + sourceReference + " is null or empty. " String message = "Source file with reference: " + sourceReference + " is null or empty. "
+ "Transformation will fail and stop now as there is no content to be transformed."; + "Transformation will fail and stop now as there is no content to be transformed.";
logger.warn(message); logger.warn(message);
throw new TransformException(BAD_REQUEST.value(), message); throw new TransformException(BAD_REQUEST, message);
} }
final File file = createTempFile("source_", "." + extension); final File file = createTempFile("source_", "." + extension);
@ -542,8 +545,7 @@ public abstract class AbstractTransformerController implements TransformControll
sourceSizeInBytes, targetMimetype, transformOptions, null); sourceSizeInBytes, targetMimetype, transformOptions, null);
if (transformerName == null) if (transformerName == null)
{ {
throw new TransformException(BAD_REQUEST.value(), throw new TransformException(BAD_REQUEST, "No transforms for:");
"No transforms were able to handle the request");
} }
return transformerName; return transformerName;
} }

View File

@ -50,6 +50,8 @@ import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Queue Transformer service. * Queue Transformer service.
* This service reads all the requests for the particular engine, forwards them to the worker * This service reads all the requests for the particular engine, forwards them to the worker
* component (at this time the injected controller - to be refactored) and sends back the reply * component (at this time the injected controller - to be refactored) and sends back the reply
@ -58,6 +60,7 @@ import org.springframework.stereotype.Component;
* @author Lucian Tuca * @author Lucian Tuca
* created on 18/12/2018 * created on 18/12/2018
*/ */
@Deprecated
@Component @Component
@ConditionalOnProperty(name = "activemq.url") @ConditionalOnProperty(name = "activemq.url")
public class QueueTransformService public class QueueTransformService
@ -146,8 +149,7 @@ public class QueueTransformService
{ {
try try
{ {
TransformRequest request = (TransformRequest) transformMessageConverter TransformRequest request = (TransformRequest) transformMessageConverter.fromMessage(msg);
.fromMessage(msg);
return Optional.ofNullable(request); return Optional.ofNullable(request);
} }
catch (MessageConversionException e) catch (MessageConversionException e)
@ -155,23 +157,21 @@ public class QueueTransformService
String message = String message =
"MessageConversionException during T-Request deserialization of message with correlationID " "MessageConversionException during T-Request deserialization of message with correlationID "
+ correlationId + ": "; + correlationId + ": ";
throw new TransformException(BAD_REQUEST.value(), message + e.getMessage()); throw new TransformException(BAD_REQUEST, message + e.getMessage());
} }
catch (JMSException e) catch (JMSException e)
{ {
String message = String message =
"JMSException during T-Request deserialization of message with correlationID " "JMSException during T-Request deserialization of message with correlationID "
+ correlationId + ": "; + correlationId + ": ";
throw new TransformException(INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR, message + e.getMessage());
message + e.getMessage());
} }
catch (Exception e) catch (Exception e)
{ {
String message = String message =
"Exception during T-Request deserialization of message with correlationID " "Exception during T-Request deserialization of message with correlationID "
+ correlationId + ": "; + correlationId + ": ";
throw new TransformException(INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR, message + e.getMessage());
message + e.getMessage());
} }
} }

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -54,11 +54,14 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* TransformController interface. * TransformController interface.
* <br/> * <br/>
* It contains much of the common boilerplate code that each of * It contains much of the common boilerplate code that each of
* its concrete implementations need as default methods. * its concrete implementations need as default methods.
*/ */
@Deprecated
public interface TransformController public interface TransformController
{ {
Logger logger = LoggerFactory.getLogger(TransformController.class); Logger logger = LoggerFactory.getLogger(TransformController.class);
@ -210,7 +213,7 @@ public interface TransformController
TransformException e) throws IOException TransformException e) throws IOException
{ {
final String message = e.getMessage(); final String message = e.getMessage();
final int statusCode = e.getStatusCode(); final int statusCode = e.getStatus().value();
logger.error(message, e); logger.error(message, e);

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -37,10 +37,13 @@ import org.alfresco.transformer.logging.LogEntry;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* TransformInterceptor * TransformInterceptor
* <br/> * <br/>
* Handles ThreadLocal Log entries for each request. * Handles ThreadLocal Log entries for each request.
*/ */
@Deprecated
public class TransformInterceptor extends HandlerInterceptorAdapter public class TransformInterceptor extends HandlerInterceptorAdapter
{ {
@Override @Override

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@ -26,7 +26,7 @@
package org.alfresco.transformer; package org.alfresco.transformer;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import static org.alfresco.transform.client.model.config.CoreVersionDecorator.setCoreVersionOnSingleStepTransformers; import static org.alfresco.transform.config.CoreVersionDecorator.setCoreVersionOnSingleStepTransformers;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import java.io.IOException; import java.io.IOException;
@ -35,10 +35,10 @@ import java.io.Reader;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import org.alfresco.transform.client.model.config.TransformConfig; import org.alfresco.transform.config.TransformConfig;
import org.alfresco.transform.client.registry.AbstractTransformRegistry; import org.alfresco.transform.registry.AbstractTransformRegistry;
import org.alfresco.transform.client.registry.CombinedTransformConfig; import org.alfresco.transform.registry.CombinedTransformConfig;
import org.alfresco.transform.client.registry.TransformCache; import org.alfresco.transform.registry.TransformCache;
import org.alfresco.transform.exceptions.TransformException; import org.alfresco.transform.exceptions.TransformException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -50,8 +50,11 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Used by clients to work out if a transformation is supported based on the engine_config.json. * Used by clients to work out if a transformation is supported based on the engine_config.json.
*/ */
@Deprecated
public class TransformRegistryImpl extends AbstractTransformRegistry public class TransformRegistryImpl extends AbstractTransformRegistry
{ {
private static final Logger log = LoggerFactory.getLogger(TransformRegistryImpl.class); private static final Logger log = LoggerFactory.getLogger(TransformRegistryImpl.class);
@ -92,8 +95,7 @@ public class TransformRegistryImpl extends AbstractTransformRegistry
} }
catch (IOException e) catch (IOException e)
{ {
throw new TransformException(INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR, "Could not read " + locationFromProperty, e);
"Could not read " + locationFromProperty, e);
} }
} }

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -45,8 +45,11 @@ import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Simple Rest client that call Alfresco Shared File Store * Simple Rest client that call Alfresco Shared File Store
*/ */
@Deprecated
public class AlfrescoSharedFileStoreClient public class AlfrescoSharedFileStoreClient
{ {
@Value("${fileStoreUrl}") @Value("${fileStoreUrl}")
@ -70,7 +73,7 @@ public class AlfrescoSharedFileStoreClient
} }
catch (HttpClientErrorException e) catch (HttpClientErrorException e)
{ {
throw new TransformException(e.getStatusCode().value(), e.getMessage(), e); throw new TransformException(e.getStatusCode(), e.getMessage(), e);
} }
} }
@ -97,7 +100,7 @@ public class AlfrescoSharedFileStoreClient
} }
catch (HttpClientErrorException e) catch (HttpClientErrorException e)
{ {
throw new TransformException(e.getStatusCode().value(), e.getMessage(), e); throw new TransformException(e.getStatusCode(), e.getMessage(), e);
} }
} }
} }

View File

@ -26,9 +26,9 @@
*/ */
package org.alfresco.transformer.config; package org.alfresco.transformer.config;
import org.alfresco.transform.client.model.TransformRequestValidator; import org.alfresco.transform.messages.TransformRequestValidator;
import org.alfresco.transform.client.registry.TransformServiceRegistry; import org.alfresco.transform.registry.TransformServiceRegistry;
import org.alfresco.transform.router.TransformerDebug; import org.alfresco.transform.common.TransformerDebug;
import org.alfresco.transformer.TransformInterceptor; import org.alfresco.transformer.TransformInterceptor;
import org.alfresco.transformer.TransformRegistryImpl; import org.alfresco.transformer.TransformRegistryImpl;
import org.alfresco.transformer.clients.AlfrescoSharedFileStoreClient; import org.alfresco.transformer.clients.AlfrescoSharedFileStoreClient;
@ -38,8 +38,12 @@ import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import static org.alfresco.transform.client.util.RequestParamMap.ENDPOINT_TRANSFORM; import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM;
/**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*/
@Deprecated
@Configuration @Configuration
public class WebApplicationConfig implements WebMvcConfigurer public class WebApplicationConfig implements WebMvcConfigurer
{ {
@ -84,6 +88,6 @@ public class WebApplicationConfig implements WebMvcConfigurer
@Bean @Bean
public TransformerDebug transformerDebug() public TransformerDebug transformerDebug()
{ {
return new TransformerDebug().setIsTEngine(true); return new TransformerDebug().setIsTRouter(false);
} }
} }

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -36,8 +36,9 @@ import java.util.Map;
import org.alfresco.transform.exceptions.TransformException; import org.alfresco.transform.exceptions.TransformException;
/** /**
* * @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*/ */
@Deprecated
public abstract class AbstractCommandExecutor implements CommandExecutor public abstract class AbstractCommandExecutor implements CommandExecutor
{ {
protected RuntimeExec transformCommand = createTransformCommand(); protected RuntimeExec transformCommand = createTransformCommand();
@ -55,14 +56,12 @@ public abstract class AbstractCommandExecutor implements CommandExecutor
if (result.getExitValue() != 0 && result.getStdErr() != null && result.getStdErr().length() > 0) if (result.getExitValue() != 0 && result.getStdErr() != null && result.getStdErr().length() > 0)
{ {
throw new TransformException(BAD_REQUEST.value(), throw new TransformException(BAD_REQUEST, "Transformer exit code was not 0: \n" + result.getStdErr());
"Transformer exit code was not 0: \n" + result.getStdErr());
} }
if (!targetFile.exists() || targetFile.length() == 0) if (!targetFile.exists() || targetFile.length() == 0)
{ {
throw new TransformException(INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR, "Transformer failed to create an output file");
"Transformer failed to create an output file");
} }
} }
@ -74,14 +73,14 @@ public abstract class AbstractCommandExecutor implements CommandExecutor
final ExecutionResult result = checkCommand.execute(); final ExecutionResult result = checkCommand.execute();
if (result.getExitValue() != 0 && result.getStdErr() != null && result.getStdErr().length() > 0) if (result.getExitValue() != 0 && result.getStdErr() != null && result.getStdErr().length() > 0)
{ {
throw new TransformException(INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR,
"Transformer version check exit code was not 0: \n" + result); "Transformer version check exit code was not 0: \n" + result);
} }
final String version = result.getStdOut().trim(); final String version = result.getStdOut().trim();
if (version.isEmpty()) if (version.isEmpty())
{ {
throw new TransformException(INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR,
"Transformer version check failed to create any output"); "Transformer version check failed to create any output");
} }
return version; return version;

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -33,10 +33,13 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Basic interface for executing transformations via Shell commands * Basic interface for executing transformations via Shell commands
* *
* @author Cezar Leahu * @author Cezar Leahu
*/ */
@Deprecated
public interface CommandExecutor extends Transformer public interface CommandExecutor extends Transformer
{ {
void run(Map<String, String> properties, File targetFile, Long timeout); void run(Map<String, String> properties, File targetFile, Long timeout);

View File

@ -0,0 +1,363 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #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;
/**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* 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):
* <ul>
* <li><tt>-font Helvetica -pointsize 50</tt></li>
* <li><tt>-font Helvetica -pointsize 50 -draw "circle 100,100 150,150"</tt></li>
* <li><tt>-font Helvetica -pointsize 50 -draw "gravity south fill black text 0,12 'CopyRight'"</tt></li>
* </ul>
* The first is the simple case which would be parsed into Strings as follows:
* <tt>"-font", "Helvetica", "-pointsize", "50"</tt>
* <p/>
* The second is more complex in that it includes a quoted parameter, which would be parsed as a single String:
* <tt>"-font", "Helvetica", "-pointsize", "50", "circle 100,100 150,150"</tt>
* Note however that the quotation characters will be stripped from the token.
* <p/>
* The third shows an example with embedded quotation marks, which would parse to:
* <tt>"-font", "Helvetica", "-pointsize", "50", "gravity south fill black text 0,12 'CopyRight'"</tt>
* In this case, the embedded quotation marks (which must be different from those surrounding the parameter)
* are preserved in the extracted token.
* <p/>
* The class does not understand escaped quotes such as <tt>p1 p2 "a b c \"hello\" d" p4</tt>
*
* @author Neil Mc Erlean
* @since 3.4.2
*/
@Deprecated
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<String> 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.
* <p/>
* See above for examples.
*
* @throws NullPointerException if the string to be tokenized was null.
*/
public List<String> 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<Pair<Integer, Integer>> quotedRegions = new ArrayList<>();
for (Pair<Integer, Integer> 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<Substring> 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<Substring> getSubstrings(String str,
List<Pair<Integer, Integer>> quotedRegionIndices)
{
List<Substring> result = new ArrayList<>();
int cursorPosition = 0;
for (Pair<Integer, Integer> 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<Integer, Integer> 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<Integer, Integer> 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<String> 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<String> getTokens()
{
StringTokenizer t = new StringTokenizer(regionString);
List<String> 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<String> 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<F, S> 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 + ")";
}
}
}

View File

@ -0,0 +1,43 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer.executors;
import java.io.File;
/**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Basic interface for executing transformations inside Java/JVM.
*
* @author Cezar Leahu
* @author adavis
*/
@Deprecated
public interface JavaExecutor extends Transformer
{
void call(File sourceFile, File targetFile, String... args) throws Exception;
}

View File

@ -0,0 +1,989 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #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;
/**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* DUPLICATED FROM *alfresco-core*.
*
* This acts as a session similar to the <code>java.lang.Process</code>, but
* logs the system standard and error streams.
* <p>
* The bean can be configured to execute a command directly, or be given a map
* of commands keyed by the <i>os.name</i> Java system property. In this map,
* the default key that is used when no match is found is the
* <b>{@link #KEY_OS_DEFAULT *}</b> key.
* <p>
* 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.
* <p>
* Commands may use placeholders, e.g.
* <pre><code>
* find
* -name
* ${filename}
* </code></pre>
* The <b>filename</b> 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.
* <p>
* Sometimes, a variable may contain several arguments. . In this case, the arguments
* need to be tokenized using a standard <tt>StringTokenizer</tt>. To force tokenization
* of a value, use:
* <pre><code>
* SPLIT:${userArgs}
* </code></pre>
* You should not use this just to split up arguments that are known to require tokenization
* up front. The <b>SPLIT:</b> directive works for the entire argument and will not do anything
* if it is not at the beginning of the argument. Do not use <b>SPLIT:</b> to break up arguments
* that are fixed, so avoid doing this:
* <pre><code>
* SPLIT:ls -lih
* </code></pre>
* Instead, break the command up explicitly:
* <pre><code>
* ls
* -lih
* </code></pre>
*
* Tokenization of quoted parameter values is handled by ExecParameterTokenizer, which
* describes the support in more detail.
*
* @author Derek Hulley
*/
@Deprecated
public class RuntimeExec
{
private static final Logger logger = LoggerFactory.getLogger(RuntimeExec.class);
/**
* the key to use when specifying a command for any other OS: <b>*</b>
*/
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<String, String> defaultProperties = emptyMap();
private String[] processProperties;
private File processDirectory;
private final Set<Integer> 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 <i>out</i> and <i>err</i> 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 <tt>true</tt> (default) is to wait for the command to exit,
* or <tt>false</tt> 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 <i>os.name</i> 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.
* <p>
* 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.
* <p>
* 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 <b>SPLIT:</b> 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:<br>
* '<b>SPLIT: dir . ..</b>' becomes '<b>dir</b>', '<b>.</b>' and '<b>..</b>'.<br>
* '<b>SPLIT: dir ${path}</b>' (if path is '<b>. ..</b>') becomes '<b>dir</b>', '<b>.</b>' and '<b>..</b>'.<br>
* The splitting occurs post-subtitution. Where the arguments are known, it is advisable to avoid
* <b>SPLIT:</b>.
*
* @param commandsByOS a map of command string arrays, keyed by operating system names
* @see #setDefaultProperties(Map)
* @since 3.0
*/
public void setCommandsAndArguments(Map<String, String[]> 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 <i>os.name</i> 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<String, String> 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<String, String[]> fixed = new LinkedHashMap<>();
for (Map.Entry<String, String> 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.
* <p>
* <code>null</code> properties will be treated as an empty string for substitution
* purposes.
*
* @param defaultProperties property values
*/
public void setDefaultProperties(Map<String, String> defaultProperties)
{
this.defaultProperties = defaultProperties;
}
/**
* Set additional runtime properties (environment properties) that will used
* by the executing process.
* <p>
* Any keys or properties that start and end with <b>${...}</b> will be removed on the assumption
* that these are unset properties. <tt>null</tt> 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<String, String> processProperties)
{
ArrayList<String> processPropList = new ArrayList<>(processProperties.size());
boolean hasPath = false;
String systemPath = System.getenv("PATH");
for (Map.Entry<String, String> 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.
* <p>
* If the value is an unsubsititued variable (<b>${...}</b>) 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 <b>"1, 2"</b>.
*
* @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.
* <code>null</code> properties will be treated as an empty string for substitution
* purposes.
* @return Returns the full execution results
*/
public ExecutionResult execute(Map<String, String> 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.
* <code>null</code> 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<String, String> 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<String, String> envVariables = System.getenv();
for (Map.Entry<String, String> 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.
* <p>
* <code>null</code> 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<String, String> properties)
{
Map<String, String> 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<String> adjustedCommandElements = new ArrayList<>(20);
for (String s : command)
{
StringBuilder sb = new StringBuilder(s);
for (Map.Entry<String, String> 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<String> 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<Integer> errCodes;
private final int exitValue;
private final String stdOut;
private final String stdErr;
/**
* @param process the process attached to Java - <tt>null</tt> is allowed
*/
private ExecutionResult(
final Process process,
final String[] command,
final Set<Integer> 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 <tt>false</tt> then the process may still be running when this result is returned.
*
* @return <tt>true</tt> if the process was killed, otherwise <tt>false</tt>
*/
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 <code>InputStream</code> and writes it into a
* <code>StringBuffer</code>
* <p>
* 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.
* <p>
* <b>Remember to <code>start</code> 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();
}
}
}

View File

@ -32,17 +32,20 @@ import org.alfresco.transform.exceptions.TransformException;
import java.io.File; import java.io.File;
import java.util.Map; import java.util.Map;
import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_METADATA_EMBED; import static org.alfresco.transform.common.Mimetype.MIMETYPE_METADATA_EMBED;
import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_METADATA_EXTRACT; import static org.alfresco.transform.common.Mimetype.MIMETYPE_METADATA_EXTRACT;
import static org.alfresco.transformer.util.RequestParamMap.TRANSFORM_NAME_PARAMETER; import static org.alfresco.transformer.util.RequestParamMap.TRANSFORM_NAME_PARAMETER;
import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Basic interface for executing transforms and metadata extract or embed actions. * Basic interface for executing transforms and metadata extract or embed actions.
* *
* @author adavis * @author adavis
*/ */
@Deprecated
public interface Transformer public interface Transformer
{ {
/** /**
@ -82,20 +85,20 @@ public interface Transformer
} }
catch (IllegalArgumentException e) catch (IllegalArgumentException e)
{ {
throw new TransformException(BAD_REQUEST.value(), getMessage(e), e); throw new TransformException(BAD_REQUEST, getMessage(e), e);
} }
catch (Exception e) catch (Exception e)
{ {
throw new TransformException(INTERNAL_SERVER_ERROR.value(), getMessage(e), e); throw new TransformException(INTERNAL_SERVER_ERROR, getMessage(e), e);
} }
if (!targetFile.exists()) if (!targetFile.exists())
{ {
throw new TransformException(INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR,
"Transformer failed to create an output file. Target file does not exist."); "Transformer failed to create an output file. Target file does not exist.");
} }
if (sourceFile.length() > 0 && targetFile.length() == 0) if (sourceFile.length() > 0 && targetFile.length() == 0)
{ {
throw new TransformException(INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR,
"Transformer failed to create an output file. Target file is empty but source file was not empty."); "Transformer failed to create an output file. Target file is empty but source file was not empty.");
} }
} }

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -47,13 +47,15 @@ import org.alfresco.transformer.logging.LogEntry;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource; import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriUtils; import org.springframework.web.util.UriUtils;
/** /**
* * @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*/ */
@Deprecated
public class FileManager public class FileManager
{ {
public static final String SOURCE_FILE = "sourceFile"; public static final String SOURCE_FILE = "sourceFile";
@ -104,9 +106,8 @@ public class FileManager
if (filename == null || filename.isEmpty()) if (filename == null || filename.isEmpty())
{ {
String sourceOrTarget = source ? "source" : "target"; String sourceOrTarget = source ? "source" : "target";
int statusCode = source ? BAD_REQUEST.value() : INTERNAL_SERVER_ERROR.value(); HttpStatus statusCode = source ? BAD_REQUEST : INTERNAL_SERVER_ERROR;
throw new TransformException(statusCode, throw new TransformException(statusCode, "The " + sourceOrTarget + " filename was not supplied");
"The " + sourceOrTarget + " filename was not supplied");
} }
return filename; return filename;
} }
@ -120,8 +121,7 @@ public class FileManager
} }
catch (IOException e) catch (IOException e)
{ {
throw new TransformException(INSUFFICIENT_STORAGE.value(), throw new TransformException(INSUFFICIENT_STORAGE, "Failed to store the source file", e);
"Failed to store the source file", e);
} }
} }
@ -133,8 +133,7 @@ public class FileManager
} }
catch (IOException e) catch (IOException e)
{ {
throw new TransformException(INSUFFICIENT_STORAGE.value(), throw new TransformException(INSUFFICIENT_STORAGE, "Failed to store the source file", e);
"Failed to store the source file", e);
} }
} }
@ -149,13 +148,13 @@ public class FileManager
} }
else else
{ {
throw new TransformException(INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR,
"Could not read the target file: " + file.getPath()); "Could not read the target file: " + file.getPath());
} }
} }
catch (MalformedURLException e) catch (MalformedURLException e)
{ {
throw new TransformException(INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR,
"The target filename was malformed: " + file.getPath(), e); "The target filename was malformed: " + file.getPath(), e);
} }
} }
@ -238,7 +237,7 @@ public class FileManager
Resource targetResource = load(targetFile); Resource targetResource = load(targetFile);
targetFilename = UriUtils.encodePath(getFilename(targetFilename), "UTF-8"); targetFilename = UriUtils.encodePath(getFilename(targetFilename), "UTF-8");
return ResponseEntity.ok().header(CONTENT_DISPOSITION, return ResponseEntity.ok().header(CONTENT_DISPOSITION,
"attachment; filename*= UTF-8''" + targetFilename).body(targetResource); "attachment; filename*=UTF-8''" + targetFilename).body(targetResource);
} }
/** /**

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -40,11 +40,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Provides setter and getter methods to allow the current Thread to set various log properties and for these * Provides setter and getter methods to allow the current Thread to set various log properties and for these
* values to be retrieved. The {@link #complete()} method should be called at the end of a request to flush the * values to be retrieved. The {@link #complete()} method should be called at the end of a request to flush the
* current entry to an internal log Collection of the latest entries. The {@link #getLog()} method is used to obtain * current entry to an internal log Collection of the latest entries. The {@link #getLog()} method is used to obtain
* access to this collection. * access to this collection.
*/ */
@Deprecated
public final class LogEntry public final class LogEntry
{ {
private static final Logger logger = LoggerFactory.getLogger(LogEntry.class); private static final Logger logger = LoggerFactory.getLogger(LogEntry.class);

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -26,6 +26,10 @@
*/ */
package org.alfresco.transformer.logging; package org.alfresco.transformer.logging;
/**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*/
@Deprecated
public interface StandardMessages public interface StandardMessages
{ {
String LICENCE = String LICENCE =

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -29,7 +29,7 @@ package org.alfresco.transformer.messaging;
import javax.jms.ConnectionFactory; import javax.jms.ConnectionFactory;
import javax.jms.Queue; import javax.jms.Queue;
import org.alfresco.transform.client.model.TransformRequestValidator; import org.alfresco.transform.messages.TransformRequestValidator;
import org.apache.activemq.command.ActiveMQQueue; import org.apache.activemq.command.ActiveMQQueue;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -46,12 +46,15 @@ import org.springframework.messaging.handler.annotation.support.DefaultMessageHa
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* JMS and messaging configuration for the T-Engines. Contains the basic config in order to have the * JMS and messaging configuration for the T-Engines. Contains the basic config in order to have the
* T-Engine able to read from queues and send a reply back. * T-Engine able to read from queues and send a reply back.
* *
* @author Lucian Tuca * @author Lucian Tuca
* created on 18/12/2018 * created on 18/12/2018
*/ */
@Deprecated
@Configuration @Configuration
@ConditionalOnProperty(name = "activemq.url") @ConditionalOnProperty(name = "activemq.url")
public class MessagingConfig implements JmsListenerConfigurer public class MessagingConfig implements JmsListenerConfigurer

View File

@ -0,0 +1,70 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer.messaging;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Prints JMS status information at application startup.
*
* @author Cezar Leahu
*/
@Deprecated
@Configuration
public class MessagingInfo
{
private static final Logger logger = LoggerFactory.getLogger(MessagingInfo.class);
@Value("${activemq.url:}")
private String activemqUrl;
@PostConstruct
public void init()
{
// For backwards-compatibility, we continue to rely on setting ACTIVEMQ_URL environment variable (see application.yaml)
// The MessagingConfig class uses on ConditionalOnProperty (ie. activemq.url is set and not false)
// Note: as per application.yaml the broker url is appended with "?jms.watchTopicAdvisories=false". If this needs to be fully
// overridden then it would require explicitly setting both "spring.activemq.broker-url" *and* "activemq.url" (latter to non-false value).
if ((activemqUrl != null) && (! activemqUrl.equals("false")))
{
logger.info("JMS client is ENABLED - ACTIVEMQ_URL ='{}'", activemqUrl);
}
else
{
logger.info("JMS client is DISABLED - ACTIVEMQ_URL is not set");
}
}
}

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -27,14 +27,11 @@
package org.alfresco.transformer.messaging; package org.alfresco.transformer.messaging;
import javax.jms.JMSException; import com.fasterxml.jackson.databind.JavaType;
import javax.jms.Message; import com.fasterxml.jackson.databind.type.TypeFactory;
import javax.jms.Session; import com.google.common.collect.ImmutableMap;
import org.alfresco.transform.client.model.TransformReply; import org.alfresco.transform.client.model.TransformReply;
import org.alfresco.transform.client.model.TransformRequest; import org.alfresco.transform.client.model.TransformRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter; import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConversionException; import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter; import org.springframework.jms.support.converter.MessageConverter;
@ -42,21 +39,22 @@ import org.springframework.jms.support.converter.MessageType;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.JavaType; import javax.jms.JMSException;
import com.fasterxml.jackson.databind.type.TypeFactory; import javax.jms.Message;
import com.google.common.collect.ImmutableMap; import javax.jms.Session;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* TODO: Duplicated from the Router * TODO: Duplicated from the Router
* Custom wrapper over MappingJackson2MessageConverter for T-Request/T-Reply objects. * Custom wrapper over MappingJackson2MessageConverter for T-Request/T-Reply objects.
* *
* @author Cezar Leahu * @author Cezar Leahu
*/ */
@Deprecated
@Service @Service
public class TransformMessageConverter implements MessageConverter public class TransformMessageConverter implements MessageConverter
{ {
private static final Logger logger = LoggerFactory.getLogger(TransformMessageConverter.class);
private static final MappingJackson2MessageConverter converter; private static final MappingJackson2MessageConverter converter;
private static final JavaType TRANSFORM_REQUEST_TYPE = private static final JavaType TRANSFORM_REQUEST_TYPE =
TypeFactory.defaultInstance().constructType(TransformRequest.class); TypeFactory.defaultInstance().constructType(TransformRequest.class);

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -36,6 +36,8 @@ import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* TODO: Duplicated from the Router * TODO: Duplicated from the Router
* TransformReplySender Bean * TransformReplySender Bean
* <p/> * <p/>
@ -43,6 +45,7 @@ import org.springframework.stereotype.Component;
* *
* @author Cezar Leahu * @author Cezar Leahu
*/ */
@Deprecated
@Component @Component
public class TransformReplySender public class TransformReplySender
{ {
@ -56,8 +59,9 @@ public class TransformReplySender
send(destination, reply, reply.getRequestId()); send(destination, reply, reply.getRequestId());
} }
public void send(final Destination destination, final TransformReply reply, public void send(final Destination destination, final TransformReply reply, final String correlationId)
final String correlationId) {
if (destination != null)
{ {
try try
{ {
@ -70,8 +74,8 @@ public class TransformReplySender
} }
catch (Exception e) catch (Exception e)
{ {
logger.error( logger.error("Failed to send T-Reply " + reply + " - for correlation ID " + correlationId, e);
"Failed to send T-Reply " + reply + " - for correlation ID " + correlationId, e); }
} }
} }
} }

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005-2021 Alfresco Software Limited * Copyright (C) 2005-2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -49,6 +49,8 @@ import java.util.StringTokenizer;
import java.util.TreeMap; import java.util.TreeMap;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Helper methods for metadata extract and embed. * Helper methods for metadata extract and embed.
* <p> * <p>
* <i>Much of the code is based on AbstractMappingMetadataExtracter from the * <i>Much of the code is based on AbstractMappingMetadataExtracter from the
@ -91,6 +93,7 @@ import java.util.TreeMap;
* @author Derek Hulley * @author Derek Hulley
* @author adavis * @author adavis
*/ */
@Deprecated
public abstract class AbstractMetadataExtractor public abstract class AbstractMetadataExtractor
{ {
private static final String EXTRACT = "extract"; private static final String EXTRACT = "extract";

View File

@ -0,0 +1,80 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer.model;
import java.util.Objects;
/**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* TODO: Copied from org.alfresco.store.entity (alfresco-shared-file-store). To be discussed
*
* POJO that represents content reference ({@link java.util.UUID})
*/
@Deprecated
public class FileRefEntity
{
private String fileRef;
public FileRefEntity() {}
public FileRefEntity(String fileRef)
{
this.fileRef = fileRef;
}
public void setFileRef(String fileRef)
{
this.fileRef = fileRef;
}
public String getFileRef()
{
return fileRef;
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FileRefEntity that = (FileRefEntity) o;
return Objects.equals(fileRef, that.fileRef);
}
@Override
public int hashCode()
{
return Objects.hash(fileRef);
}
@Override
public String toString()
{
return fileRef;
}
}

View File

@ -0,0 +1,57 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer.model;
/**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* TODO: Copied from org.alfresco.store.entity (alfresco-shared-file-store). To be discussed
*
* POJO that describes the ContentRefEntry response, contains {@link FileRefEntity} according to API spec
*/
@Deprecated
public class FileRefResponse
{
private FileRefEntity entry;
public FileRefResponse() {}
public FileRefResponse(FileRefEntity entry)
{
this.entry = entry;
}
public FileRefEntity getEntry()
{
return entry;
}
public void setEntry(FileRefEntity entry)
{
this.entry = entry;
}
}

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -51,12 +51,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Provides the logic performing test transformations by the live and ready probes. * Provides the logic performing test transformations by the live and ready probes.
* *
* <p><b>K8s probes</b>: A readiness probe indicates if the pod should accept request. <b>It does not indicate that a pod is * <p><b>K8s probes</b>: A readiness probe indicates if the pod should accept request. <b>It does not indicate that a pod is
* ready after startup</b>. The liveness probe indicates when to kill the pod. <b>Both probes are called throughout the * ready after startup</b>. The liveness probe indicates when to kill the pod. <b>Both probes are called throughout the
* lifetime of the pod</b> and a <b>liveness probes can take place before a readiness probe.</b> The k8s * lifetime of the pod</b> and a <b>liveness probes can take place before a readiness probe.</b> The k8s
* <b>initialDelaySeconds field is not fully honoured</b> as it multiplied by a random number, so is * <b>initialDelaySeconds field is not fully honoured</b> as it is multiplied by a random number, so is
* actually a maximum initial delay in seconds, but could be 0. </p> * actually a maximum initial delay in seconds, but could be 0. </p>
* *
* <p>Live and readiness probes might do test transforms. The first 6 requests result in a transformation * <p>Live and readiness probes might do test transforms. The first 6 requests result in a transformation
@ -72,6 +74,7 @@ import org.slf4j.LoggerFactory;
* <li>maxTransformSeconds - the maximum time for a transformation, including failed ones.</li> * <li>maxTransformSeconds - the maximum time for a transformation, including failed ones.</li>
* </ul> * </ul>
*/ */
@Deprecated
public abstract class ProbeTestTransform public abstract class ProbeTestTransform
{ {
private final Logger logger = LoggerFactory.getLogger(ProbeTestTransform.class); private final Logger logger = LoggerFactory.getLogger(ProbeTestTransform.class);
@ -229,7 +232,7 @@ public abstract class ProbeTestTransform
if (time > maxTime) if (time > maxTime)
{ {
throw new TransformException(INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR,
getMessagePrefix(isLiveProbe) + getMessagePrefix(isLiveProbe) +
message + " which is more than " + livenessPercent + message + " which is more than " + livenessPercent +
"% slower than the normal value of " + normalTime + "ms"); "% slower than the normal value of " + normalTime + "ms");
@ -247,14 +250,14 @@ public abstract class ProbeTestTransform
{ {
if (die.get()) if (die.get())
{ {
throw new TransformException(TOO_MANY_REQUESTS.value(), throw new TransformException(TOO_MANY_REQUESTS,
getMessagePrefix(isLiveProbe) + "Transformer requested to die. A transform took " + getMessagePrefix(isLiveProbe) + "Transformer requested to die. A transform took " +
"longer than " + (maxTransformTime * 1000) + " seconds"); "longer than " + (maxTransformTime / 1000) + " seconds");
} }
if (maxTransformCount > 0 && transformCount.get() > maxTransformCount) if (maxTransformCount > 0 && transformCount.get() > maxTransformCount)
{ {
throw new TransformException(TOO_MANY_REQUESTS.value(), throw new TransformException(TOO_MANY_REQUESTS,
getMessagePrefix(isLiveProbe) + "Transformer requested to die. It has performed " + getMessagePrefix(isLiveProbe) + "Transformer requested to die. It has performed " +
"more than " + maxTransformCount + " transformations"); "more than " + maxTransformCount + " transformations");
} }
@ -271,7 +274,7 @@ public abstract class ProbeTestTransform
} }
catch (IOException e) catch (IOException e)
{ {
throw new TransformException(INSUFFICIENT_STORAGE.value(), throw new TransformException(INSUFFICIENT_STORAGE,
getMessagePrefix(isLiveProbe) + "Failed to store the source file", e); getMessagePrefix(isLiveProbe) + "Failed to store the source file", e);
} }
long length = sourceFile.length(); long length = sourceFile.length();
@ -329,13 +332,13 @@ public abstract class ProbeTestTransform
String probeMessage = getProbeMessage(isLiveProbe); String probeMessage = getProbeMessage(isLiveProbe);
if (!targetFile.exists() || !targetFile.isFile()) if (!targetFile.exists() || !targetFile.isFile())
{ {
throw new TransformException(INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR,
probeMessage + "Target File \"" + targetFile.getAbsolutePath() + "\" did not exist"); probeMessage + "Target File \"" + targetFile.getAbsolutePath() + "\" did not exist");
} }
long length = targetFile.length(); long length = targetFile.length();
if (length < minExpectedLength || length > maxExpectedLength) if (length < minExpectedLength || length > maxExpectedLength)
{ {
throw new TransformException(INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR,
probeMessage + "Target File \"" + targetFile.getAbsolutePath() + probeMessage + "Target File \"" + targetFile.getAbsolutePath() +
"\" was the wrong size (" + length + "). Needed to be between " + "\" was the wrong size (" + length + "). Needed to be between " +
minExpectedLength + " and " + maxExpectedLength); minExpectedLength + " and " + maxExpectedLength);

View File

@ -0,0 +1,37 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2020 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer.util;
/**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Partially duplicated from *alfresco-data-model*.
*/
@Deprecated
public interface MimetypeMap extends org.alfresco.transform.common.Mimetype
{
}

View File

@ -27,9 +27,12 @@
package org.alfresco.transformer.util; package org.alfresco.transformer.util;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Extends the list of transform options with historic request parameters or 'extra' parameters used in testing * Extends the list of transform options with historic request parameters or 'extra' parameters used in testing
* or communication in the all-in-one transformer. * or communication in the all-in-one transformer.
*/ */
@Deprecated
public interface RequestParamMap extends org.alfresco.transform.client.util.RequestParamMap public interface RequestParamMap extends org.alfresco.transform.client.util.RequestParamMap
{ {
// This property can be sent by acs repository's legacy transformers to force a transform, // This property can be sent by acs repository's legacy transformers to force a transform,
@ -41,10 +44,5 @@ public interface RequestParamMap extends org.alfresco.transform.client.util.Requ
String TRANSFORM_NAME_PROPERTY = "transformName"; String TRANSFORM_NAME_PROPERTY = "transformName";
String TRANSFORM_NAME_PARAMETER = "alfresco.transform-name-parameter"; String TRANSFORM_NAME_PARAMETER = "alfresco.transform-name-parameter";
String FILE = "file";
String SOURCE_EXTENSION = "sourceExtension";
String SOURCE_MIMETYPE = "sourceMimetype";
String TARGET_EXTENSION = "targetExtension";
String TARGET_MIMETYPE = "targetMimetype";
String TEST_DELAY = "testDelay"; String TEST_DELAY = "testDelay";
} }

View File

@ -0,0 +1,67 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transformer.util;
/**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*/
@Deprecated
public class Util
{
/**
* Safely converts a {@link String} to an {@link Integer}
*
* @param param String to be converted
* @return Null if param is null or converted value as {@link Integer}
*/
public static Integer stringToInteger(final String param)
{
return param == null ? null : Integer.parseInt(param);
}
/**
* Safely converts a {@link String} to a {@link Boolean}
*
* @param param String to be converted
* @return Null if param is null or converted value as {@link Boolean}
*/
public static Boolean stringToBoolean(final String param)
{
return param == null ? null : Boolean.parseBoolean(param);
}
/**
* Safely converts a {@link String} to a {@link Long}
*
* @param param String to be converted
* @return Null if param is null or converted value as {@link Boolean}
*/
public static Long stringToLong(final String param)
{
return param == null ? null : Long.parseLong(param);
}
}

View File

@ -31,7 +31,7 @@ logging:
org.alfresco.transformer.ImageMagickController: debug org.alfresco.transformer.ImageMagickController: debug
org.alfresco.transformer.TikaController: debug org.alfresco.transformer.TikaController: debug
org.alfresco.transformer.MiscellaneousTransformersController: debug org.alfresco.transformer.MiscellaneousTransformersController: debug
org.alfresco.transform.router.TransformerDebug: debug org.alfresco.transform.common.TransformerDebug: debug
fileStoreUrl: ${FILE_STORE_URL:http://localhost:8099/alfresco/api/-default-/private/sfs/versions/1/file} fileStoreUrl: ${FILE_STORE_URL:http://localhost:8099/alfresco/api/-default-/private/sfs/versions/1/file}

View File

@ -26,8 +26,8 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import static org.alfresco.transform.client.util.RequestParamMap.DIRECT_ACCESS_URL; import static org.alfresco.transform.common.RequestParamMap.DIRECT_ACCESS_URL;
import static org.alfresco.transform.client.util.RequestParamMap.ENDPOINT_TRANSFORM; import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.http.HttpMethod.POST; import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA; import static org.springframework.http.MediaType.MULTIPART_FORM_DATA;
@ -43,9 +43,12 @@ import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Super class for testing controllers with a server. Includes tests for the AbstractTransformerController itself. * Super class for testing controllers with a server. Includes tests for the AbstractTransformerController itself.
* Note: Currently uses json rather than HTML as json is returned by this spring boot test harness. * Note: Currently uses json rather than HTML as json is returned by this spring boot test harness.
*/ */
@Deprecated
public abstract class AbstractHttpRequestTest public abstract class AbstractHttpRequestTest
{ {
@LocalServerPort @LocalServerPort

View File

@ -28,7 +28,7 @@ package org.alfresco.transformer;
import static java.text.MessageFormat.format; import static java.text.MessageFormat.format;
import static org.alfresco.transformer.EngineClient.sendTRequest; import static org.alfresco.transformer.EngineClient.sendTRequest;
import static org.alfresco.transformer.util.MimetypeMap.MIMETYPE_METADATA_EXTRACT; import static org.alfresco.transform.common.Mimetype.MIMETYPE_METADATA_EXTRACT;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail;
import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.HttpStatus.OK;
@ -47,6 +47,8 @@ import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Super class of metadata integration tests. Sub classes should provide the following: * Super class of metadata integration tests. Sub classes should provide the following:
* <p> * <p>
* <ul> * <ul>
@ -72,6 +74,7 @@ import org.springframework.http.ResponseEntity;
* @author adavis * @author adavis
* @author dedwards * @author dedwards
*/ */
@Deprecated
public abstract class AbstractMetadataExtractsIT public abstract class AbstractMetadataExtractsIT
{ {
private static final String ENGINE_URL = "http://localhost:8090"; private static final String ENGINE_URL = "http://localhost:8090";

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -39,9 +39,12 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.core.JmsTemplate;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* @author Lucian Tuca * @author Lucian Tuca
* created on 15/01/2019 * created on 15/01/2019
*/ */
@Deprecated
@SpringBootTest(properties = {"activemq.url=nio://localhost:61616"}) @SpringBootTest(properties = {"activemq.url=nio://localhost:61616"})
public abstract class AbstractQueueTransformServiceIT public abstract class AbstractQueueTransformServiceIT
{ {

View File

@ -26,53 +26,21 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import com.fasterxml.jackson.databind.ObjectMapper;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN; import com.google.common.collect.ImmutableList;
import static org.alfresco.transform.client.util.RequestParamMap.DIRECT_ACCESS_URL; import com.google.common.collect.ImmutableMap;
import static org.alfresco.transform.client.util.RequestParamMap.ENDPOINT_TRANSFORM; import com.google.common.collect.ImmutableSet;
import static org.alfresco.transform.client.util.RequestParamMap.ENDPOINT_TRANSFORM_CONFIG_LATEST;
import static org.alfresco.transform.client.util.RequestParamMap.ENDPOINT_TRANSFORM_CONFIG;
import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.http.HttpHeaders.ACCEPT;
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.alfresco.transform.client.model.InternalContext; import org.alfresco.transform.client.model.InternalContext;
import org.alfresco.transform.client.model.TransformReply; import org.alfresco.transform.client.model.TransformReply;
import org.alfresco.transform.client.model.TransformRequest; import org.alfresco.transform.client.model.TransformRequest;
import org.alfresco.transform.client.model.config.SupportedSourceAndTarget; import org.alfresco.transform.config.SupportedSourceAndTarget;
import org.alfresco.transform.client.model.config.TransformConfig; import org.alfresco.transform.config.TransformConfig;
import org.alfresco.transform.client.model.config.TransformOption; import org.alfresco.transform.config.TransformOption;
import org.alfresco.transform.client.model.config.TransformOptionGroup; import org.alfresco.transform.config.TransformOptionGroup;
import org.alfresco.transform.client.model.config.TransformOptionValue; import org.alfresco.transform.config.TransformOptionValue;
import org.alfresco.transform.client.model.config.Transformer; import org.alfresco.transform.config.Transformer;
import org.alfresco.transform.client.registry.TransformServiceRegistry; import org.alfresco.transform.messages.TransformStack;
import org.alfresco.transform.router.TransformStack; import org.alfresco.transform.registry.TransformServiceRegistry;
import org.alfresco.transformer.clients.AlfrescoSharedFileStoreClient; import org.alfresco.transformer.clients.AlfrescoSharedFileStoreClient;
import org.alfresco.transformer.model.FileRefEntity; import org.alfresco.transformer.model.FileRefEntity;
import org.alfresco.transformer.model.FileRefResponse; import org.alfresco.transformer.model.FileRefResponse;
@ -91,14 +59,47 @@ import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File;
import com.google.common.collect.ImmutableList; import java.io.FileInputStream;
import com.google.common.collect.ImmutableMap; import java.io.FileOutputStream;
import com.google.common.collect.ImmutableSet; import java.io.IOException;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import static org.alfresco.transform.common.RequestParamMap.DIRECT_ACCESS_URL;
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM;
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM_CONFIG;
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM_CONFIG_LATEST;
import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.http.HttpHeaders.ACCEPT;
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* Super class for testing controllers without a server. Includes tests for the AbstractTransformerController itself. * Super class for testing controllers without a server. Includes tests for the AbstractTransformerController itself.
*/ */
@Deprecated
public abstract class AbstractTransformerControllerTest public abstract class AbstractTransformerControllerTest
{ {
@TempDir // added as part of ATS-702 to allow test resources to be read from the imported jar files to prevent test resource duplication @TempDir // added as part of ATS-702 to allow test resources to be read from the imported jar files to prevent test resource duplication
@ -222,8 +223,7 @@ public abstract class AbstractTransformerControllerTest
return testFileUrl == null ? null : testFile; return testFileUrl == null ? null : testFile;
} }
protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile, protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile, String... params)
String... params)
{ {
if (sourceFile == null) if (sourceFile == null)
{ {
@ -612,64 +612,4 @@ public abstract class AbstractTransformerControllerTest
transformer.setSupportedSourceAndTargetList(supportedSourceAndTargetList); transformer.setSupportedSourceAndTargetList(supportedSourceAndTargetList);
return transformer; return transformer;
} }
@Test
public void queueTransformRequestUsingDirectAccessUrlTest() throws Exception
{
// Files
String sourceFileRef = UUID.randomUUID().toString();
File sourceFile = getTestFile("quick." + sourceExtension, true);
String targetFileRef = UUID.randomUUID().toString();
TransformRequest transformRequest = createTransformRequest(sourceFileRef, sourceFile);
Map<String, String> transformRequestOptions = transformRequest.getTransformRequestOptions();
String directUrl = "file://" + sourceFile.toPath();
transformRequestOptions.put(DIRECT_ACCESS_URL, directUrl);
transformRequest.setTransformRequestOptions(transformRequestOptions);
when(alfrescoSharedFileStoreClient.saveFile(any()))
.thenReturn(new FileRefResponse(new FileRefEntity(targetFileRef)));
// Update the Transformation Request with any specific params before sending it
updateTransformRequestWithSpecificOptions(transformRequest);
// Serialize and call the transformer
String tr = objectMapper.writeValueAsString(transformRequest);
String transformationReplyAsString = mockMvc
.perform(MockMvcRequestBuilders
.post("/transform")
.header(ACCEPT, APPLICATION_JSON_VALUE)
.header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
.content(tr))
.andExpect(status().is(CREATED.value()))
.andReturn().getResponse().getContentAsString();
TransformReply transformReply = objectMapper.readValue(transformationReplyAsString,
TransformReply.class);
// Assert the reply
assertEquals(transformRequest.getRequestId(), transformReply.getRequestId());
assertEquals(transformRequest.getClientData(), transformReply.getClientData());
assertEquals(transformRequest.getSchema(), transformReply.getSchema());
}
@Test
public void httpTransformRequestUsingDirectAccessUrlTest() throws Exception
{
File dauSourceFile = getTestFile("quick." + sourceExtension, true);
String directUrl = "file://" + dauSourceFile.toPath();
ResultActions resultActions = mockMvc.perform(
mockMvcRequest(ENDPOINT_TRANSFORM, null)
.param("targetExtension", targetExtension)
.param(DIRECT_ACCESS_URL, directUrl))
.andExpect(status().is(OK.value()));
if (expectedTargetFileBytes != null)
{
resultActions.andExpect(content().bytes(expectedTargetFileBytes));
}
}
} }

View File

@ -8,7 +8,7 @@
package org.alfresco.transformer; package org.alfresco.transformer;
import static java.util.Collections.emptyMap; import static java.util.Collections.emptyMap;
import static org.alfresco.transform.client.util.RequestParamMap.ENDPOINT_TRANSFORM; import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA; import static org.springframework.http.MediaType.MULTIPART_FORM_DATA;
import java.util.Map; import java.util.Map;
@ -23,8 +23,11 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
/** /**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*
* @author Cezar Leahu * @author Cezar Leahu
*/ */
@Deprecated
public class EngineClient public class EngineClient
{ {
private static final RestTemplate REST_TEMPLATE = new RestTemplate(); private static final RestTemplate REST_TEMPLATE = new RestTemplate();

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Transform Core * Alfresco Transform Core
* %% * %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited * Copyright (C) 2005 - 2022 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* - * -
@ -55,6 +55,10 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.jms.support.converter.MessageConversionException; import org.springframework.jms.support.converter.MessageConversionException;
/**
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
*/
@Deprecated
public class QueueTransformServiceTest public class QueueTransformServiceTest
{ {
@Mock @Mock

Some files were not shown because too many files have changed in this diff Show More