Move SFSUtil (SfsClient), JmsClient from t-router into t-engine base

This commit is contained in:
alandavis
2022-08-02 18:18:18 +01:00
parent 76486e4a83
commit 1255124300
16 changed files with 479 additions and 26 deletions

View File

@@ -79,6 +79,16 @@
<artifactId>logback-classic</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>

View File

@@ -27,7 +27,7 @@
package org.alfresco.transform.base;
import static java.text.MessageFormat.format;
import static org.alfresco.transform.base.EngineClient.sendTRequest;
import static org.alfresco.transform.base.clients.HttpClient.sendTRequest;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_METADATA_EXTRACT;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
@@ -43,6 +43,7 @@ import java.util.Map;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.alfresco.transform.base.clients.FileInfo;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;

View File

@@ -24,7 +24,7 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transform.base;
package org.alfresco.transform.base.clients;
/**
* @author Cezar Leahu

View File

@@ -5,7 +5,7 @@
* pursuant to a written agreement and any use of this program without such an
* agreement is prohibited.
*/
package org.alfresco.transform.base;
package org.alfresco.transform.base.clients;
import static java.util.Collections.emptyMap;
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM;
@@ -25,7 +25,7 @@ import org.springframework.web.client.RestTemplate;
/**
* @author Cezar Leahu
*/
public class EngineClient
public class HttpClient
{
private static final RestTemplate REST_TEMPLATE = new RestTemplate();

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2015-2022 Alfresco Software, Ltd. All rights reserved.
*
* License rights for this program may be obtained from Alfresco Software, Ltd.
* pursuant to a written agreement and any use of this program without such an
* agreement is prohibited.
*/
package org.alfresco.transform.base.clients;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonSerializer
{
private static final ObjectMapper MAPPER;
static
{
MAPPER = new ObjectMapper();
MAPPER.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MAPPER.setSerializationInclusion(Include.NON_NULL);
}
public static <T> byte[] serialize(T value) throws Exception
{
try (final ByteArrayOutputStream stream = new ByteArrayOutputStream(1024);
final OutputStreamWriter writer = new OutputStreamWriter(stream, UTF_8))
{
MAPPER.writer().writeValue(writer, value);
return stream.toByteArray();
}
}
public static <T> T deserialize(byte[] data, Class<T> cls) throws Exception
{
return MAPPER.readValue(data, cls);
}
public static <T> T deserialize(byte[] data, int len, Class<T> cls) throws Exception
{
return MAPPER.readValue(data, 0, len, cls);
}
public static String readStringValue(String json, String key) throws Exception
{
JsonNode node = MAPPER.readTree(json);
for (String k : key.split("\\."))
{
node = node.get(k);
}
return node.asText();
}
}

View File

@@ -0,0 +1,190 @@
/*
* Copyright 2015-2022 Alfresco Software, Ltd. All rights reserved.
*
* License rights for this program may be obtained from Alfresco Software, Ltd.
* pursuant to a written agreement and any use of this program without such an
* agreement is prohibited.
*/
package org.alfresco.transform.base.clients;
import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.alfresco.transform.client.model.TransformReply;
import org.alfresco.transform.client.model.TransformRequest;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
/**
* JMSClient
*
* Contains the bare minimum logic necessary for sending and receiving T-Request/Reply messages
* through the basic vanilla ActiveMQ client.
*
* Used by Aspose t-engine and t-router, but likely to be useful in other t-engines.
*
* @author Cezar Leahu
*/
public class JmsClient
{
private final ConnectionFactory factory;
private final ActiveMQQueue queue;
public JmsClient(final String server, final String queueName)
{
factory = new ActiveMQConnectionFactory(server);
queue = new ActiveMQQueue(queueName);
}
public ActiveMQQueue getDestination()
{
return queue;
}
private static void deleteQueues(final ConnectionFactory factory,
final ActiveMQQueue... queues) throws Exception
{
try (final Connection connection = factory.createConnection())
{
for (ActiveMQQueue q : queues)
{
// will fail if there are active subscribers
((ActiveMQConnection) connection).destroyDestination(q);
}
}
}
public void sendBytesMessage(final TransformRequest request)
throws Exception
{
sendBytesMessage(request, request.getRequestId());
}
public void sendBytesMessage(final TransformRequest request, final String correlationID)
throws Exception
{
sendBytesMessage(JacksonSerializer.serialize(request), correlationID);
}
public void sendBytesMessage(final TransformRequest request, final String correlationID,
final Destination replyTo) throws Exception
{
sendBytesMessage(JacksonSerializer.serialize(request), correlationID, replyTo);
}
public void sendBytesMessage(final byte[] data, final String correlationID) throws
Exception
{
try (final Connection connection = factory.createConnection();
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
final MessageProducer producer = session.createProducer(queue))
{
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
final BytesMessage message = session.createBytesMessage();
message.writeBytes(data);
if (correlationID != null)
{
message.setJMSCorrelationID(correlationID);
}
producer.send(message);
}
}
public void sendBytesMessage(final byte[] data, final String correlationID,
final Destination replyTo) throws Exception
{
try (final Connection connection = factory.createConnection();
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
final MessageProducer producer = session.createProducer(queue))
{
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
final BytesMessage message = session.createBytesMessage();
message.writeBytes(data);
if (correlationID != null)
{
message.setJMSCorrelationID(correlationID);
}
if (replyTo != null)
{
message.setJMSReplyTo(replyTo);
}
producer.send(message);
}
}
public void sendTextMessage(final TransformRequest request)
throws Exception
{
sendTextMessage(request, request.getRequestId());
}
public void sendTextMessage(final TransformRequest request, final String correlationID)
throws Exception
{
sendTextMessage(new String(JacksonSerializer.serialize(request)), correlationID);
}
public void sendTextMessage(final String data, final String correlationID) throws
Exception
{
try (final Connection connection = factory.createConnection();
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
final MessageProducer producer = session.createProducer(queue))
{
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
final TextMessage message = session.createTextMessage(data);
if (correlationID != null)
{
message.setJMSCorrelationID(correlationID);
}
producer.send(message);
}
}
public TransformReply receiveMessage() throws Exception
{
return receiveMessage(2 * 60 * 1000); // 2 m
}
public TransformReply receiveMessage(final long timeout)
throws Exception
{
try (final Connection connection = factory.createConnection();
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
final MessageConsumer consumer = session.createConsumer(queue))
{
connection.start();
final BytesMessage message = (BytesMessage) consumer.receive(timeout);
if (message == null)
{
throw new Exception("No reply was received for the multi-step transform request");
}
final byte[] data = new byte[2048];
int len = message.readBytes(data);
return JacksonSerializer.deserialize(data, len, TransformReply.class);
}
}
public void cleanQueue()
{
try
{
while (receiveMessage(2 * 1000) != null)
{
}
}
catch (Exception ignore)
{
}
}
}

View File

@@ -0,0 +1,181 @@
/*
* Copyright 2015-2022 Alfresco Software, Ltd. All rights reserved.
*
* License rights for this program may be obtained from Alfresco Software, Ltd.
* pursuant to a written agreement and any use of this program without such an
* agreement is prohibited.
*/
package org.alfresco.transform.base.clients;
import static java.text.MessageFormat.format;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableMap;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
/**
* Used by Aspose t-engine and t-router, but likely to be useful in other t-engines.
*
* @author Cezar Leahu
*/
public class SfsClient
{
static
{
((Logger) LoggerFactory.getLogger("org.apache.http.client.protocol")).setLevel(Level.INFO);
((Logger) LoggerFactory.getLogger("org.apache.http.impl.conn")).setLevel(Level.INFO);
((Logger) LoggerFactory.getLogger("org.apache.http.headers")).setLevel(Level.INFO);
((Logger) LoggerFactory.getLogger("org.apache.http.wire")).setLevel(Level.INFO);
((Logger) LoggerFactory.getLogger("org.apache.http.wire")).setAdditive(false);
}
private static final String SFS_BASE_URL = "http://localhost:8099";
public static String uploadFile(final String fileToUploadName) throws Exception
{
return uploadFile(fileToUploadName, SFS_BASE_URL);
}
public static String uploadFile(final String fileToUploadName, final String sfsBaseUrl) throws Exception
{
final File file = readFile(fileToUploadName);
final HttpPost post = new HttpPost(
sfsBaseUrl+"/alfresco/api/-default-/private/sfs/versions/1/file");
post.setEntity(MultipartEntityBuilder
.create()
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
.addPart("file", new FileBody(file, ContentType.DEFAULT_BINARY))
.build());
try (CloseableHttpClient client = HttpClients.createDefault())
{
final HttpResponse response = client.execute(post);
int status = response.getStatusLine().getStatusCode();
if (status >= 200 && status < 300)
{
return JacksonSerializer.readStringValue(EntityUtils.toString(response.getEntity()),
"entry.fileRef");
}
else
{
throw new Exception("Failed to upload source file to SFS");
}
}
}
private static File readFile(final String filename) throws Exception
{
final URL url = SfsClient.class.getClassLoader().getResource(filename);
if (url == null)
{
throw new Exception("Failed to load resource URL with filename " + filename);
}
final URI uri = url.toURI();
try
{
return Paths.get(uri).toFile();
}
catch (Exception e)
{
return readFileFromJar(uri);
}
}
private static File readFileFromJar(final URI uri) throws Exception
{
final String[] array = uri.toString().split("!");
try (final FileSystem fs = FileSystems.newFileSystem(URI.create(array[0]),
ImmutableMap.of("create", "true")))
{
File temp = File.createTempFile("temp-", "", new File(System.getProperty("user.dir")));
temp.deleteOnExit();
Files.copy(fs.getPath(array[1]), temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
temp.deleteOnExit();
return temp;
}
}
public static boolean checkFile(final String uuid) throws Exception
{
return checkFile(uuid, SFS_BASE_URL);
}
public static boolean checkFile(final String uuid, final String sfsBaseUrl) throws Exception
{
final HttpHead head = new HttpHead(format(
sfsBaseUrl+"/alfresco/api/-default-/private/sfs/versions/1/file/{0}",
uuid));
try (CloseableHttpClient client = HttpClients.createDefault())
{
final HttpResponse response = client.execute(head);
final int status = response.getStatusLine().getStatusCode();
return status >= 200 && status < 300;
}
}
public static File downloadFile(final String uuid) throws Exception
{
return downloadFile(uuid, SFS_BASE_URL);
}
public static File downloadFile(final String uuid, final String sfsBaseUrl) throws Exception
{
final HttpGet get = new HttpGet(format(
sfsBaseUrl+"/alfresco/api/-default-/private/sfs/versions/1/file/{0}",
uuid));
try (CloseableHttpClient client = HttpClients.createDefault())
{
final HttpResponse response = client.execute(get);
final int status = response.getStatusLine().getStatusCode();
if (status < 200 || status >= 300)
{
throw new Exception("File with UUID " + uuid + " was not found on SFS");
}
final HttpEntity entity = response.getEntity();
if (entity == null)
{
throw new Exception("Failed to read HTTP reply entity for file with UUID " + uuid);
}
final File file = File.createTempFile(uuid, "_tmp",
new File(System.getProperty("user.dir")));
file.deleteOnExit();
try (OutputStream os = new FileOutputStream(file))
{
entity.writeTo(os);
}
return file;
}
}
}

View File

@@ -24,7 +24,7 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transform.base;
package org.alfresco.transform.base.clients;
import java.util.Objects;

View File

@@ -30,8 +30,8 @@ import static java.text.MessageFormat.format;
import static java.util.Collections.emptyMap;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;
import static org.alfresco.transform.base.EngineClient.sendTRequest;
import static org.alfresco.transform.base.FileInfo.testFile;
import static org.alfresco.transform.base.clients.HttpClient.sendTRequest;
import static org.alfresco.transform.base.clients.FileInfo.testFile;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_APPLICATION_EPS;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_IMAGE_BMP;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_IMAGE_CGM;
@@ -76,7 +76,7 @@ import java.util.stream.Stream;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.alfresco.transform.base.FileInfo;
import org.alfresco.transform.base.clients.FileInfo;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

View File

@@ -29,8 +29,8 @@ package org.alfresco.transform.libreoffice;
import static java.text.MessageFormat.format;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;
import static org.alfresco.transform.base.EngineClient.sendTRequest;
import static org.alfresco.transform.base.FileInfo.testFile;
import static org.alfresco.transform.base.clients.HttpClient.sendTRequest;
import static org.alfresco.transform.base.clients.FileInfo.testFile;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_EXCEL;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_HTML;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_IMAGE_SVG;
@@ -71,7 +71,7 @@ import java.util.stream.Stream;
import com.google.common.collect.ImmutableSet;
import org.alfresco.transform.base.FileInfo;
import org.alfresco.transform.base.clients.FileInfo;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

View File

@@ -27,14 +27,12 @@
package org.alfresco.transform.misc;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_HTML;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_RFC822;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_XHTML;
import static org.alfresco.transform.base.FileInfo.testFile;
import static org.alfresco.transform.base.clients.FileInfo.testFile;
import java.util.stream.Stream;
import org.alfresco.transform.base.AbstractMetadataExtractsIT;
import org.alfresco.transform.base.FileInfo;
import org.alfresco.transform.base.clients.FileInfo;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

View File

@@ -26,8 +26,8 @@
*/
package org.alfresco.transform.misc;
import org.alfresco.transform.base.FileInfo;
import org.alfresco.transform.base.SourceTarget;
import org.alfresco.transform.base.clients.FileInfo;
import org.alfresco.transform.base.clients.SourceTarget;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.core.io.Resource;
@@ -39,8 +39,8 @@ import java.util.stream.Stream;
import static java.text.MessageFormat.format;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;
import static org.alfresco.transform.base.EngineClient.sendTRequest;
import static org.alfresco.transform.base.FileInfo.testFile;
import static org.alfresco.transform.base.clients.HttpClient.sendTRequest;
import static org.alfresco.transform.base.clients.FileInfo.testFile;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_DITA;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_EXCEL;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_HTML;

View File

@@ -29,8 +29,8 @@ package org.alfresco.transform.pdfrenderer;
import static java.text.MessageFormat.format;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;
import static org.alfresco.transform.base.EngineClient.sendTRequest;
import static org.alfresco.transform.base.FileInfo.testFile;
import static org.alfresco.transform.base.clients.HttpClient.sendTRequest;
import static org.alfresco.transform.base.clients.FileInfo.testFile;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import static org.springframework.http.HttpStatus.OK;
@@ -38,7 +38,7 @@ import static org.springframework.http.HttpStatus.OK;
import java.util.Map;
import java.util.stream.Stream;
import org.alfresco.transform.base.FileInfo;
import org.alfresco.transform.base.clients.FileInfo;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.slf4j.Logger;

View File

@@ -28,7 +28,7 @@ package org.alfresco.transform.tika;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_APP_DWG;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_OUTLOOK_MSG;
import static org.alfresco.transform.base.FileInfo.testFile;
import static org.alfresco.transform.base.clients.FileInfo.testFile;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_AUDIO_MP4;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_EXCEL;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_IMAGE_BMP;
@@ -75,7 +75,7 @@ import static org.alfresco.transform.common.Mimetype.MIMETYPE_IMAGE_RAW_NEF;
import java.util.stream.Stream;
import org.alfresco.transform.base.AbstractMetadataExtractsIT;
import org.alfresco.transform.base.FileInfo;
import org.alfresco.transform.base.clients.FileInfo;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

View File

@@ -27,7 +27,7 @@
package org.alfresco.transform.tika;
import com.google.common.collect.ImmutableMap;
import org.alfresco.transform.base.EngineClient;
import org.alfresco.transform.base.clients.HttpClient;
import org.apache.commons.lang3.tuple.Triple;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
@@ -77,7 +77,7 @@ public class TikaTransformationIT
sourceFile, sourceMimetype, targetMimetype, targetExtension);
try
{
final ResponseEntity<Resource> response = EngineClient.sendTRequest(ENGINE_URL, sourceFile, null,
final ResponseEntity<Resource> response = HttpClient.sendTRequest(ENGINE_URL, sourceFile, null,
targetMimetype, targetExtension, ImmutableMap.of(
"targetEncoding", "UTF-8",
"sourceMimetype", sourceMimetype));

10
pom.xml
View File

@@ -249,6 +249,16 @@
<artifactId>junit</artifactId>
<version>${dependency.junit.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.13</version>
</dependency>
</dependencies>
</dependencyManagement>