mirror of
https://github.com/Alfresco/alfresco-transform-core.git
synced 2025-10-08 14:51:18 +00:00
ATS-671: Split engines into fat & skinny modules (ATS-674) (#192)
Each transform engine project has been separated into 2 modules so that an executable and non-executable jar can be created. Modules have been renamed such that *docker* has been removed from the artifactIds and project names. Co-authored-by: Erik Knizat <erik.knizat@alfresco.com> Co-authored-by: David Edwards <david.edwards@alfresco.com>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
target/docker/
|
@@ -0,0 +1,32 @@
|
||||
# Image provides a container in which to run miscellaneous transformations for Alfresco Content Services.
|
||||
|
||||
FROM alfresco/alfresco-base-java:11.0.1-openjdk-centos-7-72b88c6f1f4c
|
||||
|
||||
ENV APACHE_LICENSE_FILE=https://github.com/Alfresco/acs-community-packaging/blob/master/distribution/src/main/resources/licenses/3rd-party/Apache%202.0.txt
|
||||
ENV JAVA_OPTS=""
|
||||
|
||||
# Set default user information
|
||||
ARG GROUPNAME=Alfresco
|
||||
ARG GROUPID=1000
|
||||
ARG MISCUSERNAME=transform-misc
|
||||
ARG USERID=33004
|
||||
|
||||
COPY target/${env.project_artifactId}-${env.project_version}.jar /usr/bin
|
||||
|
||||
RUN ln /usr/bin/${env.project_artifactId}-${env.project_version}.jar /usr/bin/${env.project_artifactId}.jar && \
|
||||
curl -s -S $APACHE_LICENSE_FILE -o Apache\ 2.0.txt && \
|
||||
yum clean all
|
||||
|
||||
ADD target/generated-resources/licenses /licenses
|
||||
ADD target/generated-resources/licenses.xml /licenses/
|
||||
ADD target/generated-sources/license/THIRD-PARTY.txt /licenses/
|
||||
|
||||
RUN groupadd -g ${GROUPID} ${GROUPNAME} && \
|
||||
useradd -u ${USERID} -G ${GROUPNAME} ${MISCUSERNAME} && \
|
||||
chgrp -R ${GROUPNAME} /usr/bin/${env.project_artifactId}.jar
|
||||
|
||||
EXPOSE 8090
|
||||
|
||||
USER ${MISCUSERNAME}
|
||||
|
||||
ENTRYPOINT java $JAVA_OPTS -jar /usr/bin/${env.project_artifactId}.jar
|
291
alfresco-transform-misc/alfresco-transform-misc-boot/pom.xml
Normal file
291
alfresco-transform-misc/alfresco-transform-misc-boot/pom.xml
Normal file
@@ -0,0 +1,291 @@
|
||||
<?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-boot</artifactId>
|
||||
<name>Alfresco Docker Miscellaneous Transformers</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-transform-core</artifactId>
|
||||
<version>2.2.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<image.name>alfresco/alfresco-transform-misc</image.name>
|
||||
<image.registry>quay.io</image.registry>
|
||||
<env.project_artifactId>${project.artifactId}</env.project_artifactId>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-transformer-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-transformer-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-transform-misc</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</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>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dom4j</groupId>
|
||||
<artifactId>dom4j</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>docker-it-setup</id>
|
||||
<!-- raises an ActiveMq container for the Integration Tests -->
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>docker-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<images>
|
||||
<image>
|
||||
<alias>activemq</alias>
|
||||
<name>alfresco/alfresco-activemq:5.15.8</name>
|
||||
<run>
|
||||
<hostname>activemq</hostname>
|
||||
<ports>
|
||||
<port>8161:8161</port>
|
||||
<port>5672:5672</port>
|
||||
<port>61616:61616</port>
|
||||
</ports>
|
||||
<wait>
|
||||
<log>Apache ActiveMQ 5.15.8 .* started</log>
|
||||
<time>20000</time>
|
||||
<kill>500</kill>
|
||||
<shutdown>100</shutdown>
|
||||
<exec>
|
||||
<preStop>kill 1</preStop>
|
||||
<preStop>kill -9 1</preStop>
|
||||
</exec>
|
||||
</wait>
|
||||
</run>
|
||||
</image>
|
||||
|
||||
<image>
|
||||
<alias>misc</alias>
|
||||
<name>${image.name}:${image.tag}</name>
|
||||
<run>
|
||||
<ports>
|
||||
<port>8090:8090</port>
|
||||
</ports>
|
||||
<wait>
|
||||
<http>
|
||||
<url>http://localhost:8090/transform/config</url>
|
||||
<method>GET</method>
|
||||
<status>200...299</status>
|
||||
</http>
|
||||
<time>300000</time>
|
||||
<kill>500</kill>
|
||||
<shutdown>100</shutdown>
|
||||
<exec>
|
||||
<preStop>kill 1</preStop>
|
||||
<preStop>kill -9 1</preStop>
|
||||
</exec>
|
||||
</wait>
|
||||
</run>
|
||||
</image>
|
||||
</images>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>local</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>fabric8-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<images>
|
||||
<image>
|
||||
<name>${image.name}:${image.tag}</name>
|
||||
<build>
|
||||
<dockerFileDir>${project.basedir}/</dockerFileDir>
|
||||
<buildOptions>
|
||||
<squash>true</squash>
|
||||
</buildOptions>
|
||||
</build>
|
||||
</image>
|
||||
</images>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>build-image</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>internal</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>fabric8-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<images>
|
||||
<!-- QuayIO image -->
|
||||
<image>
|
||||
<name>${image.name}:${image.tag}</name>
|
||||
<registry>${image.registry}</registry>
|
||||
<build>
|
||||
<dockerFileDir>${project.basedir}/</dockerFileDir>
|
||||
<buildOptions>
|
||||
<squash>true</squash>
|
||||
</buildOptions>
|
||||
</build>
|
||||
</image>
|
||||
<!-- DockerHub image -->
|
||||
<image>
|
||||
<name>${image.name}:${image.tag}</name>
|
||||
<build>
|
||||
<dockerFileDir>${project.basedir}/</dockerFileDir>
|
||||
<buildOptions>
|
||||
<squash>true</squash>
|
||||
</buildOptions>
|
||||
</build>
|
||||
</image>
|
||||
</images>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>build-image</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>push-image</id>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>push</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>fabric8-maven-plugin</artifactId>
|
||||
<configuration combine.self="override">
|
||||
<images>
|
||||
<!-- QuayIO image -->
|
||||
<image>
|
||||
<name>${image.name}:${project.version}</name>
|
||||
<registry>${image.registry}</registry>
|
||||
<build>
|
||||
<dockerFileDir>${project.basedir}/</dockerFileDir>
|
||||
<buildOptions>
|
||||
<squash>true</squash>
|
||||
</buildOptions>
|
||||
</build>
|
||||
</image>
|
||||
<!-- DockerHub image -->
|
||||
<image>
|
||||
<name>${image.name}:${project.version}</name>
|
||||
<build>
|
||||
<dockerFileDir>${project.basedir}/</dockerFileDir>
|
||||
<buildOptions>
|
||||
<squash>true</squash>
|
||||
</buildOptions>
|
||||
</build>
|
||||
</image>
|
||||
</images>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>build-push-image</id>
|
||||
<phase>deploy</phase>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
<goal>push</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer;
|
||||
|
||||
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 io.micrometer.core.instrument.MeterRegistry;
|
||||
|
||||
@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("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
|
||||
logger.info("The transformers in this project use libraries from Apache. See the license at http://www.apache.org/licenses/LICENSE-2.0. or in /Apache\\\\ 2.0.txt");
|
||||
logger.info("Additional libraries used:");
|
||||
logger.info("* htmlparser http://htmlparser.sourceforge.net/license.html");
|
||||
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
|
||||
|
||||
logger.info("Starting application components... Done");
|
||||
}
|
||||
}
|
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer;
|
||||
|
||||
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.fs.FileManager.createAttachment;
|
||||
import static org.alfresco.transformer.fs.FileManager.createSourceFile;
|
||||
import static org.alfresco.transformer.fs.FileManager.createTargetFile;
|
||||
import static org.alfresco.transformer.fs.FileManager.createTargetFileName;
|
||||
import static org.alfresco.transformer.transformers.HtmlParserContentTransformer.SOURCE_ENCODING;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.alfresco.transformer.logging.LogEntry;
|
||||
import org.alfresco.transformer.probes.ProbeTestTransform;
|
||||
import org.alfresco.transformer.transformers.SelectingTransformer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@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");
|
||||
transformer.transform("html", sourceFile, targetFile, MIMETYPE_HTML,
|
||||
MIMETYPE_TEXT_PLAIN, parameters);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processTransform(final File sourceFile, final File targetFile,
|
||||
final String sourceMimetype, final String targetMimetype,
|
||||
final Map<String, String> transformOptions, final Long timeout)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(
|
||||
"Processing request with: sourceFile '{}', targetFile '{}', transformOptions" +
|
||||
" '{}', timeout {} ms", sourceFile, targetFile, transformOptions, timeout);
|
||||
}
|
||||
|
||||
final String transform = getTransformerName(sourceFile, sourceMimetype, targetMimetype,
|
||||
transformOptions);
|
||||
transformer.transform(transform, sourceFile, targetFile, sourceMimetype, targetMimetype,
|
||||
transformOptions);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/transform", consumes = MULTIPART_FORM_DATA_VALUE)
|
||||
public ResponseEntity<Resource> transform(HttpServletRequest request,
|
||||
@RequestParam("file") MultipartFile sourceMultipartFile,
|
||||
@RequestParam("targetExtension") String targetExtension,
|
||||
@RequestParam("targetMimetype") String targetMimetype,
|
||||
@RequestParam(value = "targetEncoding", required = false) String targetEncoding,
|
||||
@RequestParam("sourceMimetype") String sourceMimetype,
|
||||
@RequestParam(value = "sourceEncoding", required = false) String sourceEncoding,
|
||||
@RequestParam(value = "pageLimit", required = false) String pageLimit,
|
||||
@RequestParam(value = "testDelay", required = false) Long testDelay)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(
|
||||
"Processing request with: sourceMimetype '{}', sourceEncoding '{}', " +
|
||||
"targetMimetype '{}', targetExtension '{}', targetEncoding '{}', pageLimit '{}'",
|
||||
sourceMimetype, sourceEncoding, targetMimetype, targetExtension, targetEncoding,
|
||||
pageLimit);
|
||||
}
|
||||
|
||||
final String targetFilename = createTargetFileName(
|
||||
sourceMultipartFile.getOriginalFilename(), targetExtension);
|
||||
getProbeTestTransform().incrementTransformerCount();
|
||||
final File sourceFile = createSourceFile(request, sourceMultipartFile);
|
||||
final File targetFile = createTargetFile(request, targetFilename);
|
||||
|
||||
final Map<String, String> transformOptions = createTransformOptions(
|
||||
"sourceEncoding", sourceEncoding,
|
||||
"targetEncoding", targetEncoding,
|
||||
"pageLimit", pageLimit);
|
||||
|
||||
final String transform = getTransformerName(sourceFile, sourceMimetype, targetMimetype,
|
||||
transformOptions);
|
||||
transformer.transform(transform, sourceFile, targetFile, sourceMimetype, targetMimetype,
|
||||
transformOptions);
|
||||
|
||||
final ResponseEntity<Resource> body = createAttachment(targetFilename, targetFile);
|
||||
LogEntry.setTargetSize(targetFile.length());
|
||||
long time = LogEntry.setStatusCodeAndMessage(OK.value(), "Success");
|
||||
time += LogEntry.addDelay(testDelay);
|
||||
getProbeTestTransform().recordTransformTime(time);
|
||||
return body;
|
||||
}
|
||||
}
|
@@ -0,0 +1,2 @@
|
||||
queue:
|
||||
engineRequestQueue: ${TRANSFORM_ENGINE_REQUEST_QUEUE:org.alfresco.transform.engine.misc.acs}
|
@@ -0,0 +1,80 @@
|
||||
{
|
||||
"transformOptions": {
|
||||
"textToPdfOptions": [
|
||||
{"value": {"name": "pageLimit"}},
|
||||
{"value": {"name": "sourceEncoding"}}
|
||||
],
|
||||
"stringOptions": [
|
||||
{"value": {"name": "sourceEncoding"}},
|
||||
{"value": {"name": "targetEncoding"}}
|
||||
],
|
||||
"htmlOptions": [
|
||||
{"value": {"name": "sourceEncoding"}}
|
||||
]
|
||||
},
|
||||
"transformers": [
|
||||
{
|
||||
"transformerName": "html",
|
||||
"supportedSourceAndTargetList": [
|
||||
{"sourceMediaType": "text/html", "targetMediaType": "text/plain"}
|
||||
],
|
||||
"transformOptions": [
|
||||
"htmlOptions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
<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>
|
@@ -0,0 +1,29 @@
|
||||
<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>
|
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_HTML;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IMAGE_JPEG;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_KEYNOTE;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_NUMBERS;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_WORDPROCESSING;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_PDF;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_RFC822;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.alfresco.transform.client.model.TransformRequest;
|
||||
import org.alfresco.transformer.transformers.SelectingTransformer;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.text.PDFTextStripper;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
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.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebMvcTest(MiscController.class)
|
||||
public class MiscControllerTest extends AbstractTransformerControllerTest
|
||||
{
|
||||
@Autowired
|
||||
private MiscController controller;
|
||||
|
||||
private final String sourceEncoding = "UTF-8";
|
||||
private final String targetEncoding = "UTF-8";
|
||||
private final String targetMimetype = MIMETYPE_TEXT_PLAIN;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception
|
||||
{
|
||||
sourceMimetype = MIMETYPE_HTML;
|
||||
sourceExtension = "html";
|
||||
targetExtension = "txt";
|
||||
expectedOptions = null;
|
||||
expectedSourceSuffix = null;
|
||||
expectedSourceFileBytes = readTestFile(sourceExtension);
|
||||
expectedTargetFileBytes = readTestFile(targetExtension);
|
||||
//expectedTargetFileBytes = null;
|
||||
sourceFile = new MockMultipartFile("file", "quick." + sourceExtension, sourceMimetype,
|
||||
expectedSourceFileBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mockTransformCommand(String sourceExtension, String targetExtension,
|
||||
String sourceMimetype, boolean readTargetFileBytes)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractTransformerController getController()
|
||||
{
|
||||
return controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateTransformRequestWithSpecificOptions(TransformRequest transformRequest)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile,
|
||||
String... params)
|
||||
{
|
||||
final MockHttpServletRequestBuilder builder = super
|
||||
.mockMvcRequest(url, sourceFile, params)
|
||||
.param("sourceEncoding", sourceEncoding)
|
||||
.param("targetMimetype", targetMimetype)
|
||||
.param("sourceMimetype", sourceMimetype);
|
||||
|
||||
// Only the 'string' transformer should have the targetEncoding.
|
||||
if (!"message/rfc822".equals(sourceMimetype) && !"text/html".equals(sourceMimetype))
|
||||
{
|
||||
builder.param("targetEncoding", targetEncoding);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void noTargetFileTest()
|
||||
{
|
||||
// Ignore the test in super class as the Misc transforms are real rather than mocked up.
|
||||
// It is the mock that returns a zero length file for other transformers, when we supply an invalid targetExtension.
|
||||
}
|
||||
|
||||
/**
|
||||
* Test transforming a valid eml file to text
|
||||
*/
|
||||
@Test
|
||||
public void testRFC822ToText() throws Exception
|
||||
{
|
||||
String expected = "Gym class featuring a brown fox and lazy dog";
|
||||
MvcResult result = sendRequest("eml",
|
||||
null,
|
||||
MIMETYPE_RFC822,
|
||||
"txt",
|
||||
MIMETYPE_TEXT_PLAIN,
|
||||
null,
|
||||
readTestFile("eml"));
|
||||
assertTrue("Content from eml transform didn't contain expected value. ",
|
||||
result.getResponse().getContentAsString().contains(expected));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test transforming a non-ascii eml file to text
|
||||
*/
|
||||
@Test
|
||||
public void testNonAsciiRFC822ToText() throws Exception
|
||||
{
|
||||
String expected = "El r\u00E1pido zorro marr\u00F3n salta sobre el perro perezoso";
|
||||
MvcResult result = sendRequest("eml",
|
||||
null,
|
||||
MIMETYPE_RFC822,
|
||||
"txt",
|
||||
MIMETYPE_TEXT_PLAIN,
|
||||
null,
|
||||
readTestFile("spanish.eml"));
|
||||
|
||||
String contentResult = new String(result.getResponse().getContentAsByteArray(), UTF_8);
|
||||
assertTrue("Content from eml transform didn't contain expected value. ",
|
||||
contentResult.contains(expected));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test transforming a valid eml with an attachment to text; attachment should be ignored
|
||||
*/
|
||||
@Test
|
||||
public void testRFC822WithAttachmentToText() throws Exception
|
||||
{
|
||||
String expected = "Mail with attachment content";
|
||||
String notExpected = "File attachment content";
|
||||
MvcResult result = sendRequest("eml",
|
||||
null,
|
||||
MIMETYPE_RFC822,
|
||||
"txt",
|
||||
MIMETYPE_TEXT_PLAIN,
|
||||
null,
|
||||
readTestFile("attachment.eml"));
|
||||
assertTrue("Content from eml transform didn't contain expected value. ",
|
||||
result.getResponse().getContentAsString().contains(expected));
|
||||
assertFalse(result.getResponse().getContentAsString().contains(notExpected));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test transforming a valid eml with minetype multipart/alternative to text
|
||||
*/
|
||||
@Test
|
||||
public void testRFC822AlternativeToText() throws Exception
|
||||
{
|
||||
String expected = "alternative plain text";
|
||||
MvcResult result = sendRequest("eml",
|
||||
null,
|
||||
MIMETYPE_RFC822,
|
||||
"txt",
|
||||
MIMETYPE_TEXT_PLAIN,
|
||||
null,
|
||||
readTestFile("alternative.eml"));
|
||||
assertTrue("Content from eml transform didn't contain expected value. ",
|
||||
result.getResponse().getContentAsString().contains(expected));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test transforming a valid eml with nested mimetype multipart/alternative to text
|
||||
*/
|
||||
@Test
|
||||
public void testRFC822NestedAlternativeToText() throws Exception
|
||||
{
|
||||
String expected = "nested alternative plain text";
|
||||
MvcResult result = sendRequest("eml",
|
||||
null,
|
||||
MIMETYPE_RFC822,
|
||||
"txt",
|
||||
MIMETYPE_TEXT_PLAIN,
|
||||
null,
|
||||
readTestFile("nested.alternative.eml"));
|
||||
assertTrue("Content from eml transform didn't contain expected value. ",
|
||||
result.getResponse().getContentAsString().contains(expected));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test transforming a valid eml with a html part containing html special characters to text
|
||||
*/
|
||||
@Test
|
||||
public void testHtmlSpecialCharsToText() throws Exception
|
||||
{
|
||||
String expected = " ";
|
||||
MvcResult result = sendRequest("eml",
|
||||
null,
|
||||
MIMETYPE_RFC822,
|
||||
"txt",
|
||||
MIMETYPE_TEXT_PLAIN,
|
||||
null,
|
||||
readTestFile("htmlChars.eml"));
|
||||
assertFalse(result.getResponse().getContentAsString().contains(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHTMLtoString() 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;
|
||||
|
||||
MvcResult result = sendRequest("html",
|
||||
"UTF-8",
|
||||
MIMETYPE_HTML,
|
||||
"txt",
|
||||
MIMETYPE_TEXT_PLAIN,
|
||||
null,
|
||||
expected.getBytes());
|
||||
|
||||
String contentResult = new String(result.getResponse().getContentAsByteArray(),
|
||||
targetEncoding);
|
||||
assertTrue("The content did not include \"" + expected, contentResult.contains(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringToString() throws Exception
|
||||
{
|
||||
String expected;
|
||||
byte[] content;
|
||||
try
|
||||
{
|
||||
content = "azAz10!<21>$%^&*()\t\r\n".getBytes(UTF_8);
|
||||
expected = new String(content, "MacDingbat");
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
throw new RuntimeException("Encoding not recognised", e);
|
||||
}
|
||||
|
||||
MvcResult result = sendRequest("txt",
|
||||
"MacDingbat",
|
||||
MIMETYPE_TEXT_PLAIN,
|
||||
"txt",
|
||||
MIMETYPE_TEXT_PLAIN,
|
||||
"UTF-8",
|
||||
content);
|
||||
|
||||
String contentResult = new String(result.getResponse().getContentAsByteArray(),
|
||||
targetEncoding);
|
||||
assertTrue("The content did not include \"" + expected, contentResult.contains(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyTextFileReturnsEmptyFile() throws Exception
|
||||
{
|
||||
// Use empty content to create an empty source file
|
||||
byte[] content = new byte[0];
|
||||
|
||||
MvcResult result = sendRequest("txt",
|
||||
"UTF-8",
|
||||
MIMETYPE_TEXT_PLAIN,
|
||||
"txt",
|
||||
MIMETYPE_TEXT_PLAIN,
|
||||
"UTF-8",
|
||||
content);
|
||||
|
||||
assertEquals("Returned content should be empty for an empty source file", 0,
|
||||
result.getResponse().getContentLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void textToPdf() throws Exception
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 1; i <= 5; i++)
|
||||
{
|
||||
sb.append(i);
|
||||
sb.append(" I must not talk in class or feed my homework to my cat.\n");
|
||||
}
|
||||
sb.append("\nBart\n");
|
||||
String expected = sb.toString();
|
||||
|
||||
MvcResult result = sendRequest("txt",
|
||||
"UTF-8",
|
||||
MIMETYPE_TEXT_PLAIN,
|
||||
"pdf",
|
||||
MIMETYPE_PDF,
|
||||
null,
|
||||
expected.getBytes());
|
||||
|
||||
// Read back in the PDF and check it
|
||||
PDDocument doc = PDDocument.load(result.getResponse().getContentAsByteArray());
|
||||
PDFTextStripper textStripper = new PDFTextStripper();
|
||||
StringWriter textWriter = new StringWriter();
|
||||
textStripper.writeText(doc, textWriter);
|
||||
doc.close();
|
||||
|
||||
expected = clean(expected);
|
||||
String actual = clean(textWriter.toString());
|
||||
|
||||
assertEquals("The content did not match.", expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppleIWorksPages() throws Exception
|
||||
{
|
||||
MvcResult result = sendRequest("numbers", null, MIMETYPE_IWORK_NUMBERS,
|
||||
"jpeg", MIMETYPE_IMAGE_JPEG, null, readTestFile("pages"));
|
||||
assertTrue("Expected image content but content is empty.",
|
||||
result.getResponse().getContentLengthLong() > 0L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppleIWorksNumbers() throws Exception
|
||||
{
|
||||
MvcResult result = sendRequest("numbers", null, MIMETYPE_IWORK_NUMBERS,
|
||||
"jpeg", MIMETYPE_IMAGE_JPEG, null, readTestFile("numbers"));
|
||||
assertTrue("Expected image content but content is empty.",
|
||||
result.getResponse().getContentLengthLong() > 0L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppleIWorksKey() throws Exception
|
||||
{
|
||||
MvcResult result = sendRequest("key", null, MIMETYPE_IWORK_KEYNOTE,
|
||||
"jpeg", MIMETYPE_IMAGE_JPEG, null, readTestFile("key"));
|
||||
assertTrue("Expected image content but content is empty.",
|
||||
result.getResponse().getContentLengthLong() > 0L);
|
||||
}
|
||||
|
||||
// @Test
|
||||
// TODO Doesn't work with java 11, enable when fixed
|
||||
public void testOOXML() throws Exception
|
||||
{
|
||||
MvcResult result = sendRequest("docx", null, MIMETYPE_OPENXML_WORDPROCESSING,
|
||||
"jpeg", MIMETYPE_IMAGE_JPEG, null, readTestFile("docx"));
|
||||
assertTrue("Expected image content but content is empty.",
|
||||
result.getResponse().getContentLengthLong() > 0L);
|
||||
}
|
||||
|
||||
private MvcResult sendRequest(String sourceExtension,
|
||||
String sourceEncoding,
|
||||
String sourceMimetype,
|
||||
String targetExtension,
|
||||
String targetMimetype,
|
||||
String targetEncoding,
|
||||
byte[] content) throws Exception
|
||||
{
|
||||
final MockMultipartFile sourceFile = new MockMultipartFile("file",
|
||||
"test_file." + sourceExtension, sourceMimetype, content);
|
||||
|
||||
final MockHttpServletRequestBuilder requestBuilder = super
|
||||
.mockMvcRequest("/transform", sourceFile)
|
||||
.param("targetExtension", targetExtension)
|
||||
.param("targetMimetype", targetMimetype)
|
||||
.param("sourceMimetype", sourceMimetype);
|
||||
|
||||
if (sourceEncoding != null)
|
||||
{
|
||||
requestBuilder.param("sourceEncoding", sourceEncoding);
|
||||
}
|
||||
if (targetEncoding != null)
|
||||
{
|
||||
requestBuilder.param("targetEncoding", targetEncoding);
|
||||
}
|
||||
|
||||
return mockMvc.perform(requestBuilder)
|
||||
.andExpect(status().is(OK.value()))
|
||||
.andExpect(header().string("Content-Disposition",
|
||||
"attachment; filename*= " +
|
||||
(targetEncoding == null ? "UTF-8" : targetEncoding) +
|
||||
"''test_file." + targetExtension))
|
||||
.andReturn();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer;
|
||||
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_HTML;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.alfresco.transform.client.model.TransformRequest;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {"activemq.url=nio://localhost:61616"})
|
||||
public class MiscQueueTransformServiceIT extends AbstractQueueTransformServiceIT
|
||||
{
|
||||
@Override
|
||||
protected TransformRequest buildRequest()
|
||||
{
|
||||
return TransformRequest
|
||||
.builder()
|
||||
.withRequestId(UUID.randomUUID().toString())
|
||||
.withSourceMediaType(MIMETYPE_HTML)
|
||||
.withTargetMediaType(MIMETYPE_TEXT_PLAIN)
|
||||
.withTargetExtension("txt")
|
||||
.withSchema(1)
|
||||
.withClientData("ACS")
|
||||
.withSourceReference(UUID.randomUUID().toString())
|
||||
.withSourceSize(32L).build();
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class MiscTransformerHttpRequestTest extends AbstractHttpRequestTest
|
||||
{
|
||||
@Override
|
||||
protected String getTransformerName()
|
||||
{
|
||||
return "Miscellaneous Transformers";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSourceExtension()
|
||||
{
|
||||
return "html";
|
||||
}
|
||||
}
|
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer;
|
||||
|
||||
import static java.text.MessageFormat.format;
|
||||
import static java.util.function.Function.identity;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_DITA;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_EXCEL;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_HTML;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IMAGE_GIF;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IMAGE_JPEG;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IMAGE_PNG;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IMAGE_TIFF;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_KEYNOTE;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_NUMBERS;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_PAGES;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_JAVASCRIPT;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_PRESENTATION;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_SPREADSHEET;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_WORDPROCESSING;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OUTLOOK_MSG;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_PDF;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_PPT;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_RFC822;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_CSS;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_CSV;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_JAVASCRIPT;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_MEDIAWIKI;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_WORD;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_XML;
|
||||
import static org.alfresco.transformer.EngineClient.sendTRequest;
|
||||
import static org.alfresco.transformer.TestFileInfo.testFile;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
/**
|
||||
* @author Cezar Leahu
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class MiscTransformsIT
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(MiscTransformsIT.class);
|
||||
private static final String ENGINE_URL = "http://localhost:8090";
|
||||
|
||||
private static final Map<String, TestFileInfo> TEST_FILES = Stream.of(
|
||||
testFile(MIMETYPE_IMAGE_GIF, "gif", "quick.gif"),
|
||||
testFile(MIMETYPE_IMAGE_JPEG, "jpg", "quick.jpg"),
|
||||
testFile(MIMETYPE_IMAGE_PNG, "png", "quick.png"),
|
||||
testFile(MIMETYPE_IMAGE_TIFF, "tiff", "quick.tiff"),
|
||||
testFile(MIMETYPE_WORD, "doc", "quick.doc"),
|
||||
testFile(MIMETYPE_OPENXML_WORDPROCESSING, "docx", "quick.docx"),
|
||||
testFile(MIMETYPE_EXCEL, "xls", "quick.xls"),
|
||||
testFile(MIMETYPE_OPENXML_SPREADSHEET, "xlsx", "quick.xlsx"),
|
||||
testFile(MIMETYPE_PPT, "ppt", "quick.ppt"),
|
||||
testFile(MIMETYPE_OPENXML_PRESENTATION, "pptx", "quick.pptx"),
|
||||
testFile(MIMETYPE_OUTLOOK_MSG, "msg", "quick.msg"),
|
||||
testFile(MIMETYPE_PDF, "pdf", "quick.pdf"),
|
||||
testFile(MIMETYPE_TEXT_PLAIN, "txt", "quick.txt"),
|
||||
|
||||
testFile("text/richtext", "rtf", "sample.rtf"),
|
||||
testFile("text/sgml", "sgml", "sample.sgml"),
|
||||
testFile("text/tab-separated-values", "tsv", "sample.tsv"),
|
||||
testFile("text/x-setext", "etx", "sample.etx"),
|
||||
testFile("text/x-java-source", "java", "Sample.java.txt"),
|
||||
testFile("text/x-jsp", "jsp", "sample.jsp.txt"),
|
||||
testFile("text/x-markdown", "md", "sample.md"),
|
||||
testFile("text/calendar", "ics", "sample.ics"),
|
||||
|
||||
testFile(MIMETYPE_TEXT_MEDIAWIKI, "mw", "sample.mw"),
|
||||
testFile(MIMETYPE_TEXT_CSS, "css", "style.css"),
|
||||
testFile(MIMETYPE_TEXT_CSV, "csv", "people.csv"),
|
||||
testFile(MIMETYPE_TEXT_JAVASCRIPT, "js", "script.js"),
|
||||
testFile(MIMETYPE_XML, "xml", "quick.xml"),
|
||||
testFile(MIMETYPE_HTML, "html", "quick.html"),
|
||||
testFile(MIMETYPE_JAVASCRIPT, "js", "script.js"),
|
||||
testFile(MIMETYPE_DITA, "dita", "quickConcept.dita"),
|
||||
testFile(MIMETYPE_IWORK_KEYNOTE, "key", "quick.key"),
|
||||
testFile(MIMETYPE_IWORK_NUMBERS, "number", "quick.numbers"),
|
||||
testFile(MIMETYPE_IWORK_PAGES, "pages", "quick.pages"),
|
||||
testFile(MIMETYPE_RFC822, "eml", "quick.eml")
|
||||
).collect(toMap(TestFileInfo::getMimeType, identity()));
|
||||
|
||||
private final String sourceMimetype;
|
||||
private final String targetMimetype;
|
||||
|
||||
public MiscTransformsIT(final SourceTarget sourceTarget)
|
||||
{
|
||||
sourceMimetype = sourceTarget.source;
|
||||
targetMimetype = sourceTarget.target;
|
||||
}
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Set<SourceTarget> engineTransformations()
|
||||
{
|
||||
return Stream.of(
|
||||
SourceTarget.of("text/html", "text/plain"), //duplicate
|
||||
|
||||
SourceTarget.of("text/plain", "text/plain"),
|
||||
SourceTarget.of("text/mediawiki", "text/plain"),
|
||||
SourceTarget.of("text/css", "text/plain"),
|
||||
SourceTarget.of("text/csv", "text/plain"),
|
||||
SourceTarget.of("text/xml", "text/plain"),
|
||||
SourceTarget.of("text/html", "text/plain"),
|
||||
SourceTarget.of("text/richtext", "text/plain"),
|
||||
SourceTarget.of("text/sgml", "text/plain"),
|
||||
SourceTarget.of("text/tab-separated-values", "text/plain"),
|
||||
SourceTarget.of("text/x-setext", "text/plain"),
|
||||
SourceTarget.of("text/x-java-source", "text/plain"),
|
||||
SourceTarget.of("text/x-jsp", "text/plain"),
|
||||
SourceTarget.of("text/x-markdown", "text/plain"),
|
||||
SourceTarget.of("text/calendar", "text/plain"),
|
||||
SourceTarget.of("application/x-javascript", "text/plain"),
|
||||
SourceTarget.of("application/dita+xml", "text/plain"),
|
||||
|
||||
SourceTarget.of("application/vnd.apple.keynote", "image/jpeg"),
|
||||
SourceTarget.of("application/vnd.apple.numbers", "image/jpeg"),
|
||||
SourceTarget.of("application/vnd.apple.pages", "image/jpeg"),
|
||||
|
||||
SourceTarget.of("text/plain", "application/pdf"),
|
||||
SourceTarget.of("text/csv", "application/pdf"),
|
||||
SourceTarget.of("application/dita+xml", "application/pdf"),
|
||||
SourceTarget.of("text/xml", "application/pdf"),
|
||||
|
||||
SourceTarget.of("message/rfc822", "text/plain")
|
||||
).collect(toSet());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransformation()
|
||||
{
|
||||
final String sourceFile = TEST_FILES.get(sourceMimetype).getPath();
|
||||
final String targetExtension = TEST_FILES.get(targetMimetype).getExtension();
|
||||
|
||||
final String descriptor = format("Transform ({0}, {1} -> {2}, {3})",
|
||||
sourceFile, sourceMimetype, targetMimetype, targetExtension);
|
||||
|
||||
try
|
||||
{
|
||||
final ResponseEntity<Resource> response = sendTRequest(ENGINE_URL, sourceFile,
|
||||
sourceMimetype, targetMimetype, targetExtension);
|
||||
assertEquals(descriptor, OK, response.getStatusCode());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
fail(descriptor + " exception: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
package org.alfresco.transformer;
|
||||
|
||||
public class Sample
|
||||
{
|
||||
private final String mimeType;
|
||||
private final String extension;
|
||||
private final String path;
|
||||
private final boolean exactMimeType;
|
||||
|
||||
public Sample(final String mimeType, final String extension, final String path,
|
||||
final boolean exactMimeType)
|
||||
{
|
||||
this.mimeType = mimeType;
|
||||
this.extension = extension;
|
||||
this.path = path;
|
||||
this.exactMimeType = exactMimeType;
|
||||
}
|
||||
|
||||
public String getMimeType()
|
||||
{
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
public String getExtension()
|
||||
{
|
||||
return extension;
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
public boolean isExactMimeType()
|
||||
{
|
||||
return exactMimeType;
|
||||
}
|
||||
|
||||
public static Sample testFile(final String mimeType, final String extension,
|
||||
final String path, final boolean exactMimeType)
|
||||
{
|
||||
return new Sample(mimeType, extension, path, exactMimeType);
|
||||
}
|
||||
|
||||
public static Sample testFile(final String mimeType, final String extension,
|
||||
final String path)
|
||||
{
|
||||
return new Sample(mimeType, extension, path, false);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,4 @@
|
||||
:ID,name,joined:date,active:boolean,points:int
|
||||
user01,Joe Soap,2017-05-05,true,10
|
||||
user02,Jane Doe,2017-08-21,true,15
|
||||
user03,Moe Know,2018-02-17,false,7
|
|
@@ -0,0 +1,30 @@
|
||||
MIME-Version: 1.0
|
||||
Received: by 10.000.0.000 with HTTP; Thu, 16 Aug 2012 08:13:29 -0700 (PDT)
|
||||
Date: Thu, 16 Aug 2012 16:13:29 +0100
|
||||
Delivered-To: jane.doe@alfresco.com
|
||||
Message-ID: <CAL0uq1f9vPczLRinL3xB5U_oSSd5U0ob=408nBgosCY0OVFyBw@mail.alfresco.com>
|
||||
Subject: Attachment test
|
||||
From: <john.doe@alfresco.com>
|
||||
To: <jane.doe@alfresco.com>
|
||||
Content-Type: multipart/alternative;
|
||||
boundary="----=_NextPart_000_0005_01D06C6A.DBA98EC0"
|
||||
|
||||
This is a multipart message in MIME format.
|
||||
|
||||
------=_NextPart_000_0005_01D06C6A.DBA98EC0
|
||||
Content-Type: text/plain;
|
||||
charset="utf-8"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
alternative plain text
|
||||
|
||||
------=_NextPart_000_0005_01D06C6A.DBA98EC0
|
||||
Content-Type: text/html;
|
||||
charset="utf-8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
<div dir=3D"ltr">alternative html text</div>
|
||||
|
||||
------=_NextPart_000_0005_01D06C6A.DBA98EC0--
|
||||
Parts form an multipart/alternative should represent the same content in different formats
|
||||
In this eml example the content differs with the purpose of determining if right part was used in transformation
|
@@ -0,0 +1,44 @@
|
||||
MIME-Version: 1.0
|
||||
Received: by 10.000.0.000 with HTTP; Thu, 16 Aug 2012 08:13:29 -0700 (PDT)
|
||||
Date: Thu, 16 Aug 2012 16:13:29 +0100
|
||||
Delivered-To: jane.doe@alfresco.com
|
||||
Message-ID: <CAL0uq1f9vPczLRinL3xB5U_oSSd5U0ob=408nBgosCY0OVFyBw@mail.alfresco.com>
|
||||
Subject: Attachment test
|
||||
From: <john.doe@alfresco.com>
|
||||
To: <jane.doe@alfresco.com>
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="----=_NextPart_000_0000_01D06C6A.D04F3750"
|
||||
|
||||
This is a multipart message in MIME format.
|
||||
|
||||
------=_NextPart_000_0000_01D06C6A.D04F3750
|
||||
Content-Type: multipart/alternative;
|
||||
boundary="----=_NextPart_001_0001_01D06C6A.D04F3750"
|
||||
|
||||
|
||||
------=_NextPart_001_0001_01D06C6A.D04F3750
|
||||
Content-Type: text/plain;
|
||||
charset="utf-8"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Mail with attachment content
|
||||
|
||||
------=_NextPart_001_0001_01D06C6A.D04F3750
|
||||
Content-Type: text/html;
|
||||
charset="utf-8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
<div dir=3D"ltr">Mail with attachment content</div>
|
||||
|
||||
------=_NextPart_001_0001_01D06C6A.D04F3750--
|
||||
|
||||
------=_NextPart_000_0000_01D06C6A.D04F3750
|
||||
Content-Type: text/plain;
|
||||
name="alt.txt"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-ID: <796B1E07B04ACC41A78199F35721150F@eurprd04.prod.outlook.com>
|
||||
Content-Disposition: attachment;
|
||||
filename="alt.txt"
|
||||
|
||||
File attachment content
|
||||
------=_NextPart_000_0000_01D06C6A.D04F3750--
|
Binary file not shown.
@@ -0,0 +1,10 @@
|
||||
From: Nevin Nollop <nevin.nollop@alfresco.com>
|
||||
To: Nevin Nollop <nevin.nollop@alfresco.com>
|
||||
Cc: Nevin Nollop <nevinn@alfresco.com>
|
||||
Message-ID: <20040604122322.GV1905@phoenix.home>
|
||||
Date: Fri, 4 Jun 2004 14:23:22 +0200
|
||||
Subject: The quick brown fox jumps over the lazy dog
|
||||
|
||||
Gym class featuring a brown fox and lazy dog
|
||||
|
||||
The quick brown fox jumps over the lazy dog
|
@@ -0,0 +1,17 @@
|
||||
<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>
|
@@ -0,0 +1,28 @@
|
||||
MIME-Version: 1.0
|
||||
Received: by 10.000.0.000 with HTTP; Thu, 16 Aug 2012 08:13:29 -0700 (PDT)
|
||||
Date: Thu, 16 Aug 2012 16:13:29 +0100
|
||||
Delivered-To: jane.doe@alfresco.com
|
||||
Message-ID: <CAL0uq1f9vPczLRinL3xB5U_oSSd5U0ob=408nBgosCY0OVFyBw@mail.alfresco.com>
|
||||
Subject: Attachment test
|
||||
From: <john.doe@alfresco.com>
|
||||
To: <jane.doe@alfresco.com>
|
||||
Content-Type: multipart/alternative;
|
||||
boundary="----=_NextPart_000_0005_01D06C6A.DBA98EC0"
|
||||
|
||||
This is a multipart message in MIME format.
|
||||
|
||||
------=_NextPart_000_0005_01D06C6A.DBA98EC0
|
||||
Content-Type: text/plain;
|
||||
charset="utf-8"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
html special characters
|
||||
|
||||
------=_NextPart_000_0005_01D06C6A.DBA98EC0
|
||||
Content-Type: text/html;
|
||||
charset="utf-8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
<div dir=3D"ltr">html special characters</div>
|
||||
|
||||
------=_NextPart_000_0005_01D06C6A.DBA98EC0--
|
Binary file not shown.
@@ -0,0 +1,41 @@
|
||||
MIME-Version: 1.0
|
||||
Received: by 10.000.0.000 with HTTP; Thu, 16 Aug 2012 08:13:29 -0700 (PDT)
|
||||
Date: Thu, 16 Aug 2012 16:13:29 +0100
|
||||
Delivered-To: jane.doe@alfresco.com
|
||||
Message-ID: <CAL0uq1f9vPczLRinL3xB5U_oSSd5U0ob=408nBgosCY0OVFyBw@mail.alfresco.com>
|
||||
Subject: Attachment test
|
||||
From: <john.doe@alfresco.com>
|
||||
To: <jane.doe@alfresco.com>
|
||||
Content-Type: multipart/related;
|
||||
boundary="--_=_NextPart1_03fb5278-acd0-44a8-88cd-bfd1347fd423";
|
||||
type="multipart/alternative"
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
|
||||
----_=_NextPart1_03fb5278-acd0-44a8-88cd-bfd1347fd423
|
||||
Content-Type: multipart/alternative; boundary="--_=_NextPart0_f68fab3d-a986-41a5-9cf0-3a3aefb21362"
|
||||
|
||||
|
||||
----_=_NextPart0_f68fab3d-a986-41a5-9cf0-3a3aefb21362
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
nested alternative plain text
|
||||
|
||||
----_=_NextPart0_f68fab3d-a986-41a5-9cf0-3a3aefb21362
|
||||
Content-Type: text/html; charset="utf-8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
<div dir=3D"ltr">nested alternative html text</div>
|
||||
|
||||
----_=_NextPart0_f68fab3d-a986-41a5-9cf0-3a3aefb21362--
|
||||
|
||||
----_=_NextPart1_03fb5278-acd0-44a8-88cd-bfd1347fd423
|
||||
Content-Type: image/jpeg; name="image001.jpg"
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-ID: <image001.jpg@01D146F0.63006280>
|
||||
|
||||
image
|
||||
|
||||
----_=_NextPart1_03fb5278-acd0-44a8-88cd-bfd1347fd423--
|
||||
|
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,31 @@
|
||||
MIME-Version: 1.0
|
||||
Received: by 10.000.0.000 with HTTP; Thu, 16 Aug 2012 08:13:29 -0700 (PDT)
|
||||
Date: Thu, 16 Aug 2012 16:13:29 +0100
|
||||
Delivered-To: jane.doe@alfresco.com
|
||||
Message-ID: <CAL0uq1f9vPczLRinL3xB5U_oSSd5U0ob=408nBgosCY0OVFyBw@mail.alfresco.com>
|
||||
Subject: The quick brown fox jumps over the lazy dog
|
||||
From: <john.doe@alfresco.com>
|
||||
To: <jane.doe@alfresco.com>
|
||||
Content-Type: multipart/alternative;
|
||||
boundary="----=_NextPart_000_0009_01D06BC5.14D754D0"
|
||||
|
||||
This is a multipart message in MIME format.
|
||||
|
||||
------=_NextPart_000_0009_01D06BC5.14D754D0
|
||||
Content-Type: text/plain;
|
||||
charset="utf-8"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
El rápido zorro marrón salta sobre el perro perezoso
|
||||
|
||||
|
||||
------=_NextPart_000_0009_01D06BC5.14D754D0
|
||||
Content-Type: text/html;
|
||||
charset="utf-8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
<div dir=3D"ltr">El r=C3=A1pido zorro marr=C3=B3n salta sobre el perro =
|
||||
perezoso <br></div>
|
||||
|
||||
------=_NextPart_000_0009_01D06BC5.14D754D0--
|
||||
|
@@ -0,0 +1,18 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
The quick brown fox jumps over the lazy dog
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
The quick brown fox jumps over the lazy dog
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
|
||||
<document>
|
||||
<text>The quick brown fox jumps over the lazy dog</text>
|
||||
</document>
|
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "http://docs.oasis-open.org/dita/v1.1/OS/dtd/concept.dtd">
|
||||
<concept id="quickConcept">
|
||||
<title>The quick brown fox jumps over the lazy dog</title>
|
||||
<shortdesc>Gym class featuring a brown fox and lazy dog</shortdesc>
|
||||
<prolog>
|
||||
<author>Alfresco Documentation</author>
|
||||
<copyright>
|
||||
<copyryear year="2011"/>
|
||||
<copyrholder>Alfresco Software, Inc.</copyrholder>
|
||||
</copyright>
|
||||
<metadata>
|
||||
<audience experiencelevel="expert" job="Customizing" type="Administrator"/>
|
||||
<category>Testing</category>
|
||||
<keywords>
|
||||
<keyword>Pangram</keyword>
|
||||
<keyword>Fox</keyword>
|
||||
<keyword>Dog</keyword>
|
||||
</keywords>
|
||||
<prodinfo>
|
||||
<prodname>Enterprise</prodname>
|
||||
<vrmlist>
|
||||
<vrm version="3.4.x" release="Enterprise" modification="2011/11/11"/>
|
||||
</vrmlist>
|
||||
</prodinfo>
|
||||
</metadata>
|
||||
</prolog>
|
||||
<conbody>
|
||||
<p>The quick brown fox jumps over the lazy dog</p>
|
||||
</conbody>
|
||||
</concept>
|
@@ -0,0 +1,17 @@
|
||||
The quick brown fox
|
||||
==========================
|
||||
|
||||
The quick brown fox jumps over the lazy dog.
|
||||
|
||||
The quick brown fox jumps over the lazy dog.
|
||||
|
||||
The Fox
|
||||
----------
|
||||
|
||||
The quick brown fox jumps over the lazy dog.
|
||||
|
||||
The Dog
|
||||
--------------------
|
||||
|
||||
The quick brown fox jumps over the lazy dog.
|
||||
|
@@ -0,0 +1,13 @@
|
||||
BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
|
||||
BEGIN:VEVENT
|
||||
UID:uid1@example.com
|
||||
DTSTAMP:19970714T170000Z
|
||||
ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com
|
||||
DTSTART:19970714T170000Z
|
||||
DTEND:19970715T035959Z
|
||||
SUMMARY:Bastille Day Party
|
||||
GEO:48.85299;2.36885
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
@@ -0,0 +1,12 @@
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@ page import="java.time.LocalDateTime" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The quick brown fox</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>The quick brown fox jumps over the lazy dog!</h1>
|
||||
<h2>Current time is <%= LocalDateTime.now() %></h2>
|
||||
</body>
|
||||
</html>
|
@@ -0,0 +1,11 @@
|
||||
The quick brown fox
|
||||
============
|
||||
|
||||
The quick brown fox jumps over the lazy dog.
|
||||
|
||||
The quick brown fox:
|
||||
* jumps
|
||||
* over
|
||||
* the lazy dog.
|
||||
|
||||
> The quick brown fox jumps over the lazy dog.
|
@@ -0,0 +1,5 @@
|
||||
"Take some more [[tea]]," the March Hare said to Alice, very earnestly.
|
||||
|
||||
"I've had '''nothing''' yet," Alice replied in an offended tone, "so I can't take more."
|
||||
|
||||
"You mean you can't take ''less''," said the Hatter. "It's very easy to take ''more'' than nothing."<Paste>
|
@@ -0,0 +1,214 @@
|
||||
{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31506\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1048\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}
|
||||
{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
|
||||
{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;}
|
||||
{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
|
||||
{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}
|
||||
{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f42\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f43\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
|
||||
{\f45\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f46\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f47\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f48\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
|
||||
{\f49\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f50\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f412\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f413\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}
|
||||
{\f415\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f416\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f417\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\f418\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}
|
||||
{\f419\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f420\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
|
||||
{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
|
||||
{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
|
||||
{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
|
||||
{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
|
||||
{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
|
||||
{\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}
|
||||
{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31533\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}{\fhimajor\f31534\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);}
|
||||
{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
|
||||
{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
|
||||
{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
|
||||
{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
|
||||
{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
|
||||
{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
|
||||
{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
|
||||
{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
|
||||
{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}
|
||||
{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
|
||||
{\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}
|
||||
{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
|
||||
{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
|
||||
{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}
|
||||
{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;
|
||||
\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red0\green0\blue0;\red0\green0\blue0;}{\*\defchp \f31506\fs24 }{\*\defpap
|
||||
\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0
|
||||
\f31506\fs24\lang1048\langfe1033\cgrid\langnp1048\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
|
||||
\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv
|
||||
\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1048\langfe1033\cgrid\langnp1048\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}}
|
||||
{\*\rsidtbl \rsid2693434\rsid4215609\rsid7808163\rsid16662808}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Cezar Leahu}{\operator Cezar Leahu}
|
||||
{\creatim\yr2019\mo8\dy29\hr15\min41}{\revtim\yr2019\mo8\dy29\hr15\min43}{\version2}{\edmins2}{\nofpages1}{\nofwords17}{\nofchars102}{\nofcharsws118}{\vern2821}}{\*\userprops {\propname MSIP_Label_ffb520d8-df98-444b-9f20-0dd9d08cf98c_Enabled}\proptype30
|
||||
{\staticval true}{\propname MSIP_Label_ffb520d8-df98-444b-9f20-0dd9d08cf98c_SetDate}\proptype30{\staticval 2019-08-29T12:41:57+0200}{\propname MSIP_Label_ffb520d8-df98-444b-9f20-0dd9d08cf98c_Method}\proptype30{\staticval Standard}{\propname MSIP_Label_ffb
|
||||
520d8-df98-444b-9f20-0dd9d08cf98c_Name}\proptype30{\staticval ffb520d8-df98-444b-9f20-0dd9d08cf98c}{\propname MSIP_Label_ffb520d8-df98-444b-9f20-0dd9d08cf98c_SiteId}\proptype30{\staticval 65bc0b3b-7ca2-488c-ba9c-b1bebdd49af6}{\propname MSIP_Label_ffb520d8
|
||||
-df98-444b-9f20-0dd9d08cf98c_ActionId}\proptype30{\staticval 6097ae90-22f7-448a-b9b7-0000b0413133}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}
|
||||
\paperw11900\paperh16840\margl1417\margr1417\margt1417\margb1417\gutter0\ltrsect
|
||||
\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen
|
||||
\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1417\dgvorigin1417\dghshow1\dgvshow1
|
||||
\jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct
|
||||
\asianbrkrule\rsidroot4215609\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0
|
||||
{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sectrsid2693434\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}
|
||||
{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}
|
||||
{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9
|
||||
\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid16662808 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0
|
||||
\f31506\fs24\lang1048\langfe1033\cgrid\langnp1048\langfenp1033 {\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid16662808
|
||||
\par
|
||||
\par
|
||||
\par
|
||||
\par
|
||||
\par The quick brown fox jumps over the lazy dog
|
||||
\par
|
||||
\par
|
||||
\par
|
||||
\par
|
||||
\par
|
||||
\par
|
||||
\par
|
||||
\par The quick brown fox jumps over the lazy dog
|
||||
\par
|
||||
\par
|
||||
\par
|
||||
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 {\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid4996987
|
||||
\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
|
||||
9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
|
||||
5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6
|
||||
b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0
|
||||
0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6
|
||||
a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f
|
||||
c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512
|
||||
0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462
|
||||
a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865
|
||||
6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b
|
||||
4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b
|
||||
4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100b6f4679893070000c9200000160000007468656d652f7468656d652f
|
||||
7468656d65312e786d6cec59cd8b1bc915bf07f23f347d97f5d5ad8fc1f2a24fcfda33b6b164873dd648a5eef2547789aad28cc56208de532e81c026e49085bd
|
||||
ed21842cecc22eb9e48f31d8249b3f22afaa5bdd5552c99e191c3061463074977eefd5afde7bf5de53d5ddcf5e26d4bbc05c1096f6fcfa9d9aefe174ce16248d
|
||||
7afeb3d9a4d2f13d2151ba4094a5b8e76fb0f03fbbf7eb5fdd454732c609f6403e1547a8e7c752ae8eaa5531876124eeb0154ee1bb25e30992f0caa3ea82a34b
|
||||
d09bd06aa3566b55134452df4b51026a1f2f97648ebd9952e9dfdb2a1f53784da5500373caa74a35b6243476715e5708b11143cabd0b447b3eccb3609733fc52
|
||||
fa1e4542c2173dbfa6fffceabdbb5574940b517940d6909be8bf5c2e17589c37f49c3c3a2b260d823068f50bfd1a40e53e6edc1eb7c6ad429f06a0f91c569a71
|
||||
b175b61bc320c71aa0ecd1a17bd41e35eb16ded0dfdce3dc0fd5c7c26b50a63fd8c34f2643b0a285d7a00c1feee1c3417730b2f56b50866fede1dbb5fe28685b
|
||||
fa3528a6243ddf43d7c25673b85d6d0159327aec8477c360d26ee4ca4b144443115d6a8a254be5a1584bd00bc6270050408a24493db959e1259a43140f112567
|
||||
9c7827248a21f056286502866b8ddaa4d684ffea13e827ed5174849121ad780113b137a4f87862cec94af6fc07a0d537206f7ffef9cdeb1fdfbcfee9cd575fbd
|
||||
79fdf77c6eadca923b466964cafdf2dd1ffef3cd6fbd7ffff0ed2f5fff319b7a172f4cfcbbbffdeedd3ffef93ef5b0e2d2146ffff4fdbb1fbf7ffbe7dfffebaf
|
||||
5f3bb4f7393a33e1339260e13dc297de5396c0021dfcf119bf9ec42c46c494e8a791402952b338f48f656ca11f6d10450edc00db767cce21d5b880f7d72f2cc2
|
||||
d398af2571687c182716f094313a60dc6985876a2ec3ccb3751ab927e76b13f714a10bd7dc43945a5e1eaf579063894be530c616cd2714a5124538c5d253dfb1
|
||||
738c1dabfb8210cbaea764ce99604be97d41bc01224e93ccc899154da5d03149c02f1b1741f0b7659bd3e7de8051d7aa47f8c246c2de40d4417e86a965c6fb68
|
||||
2d51e252394309350d7e8264ec2239ddf0b9891b0b099e8e3065de78818570c93ce6b05ec3e90f21cdb8dd7e4a37898de4929cbb749e20c64ce4889d0f6394ac
|
||||
5cd829496313fbb938871045de13265df05366ef10f50e7e40e941773f27d872f787b3c133c8b026a53240d4376beef0e57dccacf89d6ee8126157aae9f3c44a
|
||||
b17d4e9cd131584756689f604cd1255a60ec3dfbdcc160c05696cd4bd20f62c82ac7d815580f901dabea3dc5027a25d5dcece7c91322ac909de2881de073bad9
|
||||
493c1b9426881fd2fc08bc6eda7c0ca52e7105c0633a3f37818f08f480102f4ea33c16a0c308ee835a9fc4c82a60ea5db8e375c32dff5d658fc1be7c61d1b8c2
|
||||
be04197c6d1948eca6cc7b6d3343d49aa00c9819822ec3956e41c4727f29a28aab165b3be596f6a62ddd00dd91d5f42424fd6007b4d3fb84ffbbde073a8cb77f
|
||||
f9c6b10f3e4ebfe3566c25ab6b763a8792c9f14e7f7308b7dbd50c195f904fbfa919a175fa04431dd9cf58b73dcd6d4fe3ffdff73487f6f36d2773a8dfb8ed64
|
||||
7ce8306e3b99fc70e5e3743265f3027d8d3af0c80e7af4b14f72f0d46749289dca0dc527421ffc08f83db398c0a092d3279eb838055cc5f0a8ca1c4c60e1228e
|
||||
b48cc799fc0d91f134462b381daafb4a492472d591f0564cc0a1911e76ea5678ba4e4ed9223becacd7d5c16656590592e5782d2cc6e1a04a66e856bb3cc02bd4
|
||||
6bb6913e68dd1250b2d721614c6693683a48b4b783ca48fa58178ce620a157f65158741d2c3a4afdd6557b2c805ae115f8c1edc1cff49e1f06200242701e07cd
|
||||
f942f92973f5d6bbda991fd3d3878c69450034d8db08283ddd555c0f2e4fad2e0bb52b78da2261849b4d425b46377822869fc17974aad1abd0b8aeafbba54b2d
|
||||
7aca147a3e08ad9246bbf33e1637f535c8ede6069a9a9982a6de65cf6f35430899395af5fc251c1ac363b282d811ea3717a211dcbccc25cf36fc4d32cb8a0b39
|
||||
4222ce0cae934e960d122231f728497abe5a7ee1069aea1ca2b9d51b90103e59725d482b9f1a3970baed64bc5ce2b934dd6e8c284b67af90e1b35ce1fc568bdf
|
||||
1cac24d91adc3d8d1797de195df3a708422c6cd795011744c0dd413db3e682c0655891c8caf8db294c79da356fa3740c65e388ae62945714339967709dca0b3a
|
||||
faadb081f196af190c6a98242f8467912ab0a651ad6a5a548d8cc3c1aafb6121653923699635d3ca2aaa6abab39835c3b60cecd8f26645de60b53531e434b3c2
|
||||
67a97b37e576b7b96ea74f28aa0418bcb09fa3ea5ea12018d4cac92c6a8af17e1a56393b1fb56bc776811fa07695226164fdd656ed8edd8a1ae19c0e066f54f9
|
||||
416e376a6168b9ed2bb5a5f5adb979b1cdce5e40f2184197bba6526857c2c92e47d0104d754f92a50dd8222f65be35e0c95b73d2f3bfac85fd60d80887955a27
|
||||
1c57826650ab74c27eb3d20fc3667d1cd66ba341e31514161927f530bbb19fc00506dde4f7f67a7cefee3ed9ded1dc99b3a4caf4dd7c5513d777f7f5c6e1bb7b
|
||||
8f40d2f9b2d598749bdd41abd26df627956034e854bac3d6a0326a0ddba3c9681876ba9357be77a1c141bf390c5ae34ea5551f0e2b41aba6e877ba9576d068f4
|
||||
8376bf330efaaff23606569ea58fdc16605ecdebde7f010000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d65
|
||||
2f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d36
|
||||
3f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e
|
||||
3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d985
|
||||
0528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c020000130000000000000000000000
|
||||
0000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000000000
|
||||
000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c0000000000000000000000000019020000
|
||||
7468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d0014000600080000002100b6f4679893070000c92000001600000000000000
|
||||
000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b01000027000000
|
||||
000000000000000000009d0a00007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000980b00000000}
|
||||
{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
|
||||
617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
|
||||
6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
|
||||
656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
|
||||
{\*\latentstyles\lsdstimax375\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;
|
||||
\lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Table;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 1;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 2;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 2;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 3;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 2;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 6;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 2;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 6;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 2;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Contemporary;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Elegant;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Professional;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 2;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Theme;\lsdsemihidden1 \lsdlocked0 Placeholder Text;
|
||||
\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid;\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;
|
||||
\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;
|
||||
\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdpriority61 \lsdlocked0 Light List Accent 1;
|
||||
\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdsemihidden1 \lsdlocked0 Revision;
|
||||
\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;
|
||||
\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdpriority72 \lsdlocked0 Colorful List Accent 1;
|
||||
\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;
|
||||
\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;
|
||||
\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;
|
||||
\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;
|
||||
\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;
|
||||
\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;
|
||||
\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;
|
||||
\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;
|
||||
\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;\lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;
|
||||
\lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;
|
||||
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;
|
||||
\lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6;
|
||||
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;
|
||||
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;
|
||||
\lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;
|
||||
\lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4;
|
||||
\lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4;
|
||||
\lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1;
|
||||
\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1;
|
||||
\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2;
|
||||
\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2;
|
||||
\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3;
|
||||
\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4;
|
||||
\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4;
|
||||
\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5;
|
||||
\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5;
|
||||
\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6;
|
||||
\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6;
|
||||
\lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark;
|
||||
\lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1;
|
||||
\lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1;
|
||||
\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2;
|
||||
\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3;
|
||||
\lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3;
|
||||
\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4;
|
||||
\lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4;
|
||||
\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5;
|
||||
\lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5;
|
||||
\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6;
|
||||
\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Mention;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hashtag;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Unresolved Mention;}}{\*\datastore }}
|
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
|
||||
|
||||
<article>
|
||||
<sect1 id="introduction">
|
||||
<title>The quick brown fox</title>
|
||||
|
||||
<para>
|
||||
The quick brown fox jumps over the lazy dog
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
</article>
|
@@ -0,0 +1,4 @@
|
||||
Name Age Address
|
||||
Lucy 12 1234 St John
|
||||
The quick brown fox 5 Forest
|
||||
The lazy dog 6 7 Garfield Street
|
|
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
function myFunction() {
|
||||
document.getElementById("bla").innerHTML = "The quick brown fox jumps over the lazy dog";
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
body {
|
||||
background-color: lightblue;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: navy;
|
||||
margin-left: 20px;
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
### Licenses
|
||||
|
||||
* htmlparser http://htmlparser.sourceforge.net/license.html
|
||||
* commons-compress http://jakarta.apache.org/commons/
|
||||
* pdfbox-tools http://pdfbox.apache.org/
|
||||
* poi-ooxml http://poi.apache.org/
|
||||
* commons-compress, PDFBox and poi-ooxml are from Apache. See the license at http://www.apache.org/licenses/LICENSE-2.0 or the
|
||||
[Apache 2.0.txt](https://github.com/Alfresco/acs-community-packaging/blob/master/distribution/src/main/resources/licenses/3rd-party/Apache%202.0.txt)
|
||||
file placed in the root directory of the docker image.
|
91
alfresco-transform-misc/alfresco-transform-misc/pom.xml
Normal file
91
alfresco-transform-misc/alfresco-transform-misc/pom.xml
Normal file
@@ -0,0 +1,91 @@
|
||||
<?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 Transformers</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<artifactId>alfresco-transform-core</artifactId>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<version>2.2.0-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.19</version>
|
||||
</dependency>
|
||||
|
||||
<!-- OOXMLThumbnailContentTransformer -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>${dependency.poi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- EMLTransformer -->
|
||||
<dependency>
|
||||
<groupId>com.sun.mail</groupId>
|
||||
<artifactId>javax.mail</artifactId>
|
||||
<version>1.6.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>4.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer.transformers;
|
||||
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IMAGE_JPEG;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* Converts Apple iWorks files to JPEGs for thumbnailing and previewing.
|
||||
* The transformer will only work for iWorks 2013/14 files. Support for iWorks 2008/9 has been dropped as we cannot
|
||||
* support both, because the newer format does not contain a PDF. If we say this transformer supports PDF, Share will
|
||||
* assume incorrectly that we can convert to PDF and we would only get a preview for the older format and never the
|
||||
* newer one. Both formats have the same mimetype.
|
||||
*
|
||||
* <p>
|
||||
* This code is based on a class of the same name originally implemented in alfresco-repository.
|
||||
* </p>
|
||||
*
|
||||
* @author Neil Mc Erlean
|
||||
* @author eknizat
|
||||
* @since 4.0
|
||||
*/
|
||||
public class AppleIWorksContentTransformer implements SelectableTransformer
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(
|
||||
AppleIWorksContentTransformer.class);
|
||||
|
||||
// Apple's zip entry names for previews in iWorks have changed over time.
|
||||
private static final List<String> PDF_PATHS = ImmutableList.of(
|
||||
"QuickLook/Preview.pdf"); // iWorks 2008/9
|
||||
private static final List<String> JPG_PATHS = ImmutableList.of(
|
||||
"QuickLook/Thumbnail.jpg", // iWorks 2008/9
|
||||
"preview.jpg"); // iWorks 2013/14 (720 x 552) We use the best quality image. Others are:
|
||||
// (225 x 173) preview-web.jpg
|
||||
// (53 x 41) preview-micro.jpg
|
||||
|
||||
@Override
|
||||
public void transform(final File sourceFile, final File targetFile, final String sourceMimetype,
|
||||
final String targetMimetype, final Map<String, String> parameters)
|
||||
{
|
||||
logger.debug("Performing IWorks to jpeg transform with sourceMimetype={} targetMimetype={}",
|
||||
sourceMimetype, targetMimetype);
|
||||
|
||||
// iWorks files are zip (or package) files.
|
||||
// If it's not a zip file, the resultant ZipException will be caught as an IOException below.
|
||||
try (ZipArchiveInputStream iWorksZip = new ZipArchiveInputStream(
|
||||
new BufferedInputStream(new FileInputStream(sourceFile))))
|
||||
{
|
||||
// Look through the zip file entries for the preview/thumbnail.
|
||||
List<String> paths = MIMETYPE_IMAGE_JPEG.equals(targetMimetype) ? JPG_PATHS : PDF_PATHS;
|
||||
ZipArchiveEntry entry;
|
||||
boolean found = false;
|
||||
while ((entry = iWorksZip.getNextZipEntry()) != null)
|
||||
{
|
||||
String name = entry.getName();
|
||||
if (paths.contains(name))
|
||||
{
|
||||
Files.copy(iWorksZip, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"The source " + sourceMimetype + " file did not contain a " + targetMimetype + " preview");
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"Unable to transform " + sourceMimetype + " file. It should have been a zip format file.",
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer.transformers;
|
||||
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_HTML;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_MULTIPART_ALTERNATIVE;
|
||||
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Multipart;
|
||||
import javax.mail.Part;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
|
||||
import org.alfresco.transformer.fs.FileManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Uses javax.mail.MimeMessage to generate plain text versions of RFC822 email
|
||||
* messages. Searches for all text content parts, and returns them. Any
|
||||
* attachments are ignored. TIKA Note - could be replaced with the Tika email
|
||||
* parser. Would require a recursing parser to be specified, but not the full
|
||||
* Auto one (we don't want attachments), just one containing text and html
|
||||
* related parsers.
|
||||
*
|
||||
* <p>
|
||||
* This code is based on a class of the same name originally implemented in alfresco-repository.
|
||||
* </p>
|
||||
*/
|
||||
public class EMLTransformer implements SelectableTransformer
|
||||
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(EMLTransformer.class);
|
||||
|
||||
private static final String CHARSET = "charset";
|
||||
private static final String DEFAULT_ENCODING = "UTF-8";
|
||||
|
||||
@Override
|
||||
public void transform(final File sourceFile, final File targetFile, final String sourceMimetype,
|
||||
final String targetMimetype, final Map<String, String> parameters) throws Exception
|
||||
{
|
||||
logger.debug("Performing RFC822 to text transform.");
|
||||
// Use try with resource
|
||||
try (InputStream contentInputStream = new BufferedInputStream(
|
||||
new FileInputStream(sourceFile));
|
||||
Writer bufferedFileWriter = new BufferedWriter(new FileWriter(targetFile)))
|
||||
{
|
||||
MimeMessage mimeMessage = new MimeMessage(Session.getDefaultInstance(new Properties()),
|
||||
contentInputStream);
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
Object content = mimeMessage.getContent();
|
||||
if (content instanceof Multipart)
|
||||
{
|
||||
processMultiPart((Multipart) content, sb);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(content.toString());
|
||||
}
|
||||
bufferedFileWriter.write(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find "text" parts of message recursively and appends it to sb StringBuilder
|
||||
*
|
||||
* @param multipart Multipart to process
|
||||
* @param sb StringBuilder
|
||||
* @throws MessagingException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void processMultiPart(Multipart multipart, StringBuilder sb) throws MessagingException,
|
||||
IOException
|
||||
{
|
||||
boolean isAlternativeMultipart = multipart.getContentType().contains(
|
||||
MIMETYPE_MULTIPART_ALTERNATIVE);
|
||||
if (isAlternativeMultipart)
|
||||
{
|
||||
processAlternativeMultipart(multipart, sb);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0, n = multipart.getCount(); i < n; i++)
|
||||
{
|
||||
Part part = multipart.getBodyPart(i);
|
||||
if (part.getContent() instanceof Multipart)
|
||||
{
|
||||
processMultiPart((Multipart) part.getContent(), sb);
|
||||
}
|
||||
else
|
||||
{
|
||||
processPart(part, sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the suitable part from an multipart/alternative and appends it's text content to StringBuilder sb
|
||||
*
|
||||
* @param multipart
|
||||
* @param sb
|
||||
* @throws IOException
|
||||
* @throws MessagingException
|
||||
*/
|
||||
private void processAlternativeMultipart(Multipart multipart, StringBuilder sb) throws
|
||||
IOException, MessagingException
|
||||
{
|
||||
Part partToUse = null;
|
||||
for (int i = 0, n = multipart.getCount(); i < n; i++)
|
||||
{
|
||||
Part part = multipart.getBodyPart(i);
|
||||
if (part.getContentType().contains(MIMETYPE_TEXT_PLAIN))
|
||||
{
|
||||
partToUse = part;
|
||||
break;
|
||||
}
|
||||
else if (part.getContentType().contains(MIMETYPE_HTML))
|
||||
{
|
||||
partToUse = part;
|
||||
}
|
||||
else if (part.getContentType().contains(MIMETYPE_MULTIPART_ALTERNATIVE))
|
||||
{
|
||||
if (part.getContent() instanceof Multipart)
|
||||
{
|
||||
processAlternativeMultipart((Multipart) part.getContent(), sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (partToUse != null)
|
||||
{
|
||||
processPart(partToUse, sb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds text on a given mail part. Accepted parts types are text/html and text/plain.
|
||||
* Attachments are ignored
|
||||
*
|
||||
* @param part
|
||||
* @param sb
|
||||
* @throws IOException
|
||||
* @throws MessagingException
|
||||
*/
|
||||
private void processPart(Part part, StringBuilder sb) throws IOException, MessagingException
|
||||
{
|
||||
boolean isAttachment = Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition());
|
||||
if (isAttachment)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (part.getContentType().contains(MIMETYPE_TEXT_PLAIN))
|
||||
{
|
||||
sb.append(part.getContent().toString());
|
||||
}
|
||||
else if (part.getContentType().contains(MIMETYPE_HTML))
|
||||
{
|
||||
String mailPartContent = part.getContent().toString();
|
||||
|
||||
//create a temporary html file with same mail part content and encoding
|
||||
File tempHtmlFile = FileManager.TempFileProvider.createTempFile("EMLTransformer_",
|
||||
".html");
|
||||
String encoding = getMailPartContentEncoding(part);
|
||||
try (OutputStreamWriter osWriter = new OutputStreamWriter(
|
||||
new FileOutputStream(tempHtmlFile), encoding))
|
||||
{
|
||||
osWriter.write(mailPartContent);
|
||||
}
|
||||
|
||||
//transform html file's content to plain text
|
||||
HtmlParserContentTransformer.EncodingAwareStringBean extractor = new HtmlParserContentTransformer.EncodingAwareStringBean();
|
||||
extractor.setCollapse(false);
|
||||
extractor.setLinks(false);
|
||||
extractor.setReplaceNonBreakingSpaces(false);
|
||||
extractor.setURL(tempHtmlFile, encoding);
|
||||
sb.append(extractor.getStrings());
|
||||
|
||||
tempHtmlFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private String getMailPartContentEncoding(Part part) throws MessagingException
|
||||
{
|
||||
String encoding = DEFAULT_ENCODING;
|
||||
String contentType = part.getContentType();
|
||||
int startIndex = contentType.indexOf(CHARSET);
|
||||
if (startIndex > 0)
|
||||
{
|
||||
encoding = contentType.substring(startIndex + CHARSET.length() + 1)
|
||||
.replaceAll("\"", "");
|
||||
}
|
||||
return encoding;
|
||||
}
|
||||
}
|
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer.transformers;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.IllegalCharsetNameException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.htmlparser.Parser;
|
||||
import org.htmlparser.beans.StringBean;
|
||||
import org.htmlparser.util.ParserException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Content transformer which wraps the HTML Parser library for
|
||||
* parsing HTML content.
|
||||
*
|
||||
* <p>
|
||||
* This code is based on a class of the same name originally implemented in alfresco-repository.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Since HTML Parser was updated from v1.6 to v2.1, META tags
|
||||
* defining an encoding for the content via http-equiv=Content-Type
|
||||
* will ONLY be respected if the encoding of the content item
|
||||
* itself is set to ISO-8859-1.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Tika Note - could be converted to use the Tika HTML parser,
|
||||
* but we'd potentially need a custom text handler to replicate
|
||||
* the current settings around links and non-breaking spaces.
|
||||
* </p>
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @author eknizat
|
||||
* @see <a href="http://htmlparser.sourceforge.net/">http://htmlparser.sourceforge.net</a>
|
||||
* @see org.htmlparser.beans.StringBean
|
||||
* @see <a href="http://sourceforge.net/tracker/?func=detail&aid=1644504&group_id=24399&atid=381401">HTML Parser</a>
|
||||
*/
|
||||
public class HtmlParserContentTransformer implements SelectableTransformer
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(
|
||||
HtmlParserContentTransformer.class);
|
||||
|
||||
@Override
|
||||
public void transform(final File sourceFile, final File targetFile, final String sourceMimetype,
|
||||
final String targetMimetype, final Map<String, String> parameters) throws Exception
|
||||
{
|
||||
String sourceEncoding = parameters.get(SOURCE_ENCODING);
|
||||
checkEncodingParameter(sourceEncoding, SOURCE_ENCODING);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Performing HTML to text transform with sourceEncoding=" + sourceEncoding);
|
||||
}
|
||||
|
||||
// Create the extractor
|
||||
EncodingAwareStringBean extractor = new EncodingAwareStringBean();
|
||||
extractor.setCollapse(false);
|
||||
extractor.setLinks(false);
|
||||
extractor.setReplaceNonBreakingSpaces(false);
|
||||
extractor.setURL(sourceFile, sourceEncoding);
|
||||
// get the text
|
||||
String text = extractor.getStrings();
|
||||
|
||||
// write it to the writer
|
||||
try (Writer writer = new BufferedWriter(
|
||||
new OutputStreamWriter(new FileOutputStream(targetFile))))
|
||||
{
|
||||
writer.write(text);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkEncodingParameter(String encoding, String parameterName)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (encoding != null && !Charset.isSupported(encoding))
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
parameterName + "=" + encoding + " is not supported by the JVM.");
|
||||
}
|
||||
}
|
||||
catch (IllegalCharsetNameException e)
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
parameterName + "=" + encoding + " is not a valid encoding.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This code is based on a class of the same name, originally implemented in alfresco-repository.
|
||||
* </p>
|
||||
*
|
||||
* A version of {@link StringBean} which allows control of the
|
||||
* encoding in the underlying HTML Parser.
|
||||
* Unfortunately, StringBean doesn't allow easy over-riding of
|
||||
* this, so we have to duplicate some code to control this.
|
||||
* This allows us to correctly handle HTML files where the encoding
|
||||
* is specified against the content property (rather than in the
|
||||
* HTML Head Meta), see ALF-10466 for details.
|
||||
*/
|
||||
public static class EncodingAwareStringBean extends StringBean
|
||||
{
|
||||
private static final long serialVersionUID = -9033414360428669553L;
|
||||
|
||||
/**
|
||||
* Sets the File to extract strings from, and the encoding
|
||||
* it's in (if known to Alfresco)
|
||||
*
|
||||
* @param file The File that text should be fetched from.
|
||||
* @param encoding The encoding of the input
|
||||
*/
|
||||
public void setURL(File file, String encoding)
|
||||
{
|
||||
String previousURL = getURL();
|
||||
String newURL = file.getAbsolutePath();
|
||||
|
||||
if (previousURL == null || !newURL.equals(previousURL))
|
||||
{
|
||||
try
|
||||
{
|
||||
URLConnection conn = getConnection();
|
||||
|
||||
if (null == mParser)
|
||||
{
|
||||
mParser = new Parser(newURL);
|
||||
}
|
||||
else
|
||||
{
|
||||
mParser.setURL(newURL);
|
||||
}
|
||||
|
||||
if (encoding != null)
|
||||
{
|
||||
mParser.setEncoding(encoding);
|
||||
}
|
||||
|
||||
mPropertySupport.firePropertyChange(StringBean.PROP_URL_PROPERTY, previousURL,
|
||||
getURL());
|
||||
mPropertySupport.firePropertyChange(StringBean.PROP_CONNECTION_PROPERTY, conn,
|
||||
mParser.getConnection());
|
||||
setStrings();
|
||||
}
|
||||
catch (ParserException pe)
|
||||
{
|
||||
updateStrings(pe.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getEncoding()
|
||||
{
|
||||
return mParser.getEncoding();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer.transformers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
|
||||
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Extracts out Thumbnail JPEGs from OOXML files for thumbnailing and previewing.
|
||||
* This transformer will only work for OOXML files where thumbnailing was enabled,
|
||||
* which isn't on by default on Windows, but is more common on Mac.
|
||||
*
|
||||
* <p>
|
||||
* This code is based on a class of the same name originally implemented in alfresco-repository.
|
||||
* </p>
|
||||
*
|
||||
* @author Nick Burch
|
||||
* @author eknizat
|
||||
*/
|
||||
public class OOXMLThumbnailContentTransformer implements SelectableTransformer
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(
|
||||
OOXMLThumbnailContentTransformer.class);
|
||||
|
||||
@Override
|
||||
public void transform(final File sourceFile, final File targetFile, final String sourceMimetype,
|
||||
final String targetMimetype, final Map<String, String> parameters) throws Exception
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Performing OOXML to jpeg transform with sourceMimetype=" + sourceMimetype
|
||||
+ " targetMimetype=" + targetMimetype);
|
||||
}
|
||||
|
||||
try (OPCPackage pkg = OPCPackage.open(sourceFile.getPath()))
|
||||
{
|
||||
|
||||
// Does it have a thumbnail?
|
||||
PackageRelationshipCollection rels = pkg.getRelationshipsByType(
|
||||
PackageRelationshipTypes.THUMBNAIL);
|
||||
if (rels.size() > 0)
|
||||
{
|
||||
// Get the thumbnail part
|
||||
PackageRelationship tRel = rels.getRelationship(0);
|
||||
PackagePart tPart = pkg.getPart(tRel);
|
||||
|
||||
// Write it to the target
|
||||
InputStream tStream = tPart.getInputStream();
|
||||
Files.copy(tStream, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
tStream.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.debug("No thumbnail present in file.");
|
||||
throw new Exception(
|
||||
"No thumbnail present in file, unable to generate " + targetMimetype);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException("Unable to transform file.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO Add this back to engine_config.json when the transformer is fixed for java 11
|
||||
{
|
||||
"transformerName": "ooxmlThumbnail",
|
||||
"supportedSourceAndTargetList": [
|
||||
{"sourceMediaType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.ms-word.document.macroenabled.12", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.openxmlformats-officedocument.wordprocessingml.template", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.ms-word.template.macroenabled.12", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.presentation", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.ms-powerpoint.presentation.macroenabled.12", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.slideshow", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.ms-powerpoint.slideshow.macroenabled.12", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.template", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.ms-powerpoint.template.macroenabled.12", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.ms-powerpoint.addin.macroenabled.12", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.slide", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.ms-powerpoint.slide.macroenabled.12", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.openxmlformats-officedocument.spreadsheetml.template", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.ms-excel.sheet.macroenabled.12", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.ms-excel.template.macroenabled.12", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.ms-excel.addin.macroenabled.12", "targetMediaType": "image/jpeg"},
|
||||
{"sourceMediaType": "application/vnd.ms-excel.sheet.binary.macroenabled.12", "targetMediaType": "image/jpeg"}
|
||||
],
|
||||
"transformOptions": [
|
||||
]
|
||||
}
|
||||
*/
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer.transformers;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Implemented by transformers used by {@link SelectingTransformer}.
|
||||
*
|
||||
* @author eknizat
|
||||
*/
|
||||
public interface SelectableTransformer
|
||||
{
|
||||
String SOURCE_ENCODING = "sourceEncoding";
|
||||
String TARGET_ENCODING = "targetEncoding";
|
||||
|
||||
/**
|
||||
* Implementation of the actual transformation.
|
||||
*
|
||||
* @param sourceFile
|
||||
* @param targetFile
|
||||
* @param parameters
|
||||
* @throws Exception
|
||||
*/
|
||||
void transform(File sourceFile, File targetFile, String sourceMimetype,
|
||||
String targetMimetype, Map<String, String> parameters) throws Exception;
|
||||
}
|
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer.transformers;
|
||||
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import org.alfresco.transform.exceptions.TransformException;
|
||||
import org.alfresco.transformer.logging.LogEntry;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* The SelectingTransformer selects a registered {@link SelectableTransformer}
|
||||
* and delegates the transformation to its implementation.
|
||||
*
|
||||
* @author eknizat
|
||||
*/
|
||||
public class SelectingTransformer
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(SelectingTransformer.class);
|
||||
|
||||
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())
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Performs a transform using a transformer selected based on the provided sourceMimetype and targetMimetype
|
||||
*
|
||||
* @param transform the name of the transformer
|
||||
* @param sourceFile File to transform from
|
||||
* @param targetFile File to transform to
|
||||
* @param sourceMimetype Mimetype of the source file
|
||||
* @throws TransformException if there was a problem internally
|
||||
*/
|
||||
public void transform(String transform, File sourceFile, File targetFile, String sourceMimetype,
|
||||
String targetMimetype, Map<String, String> parameters) throws TransformException
|
||||
{
|
||||
try
|
||||
{
|
||||
final SelectableTransformer transformer = transformers.get(transform);
|
||||
logOptions(sourceFile, targetFile, parameters);
|
||||
transformer.transform(sourceFile, targetFile, sourceMimetype, targetMimetype,
|
||||
parameters);
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
throw new TransformException(BAD_REQUEST.value(), getMessage(e));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new TransformException(INTERNAL_SERVER_ERROR.value(), getMessage(e));
|
||||
}
|
||||
if (!targetFile.exists())
|
||||
{
|
||||
throw new TransformException(INTERNAL_SERVER_ERROR.value(),
|
||||
"Transformer failed to create an output file. Target file does not exist.");
|
||||
}
|
||||
if (sourceFile.length() > 0 && targetFile.length() == 0)
|
||||
{
|
||||
throw new TransformException(INTERNAL_SERVER_ERROR.value(),
|
||||
"Transformer failed to create an output file. Target file is empty but source file was not empty.");
|
||||
}
|
||||
}
|
||||
|
||||
private static String getMessage(Exception e)
|
||||
{
|
||||
return e.getMessage() == null || e.getMessage().isEmpty() ? e.getClass().getSimpleName() : e.getMessage();
|
||||
}
|
||||
|
||||
private static void logOptions(File sourceFile, File targetFile, Map<String, String> parameters)
|
||||
{
|
||||
StringJoiner sj = new StringJoiner(" ");
|
||||
parameters.forEach((k, v) -> 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);
|
||||
}
|
||||
}
|
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer.transformers;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.IllegalCharsetNameException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Converts any textual format to plain text.
|
||||
* <p>
|
||||
* The transformation is sensitive to the source and target string encodings.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* This code is based on a class of the same name originally implemented in alfresco-repository.
|
||||
* </p>
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @author eknizat
|
||||
*/
|
||||
public class StringExtractingContentTransformer implements SelectableTransformer
|
||||
{
|
||||
|
||||
private static final Log logger = LogFactory.getLog(StringExtractingContentTransformer.class);
|
||||
|
||||
/**
|
||||
* Text to text conversions are done directly using the content reader and writer string
|
||||
* manipulation methods.
|
||||
* <p>
|
||||
* Extraction of text from binary content attempts to take the possible character
|
||||
* encoding into account. The text produced from this will, if the encoding was correct,
|
||||
* be unformatted but valid.
|
||||
*/
|
||||
@Override
|
||||
public void transform(final File sourceFile, final File targetFile, final String sourceMimetype,
|
||||
final String targetMimetype, final Map<String, String> parameters) throws Exception
|
||||
{
|
||||
String sourceEncoding = parameters.get(SOURCE_ENCODING);
|
||||
String targetEncoding = parameters.get(TARGET_ENCODING);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Performing text to text transform with sourceEncoding=" + sourceEncoding
|
||||
+ " targetEncoding=" + targetEncoding);
|
||||
}
|
||||
|
||||
Reader charReader = null;
|
||||
Writer charWriter = null;
|
||||
try
|
||||
{
|
||||
// Build reader
|
||||
if (sourceEncoding == null)
|
||||
{
|
||||
charReader = new BufferedReader(
|
||||
new InputStreamReader(new FileInputStream(sourceFile)));
|
||||
}
|
||||
else
|
||||
{
|
||||
checkEncodingParameter(sourceEncoding, SOURCE_ENCODING);
|
||||
charReader = new BufferedReader(
|
||||
new InputStreamReader(new FileInputStream(sourceFile), sourceEncoding));
|
||||
}
|
||||
|
||||
// Build writer
|
||||
if (targetEncoding == null)
|
||||
{
|
||||
charWriter = new BufferedWriter(
|
||||
new OutputStreamWriter(new FileOutputStream(targetFile)));
|
||||
}
|
||||
else
|
||||
{
|
||||
checkEncodingParameter(targetEncoding, TARGET_ENCODING);
|
||||
charWriter = new BufferedWriter(
|
||||
new OutputStreamWriter(new FileOutputStream(targetFile), targetEncoding));
|
||||
}
|
||||
|
||||
// copy from the one to the other
|
||||
char[] buffer = new char[8192];
|
||||
int readCount = 0;
|
||||
while (readCount > -1)
|
||||
{
|
||||
// write the last read count number of bytes
|
||||
charWriter.write(buffer, 0, readCount);
|
||||
// fill the buffer again
|
||||
readCount = charReader.read(buffer);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (charReader != null)
|
||||
{
|
||||
try { charReader.close(); } catch (Throwable e) { logger.error(e); }
|
||||
}
|
||||
if (charWriter != null)
|
||||
{
|
||||
try { charWriter.close(); } catch (Throwable e) { logger.error(e); }
|
||||
}
|
||||
}
|
||||
// done
|
||||
}
|
||||
|
||||
private void checkEncodingParameter(String encoding, String paramterName)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Charset.isSupported(encoding))
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
paramterName + "=" + encoding + " is not supported by the JVM.");
|
||||
}
|
||||
}
|
||||
catch (IllegalCharsetNameException e)
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
paramterName + "=" + encoding + " is not a valid encoding.");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer.transformers;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
||||
import org.apache.pdfbox.tools.TextToPDF;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This code is based on a class of the same name originally implemented in alfresco-repository.
|
||||
* </p>
|
||||
*
|
||||
* Makes use of the <a href="http://www.pdfbox.org/">PDFBox</a> library's <code>TextToPDF</code> utility.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @author eknizat
|
||||
*/
|
||||
public class TextToPdfContentTransformer implements SelectableTransformer
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(TextToPdfContentTransformer.class);
|
||||
|
||||
public static final String PAGE_LIMIT = "pageLimit";
|
||||
|
||||
private final PagedTextToPDF transformer;
|
||||
|
||||
public TextToPdfContentTransformer()
|
||||
{
|
||||
transformer = new PagedTextToPDF();
|
||||
}
|
||||
|
||||
public void setStandardFont(String fontName)
|
||||
{
|
||||
try
|
||||
{
|
||||
transformer.setFont(PagedTextToPDF.getStandardFont(fontName));
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"Unable to set Standard Font for PDF generation: " + fontName, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFontSize(int fontSize)
|
||||
{
|
||||
try
|
||||
{
|
||||
transformer.setFontSize(fontSize);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"Unable to set Font Size for PDF generation: " + fontSize);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(final File sourceFile, final File targetFile, final String sourceMimetype,
|
||||
final String targetMimetype, final Map<String, String> parameters) throws Exception
|
||||
{
|
||||
String sourceEncoding = parameters.get(SOURCE_ENCODING);
|
||||
String stringPageLimit = parameters.get(PAGE_LIMIT);
|
||||
int pageLimit = -1;
|
||||
if (stringPageLimit != null)
|
||||
{
|
||||
pageLimit = parseInt(stringPageLimit, PAGE_LIMIT);
|
||||
}
|
||||
|
||||
PDDocument pdf = null;
|
||||
try (InputStream is = new FileInputStream(sourceFile);
|
||||
Reader ir = new BufferedReader(buildReader(is, sourceEncoding));
|
||||
OutputStream os = new BufferedOutputStream(new FileOutputStream(targetFile)))
|
||||
{
|
||||
//TransformationOptionLimits limits = getLimits(reader, writer, options);
|
||||
//TransformationOptionPair pageLimits = limits.getPagesPair();
|
||||
pdf = transformer.createPDFFromText(ir, pageLimit);
|
||||
pdf.save(os);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pdf != null)
|
||||
{
|
||||
try { pdf.close(); } catch (Throwable e) {e.printStackTrace(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected InputStreamReader buildReader(InputStream is, String encoding)
|
||||
{
|
||||
// If they gave an encoding, try to use it
|
||||
if (encoding != null)
|
||||
{
|
||||
Charset charset = null;
|
||||
try
|
||||
{
|
||||
charset = Charset.forName(encoding);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.warn("JVM doesn't understand encoding '" + encoding +
|
||||
"' when transforming text to pdf");
|
||||
}
|
||||
if (charset != null)
|
||||
{
|
||||
logger.debug("Processing plain text in encoding " + charset.displayName());
|
||||
return new InputStreamReader(is, charset);
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back on the system default
|
||||
logger.debug("Processing plain text using system default encoding");
|
||||
return new InputStreamReader(is);
|
||||
}
|
||||
|
||||
private static class PagedTextToPDF extends TextToPDF
|
||||
{
|
||||
// REPO-1066: duplicating the following lines from org.apache.pdfbox.tools.TextToPDF because they made them private
|
||||
// before the upgrade to pdfbox 2.0.8, in pdfbox 1.8, this piece of code was public in org.apache.pdfbox.pdmodel.font.PDType1Font
|
||||
static PDType1Font getStandardFont(String name)
|
||||
{
|
||||
return STANDARD_14.get(name);
|
||||
}
|
||||
|
||||
private static final Map<String, PDType1Font> STANDARD_14 = new HashMap<>();
|
||||
|
||||
static
|
||||
{
|
||||
STANDARD_14.put(PDType1Font.TIMES_ROMAN.getBaseFont(), PDType1Font.TIMES_ROMAN);
|
||||
STANDARD_14.put(PDType1Font.TIMES_BOLD.getBaseFont(), PDType1Font.TIMES_BOLD);
|
||||
STANDARD_14.put(PDType1Font.TIMES_ITALIC.getBaseFont(), PDType1Font.TIMES_ITALIC);
|
||||
STANDARD_14.put(PDType1Font.TIMES_BOLD_ITALIC.getBaseFont(),
|
||||
PDType1Font.TIMES_BOLD_ITALIC);
|
||||
STANDARD_14.put(PDType1Font.HELVETICA.getBaseFont(), PDType1Font.HELVETICA);
|
||||
STANDARD_14.put(PDType1Font.HELVETICA_BOLD.getBaseFont(), PDType1Font.HELVETICA_BOLD);
|
||||
STANDARD_14.put(PDType1Font.HELVETICA_OBLIQUE.getBaseFont(),
|
||||
PDType1Font.HELVETICA_OBLIQUE);
|
||||
STANDARD_14.put(PDType1Font.HELVETICA_BOLD_OBLIQUE.getBaseFont(),
|
||||
PDType1Font.HELVETICA_BOLD_OBLIQUE);
|
||||
STANDARD_14.put(PDType1Font.COURIER.getBaseFont(), PDType1Font.COURIER);
|
||||
STANDARD_14.put(PDType1Font.COURIER_BOLD.getBaseFont(), PDType1Font.COURIER_BOLD);
|
||||
STANDARD_14.put(PDType1Font.COURIER_OBLIQUE.getBaseFont(), PDType1Font.COURIER_OBLIQUE);
|
||||
STANDARD_14.put(PDType1Font.COURIER_BOLD_OBLIQUE.getBaseFont(),
|
||||
PDType1Font.COURIER_BOLD_OBLIQUE);
|
||||
STANDARD_14.put(PDType1Font.SYMBOL.getBaseFont(), PDType1Font.SYMBOL);
|
||||
STANDARD_14.put(PDType1Font.ZAPF_DINGBATS.getBaseFont(), PDType1Font.ZAPF_DINGBATS);
|
||||
}
|
||||
//duplicating until here
|
||||
|
||||
// The following code is based on the code in TextToPDF with the addition of
|
||||
// checks for page limits.
|
||||
// The calling code must close the PDDocument once finished with it.
|
||||
public PDDocument createPDFFromText(Reader text, int pageLimit)
|
||||
throws IOException
|
||||
{
|
||||
//int pageLimit = (int)pageLimits.getValue();
|
||||
PDDocument doc = null;
|
||||
int pageCount = 0;
|
||||
try
|
||||
{
|
||||
final int margin = 40;
|
||||
float height = getFont().getFontDescriptor().getFontBoundingBox().getHeight() / 1000;
|
||||
|
||||
//calculate font height and increase by 5 percent.
|
||||
height = height * getFontSize() * 1.05f;
|
||||
doc = new PDDocument();
|
||||
BufferedReader data = new BufferedReader(text);
|
||||
String nextLine;
|
||||
PDPage page = new PDPage();
|
||||
PDPageContentStream contentStream = null;
|
||||
float y = -1;
|
||||
float maxStringLength = page.getMediaBox().getWidth() - 2 * margin;
|
||||
|
||||
// There is a special case of creating a PDF document from an empty string.
|
||||
boolean textIsEmpty = true;
|
||||
|
||||
outer:
|
||||
while ((nextLine = data.readLine()) != null)
|
||||
{
|
||||
|
||||
// The input text is nonEmpty. New pages will be created and added
|
||||
// to the PDF document as they are needed, depending on the length of
|
||||
// the text.
|
||||
textIsEmpty = false;
|
||||
|
||||
String[] lineWords = nextLine.trim().split(" ");
|
||||
int lineIndex = 0;
|
||||
while (lineIndex < lineWords.length)
|
||||
{
|
||||
final StringBuilder nextLineToDraw = new StringBuilder();
|
||||
float lengthIfUsingNextWord = 0;
|
||||
do
|
||||
{
|
||||
nextLineToDraw.append(lineWords[lineIndex]);
|
||||
nextLineToDraw.append(" ");
|
||||
lineIndex++;
|
||||
if (lineIndex < lineWords.length)
|
||||
{
|
||||
String lineWithNextWord = nextLineToDraw.toString() + lineWords[lineIndex];
|
||||
lengthIfUsingNextWord =
|
||||
(getFont().getStringWidth(
|
||||
lineWithNextWord) / 1000) * getFontSize();
|
||||
}
|
||||
}
|
||||
while (lineIndex < lineWords.length &&
|
||||
lengthIfUsingNextWord < maxStringLength);
|
||||
if (y < margin)
|
||||
{
|
||||
int test = pageCount + 1;
|
||||
if (pageLimit > 0 && (pageCount++ >= pageLimit))
|
||||
{
|
||||
// pageLimits.getAction().throwIOExceptionIfRequired("Page limit ("+pageLimit+
|
||||
// ") reached.", transformerDebug);
|
||||
break outer;
|
||||
}
|
||||
|
||||
// We have crossed the end-of-page boundary and need to extend the
|
||||
// document by another page.
|
||||
page = new PDPage();
|
||||
doc.addPage(page);
|
||||
if (contentStream != null)
|
||||
{
|
||||
contentStream.endText();
|
||||
contentStream.close();
|
||||
}
|
||||
contentStream = new PDPageContentStream(doc, page);
|
||||
contentStream.setFont(getFont(), getFontSize());
|
||||
contentStream.beginText();
|
||||
y = page.getMediaBox().getHeight() - margin + height;
|
||||
contentStream.moveTextPositionByAmount(margin, y);
|
||||
}
|
||||
//System.out.println( "Drawing string at " + x + "," + y );
|
||||
|
||||
if (contentStream == null)
|
||||
{
|
||||
throw new IOException("Error:Expected non-null content stream.");
|
||||
}
|
||||
contentStream.moveTextPositionByAmount(0, -height);
|
||||
y -= height;
|
||||
contentStream.drawString(nextLineToDraw.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// If the input text was the empty string, then the above while loop will have short-circuited
|
||||
// and we will not have added any PDPages to the document.
|
||||
// So in order to make the resultant PDF document readable by Adobe Reader etc, we'll add an empty page.
|
||||
if (textIsEmpty)
|
||||
{
|
||||
doc.addPage(page);
|
||||
}
|
||||
|
||||
if (contentStream != null)
|
||||
{
|
||||
contentStream.endText();
|
||||
contentStream.close();
|
||||
}
|
||||
}
|
||||
catch (IOException io)
|
||||
{
|
||||
if (doc != null)
|
||||
{
|
||||
doc.close();
|
||||
}
|
||||
throw io;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
|
||||
private int parseInt(String s, String paramName)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Integer.valueOf(s);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
throw new IllegalArgumentException(paramName + " parameter must be an integer.");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer.transformers;
|
||||
|
||||
import static org.alfresco.transformer.transformers.StringExtractingContentTransformer.SOURCE_ENCODING;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class HtmlParserContentTransformerTest
|
||||
{
|
||||
private static final String SOURCE_MIMETYPE = "text/html";
|
||||
private static final String TARGET_MIMETYPE = "text/plain";
|
||||
|
||||
HtmlParserContentTransformer transformer = new HtmlParserContentTransformer();
|
||||
|
||||
/**
|
||||
* Checks that we correctly handle text in different encodings,
|
||||
* no matter if the encoding is specified on the Content Property
|
||||
* or in a meta tag within the HTML itself. (ALF-10466)
|
||||
*
|
||||
* On Windows, org.htmlparser.beans.StringBean.carriageReturn() appends a new system dependent new line
|
||||
* so we must be careful when checking the returned text
|
||||
*/
|
||||
@Test
|
||||
public void testEncodingHandling() 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.transform(tmpS, tmpD, SOURCE_MIMETYPE, TARGET_MIMETYPE, parameters);
|
||||
|
||||
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.transform(tmpS, tmpD, SOURCE_MIMETYPE, TARGET_MIMETYPE, parameters);
|
||||
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.transform(tmpS, tmpD, SOURCE_MIMETYPE, TARGET_MIMETYPE, parameters);
|
||||
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.transform(tmpS, tmpD, SOURCE_MIMETYPE, TARGET_MIMETYPE, parameters);
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer.transformers;
|
||||
|
||||
import static org.alfresco.transformer.transformers.TextToPdfContentTransformer.PAGE_LIMIT;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.text.PDFTextStripper;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TextToPdfContentTransformerTest
|
||||
{
|
||||
TextToPdfContentTransformer transformer = new TextToPdfContentTransformer();
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
transformer.setStandardFont("Times-Roman");
|
||||
transformer.setFontSize(20);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnlimitedPages() throws Exception
|
||||
{
|
||||
transformTextAndCheckPageLength(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLimitedTo1Page() throws Exception
|
||||
{
|
||||
transformTextAndCheckPageLength(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLimitedTo2Pages() throws Exception
|
||||
{
|
||||
transformTextAndCheckPageLength(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLimitedTo50Pages() throws Exception
|
||||
{
|
||||
transformTextAndCheckPageLength(50);
|
||||
}
|
||||
|
||||
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(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.transform(sourceFile, targetFile, "text/plain", "application/pdf", parameters);
|
||||
|
||||
// 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(
|
||||
"Incorrect text in PDF when starting from text in " + encoding,
|
||||
checkText, roundTrip
|
||||
);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private void writeToFile(File file, String content, String encoding) throws Exception
|
||||
{
|
||||
try (OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream(file), encoding))
|
||||
{
|
||||
ow.append(content);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user