diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 5980b74..925f386 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -12,6 +12,8 @@ services: ports: - "${share.port}:8080" - "${share.debug.port}:8888" + depends_on: + - alfmarkdown-acs alfmarkdown-acs: image: alfresco-content-services-alfmarkdown:development build: @@ -57,6 +59,12 @@ services: APP_CONFIG_ECM_HOST: http://localhost:${acs.port} ports: - "${adw.port}:8080" + depends_on: + - alfmarkdown-acs + alfmarkdown-tengine: + image: alfmarkdown-tengine:development + ports: + - "${ate.port}:8090" volumes: alfmarkdown-acs-volume: external: true diff --git a/platform-docker/src/main/docker/alfresco-global.properties b/platform-docker/src/main/docker/alfresco-global.properties index 1ff9760..db9ead6 100644 --- a/platform-docker/src/main/docker/alfresco-global.properties +++ b/platform-docker/src/main/docker/alfresco-global.properties @@ -80,6 +80,8 @@ messaging.broker.url=vm://localhost?broker.persistent=false # Disable ATS transform.service.enabled=false -local.transform.service.enabled=false +local.transform.service.enabled=true legacy.transform.service.enabled=false jodconverter.enabled=false + +-DlocalTransform.alfmarkdown.url=http://alfmarkdown-tengine:8090/ diff --git a/pom.xml b/pom.xml index dd3acb6..563c358 100644 --- a/pom.xml +++ b/pom.xml @@ -35,13 +35,14 @@ 1.1.8 - 8280 8180 9898 alfmarkdown-acs 8080 8888 5555 + 8280 + 8190 @@ -422,6 +423,7 @@ platform-docker share share-docker + tengine diff --git a/run.bat b/run.bat index bbcb0a0..02d2904 100644 --- a/run.bat +++ b/run.bat @@ -11,7 +11,7 @@ IF NOT [%M2_HOME%]==[] ( ) IF [%1]==[] ( - echo "Usage: %0 {build_start|build_start_it_supported|start|stop|purge|tail|reload_share|reload_acs|build_test|test}" + echo "Usage: %0 {build_start|build_start_it_supported|start|stop|purge|tail|reload_tengine|reload_share|reload_acs|build_test|test}" GOTO END ) @@ -60,6 +60,12 @@ IF %1==reload_acs ( CALL :tail GOTO END ) +IF %1==reload_tengine ( + CALL :build_tengine + CALL :start_tengine + CALL :tail + GOTO END +) IF %1==build_test ( CALL :down CALL :build @@ -74,7 +80,7 @@ IF %1==test ( CALL :test GOTO END ) -echo "Usage: %0 {build_start|start|stop|purge|tail|reload_share|reload_acs|build_test|test}" +echo "Usage: %0 {build_start|start|stop|purge|tail|reload_tengine|reload_share|reload_acs|build_test|test}" :END EXIT /B %ERRORLEVEL% @@ -90,6 +96,9 @@ EXIT /B 0 :start_acs docker-compose -f "%COMPOSE_FILE_PATH%" up --build -d alfmarkdown-acs EXIT /B 0 +:start_tengine + docker-compose -f "%COMPOSE_FILE_PATH%" up --build -d alfmarkdown-tengine +EXIT /B 0 :down if exist "%COMPOSE_FILE_PATH%" ( docker-compose -f "%COMPOSE_FILE_PATH%" down @@ -108,6 +117,11 @@ EXIT /B 0 docker-compose -f "%COMPOSE_FILE_PATH%" rm -f alfmarkdown-acs call %MVN_EXEC% clean package -pl integration-tests,repo,platform-docker EXIT /B 0 +:build_tengine + docker-compose -f "%COMPOSE_FILE_PATH%" kill alfmarkdown-tengine + docker-compose -f "%COMPOSE_FILE_PATH%" rm -f alfmarkdown-tengine + call %MVN_EXEC% clean package -pl tengine +EXIT /B 0 :tail docker-compose -f "%COMPOSE_FILE_PATH%" logs -f EXIT /B 0 @@ -115,10 +129,10 @@ EXIT /B 0 docker-compose -f "%COMPOSE_FILE_PATH%" logs --tail="all" EXIT /B 0 :prepare-test - call %MVN_EXEC% verify -DskipTests=true -pl repo,integration-tests,platform-docker + call %MVN_EXEC% verify -DskipTests=true -pl repo,tengine,integration-tests,platform-docker EXIT /B 0 :test - call %MVN_EXEC% verify -pl repo,integration-tests + call %MVN_EXEC% verify -pl repo,tengine,integration-tests EXIT /B 0 :purge docker volume rm -f alfmarkdown-acs-volume diff --git a/run.sh b/run.sh index fc33a2c..591c6a6 100644 --- a/run.sh +++ b/run.sh @@ -23,6 +23,14 @@ start_acs() { docker-compose -f "$COMPOSE_FILE_PATH" up --build -d alfmarkdown-acs } +start_tengine() { + docker-compose -f "$COMPOSE_FILE_PATH" up --build -d alfmarkdown-tengine +} + +start_adw() { + docker-compose -f "$COMPOSE_FILE_PATH" up --build -d alfmarkdown-adw +} + down() { if [ -f "$COMPOSE_FILE_PATH" ]; then docker-compose -f "$COMPOSE_FILE_PATH" down @@ -51,6 +59,12 @@ build_acs() { $MVN_EXEC clean package -pl integration-tests,repo,platform-docker } +build_tengine() { + docker-compose -f "$COMPOSE_FILE_PATH" kill alfmarkdown-tengine + yes | docker-compose -f "$COMPOSE_FILE_PATH" rm -f alfmarkdown-tengine + $MVN_EXEC clean package -pl tengine +} + tail() { docker-compose -f "$COMPOSE_FILE_PATH" logs -f } @@ -60,11 +74,11 @@ tail_all() { } prepare_test() { - $MVN_EXEC verify -DskipTests=true -pl repo,integration-tests,platform-docker + $MVN_EXEC verify -DskipTests=true -pl repo,tengine,integration-tests,platform-docker } test() { - $MVN_EXEC verify -pl repo,integration-tests + $MVN_EXEC verify -pl repo,tengine,integration-tests } case "$1" in @@ -105,6 +119,11 @@ case "$1" in start_acs tail ;; + reload_tengine) + build_tengine + start_tengine + tail + ;; build_test) down build @@ -118,5 +137,5 @@ case "$1" in test ;; *) - echo "Usage: $0 {build_start|build_start_it_supported|start|stop|purge|tail|reload_share|reload_acs|build_test|test}" + echo "Usage: $0 {build_start|build_start_it_supported|start|stop|purge|tail|reload_tengine|reload_share|reload_acs|build_test|test}" esac diff --git a/tengine/pom.xml b/tengine/pom.xml new file mode 100644 index 0000000..27a2a04 --- /dev/null +++ b/tengine/pom.xml @@ -0,0 +1,251 @@ + + + 4.0.0 + + com.inteligr8.alfresco.module + alfmarkdown-tengine + 1.0-SNAPSHOT + jar + + alfmarkdown Alfresco T-Engine + + + UTF-8 + 8 + 8 + + 2.3.6 + 2.3.5.RELEASE + 5.15.8 + + docker.yateslong.us + inteligr8/${project.artifactId} + ${project.version} + + + + + org.alfresco + alfresco-transformer-base + ${ats.version} + + + org.alfresco + alfresco-transformer-base + ${ats.version} + tests + test-jar + test + + + org.springframework.boot + spring-boot-starter-thymeleaf + ${spring-boot.version} + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot.version} + test + + + com.vaadin.external.google + android-json + + + + + org.jsoup + jsoup + 1.13.1 + test + + + + + + + src/main/resources + true + + + + + src/test/resources + true + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + + + + maven-surefire-plugin + 2.22.2 + + + maven-failsafe-plugin + 2.22.2 + + + + + + + docker + + + true + + + + + maven-resources-plugin + + + copy-and-filter-docker-resources + validate + + copy-resources + + + ${project.build.directory} + + + ${basedir}/src/main/docker + true + + + + + + + + com.spotify + dockerfile-maven-plugin + 1.4.13 + + ${project.build.directory} + ${image.registry}/${image.name} + ${image.tag} + + ${project.artifactId}-${project.version}.jar + + true + + + + docker-build + package + build + + ${image.name} + + + + docker-tag-registry + install + tag + + + docker-push + deploy + push + + + + + + + + + docker-test + + + + + io.fabric8 + docker-maven-plugin + + + + activemq + alfresco/alfresco-activemq:${activemq.version} + + activemq + + 8161:8161 + 5672:5672 + 61616:61616 + + + Apache ActiveMQ ${activemq.version} .* started + + 500 + 100 + + kill 1 + kill -9 1 + + + + + + ${project.artifactId} + ${image.name}:${image.tag} + + + + 8090:8090 + + + + http://localhost:8090/transform/config + GET + 200...299 + + + 500 + 100 + + kill 1 + kill -9 1 + + + + + + + + + + + + + + + inteligr8-releases + http://repos.yateslong.us/nexus/repository/inteligr8-private + + + inteligr8-snapshots + http://repos.yateslong.us/nexus/repository/inteligr8-snapshots + + daily + + + + alfresco-public + https://artifacts.alfresco.com/nexus/content/groups/public + + + diff --git a/tengine/src/main/docker/Dockerfile b/tengine/src/main/docker/Dockerfile new file mode 100644 index 0000000..1270c1a --- /dev/null +++ b/tengine/src/main/docker/Dockerfile @@ -0,0 +1,28 @@ + +FROM docker.yateslong.us/inteligr8/ubuntu-jdk:20.04-11 + +# Set default user information +ARG JAR_FILE +ARG APPGROUPNAME=alfresco +ARG APPGROUPID=1000 +ARG APPUSERNAME=ate +ARG APPUSERID=33001 + +ENV JAVA_OPTS="-Xmx128m" +ENV JAR_PATH=/usr/local/bin/${project.artifactId}.jar + +COPY ${JAR_FILE} ${JAR_PATH} + +# Install your engine's dependencies here +#RUN apt update && \ +# apt -y install + +RUN groupadd -g ${APPGROUPID} ${APPGROUPNAME} && \ + useradd -u ${APPUSERID} -G ${APPGROUPNAME} ${APPUSERNAME} && \ + chown ${APPUSERNAME}:${APPGROUPNAME} ${JAR_PATH} + +EXPOSE 8090 + +USER ${APPUSERNAME} + +ENTRYPOINT java ${JAVA_OPTS} -jar ${JAR_PATH} diff --git a/tengine/src/main/java/com/inteligr8/alfresco/module/alfmarkdown/Application.java b/tengine/src/main/java/com/inteligr8/alfresco/module/alfmarkdown/Application.java new file mode 100644 index 0000000..76f2d49 --- /dev/null +++ b/tengine/src/main/java/com/inteligr8/alfresco/module/alfmarkdown/Application.java @@ -0,0 +1,67 @@ +/* + * #%L + * Alfresco Transform Core + * %% + * Copyright (C) 2005 - 2020 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * - + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * - + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package com.inteligr8.alfresco.module.alfmarkdown; + +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.annotation.ImportResource; +import org.springframework.context.event.EventListener; + +import io.micrometer.core.instrument.MeterRegistry; + +@SpringBootApplication +@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class }) +@ImportResource({"classpath*:application-context.xml"}) +public class Application { + + private final Logger logger = LoggerFactory.getLogger(Application.class); + + @Value("${container.name}") + private String containerName; + + @Bean + public MeterRegistryCustomizer metricsCommonTags() { + return registry -> registry.config().commonTags("containerName", this.containerName); + } + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @EventListener(ApplicationReadyEvent.class) + public void startup() { + this.logger.info("Starting application components... Done"); + } +} diff --git a/tengine/src/main/java/com/inteligr8/alfresco/module/alfmarkdown/TransformerController.java b/tengine/src/main/java/com/inteligr8/alfresco/module/alfmarkdown/TransformerController.java new file mode 100644 index 0000000..e0b2a22 --- /dev/null +++ b/tengine/src/main/java/com/inteligr8/alfresco/module/alfmarkdown/TransformerController.java @@ -0,0 +1,144 @@ +/* + * #%L + * Alfresco Transform Core + * %% + * Copyright (C) 2005 - 2020 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * - + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * - + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + * + * Copyright (C) 2020 - 2021 Inteligr8 + */ +package com.inteligr8.alfresco.module.alfmarkdown; + +import java.io.File; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.annotation.PostConstruct; + +import org.alfresco.transformer.AbstractTransformerController; +import org.alfresco.transformer.probes.ProbeTestTransform; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; + +/** + * Controller for the Spring Boot transformer. + * + * Status Codes: + * + * 200 Success + * 400 Bad Request: Request parameter is missing (missing mandatory parameter) + * 400 Bad Request: Request parameter is of the wrong type + * 400 Bad Request: Transformer exit code was not 0 (possible problem with the source file) + * 400 Bad Request: The source filename was not supplied + * 500 Internal Server Error: (no message with low level IO problems) + * 500 Internal Server Error: The target filename was not supplied (should not happen as targetExtension is checked) + * 500 Internal Server Error: Transformer version check exit code was not 0 + * 500 Internal Server Error: Transformer version check failed to create any output + * 500 Internal Server Error: Could not read the target file + * 500 Internal Server Error: The target filename was malformed (should not happen because of other checks) + * 500 Internal Server Error: Transformer failed to create an output file (the exit code was 0, so there should be some content) + * 500 Internal Server Error: Filename encoding error + * 507 Insufficient Storage: Failed to store the source file + */ +@Controller +public class TransformerController extends AbstractTransformerController { + + private final Logger logger = LoggerFactory.getLogger(TransformerController.class); + private final Pattern fileext = Pattern.compile("\\.([^\\.]+)$"); + + @Autowired + private TransformerImpl transformer; + + @Value("${transform.alfmarkdown.version}") + private String version; + + private ProbeTestTransform probe; + + @Override + public String getTransformerName() { + return "alfmarkdown"; + } + + @Override + public String version() { + return this.version; + } + + @PostConstruct + public void initProbe() { + this.probe = new ProbeTestTransform(this, "quick.src", "quick.trgt", + 7455L, 1024L, 150, 10240L, 60L * 20L + 1L, 60L * 15L - 15L) { + @Override + protected void executeTransformCommand(File sourceFile, File targetFile) { + if (logger.isTraceEnabled()) + logger.trace("getProbeTestTransform().executeTransformCommand('" + sourceFile + "', '" + targetFile + "')"); + // TODO test a transformation + } + }; + } + + @Override + public ProbeTestTransform getProbeTestTransform() { + if (this.logger.isTraceEnabled()) + this.logger.trace("getProbeTestTransform()"); + return this.probe; + } + + @Override + protected String getTransformerName(final File sourceFile, final String sourceMimetype, final String targetMimetype, final Map transformOptions) { + if (this.logger.isTraceEnabled()) + this.logger.trace("getTransformerName('" + sourceFile + "', '" + sourceMimetype + "', '" + targetMimetype + "', " + transformOptions + ")"); + // does not matter what value is returned, as it is not used because there is only one. + return this.getTransformerName(); + } + + @Override + public void transformImpl(String transformName, String sourceMimetype, String targetMimetype, Map transformOptions, File sourceFile, File targetFile) { + if (this.logger.isTraceEnabled()) + this.logger.trace("transformImpl('" + transformName + "', '" + sourceMimetype + "', '" + targetMimetype + "', " + transformOptions.keySet() + ", '" + sourceFile + "', '" + targetFile + "')"); + + if (sourceMimetype == null) { + Matcher matcher = this.fileext.matcher(sourceFile.getAbsolutePath()); + sourceMimetype = matcher.find() ? this.ext2mime(matcher.group(1)) : null; + } + if (targetMimetype == null) { + Matcher matcher = this.fileext.matcher(targetFile.getAbsolutePath()); + targetMimetype = matcher.find() ? this.ext2mime(matcher.group(1)) : MediaType.TEXT_PLAIN_VALUE; + } + + this.transformer.transform(transformName, sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile); + } + + private String ext2mime(String ext) { + switch (ext.toLowerCase()) { + // add applicable extensions here + case "text": + case "txt": return MediaType.TEXT_PLAIN_VALUE; + default: return null; + } + } +} diff --git a/tengine/src/main/java/com/inteligr8/alfresco/module/alfmarkdown/TransformerImpl.java b/tengine/src/main/java/com/inteligr8/alfresco/module/alfmarkdown/TransformerImpl.java new file mode 100644 index 0000000..745b411 --- /dev/null +++ b/tengine/src/main/java/com/inteligr8/alfresco/module/alfmarkdown/TransformerImpl.java @@ -0,0 +1,45 @@ +package com.inteligr8.alfresco.module.alfmarkdown; + +import java.io.File; +import java.util.Map; + +import javax.annotation.PostConstruct; + +import org.alfresco.transformer.executors.Transformer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class TransformerImpl implements Transformer { + + private final Logger logger = LoggerFactory.getLogger(TransformerImpl.class); + private final String id = "alfmarkdown"; + + @PostConstruct + public void init() throws Exception { + if (this.logger.isDebugEnabled()) + this.logger.debug("init()"); + } + + @Override + public String getTransformerId() { + return this.id; + } + + @Override + public void extractMetadata(String transformName, String sourceMimetype, String targetMimetype, Map transformOptions, File sourceFile, File targetFile) { + if (this.logger.isTraceEnabled()) + this.logger.trace("extractMetadata('" + transformName + "', '" + sourceMimetype + "', '" + targetMimetype + "', " + transformOptions.keySet() + ", '" + sourceFile + "', '" + targetFile + "')"); + this.transform(transformName, sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile); + } + + @Override + public void transform(String transformName, String sourceMimetype, String targetMimetype, Map transformOptions, File sourceFile, File targetFile) { + if (this.logger.isTraceEnabled()) + this.logger.trace("transform('" + transformName + "', '" + sourceMimetype + "', '" + targetMimetype + "', " + transformOptions.keySet() + ", '" + sourceFile + "', '" + targetFile + "')"); + + // TODO implement your transformation logic here + } + +} diff --git a/tengine/src/main/resources/application-context.xml b/tengine/src/main/resources/application-context.xml new file mode 100644 index 0000000..065e12d --- /dev/null +++ b/tengine/src/main/resources/application-context.xml @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/tengine/src/main/resources/application-default.yaml b/tengine/src/main/resources/application-default.yaml new file mode 100644 index 0000000..a801cc7 --- /dev/null +++ b/tengine/src/main/resources/application-default.yaml @@ -0,0 +1,13 @@ +queue: + engineRequestQueue: ${TRANSFORM_ENGINE_REQUEST_QUEUE:com.inteligr8.alfresco.module.alfmarkdown.acs} + +transform: + core: + config: + location: classpath:this_engine_config.json + alfmarkdown: + version: ${project.version} + +logging: + level: + com.inteligr8.alfresco.module: ${LOG_LEVEL:info} diff --git a/tengine/src/main/resources/templates/transformForm.html b/tengine/src/main/resources/templates/transformForm.html new file mode 100644 index 0000000..e3eea98 --- /dev/null +++ b/tengine/src/main/resources/templates/transformForm.html @@ -0,0 +1,21 @@ + + + +
+

