mirror of
https://github.com/Alfresco/alfresco-transform-core.git
synced 2025-08-14 17:58:27 +00:00
Add files to transformConfigSources
This commit is contained in:
@@ -26,19 +26,25 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.transform.base.registry;
|
package org.alfresco.transform.base.registry;
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
public abstract class AbstractTransformConfigSource implements TransformConfigSource
|
public abstract class AbstractTransformConfigSource implements TransformConfigSource
|
||||||
{
|
{
|
||||||
|
private final String sortOnName;
|
||||||
private final String readFrom;
|
private final String readFrom;
|
||||||
private final String baseUrl;
|
private final String baseUrl;
|
||||||
|
|
||||||
public AbstractTransformConfigSource(String readFrom, String baseUrl)
|
public AbstractTransformConfigSource(String sortOnName, String readFrom, String baseUrl)
|
||||||
{
|
{
|
||||||
|
this.sortOnName = sortOnName;
|
||||||
this.readFrom = readFrom;
|
this.readFrom = readFrom;
|
||||||
this.baseUrl = baseUrl == null ? "---" : baseUrl;
|
this.baseUrl = baseUrl == null ? "---" : baseUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSortOnName()
|
||||||
|
{
|
||||||
|
return sortOnName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getReadFrom()
|
public String getReadFrom()
|
||||||
{
|
{
|
||||||
|
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Transform Core
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2022 - 2022 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
* -
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
* -
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.transform.base.registry;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "transform")
|
||||||
|
public class AdditionalTransformConfigResources
|
||||||
|
{
|
||||||
|
// Populated with file paths from Spring Boot properties such as transform.config.<engineName> or
|
||||||
|
// environment variables like TRANSFORM_CONFIG_<engineName>.
|
||||||
|
private final Map<String, String> config = new HashMap<>();
|
||||||
|
|
||||||
|
public List<Resource> retrieveResources()
|
||||||
|
{
|
||||||
|
return TransformConfigFromFiles.retrieveResources(config);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Transform Core
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2022 - 2022 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
* -
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
* -
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.transform.base.registry;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.alfresco.transform.base.registry.TransformConfigFromFiles.retrieveResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to {@link AdditionalTransformConfigResources} but uses the names historically used by the t-router.
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "transformer.routes")
|
||||||
|
public class AdditionalTransformConfigResourcesHistoric
|
||||||
|
{
|
||||||
|
// Populated with file paths from Spring Boot properties such as transformer.routes.additional.<engineName> or
|
||||||
|
// environment variables like TRANSFORMER_ROUTES_ADDITIONAL_<engineName>.
|
||||||
|
private final Map<String, String> additional = new HashMap<>();
|
||||||
|
|
||||||
|
private String TRANSFORMER_ROUTES_FROM_CLASSPATH = "transformer-pipelines.json";
|
||||||
|
|
||||||
|
@Value("${transformer-routes-path}")
|
||||||
|
private String transformerRoutesExternalFile;
|
||||||
|
|
||||||
|
public List<Resource> retrieveResources()
|
||||||
|
{
|
||||||
|
ArrayList<Resource> resources = new ArrayList<>();
|
||||||
|
addStandardConfigIfItExists(resources);
|
||||||
|
resources.addAll(TransformConfigFromFiles.retrieveResources(additional));
|
||||||
|
return resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addStandardConfigIfItExists(ArrayList<Resource> resources)
|
||||||
|
{
|
||||||
|
Resource resource = null;
|
||||||
|
if (transformerRoutesExternalFile != null && !transformerRoutesExternalFile.isBlank())
|
||||||
|
{
|
||||||
|
resource = retrieveResource(transformerRoutesExternalFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resource == null || !resource.exists())
|
||||||
|
{
|
||||||
|
resource = new ClassPathResource(TRANSFORMER_ROUTES_FROM_CLASSPATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resource.exists())
|
||||||
|
{
|
||||||
|
resources.add(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Transform Core
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2022 - 2022 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
* -
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
* -
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.transform.base.registry;
|
||||||
|
|
||||||
|
import org.alfresco.transform.common.TransformConfigResourceReader;
|
||||||
|
import org.alfresco.transform.config.TransformConfig;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.core.io.FileSystemResource;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes {@link TransformConfig} from files on the classpath or externally available to the {@link TransformRegistry}.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class TransformConfigFromFiles
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private List<TransformConfigSource> transformConfigSources;
|
||||||
|
@Autowired
|
||||||
|
private AdditionalTransformConfigResources additionalTransformConfigResources;
|
||||||
|
@Autowired
|
||||||
|
private AdditionalTransformConfigResourcesHistoric additionalTransformConfigResourcesHistoric;
|
||||||
|
@Autowired
|
||||||
|
private TransformConfigResourceReader transformConfigResourceReader;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void initFileConfig()
|
||||||
|
{
|
||||||
|
final List<Resource> resources = new ArrayList<>();
|
||||||
|
resources.addAll(additionalTransformConfigResources.retrieveResources());
|
||||||
|
resources.addAll(additionalTransformConfigResourcesHistoric.retrieveResources());
|
||||||
|
resources.forEach(resource ->
|
||||||
|
{
|
||||||
|
String filename = resource.getFilename();
|
||||||
|
transformConfigSources.add(
|
||||||
|
new AbstractTransformConfigSource(filename, "Additional config "+filename,null)
|
||||||
|
{
|
||||||
|
@Override public TransformConfig getTransformConfig()
|
||||||
|
{
|
||||||
|
return transformConfigResourceReader.read(resource);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Resource> retrieveResources(Map<String, String> additional)
|
||||||
|
{
|
||||||
|
return additional
|
||||||
|
.values()
|
||||||
|
.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(String::trim)
|
||||||
|
.filter(s -> !s.isBlank())
|
||||||
|
.map(TransformConfigFromFiles::retrieveResource)
|
||||||
|
.collect(toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Resource retrieveResource(final String filename)
|
||||||
|
{
|
||||||
|
final Resource resource = new FileSystemResource(filename);
|
||||||
|
if (resource.exists())
|
||||||
|
{
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
return new ClassPathResource(filename);
|
||||||
|
}
|
||||||
|
}
|
@@ -34,6 +34,9 @@ import org.springframework.stereotype.Component;
|
|||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes {@link TransformConfig} from {@link TransformEngine}s available to the {@link TransformRegistry}.
|
||||||
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class TransformConfigFromTransformEngines
|
public class TransformConfigFromTransformEngines
|
||||||
{
|
{
|
||||||
@@ -43,7 +46,7 @@ public class TransformConfigFromTransformEngines
|
|||||||
private List<TransformConfigSource> transformConfigSources;
|
private List<TransformConfigSource> transformConfigSources;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
private void fromTransformEngineConfig()
|
public void initTransformEngineConfig()
|
||||||
{
|
{
|
||||||
if (transformEngines != null)
|
if (transformEngines != null)
|
||||||
{
|
{
|
||||||
@@ -52,8 +55,9 @@ public class TransformConfigFromTransformEngines
|
|||||||
TransformConfig transformConfig = transformEngine.getTransformConfig();
|
TransformConfig transformConfig = transformEngine.getTransformConfig();
|
||||||
if (transformConfig != null) // if not a wrapping TransformEngine like all-in-one
|
if (transformConfig != null) // if not a wrapping TransformEngine like all-in-one
|
||||||
{
|
{
|
||||||
|
String engineName = transformEngine.getTransformEngineName();
|
||||||
transformConfigSources.add(
|
transformConfigSources.add(
|
||||||
new AbstractTransformConfigSource(transformEngine.getTransformEngineName(),null)
|
new AbstractTransformConfigSource(engineName, engineName,null)
|
||||||
{
|
{
|
||||||
@Override public TransformConfig getTransformConfig()
|
@Override public TransformConfig getTransformConfig()
|
||||||
{
|
{
|
||||||
|
@@ -4,6 +4,8 @@ import org.alfresco.transform.config.TransformConfig;
|
|||||||
|
|
||||||
public interface TransformConfigSource
|
public interface TransformConfigSource
|
||||||
{
|
{
|
||||||
|
String getSortOnName();
|
||||||
|
|
||||||
String getReadFrom();
|
String getReadFrom();
|
||||||
|
|
||||||
String getBaseUrl();
|
String getBaseUrl();
|
||||||
|
@@ -34,14 +34,38 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.event.ContextRefreshedEvent;
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
import org.springframework.context.event.EventListener;
|
import org.springframework.context.event.EventListener;
|
||||||
|
import org.springframework.retry.annotation.Backoff;
|
||||||
|
import org.springframework.retry.annotation.Recover;
|
||||||
|
import org.springframework.retry.annotation.Retryable;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import static org.alfresco.transform.config.CoreVersionDecorator.setCoreVersionOnSingleStepTransformers;
|
import static org.alfresco.transform.config.CoreVersionDecorator.setCoreVersionOnSingleStepTransformers;
|
||||||
|
|
||||||
public class TransformRegistry extends AbstractTransformRegistry
|
public class TransformRegistry extends AbstractTransformRegistry
|
||||||
{
|
{
|
||||||
|
private static class Data extends TransformCache
|
||||||
|
{
|
||||||
|
private TransformConfig transformConfigBeforeIncompleteTransformsAreRemoved;
|
||||||
|
|
||||||
|
public TransformConfig getTransformConfigBeforeIncompleteTransformsAreRemoved()
|
||||||
|
{
|
||||||
|
return transformConfigBeforeIncompleteTransformsAreRemoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransformConfigBeforeIncompleteTransformsAreRemoved(
|
||||||
|
TransformConfig transformConfigBeforeIncompleteTransformsAreRemoved)
|
||||||
|
{
|
||||||
|
this.transformConfigBeforeIncompleteTransformsAreRemoved = transformConfigBeforeIncompleteTransformsAreRemoved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(TransformRegistry.class);
|
private static final Logger log = LoggerFactory.getLogger(TransformRegistry.class);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@@ -49,19 +73,56 @@ public class TransformRegistry extends AbstractTransformRegistry
|
|||||||
@Autowired
|
@Autowired
|
||||||
private List<TransformConfigSource> transformConfigSources;
|
private List<TransformConfigSource> transformConfigSources;
|
||||||
|
|
||||||
private TransformConfig transformConfigBeforeIncompleteTransformsAreRemoved;
|
// Ensures that read operations are blocked while config is being updated
|
||||||
|
private ReadWriteLock configRefreshLock = new ReentrantReadWriteLock();
|
||||||
|
|
||||||
|
private Data data = new Data();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the registry on application startup. This allows Components in projects that extend the t-engine base
|
* Load the registry on application startup. This allows Components in projects that extend the t-engine base
|
||||||
* to use @PostConstruct to add to {@code transformConfigSources}, before the registry is loaded.
|
* to use @PostConstruct to add to {@code transformConfigSources}, before the registry is loaded.
|
||||||
*/
|
*/
|
||||||
@EventListener
|
@EventListener
|
||||||
void init(final ContextRefreshedEvent event)
|
private void initRegistryOnAppStartup(final ContextRefreshedEvent event)
|
||||||
|
{
|
||||||
|
asyncRegistryInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Async
|
||||||
|
// @Retryable(include = {IllegalStateException.class},
|
||||||
|
// maxAttemptsExpression = "#{${transform.engine.config.retry.attempts}}",
|
||||||
|
// backoff = @Backoff(delayExpression = "#{${transform.engine.config.retry.timeout} * 1000}"))
|
||||||
|
public void asyncRegistryInit()
|
||||||
|
{
|
||||||
|
initRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recovery method in case all the retries fail. If not specified, the @Retryable method will cause the application
|
||||||
|
* to stop.
|
||||||
|
*/
|
||||||
|
// @Recover
|
||||||
|
private void recover(IllegalStateException e)
|
||||||
|
{
|
||||||
|
log.warn(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes the schedule from a spring-boot property
|
||||||
|
*/
|
||||||
|
// @Scheduled(cron = "${transformer.engine.config.cron}")
|
||||||
|
public void retrieveEngineConfigs()
|
||||||
|
{
|
||||||
|
log.trace("Refresh TransformRegistry");
|
||||||
|
initRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
void initRegistry()
|
||||||
{
|
{
|
||||||
CombinedTransformConfig combinedTransformConfig = new CombinedTransformConfig();
|
CombinedTransformConfig combinedTransformConfig = new CombinedTransformConfig();
|
||||||
|
|
||||||
transformConfigSources.stream()
|
transformConfigSources.stream()
|
||||||
.sorted(Comparator.comparing(TransformConfigSource::getReadFrom))
|
.sorted(Comparator.comparing(TransformConfigSource::getSortOnName))
|
||||||
.forEach(source -> {
|
.forEach(source -> {
|
||||||
TransformConfig transformConfig = source.getTransformConfig();
|
TransformConfig transformConfig = source.getTransformConfig();
|
||||||
setCoreVersionOnSingleStepTransformers(transformConfig, coreVersion);
|
setCoreVersionOnSingleStepTransformers(transformConfig, coreVersion);
|
||||||
@@ -69,22 +130,53 @@ public class TransformRegistry extends AbstractTransformRegistry
|
|||||||
this);
|
this);
|
||||||
});
|
});
|
||||||
|
|
||||||
transformConfigBeforeIncompleteTransformsAreRemoved = combinedTransformConfig.buildTransformConfig();
|
TransformConfig transformConfigBeforeIncompleteTransformsAreRemoved = combinedTransformConfig.buildTransformConfig();
|
||||||
combinedTransformConfig.combineTransformerConfig(this);
|
combinedTransformConfig.combineTransformerConfig(this);
|
||||||
combinedTransformConfig.registerCombinedTransformers(this);
|
concurrentUpdate(combinedTransformConfig, transformConfigBeforeIncompleteTransformsAreRemoved);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransformCache data = new TransformCache();
|
|
||||||
|
|
||||||
public TransformConfig getTransformConfig()
|
public TransformConfig getTransformConfig()
|
||||||
{
|
{
|
||||||
return transformConfigBeforeIncompleteTransformsAreRemoved;
|
return getData().getTransformConfigBeforeIncompleteTransformsAreRemoved();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TransformCache getData()
|
public Data getData()
|
||||||
{
|
{
|
||||||
return data;
|
return concurrentRead(() -> data );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock for reads while updating, use {@link #concurrentRead} to access locked fields
|
||||||
|
*/
|
||||||
|
private void concurrentUpdate(CombinedTransformConfig combinedTransformConfig,
|
||||||
|
TransformConfig transformConfigBeforeIncompleteTransformsAreRemoved)
|
||||||
|
{
|
||||||
|
configRefreshLock.writeLock().lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data = new Data(); // clear data
|
||||||
|
data.setTransformConfigBeforeIncompleteTransformsAreRemoved(transformConfigBeforeIncompleteTransformsAreRemoved);
|
||||||
|
combinedTransformConfig.registerCombinedTransformers(this);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
configRefreshLock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T concurrentRead(Supplier<T> s)
|
||||||
|
{
|
||||||
|
configRefreshLock.readLock().lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return s.get();
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
configRefreshLock.readLock().unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -25,6 +25,15 @@ server:
|
|||||||
transform:
|
transform:
|
||||||
core:
|
core:
|
||||||
version: @project.version@
|
version: @project.version@
|
||||||
|
engine:
|
||||||
|
config:
|
||||||
|
cron: 0 0 * * * * # once an hour on the hour
|
||||||
|
retry:
|
||||||
|
attempts: 10
|
||||||
|
timeout: 10 # seconds
|
||||||
|
|
||||||
|
# Historic values (AVOID) - Exist to help with transition to newer versions
|
||||||
|
transformer-routes-path: ${TRANSFORMER_ROUTES_FILE_LOCATION:transformer-pipelines.json}
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
level:
|
level:
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Transform Core
|
* Alfresco Transform Core
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
* Copyright (C) 2022 - 2022 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* -
|
* -
|
||||||
|
@@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Transform Core
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2022 - 2022 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
* -
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
* -
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.transform.base.registry;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import org.alfresco.transform.base.fakes.FakeTransformEngineWithAllInOne;
|
||||||
|
import org.alfresco.transform.base.fakes.FakeTransformEngineWithOneCustomTransformer;
|
||||||
|
import org.alfresco.transform.base.fakes.FakeTransformEngineWithTwoCustomTransformers;
|
||||||
|
import org.alfresco.transform.config.TransformConfig;
|
||||||
|
import org.alfresco.transform.config.Transformer;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
@AutoConfigureMockMvc
|
||||||
|
@SpringBootTest(classes={org.alfresco.transform.base.Application.class})
|
||||||
|
public class TransformRegistryTest
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private TransformRegistry transformRegistry;
|
||||||
|
@Autowired
|
||||||
|
private List<TransformConfigSource> transformConfigSources;
|
||||||
|
@Autowired
|
||||||
|
private TransformConfigFromTransformEngines transformConfigFromTransformEngines;
|
||||||
|
@Autowired
|
||||||
|
private TransformConfigFromFiles transformConfigFromFiles;
|
||||||
|
@Autowired
|
||||||
|
private AdditionalTransformConfigResources additionalTransformConfigResources;
|
||||||
|
@Autowired
|
||||||
|
private AdditionalTransformConfigResourcesHistoric additionalTransformConfigResourcesHistoric;
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
private void after()
|
||||||
|
{
|
||||||
|
transformConfigSources.clear();
|
||||||
|
ReflectionTestUtils.setField(transformConfigFromTransformEngines, "transformEngines", Collections.emptyList());
|
||||||
|
ReflectionTestUtils.setField(additionalTransformConfigResources, "config", Collections.emptyMap());
|
||||||
|
ReflectionTestUtils.setField(additionalTransformConfigResourcesHistoric, "additional", Collections.emptyMap());
|
||||||
|
transformRegistry.initRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTransformerNames(TransformConfig transformConfig)
|
||||||
|
{
|
||||||
|
return transformConfig.getTransformers().stream()
|
||||||
|
.map(Transformer::getTransformerName)
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.joining(", "));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noConfig()
|
||||||
|
{
|
||||||
|
assertEquals("", getTransformerNames(transformRegistry.getTransformConfig()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void singleTransformEngine()
|
||||||
|
{
|
||||||
|
ReflectionTestUtils.setField(transformConfigFromTransformEngines, "transformEngines", ImmutableList.of(
|
||||||
|
new FakeTransformEngineWithOneCustomTransformer()));
|
||||||
|
transformConfigFromTransformEngines.initTransformEngineConfig();
|
||||||
|
transformRegistry.initRegistry();
|
||||||
|
|
||||||
|
assertEquals("Pdf2Jpg", getTransformerNames(transformRegistry.getTransformConfig()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multipleTransformEngines()
|
||||||
|
{
|
||||||
|
ReflectionTestUtils.setField(transformConfigFromTransformEngines, "transformEngines", ImmutableList.of(
|
||||||
|
new FakeTransformEngineWithAllInOne(),
|
||||||
|
new FakeTransformEngineWithOneCustomTransformer(),
|
||||||
|
new FakeTransformEngineWithTwoCustomTransformers()));
|
||||||
|
transformConfigFromTransformEngines.initTransformEngineConfig();
|
||||||
|
transformRegistry.initRegistry();
|
||||||
|
|
||||||
|
assertEquals("Pdf2Jpg, Pdf2Png, TxT2Pdf, Txt2JpgViaPdf, Txt2PngViaPdf",
|
||||||
|
getTransformerNames(transformRegistry.getTransformConfig()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void singleTransformEngineWithAdditionalConfig()
|
||||||
|
{
|
||||||
|
ReflectionTestUtils.setField(transformConfigFromTransformEngines, "transformEngines", ImmutableList.of(
|
||||||
|
new FakeTransformEngineWithOneCustomTransformer()));
|
||||||
|
ReflectionTestUtils.setField(additionalTransformConfigResources, "config", ImmutableMap.of(
|
||||||
|
"a", "config/addA2B.json",
|
||||||
|
"foo", "config/addB2C.json"));
|
||||||
|
|
||||||
|
transformConfigFromTransformEngines.initTransformEngineConfig();
|
||||||
|
transformConfigFromFiles.initFileConfig();
|
||||||
|
transformRegistry.initRegistry();
|
||||||
|
|
||||||
|
assertEquals("A2B, B2C, Pdf2Jpg", getTransformerNames(transformRegistry.getTransformConfig()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void singleTransformEngineWithHistoricAdditionalRoutes()
|
||||||
|
{
|
||||||
|
ReflectionTestUtils.setField(transformConfigFromTransformEngines, "transformEngines", ImmutableList.of(
|
||||||
|
new FakeTransformEngineWithOneCustomTransformer()));
|
||||||
|
ReflectionTestUtils.setField(additionalTransformConfigResourcesHistoric, "additional", ImmutableMap.of(
|
||||||
|
"a", "config/addA2B.json",
|
||||||
|
"foo", "config/addB2C.json"));
|
||||||
|
|
||||||
|
transformConfigFromTransformEngines.initTransformEngineConfig();
|
||||||
|
transformConfigFromFiles.initFileConfig();
|
||||||
|
transformRegistry.initRegistry();
|
||||||
|
|
||||||
|
assertEquals("A2B, B2C, Pdf2Jpg", getTransformerNames(transformRegistry.getTransformConfig()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void singleTransformEngineWithHistoricTransformerRoutesExternalFile()
|
||||||
|
{
|
||||||
|
ReflectionTestUtils.setField(transformConfigFromTransformEngines, "transformEngines", ImmutableList.of(
|
||||||
|
new FakeTransformEngineWithOneCustomTransformer()));
|
||||||
|
ReflectionTestUtils.setField(additionalTransformConfigResourcesHistoric, "TRANSFORMER_ROUTES_FROM_CLASSPATH",
|
||||||
|
"config/removePdf2JpgAndAddA2Z.json"); // checking it is ignored
|
||||||
|
ReflectionTestUtils.setField(additionalTransformConfigResourcesHistoric, "transformerRoutesExternalFile",
|
||||||
|
"config/addA2B.json");
|
||||||
|
|
||||||
|
transformConfigFromTransformEngines.initTransformEngineConfig();
|
||||||
|
transformConfigFromFiles.initFileConfig();
|
||||||
|
transformRegistry.initRegistry();
|
||||||
|
|
||||||
|
assertEquals("A2B, Pdf2Jpg", getTransformerNames(transformRegistry.getTransformConfig()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void singleTransformEngineWithHistoricTransformerRoutesOnClasspath()
|
||||||
|
{
|
||||||
|
ReflectionTestUtils.setField(transformConfigFromTransformEngines, "transformEngines", ImmutableList.of(
|
||||||
|
new FakeTransformEngineWithOneCustomTransformer()));
|
||||||
|
ReflectionTestUtils.setField(additionalTransformConfigResourcesHistoric, "TRANSFORMER_ROUTES_FROM_CLASSPATH",
|
||||||
|
"config/removePdf2JpgAndAddA2Z.json");
|
||||||
|
|
||||||
|
transformConfigFromTransformEngines.initTransformEngineConfig();
|
||||||
|
transformConfigFromFiles.initFileConfig();
|
||||||
|
transformRegistry.initRegistry();
|
||||||
|
|
||||||
|
assertEquals("A2Z", getTransformerNames(transformRegistry.getTransformConfig()));
|
||||||
|
}
|
||||||
|
}
|
11
engines/base/src/test/resources/config/addA2B.json
Normal file
11
engines/base/src/test/resources/config/addA2B.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"transformers": [
|
||||||
|
{
|
||||||
|
"transformerName": "A2B",
|
||||||
|
"supportedSourceAndTargetList": [
|
||||||
|
{"sourceMediaType": "A", "targetMediaType": "B"}
|
||||||
|
],
|
||||||
|
"transformOptions": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
11
engines/base/src/test/resources/config/addB2C.json
Normal file
11
engines/base/src/test/resources/config/addB2C.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"transformers": [
|
||||||
|
{
|
||||||
|
"transformerName": "B2C",
|
||||||
|
"supportedSourceAndTargetList": [
|
||||||
|
{"sourceMediaType": "B", "targetMediaType": "C"}
|
||||||
|
],
|
||||||
|
"transformOptions": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"removeTransformers" : [
|
||||||
|
"Pdf2Jpg"
|
||||||
|
],
|
||||||
|
"transformers": [
|
||||||
|
{
|
||||||
|
"transformerName": "A2Z",
|
||||||
|
"supportedSourceAndTargetList": [
|
||||||
|
{"sourceMediaType": "A", "targetMediaType": "Z"}
|
||||||
|
],
|
||||||
|
"transformOptions": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@@ -70,6 +70,6 @@ public class LibreOfficeTransformEngine implements TransformEngine
|
|||||||
public ProbeTransform getProbeTransform()
|
public ProbeTransform getProbeTransform()
|
||||||
{
|
{
|
||||||
return new ProbeTransform("probe.doc", MIMETYPE_WORD, MIMETYPE_PDF, Collections.emptyMap(),
|
return new ProbeTransform("probe.doc", MIMETYPE_WORD, MIMETYPE_PDF, Collections.emptyMap(),
|
||||||
11817, 1024, 150, 10240, 60 * 30 + 1, 60 * 15 + 20);
|
9728, 1024, 150, 10240, 60 * 30 + 1, 60 * 15 + 20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -56,14 +56,19 @@ public class TransformConfigResourceReader
|
|||||||
public TransformConfig read(String engineConfigLocation)
|
public TransformConfig read(String engineConfigLocation)
|
||||||
{
|
{
|
||||||
Resource engineConfig = resourceLoader.getResource(engineConfigLocation);
|
Resource engineConfig = resourceLoader.getResource(engineConfigLocation);
|
||||||
try (Reader reader = new InputStreamReader(engineConfig.getInputStream(), UTF_8))
|
return read(engineConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransformConfig read(Resource resource)
|
||||||
|
{
|
||||||
|
try (Reader reader = new InputStreamReader(resource.getInputStream(), UTF_8))
|
||||||
{
|
{
|
||||||
TransformConfig transformConfig = jsonObjectMapper.readValue(reader, TransformConfig.class);
|
TransformConfig transformConfig = jsonObjectMapper.readValue(reader, TransformConfig.class);
|
||||||
return transformConfig;
|
return transformConfig;
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
throw new TransformException(INTERNAL_SERVER_ERROR, "Could not read " + engineConfigLocation, e);
|
throw new TransformException(INTERNAL_SERVER_ERROR, "Could not read " + resource.getFilename(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user