alfmarkdown Test Transformation

+
+ + + + + +
file *
targetExtension *
+
+
+ + + + + diff --git a/tengine/src/main/resources/this_engine_config.json b/tengine/src/main/resources/this_engine_config.json new file mode 100644 index 0000000..d46a4b5 --- /dev/null +++ b/tengine/src/main/resources/this_engine_config.json @@ -0,0 +1,18 @@ +{ + "transformOptions": { + "alfmarkdownOptions": [ + // {"value": {"name": "profile"}}, + ] + }, + "transformers": [ + { + "transformerName": "alfmarkdown", + "supportedSourceAndTargetList": [ + // {"sourceMediaType": "text/plain", "priority": 10, "targetMediaType": "text/plain" } + ], + "transformOptions": [ + "alfmarkdownOptions" + ] + } + ] +} diff --git a/tengine/src/test/java/com/inteligr8/alfresco/module/alfmarkdown/HttpRequestIT.java b/tengine/src/test/java/com/inteligr8/alfresco/module/alfmarkdown/HttpRequestIT.java new file mode 100644 index 0000000..6287a60 --- /dev/null +++ b/tengine/src/test/java/com/inteligr8/alfresco/module/alfmarkdown/HttpRequestIT.java @@ -0,0 +1,174 @@ +/* + * #%L + * Alfresco Transform Core + * %% + * Copyright (C) 2005 - 2019 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * - + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * - + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package com.inteligr8.alfresco.module.alfmarkdown; + +import java.util.HashSet; +import java.util.Set; + +import javax.annotation.PostConstruct; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import org.junit.Assert; +import org.junit.Test; +import org.junit.Ignore; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.core.io.ClassPathResource; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.web.client.HttpStatusCodeException; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class HttpRequestIT { + + private final Logger logger = LoggerFactory.getLogger(HttpRequestIT.class); + + @LocalServerPort + private int port; + + @Autowired + private TestRestTemplate restTemplate; + + protected String baseUrl; + + @PostConstruct + public void init() { + this.baseUrl = "http://localhost:" + this.port; + } + + @Test + public void testRootPath() { + String result = this.restTemplate.getForObject(this.baseUrl, String.class); + if (this.logger.isDebugEnabled()) + this.logger.debug("testRootPath(): result: " + result); + + Assert.assertNotNull("A result from the HTTP GET was expected", result); + Document htmldoc = Jsoup.parse(result); + Assert.assertNotNull("An HTML compliant result was expected: " + result.substring(0, 50), htmldoc); + + Elements elements = htmldoc.select("html body h2"); + Assert.assertFalse("The HTML body is expected to have an h2 element: html: " + htmldoc.toString(), elements.isEmpty()); + Assert.assertEquals("The HTML body is expected to have just one h2 element", 1, elements.size()); + Assert.assertEquals("The HTML body header is not what was expected", "alfmarkdown Test Transformation", elements.html()); + + elements = htmldoc.select("html input"); + Set inputs = new HashSet(); + for (Element element : elements) + inputs.add(element.attr("name")); + Assert.assertTrue("The HTML is expected to have a form input for 'file': " + inputs.toString(), inputs.contains("file")); + Assert.assertTrue("The HTML is expected to have a form input for 'targetExtension': " + inputs.toString(), inputs.contains("targetExtension")); + } + + @Test + public void testLogPath() { + String result = this.restTemplate.getForObject(this.baseUrl + "/log", String.class); + if (this.logger.isDebugEnabled()) + this.logger.debug("testLogPath(): result: " + result); + + Assert.assertNotNull("A result from the HTTP GET was expected", result); + Document htmldoc = Jsoup.parse(result); + Assert.assertNotNull("An HTML compliant result was expected: " + result.substring(0, 50), htmldoc); + + Elements elements = htmldoc.select("html body div h2"); + Assert.assertFalse("The HTML is expected to have an html/body/div/h2 element: html: " + htmldoc.select("html").toString(), elements.isEmpty()); + Assert.assertEquals("The HTML is expected to have just one html/body/div/h2 element", 1, elements.size()); + Assert.assertEquals("The HTML body header is not what was expected", "alfmarkdown Log Entries", elements.html()); + } + + @Test + public void testNoPath() { + try { + ResponseEntity response = this.restTemplate.getForEntity(this.baseUrl + "/doesnotexist", String.class); + Assert.assertEquals("An unexpected path must return a 404 error", 404, response.getStatusCodeValue()); + } catch (HttpStatusCodeException hsce) { + Assert.assertEquals("An unexpected path must return a 404 error", 404, hsce.getRawStatusCode()); + } + } + + @Test + public void testServiceGet() { + try { + ResponseEntity response = this.restTemplate.getForEntity(this.baseUrl + "/transform", String.class); + Assert.assertEquals("An unexpected path must return a 405 error", 405, response.getStatusCodeValue()); + } catch (HttpStatusCodeException hsce) { + Assert.assertEquals("An unexpected path must return a 405 error", 405, hsce.getRawStatusCode()); + } + } + + @Test + public void testServiceNoFile() { + try { + ResponseEntity response = this._testService(null, "trgt"); + Assert.assertEquals("An unexpected path must return a 400 error", 400, response.getStatusCodeValue()); + } catch (HttpStatusCodeException hsce) { + Assert.assertEquals("An unexpected path must return a 400 error", 400, hsce.getRawStatusCode()); + } + } + + @Test @Ignore + public void testServiceNoTargetExtension() { + try { + ResponseEntity response = this._testService("quick.src", null); + Assert.assertEquals("An unexpected path must return a 400 error", 400, response.getStatusCodeValue()); + } catch (HttpStatusCodeException hsce) { + Assert.assertEquals("An unexpected path must return a 400 error", 400, hsce.getRawStatusCode()); + } + } + + @Test @Ignore + public void testServiceQuick() { + this._testService("quick.src", "trgt"); + } + + protected ResponseEntity _testService(String filename, String targetExtension) { + LinkedMultiValueMap parameters = new LinkedMultiValueMap<>(); + if (filename != null) + parameters.add("file", new ClassPathResource(filename)); + if (targetExtension != null) + parameters.add("targetExtension", targetExtension); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + HttpEntity> entity = new HttpEntity<>(parameters, headers); + return this.restTemplate.postForEntity(this.baseUrl + "/transform", entity, String.class); + } + +} diff --git a/tengine/src/test/java/com/inteligr8/alfresco/module/alfmarkdown/TransformerControllerTest.java b/tengine/src/test/java/com/inteligr8/alfresco/module/alfmarkdown/TransformerControllerTest.java new file mode 100644 index 0000000..cd82991 --- /dev/null +++ b/tengine/src/test/java/com/inteligr8/alfresco/module/alfmarkdown/TransformerControllerTest.java @@ -0,0 +1,22 @@ +package com.inteligr8.alfresco.module.alfmarkdown; + +import org.alfresco.transformer.AbstractTransformerController; +import org.junit.Ignore; +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.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@WebMvcTest(controllers = TransformerController.class) +public class TransformerControllerTest { + + @Autowired + protected AbstractTransformerController controller; + + @Test @Ignore + public void test() { + + } +} diff --git a/tengine/src/test/resources/application-default.yaml b/tengine/src/test/resources/application-default.yaml new file mode 100644 index 0000000..5210440 --- /dev/null +++ b/tengine/src/test/resources/application-default.yaml @@ -0,0 +1,13 @@ +queue: + engineRequestQueue: ${TRANSFORM_ENGINE_REQUEST_QUEUE:com.inteligr8.alfresco.module.alfmarkdown.acs} + +transform: + core: + config: + location: classpath:this_engine_config.json + alfmarkdown: + version: ${project.version} + +logging: + level: + com.inteligr8.alfresco.module: ${LOG_LEVEL:trace}