diff --git a/pom.xml b/pom.xml
index d063143540..e86bbf1e1b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -64,6 +64,7 @@
5.15.9
2.0.16
3.3.2
+ 2.9.9
@@ -545,6 +546,12 @@
1.1
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${dependency.jackson.version}
+
+
org.alfresco.surf
diff --git a/src/main/java/org/alfresco/repo/content/transform/LocalTransformServiceRegistry.java b/src/main/java/org/alfresco/repo/content/transform/LocalTransformServiceRegistry.java
index 94fa728a32..95b2dd7aff 100644
--- a/src/main/java/org/alfresco/repo/content/transform/LocalTransformServiceRegistry.java
+++ b/src/main/java/org/alfresco/repo/content/transform/LocalTransformServiceRegistry.java
@@ -62,7 +62,7 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl
private static final String URL = ".url";
static final String STRICT_MIMETYPE_CHECK_WHITELIST_MIMETYPES = "transformer.strict.mimetype.check.whitelist.mimetypes";
- class LocalData extends TransformServiceRegistryImpl.Data
+ public class LocalData extends TransformServiceRegistryImpl.Data
{
private Map localTransforms = new HashMap<>();
}
@@ -130,35 +130,40 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl
}
@Override
- protected Data readConfig() throws IOException
+ public boolean readConfig() throws IOException
{
- Data data = createData();
CombinedConfig combinedConfig = new CombinedConfig(getLog());
List urls = getTEngineUrls();
- boolean successReadingRemoteConfig = combinedConfig.addRemoteConfig(urls, "T-Engine");
- setSuccessReadingRemoteConfig(data, successReadingRemoteConfig);
- combinedConfig.addLocalConfig("alfresco/transformers");
- if (!pipelineConfigDir.isEmpty())
+ boolean successReadingConfig = combinedConfig.addRemoteConfig(urls, "T-Engine");
+ successReadingConfig &= combinedConfig.addLocalConfig("alfresco/transforms");
+ if (pipelineConfigDir != null && !pipelineConfigDir.isBlank())
{
- combinedConfig.addLocalConfig(pipelineConfigDir);
+ successReadingConfig &= combinedConfig.addLocalConfig(pipelineConfigDir);
}
- combinedConfig.register(data, this);
- return data;
+ combinedConfig.register(this);
+ return successReadingConfig;
}
@Override
- protected Data createData()
+ public synchronized LocalData getData()
+ {
+ return (LocalData)super.getData();
+ }
+
+ @Override
+ public Data createData()
{
return new LocalData();
}
@Override
- protected void register(Data data, Transformer transformer, String baseUrl, String readFrom)
+ protected void register(Transformer transformer, String baseUrl, String readFrom)
{
try
{
String name = transformer.getTransformerName();
- Map localTransforms = ((LocalData)data).localTransforms;
+ LocalData data = getData();
+ Map localTransforms = data.localTransforms;
if (name == null || localTransforms.get(name) != null)
{
throw new IllegalArgumentException("Local transformer names must exist and be unique (" + name + ")."+
@@ -238,7 +243,7 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl
}
}
localTransforms.put(name, localTransform);
- super.register(data, transformer, baseUrl, readFrom);
+ super.register(transformer, baseUrl, readFrom);
}
catch (IllegalArgumentException e)
{
@@ -396,7 +401,7 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl
if (getFirstTime())
{
setFirstTime(false);
- transformerDebug.debug("Local transforms "+getCounts()+" are " + (enabled ? "enabled" : "disabled"));
+ transformerDebug.debug("Local transforms "+getData()+" are " + (enabled ? "enabled" : "disabled"));
}
return enabled
@@ -419,7 +424,8 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl
String sourceMimetype, String targetMimetype, long sourceSizeInBytes)
{
String name = getTransformerName(sourceMimetype, sourceSizeInBytes, targetMimetype, actualOptions, renditionName);
- Map localTransforms = ((LocalData)data).localTransforms;
+ LocalData data = getData();
+ Map localTransforms = data.localTransforms;
return localTransforms.get(name);
}
}
diff --git a/src/main/java/org/alfresco/repo/content/transform/TransformerDebug.java b/src/main/java/org/alfresco/repo/content/transform/TransformerDebug.java
index 67b3cdc3f1..606681f2ef 100644
--- a/src/main/java/org/alfresco/repo/content/transform/TransformerDebug.java
+++ b/src/main/java/org/alfresco/repo/content/transform/TransformerDebug.java
@@ -1717,7 +1717,13 @@ public class TransformerDebug implements ApplicationContextAware
finally
{
setStringBuilder(null);
- renditionDefinitionRegistry2.unregister(testRenditionName);
+ try
+ {
+ renditionDefinitionRegistry2.unregister(testRenditionName);
+ }
+ catch (IllegalArgumentException ignore)
+ {
+ }
deleteSourceNode(sourceNodeRef);
}
return sb.toString();
diff --git a/src/main/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistry.java b/src/main/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistry.java
index 1e73405a80..4300f75eb1 100644
--- a/src/main/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistry.java
+++ b/src/main/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistry.java
@@ -65,6 +65,11 @@ public class LegacyTransformServiceRegistry extends AbstractTransformServiceRegi
firstTime = true;
}
+ public boolean isEnabled()
+ {
+ return enabled;
+ }
+
public void setTransformerDebug(TransformerDebug transformerDebug)
{
this.transformerDebug = transformerDebug;
diff --git a/src/main/java/org/alfresco/repo/rendition2/RenditionDefinitionRegistry2Impl.java b/src/main/java/org/alfresco/repo/rendition2/RenditionDefinitionRegistry2Impl.java
index 5890440539..c9025a33f0 100644
--- a/src/main/java/org/alfresco/repo/rendition2/RenditionDefinitionRegistry2Impl.java
+++ b/src/main/java/org/alfresco/repo/rendition2/RenditionDefinitionRegistry2Impl.java
@@ -25,9 +25,19 @@
*/
package org.alfresco.repo.rendition2;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.alfresco.transform.client.model.config.TransformServiceRegistry;
+import org.alfresco.util.ConfigFileFinder;
+import org.alfresco.util.ConfigScheduler;
import org.alfresco.util.Pair;
+import org.alfresco.util.PropertyCheck;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.quartz.CronExpression;
+import org.springframework.beans.factory.InitializingBean;
+import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -39,17 +49,204 @@ import java.util.Set;
*
* @author adavis
*/
-public class RenditionDefinitionRegistry2Impl implements RenditionDefinitionRegistry2
+public class RenditionDefinitionRegistry2Impl implements RenditionDefinitionRegistry2, InitializingBean
{
- private TransformServiceRegistry transformServiceRegistry;
+ private static final Log log = LogFactory.getLog(RenditionDefinitionRegistry2Impl.class);
- private final Map renditionDefinitions = new HashMap();
- private final Map>> renditionsFor = new HashMap<>();
+ static class Data
+ {
+ Map renditionDefinitions = new HashMap();
+ Map>> renditionsFor = new HashMap<>();
+ private int count = 0;
+
+ @Override
+ public String toString()
+ {
+ return "("+count+")";
+ }
+ }
+
+ static class RenditionDef
+ {
+ private String renditionName;
+ private String targetMediaType;
+ private Set options;
+
+ public void setRenditionName(String renditionName)
+ {
+ this.renditionName = renditionName;
+ }
+
+ public void setTargetMediaType(String targetMediaType)
+ {
+ this.targetMediaType = targetMediaType;
+ }
+
+ public void setOptions(Set options)
+ {
+ this.options = options;
+ }
+ }
+
+ static class RenditionOpt
+ {
+ private String name;
+ private String value;
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+
+ public void setValue(String value)
+ {
+ this.value = value;
+ }
+ }
+
+ private TransformServiceRegistry transformServiceRegistry;
+ private String renditionConfigDir;
+ private String timeoutDefault;
+ private ObjectMapper jsonObjectMapper;
+ private CronExpression cronExpression;
+ private CronExpression initialAndOnErrorCronExpression;
+
+ private ConfigScheduler configScheduler = new ConfigScheduler(this)
+ {
+ @Override
+ public boolean readConfig() throws IOException
+ {
+ return RenditionDefinitionRegistry2Impl.this.readConfig();
+ }
+
+ @Override
+ public Object createData()
+ {
+ return RenditionDefinitionRegistry2Impl.this.createData();
+ }
+ };
+ private ConfigFileFinder configFileFinder;
public void setTransformServiceRegistry(TransformServiceRegistry transformServiceRegistry)
{
this.transformServiceRegistry = transformServiceRegistry;
- renditionsFor.clear();
+ }
+
+ public void setRenditionConfigDir(String renditionConfigDir)
+ {
+ this.renditionConfigDir = renditionConfigDir;
+ }
+
+ public void setTimeoutDefault(String timeoutDefault)
+ {
+ this.timeoutDefault = timeoutDefault;
+ }
+
+ public void setJsonObjectMapper(ObjectMapper jsonObjectMapper)
+ {
+ this.jsonObjectMapper = jsonObjectMapper;
+ }
+
+ public CronExpression getCronExpression()
+ {
+ return cronExpression;
+ }
+
+ public void setCronExpression(CronExpression cronExpression)
+ {
+ this.cronExpression = cronExpression;
+ }
+
+ public CronExpression getInitialAndOnErrorCronExpression()
+ {
+ return initialAndOnErrorCronExpression;
+ }
+
+ public void setInitialAndOnErrorCronExpression(CronExpression initialAndOnErrorCronExpression)
+ {
+ this.initialAndOnErrorCronExpression = initialAndOnErrorCronExpression;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception
+ {
+ PropertyCheck.mandatory(this, "transformServiceRegistry", transformServiceRegistry);
+ PropertyCheck.mandatory(this, "renditionConfigDir", renditionConfigDir);
+ PropertyCheck.mandatory(this, "timeoutDefault", timeoutDefault);
+ PropertyCheck.mandatory(this, "jsonObjectMapper", jsonObjectMapper);
+ if (cronExpression != null)
+ {
+ PropertyCheck.mandatory(this, "initialAndOnErrorCronExpression", initialAndOnErrorCronExpression);
+ }
+ configFileFinder = new ConfigFileFinder(jsonObjectMapper)
+ {
+ @Override
+ protected void readJson(JsonNode jsonNode, String readFromMessage, String baseUrl) throws IOException
+ {
+ try
+ {
+ JsonNode renditions = jsonNode.get("renditions");
+ if (renditions != null && renditions.isArray())
+ {
+ for (JsonNode rendition : renditions)
+ {
+ RenditionDef def = jsonObjectMapper.convertValue(rendition, RenditionDef.class);
+ Map map = new HashMap<>();
+ if (def.options != null)
+ {
+ def.options.forEach(o -> map.put(o.name, o.value));
+ }
+ if (!map.containsKey(RenditionDefinition2.TIMEOUT))
+ {
+ map.put(RenditionDefinition2.TIMEOUT, timeoutDefault);
+ }
+ new RenditionDefinition2Impl(def.renditionName, def.targetMediaType, map,
+ RenditionDefinitionRegistry2Impl.this);
+ }
+ }
+ }
+ catch (IllegalArgumentException e)
+ {
+ log.error("Error reading "+readFromMessage+" "+e.getMessage());
+ }
+ }
+ };
+ configScheduler.run(true, log, cronExpression, initialAndOnErrorCronExpression);
+ }
+
+ public Data createData()
+ {
+ return new Data();
+ }
+
+ public synchronized Data getData()
+ {
+ return configScheduler.getData();
+ }
+
+ public boolean readConfig() throws IOException
+ {
+ boolean successReadingConfig = configFileFinder.readFiles("alfresco/renditions", log);
+ if (renditionConfigDir != null && !renditionConfigDir.isBlank())
+ {
+ successReadingConfig &= configFileFinder.readFiles(renditionConfigDir, log);
+ }
+ return successReadingConfig;
+ }
+
+ public boolean isEnabled()
+ {
+ return true;
}
/**
@@ -71,12 +268,14 @@ public class RenditionDefinitionRegistry2Impl implements RenditionDefinitionRegi
{
throw new IllegalArgumentException("RenditionDefinition "+renditionName+" was already registered.");
}
- renditionDefinitions.put(renditionName, renditionDefinition);
+ Data data = getData();
+ data.renditionDefinitions.put(renditionName, renditionDefinition);
}
public void unregister(String renditionName)
{
- if (renditionDefinitions.remove(renditionName) == null)
+ Data data = getData();
+ if (data.renditionDefinitions.remove(renditionName) == null)
{
throw new IllegalArgumentException("RenditionDefinition "+renditionName+" was not registered.");
}
@@ -85,20 +284,21 @@ public class RenditionDefinitionRegistry2Impl implements RenditionDefinitionRegi
@Override
public Set getRenditionNames()
{
- return renditionDefinitions.keySet();
+ return getData().renditionDefinitions.keySet();
}
@Override
public Set getRenditionNamesFrom(String sourceMimetype, long size)
{
Set> renditionNamesWithMaxSize;
- synchronized (renditionsFor)
+ Data data = getData();
+ synchronized (data.renditionsFor)
{
- renditionNamesWithMaxSize = renditionsFor.get(sourceMimetype);
+ renditionNamesWithMaxSize = data.renditionsFor.get(sourceMimetype);
if (renditionNamesWithMaxSize == null)
{
renditionNamesWithMaxSize = getRenditionNamesWithMaxSize(sourceMimetype);
- renditionsFor.put(sourceMimetype, renditionNamesWithMaxSize);
+ data.renditionsFor.put(sourceMimetype, renditionNamesWithMaxSize);
}
}
@@ -125,7 +325,8 @@ public class RenditionDefinitionRegistry2Impl implements RenditionDefinitionRegi
private Set> getRenditionNamesWithMaxSize(String sourceMimetype)
{
Set> renditions = new HashSet();
- for (Map.Entry entry : renditionDefinitions.entrySet())
+ Data data = getData();
+ for (Map.Entry entry : data.renditionDefinitions.entrySet())
{
RenditionDefinition2 renditionDefinition2 = entry.getValue();
String targetMimetype = renditionDefinition2.getTargetMimetype();
@@ -145,6 +346,7 @@ public class RenditionDefinitionRegistry2Impl implements RenditionDefinitionRegi
@Override
public RenditionDefinition2 getRenditionDefinition(String renditionName)
{
- return renditionDefinitions.get(renditionName);
+ Data data = getData();
+ return data.renditionDefinitions.get(renditionName);
}
}
diff --git a/src/main/java/org/alfresco/transform/client/model/config/CombinedConfig.java b/src/main/java/org/alfresco/transform/client/model/config/CombinedConfig.java
index 2ce2e0979b..ea80070b63 100644
--- a/src/main/java/org/alfresco/transform/client/model/config/CombinedConfig.java
+++ b/src/main/java/org/alfresco/transform/client/model/config/CombinedConfig.java
@@ -25,12 +25,12 @@
*/
package org.alfresco.transform.client.model.config;
-import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.util.ConfigFileFinder;
import org.apache.commons.logging.Log;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
@@ -40,26 +40,15 @@ import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
-import java.io.File;
-import java.io.FileReader;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
import java.io.StringReader;
-import java.net.URL;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
/**
* This class recreates the json format used in ACS 6.1 where we just had an array of transformers and each
@@ -84,6 +73,7 @@ public class CombinedConfig
private Map allTransformOptions = new HashMap<>();
private List allTransforms = new ArrayList<>();
private ObjectMapper jsonObjectMapper = new ObjectMapper();
+ private ConfigFileFinder configFileFinder;
static class TransformNodeAndItsOrigin
{
@@ -116,26 +106,62 @@ public class CombinedConfig
public CombinedConfig(Log log)
{
this.log = log;
+
+ configFileFinder = new ConfigFileFinder(jsonObjectMapper)
+ {
+ @Override
+ protected void readJson(JsonNode jsonNode, String readFromMessage, String baseUrl) throws IOException
+ {
+ JsonNode transformOptions = jsonNode.get(TRANSFORM_OPTIONS);
+ if (transformOptions != null && transformOptions.isObject())
+ {
+ Iterator> iterator = transformOptions.fields();
+ while (iterator.hasNext())
+ {
+ Map.Entry entry = iterator.next();
+
+ JsonNode options = entry.getValue();
+ if (options.isArray())
+ {
+ String optionsName = entry.getKey();
+ allTransformOptions.put(optionsName, (ArrayNode)options);
+ }
+ }
+ }
+
+ JsonNode transformers = jsonNode.get(TRANSFORMERS);
+ if (transformers != null && transformers.isArray())
+ {
+ for (JsonNode transformer : transformers)
+ {
+ if (transformer.isObject())
+ {
+ allTransforms.add(new TransformNodeAndItsOrigin((ObjectNode)transformer, baseUrl, readFromMessage));
+ }
+ }
+ }
+ }
+ };
}
public boolean addRemoteConfig(List urls, String remoteType)
{
- boolean successReadingRemoteConfig = true;
+ boolean successReadingConfig = true;
for (String url : urls)
{
if (!addRemoteConfig(url, remoteType))
{
- successReadingRemoteConfig = false;
+ successReadingConfig = false;
}
}
- return successReadingRemoteConfig;
+ return successReadingConfig;
}
private boolean addRemoteConfig(String baseUrl, String remoteType)
{
String url = baseUrl + TRANSFORM_CONFIG;
HttpGet httpGet = new HttpGet(url);
- boolean successReadingRemoteConfig = true;
+ boolean successReadingConfig = true;
try
{
try (CloseableHttpClient httpclient = HttpClients.createDefault())
@@ -160,10 +186,10 @@ public class CombinedConfig
try (StringReader reader = new StringReader(content))
{
int transformCount = allTransforms.size();
- addJsonSource(reader, baseUrl, remoteType+" on "+baseUrl);
+ configFileFinder.readFile(reader, remoteType+" on "+baseUrl, "json", baseUrl, log);
if (transformCount == allTransforms.size())
{
- successReadingRemoteConfig = false;
+ successReadingConfig = false;
}
}
@@ -201,9 +227,9 @@ public class CombinedConfig
catch (AlfrescoRuntimeException e)
{
log.error(e.getMessage());
- successReadingRemoteConfig = false;
+ successReadingConfig = false;
}
- return successReadingRemoteConfig;
+ return successReadingConfig;
}
// Tests mock the return values
@@ -235,117 +261,15 @@ public class CombinedConfig
return message;
}
- public void addLocalConfig(String path) throws IOException
+ public boolean addLocalConfig(String path) throws IOException
{
- boolean somethingRead = false;
- final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());
- if (jarFile.isFile())
- {
- JarFile jar = new JarFile(jarFile);
- Enumeration entries = jar.entries(); // gives ALL entries in jar
- String prefix = path + "/";
- List names = new ArrayList<>();
- while (entries.hasMoreElements())
- {
- final String name = entries.nextElement().getName();
- if (name.startsWith(prefix) && name.length() > prefix.length())
- {
- names.add(name);
- }
- }
- Collections.sort(names);
- for (String name : names)
- {
- somethingRead = true;
- addJsonSource(new InputStreamReader(getResourceAsStream(name)), null,
- name+" from jar "+jarFile.getName());
- }
-
- jar.close();
- }
- else
- {
- URL url = getClass().getClassLoader().getResource(path);
- if (url != null)
- {
- File root = new File(url.getPath());
- String rootPath = root.getPath();
- if (root.isDirectory())
- {
- File[] files = root.listFiles();
- Arrays.sort(files, (file1, file2) -> file1.getName().compareTo(file2.getName()));
- for (File file: files)
- {
- somethingRead = true;
- addJsonSource(new FileReader(file), null,"File " + file.getPath());
- }
- }
- else
- {
- somethingRead = true;
- addJsonSource(new FileReader(root), null, "File " + rootPath);
- }
- }
- }
-
- if (!somethingRead)
- {
- log.warn("No config read from "+path);
- }
+ return configFileFinder.readFiles(path, log);
}
- private InputStream getResourceAsStream(String resource)
- {
- final InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
- return in == null ? getClass().getResourceAsStream(resource) : in;
- }
-
- private void addJsonSource(Reader reader, String baseUrl, String readFrom) throws IOException
- {
- JsonNode jsonNode = jsonObjectMapper.readValue(reader, new TypeReference() {});
- if (log.isTraceEnabled())
- {
- log.trace(readFrom+" config is: "+jsonNode);
- }
- else
- {
- log.debug(readFrom+" config read");
- }
-
- JsonNode transformOptions = jsonNode.get(TRANSFORM_OPTIONS);
- if (transformOptions != null && transformOptions.isObject())
- {
- Iterator> iterator = transformOptions.fields();
- while (iterator.hasNext())
- {
- Map.Entry entry = iterator.next();
-
- JsonNode options = entry.getValue();
- if (options.isArray())
- {
- String optionsName = entry.getKey();
- allTransformOptions.put(optionsName, (ArrayNode)options);
- }
- }
- }
-
- JsonNode transformers = jsonNode.get(TRANSFORMERS);
- if (transformers != null && transformers.isArray())
- {
- for (JsonNode transformer : transformers)
- {
- if (transformer.isObject())
- {
- allTransforms.add(new TransformNodeAndItsOrigin((ObjectNode)transformer, baseUrl, readFrom));
- }
- }
- }
- }
-
- public void register(TransformServiceRegistryImpl.Data data, TransformServiceRegistryImpl registry) throws IOException
+ public void register(TransformServiceRegistryImpl registry) throws IOException
{
List transformers = getTransforms();
- transformers.forEach(t->registry.register(data, t.transform, t.baseUrl, t.readFrom));
+ transformers.forEach(t->registry.register(t.transform, t.baseUrl, t.readFrom));
}
public List getTransforms() throws IOException
diff --git a/src/main/java/org/alfresco/transform/client/model/config/TransformServiceRegistryImpl.java b/src/main/java/org/alfresco/transform/client/model/config/TransformServiceRegistryImpl.java
index 6627c468f5..78310f196d 100644
--- a/src/main/java/org/alfresco/transform/client/model/config/TransformServiceRegistryImpl.java
+++ b/src/main/java/org/alfresco/transform/client/model/config/TransformServiceRegistryImpl.java
@@ -27,21 +27,11 @@ package org.alfresco.transform.client.model.config;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
+import org.alfresco.util.ConfigScheduler;
import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log;
import org.quartz.CronExpression;
-import org.quartz.CronScheduleBuilder;
-import org.quartz.CronTrigger;
-import org.quartz.Job;
-import org.quartz.JobBuilder;
-import org.quartz.JobDataMap;
-import org.quartz.JobDetail;
-import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
-import org.quartz.Scheduler;
import org.quartz.SchedulerException;
-import org.quartz.TriggerBuilder;
-import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.InitializingBean;
import java.io.IOException;
@@ -68,7 +58,12 @@ public abstract class TransformServiceRegistryImpl implements TransformServiceRe
private int transformerCount = 0;
private int transformCount = 0;
boolean firstTime = true;
- boolean successReadingRemoteConfig = true;
+
+ @Override
+ public String toString()
+ {
+ return "("+transformerCount+":"+transformCount+")";
+ }
}
static class SupportedTransform
@@ -90,40 +85,31 @@ public abstract class TransformServiceRegistryImpl implements TransformServiceRe
}
}
- public static class TransformServiceRegistryJob implements Job
- {
- @Override
- public void execute(JobExecutionContext context) throws JobExecutionException
- {
- JobDataMap dataMap = context.getJobDetail().getJobDataMap();
- TransformServiceRegistryImpl registry = (TransformServiceRegistryImpl)dataMap.get("registry");
- registry.readConfigAndReplace();
- }
- }
-
protected boolean enabled = true;
- protected Data data;
private ObjectMapper jsonObjectMapper;
- private Scheduler scheduler;
private CronExpression cronExpression;
private CronExpression initialAndOnErrorCronExpression;
- private boolean normalCronSchedule;
+
+ private ConfigScheduler configScheduler = new ConfigScheduler(this)
+ {
+ @Override
+ public boolean readConfig() throws IOException
+ {
+ return TransformServiceRegistryImpl.this.readConfig();
+ }
+
+ @Override
+ public Object createData()
+ {
+ return TransformServiceRegistryImpl.this.createData();
+ }
+ };
public void setJsonObjectMapper(ObjectMapper jsonObjectMapper)
{
this.jsonObjectMapper = jsonObjectMapper;
}
- public synchronized Scheduler getScheduler()
- {
- return scheduler;
- }
-
- public synchronized void setScheduler(Scheduler scheduler)
- {
- this.scheduler = scheduler;
- }
-
public CronExpression getCronExpression()
{
return cronExpression;
@@ -147,126 +133,31 @@ public abstract class TransformServiceRegistryImpl implements TransformServiceRe
@Override
public void afterPropertiesSet() throws Exception
{
- if (jsonObjectMapper == null)
+ PropertyCheck.mandatory(this, "jsonObjectMapper", jsonObjectMapper);
+ if (cronExpression != null)
{
- throw new IllegalStateException("jsonObjectMapper has not been set");
+ PropertyCheck.mandatory(this, "initialAndOnErrorCronExpression", initialAndOnErrorCronExpression);
}
- PropertyCheck.mandatory(this, "cronExpression", cronExpression);
- PropertyCheck.mandatory(this, "initialAndOnErrorCronExpression", initialAndOnErrorCronExpression);
- setData(null);
- if (enabled)
- {
- schedule();
- }
- }
-
- private synchronized void schedule()
- {
- // Don't do an initial readConfigAndReplace() as the first scheduled read can be done almost instantly and
- // there is little point doing two in the space of a few seconds. If however the scheduler is already running
- // we do need to run it (this is only from test cases).
- if (scheduler == null)
- {
- StdSchedulerFactory sf = new StdSchedulerFactory();
- String jobName = getClass().getName()+"Job";
- try
- {
- scheduler = sf.getScheduler();
-
- JobDetail job = JobBuilder.newJob()
- .withIdentity(jobName)
- .ofType(TransformServiceRegistryJob.class)
- .build();
- job.getJobDataMap().put("registry", this);
- CronExpression cronExpression = normalCronSchedule ? this.cronExpression : initialAndOnErrorCronExpression;
- CronTrigger trigger = TriggerBuilder.newTrigger()
- .withIdentity(jobName+"Trigger", Scheduler.DEFAULT_GROUP)
- .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
- .build();
- scheduler.startDelayed(0);
- scheduler.scheduleJob(job, trigger);
- }
- catch (SchedulerException e)
- {
- getLog().error("Failed to start "+jobName+" "+e.getMessage());
- }
- }
- else
- {
- readConfigAndReplace();
- }
- }
-
- protected void readConfigAndReplace()
- {
- boolean successReadingRemoteConfig = true;
Log log = getLog();
- log.debug("Config read started");
- try
- {
- Data data = readConfig();
- successReadingRemoteConfig = data.successReadingRemoteConfig;
- setData(data);
- log.debug("Config read finished "+getCounts());
- }
- catch (Exception e)
- {
- successReadingRemoteConfig = false;
- log.error("Config read failed. "+e.getMessage(), e);
- }
-
- // Switch schedule sequence if we were on the normal schedule and we now have problems or if
- // we are on the initial/error schedule and there were no errors.
- if (normalCronSchedule && !successReadingRemoteConfig ||
- !normalCronSchedule && successReadingRemoteConfig)
- {
- normalCronSchedule = !normalCronSchedule;
- if (scheduler != null)
- {
- try
- {
- CronExpression cronExpression = normalCronSchedule ? this.cronExpression : initialAndOnErrorCronExpression;
- scheduler.clear();
- scheduler = null;
- schedule();
- }
- catch (SchedulerException e)
- {
- getLog().error("Problem stopping scheduler for transformer configuration "+e.getMessage());
- }
- }
- else
- {
- System.out.println("Switch schedule "+normalCronSchedule+" WITHOUT new schedule");
- }
- }
+ configScheduler.run(enabled, log, cronExpression, initialAndOnErrorCronExpression);
}
- protected abstract Data readConfig() throws IOException;
-
- private synchronized void setData(Data data)
- {
- this.data = data;
- }
-
- protected synchronized Data getData()
- {
- if (data == null)
- {
- data = createData();
- }
- return data;
- }
-
- protected Data createData()
+ public Data createData()
{
return new Data();
}
- protected void setSuccessReadingRemoteConfig(Data data, boolean successReadingRemoteConfig)
+ public synchronized Data getData()
{
- data.successReadingRemoteConfig = successReadingRemoteConfig;
+ return configScheduler.getData();
+ }
+
+ public abstract boolean readConfig() throws IOException;
+
+ public boolean isEnabled()
+ {
+ return enabled;
}
public void setEnabled(boolean enabled)
@@ -287,14 +178,15 @@ public abstract class TransformServiceRegistryImpl implements TransformServiceRe
protected abstract Log getLog();
- public void register(Data data, Reader reader, String readFrom) throws IOException
+ public void register(Reader reader, String readFrom) throws IOException
{
List transformers = jsonObjectMapper.readValue(reader, new TypeReference>(){});
- transformers.forEach(t -> register(data, t, null, readFrom));
+ transformers.forEach(t -> register(t, null, readFrom));
}
- protected void register(Data data, Transformer transformer, String baseUrl, String readFrom)
+ protected void register(Transformer transformer, String baseUrl, String readFrom)
{
+ Data data = getData();
data.transformerCount++;
transformer.getSupportedSourceAndTargetList().forEach(
e -> data.transformers.computeIfAbsent(e.getSourceMediaType(),
@@ -304,11 +196,6 @@ public abstract class TransformServiceRegistryImpl implements TransformServiceRe
transformer.getTransformOptions(), e.getMaxSourceSizeBytes(), e.getPriority())));
}
- protected String getCounts()
- {
- return "("+getData().transformerCount+":"+getData().transformCount+")";
- }
-
@Override
public boolean isSupported(String sourceMimetype, long sourceSizeInBytes, String targetMimetype,
Map actualOptions, String renditionName)
@@ -366,7 +253,6 @@ public abstract class TransformServiceRegistryImpl implements TransformServiceRe
renditionName = null;
}
-
Data data = getData();
List transformListBySize = renditionName == null ? null
: data.cachedSupportedTransformList.computeIfAbsent(renditionName, k -> new ConcurrentHashMap<>()).get(sourceMimetype);
diff --git a/src/main/java/org/alfresco/util/ConfigFileFinder.java b/src/main/java/org/alfresco/util/ConfigFileFinder.java
new file mode 100644
index 0000000000..d6fd3393a3
--- /dev/null
+++ b/src/main/java/org/alfresco/util/ConfigFileFinder.java
@@ -0,0 +1,164 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * 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 org.alfresco.util;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.logging.Log;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Used to find configuration files as resources from the jar file or from some external location. The path supplied
+ * to {@link #readFiles(String, Log)} may be a directory name. Normally used by ConfigScheduler.
+ *
+ * @author adavis
+ */
+public abstract class ConfigFileFinder
+{
+ private final ObjectMapper jsonObjectMapper;
+
+ public ConfigFileFinder(ObjectMapper jsonObjectMapper)
+ {
+ this.jsonObjectMapper = jsonObjectMapper;
+ }
+
+ public boolean readFiles(String path, Log log)
+ {
+ boolean successReadingConfig = true;
+ try
+ {
+ boolean somethingRead = false;
+ final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());
+ if (jarFile.isFile())
+ {
+ Enumeration entries = new JarFile(jarFile).entries(); // gives ALL entries in jar
+ String prefix = path + "/";
+ List names = new ArrayList<>();
+ while (entries.hasMoreElements())
+ {
+ final String name = entries.nextElement().getName();
+ if (name.startsWith(prefix) && name.length() > prefix.length())
+ {
+ names.add(name);
+ }
+ }
+ Collections.sort(names);
+ for (String name : names)
+ {
+ somethingRead = true;
+ successReadingConfig &= readFile(new InputStreamReader(getResourceAsStream(name)),"resource", name, null, log);
+ }
+
+ new JarFile(jarFile).close();
+ }
+ else
+ {
+ URL url = getClass().getClassLoader().getResource(path);
+ if (url != null)
+ {
+ File root = new File(url.getPath());
+ String rootPath = root.getPath();
+ if (root.isDirectory())
+ {
+ File[] files = root.listFiles();
+ Arrays.sort(files, (file1, file2) -> file1.getName().compareTo(file2.getName()));
+ for (File file: files)
+ {
+ somethingRead = true;
+ successReadingConfig &= readFile(new FileReader(file), "file", file.getPath(), null, log);
+ }
+ }
+ else
+ {
+ somethingRead = true;
+ successReadingConfig = readFile(new FileReader(root), "file", rootPath, null, log);
+ }
+ }
+ }
+
+ if (!somethingRead)
+ {
+ log.warn("No config read from "+path);
+ }
+ }
+ catch (IOException e)
+ {
+ log.error("Error reading from "+path);
+ successReadingConfig = false;
+ }
+ return successReadingConfig;
+ }
+
+ private InputStream getResourceAsStream(String resource)
+ {
+ final InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
+ return in == null ? getClass().getResourceAsStream(resource) : in;
+ }
+
+ public boolean readFile(Reader reader, String readFrom, String path, String baseUrl, Log log)
+ {
+ // At the moment it is assumed the file is Json, but that does not need to be the case.
+ // We have the path including extension.
+ boolean successReadingConfig = true;
+ try
+ {
+ JsonNode jsonNode = jsonObjectMapper.readValue(reader, new TypeReference() {});
+ String readFromMessage = readFrom + ' ' + path;
+ if (log.isTraceEnabled())
+ {
+ log.trace(readFromMessage + " config is: " + jsonNode);
+ }
+ else
+ {
+ log.debug(readFromMessage + " config read");
+ }
+ readJson(jsonNode, readFromMessage, baseUrl);
+ }
+ catch (Exception e)
+ {
+ log.error("Error reading "+path);
+ successReadingConfig = false;
+ }
+ return successReadingConfig;
+ }
+
+ protected abstract void readJson(JsonNode jsonNode, String readFromMessage, String baseUrl) throws IOException;
+}
diff --git a/src/main/java/org/alfresco/util/ConfigScheduler.java b/src/main/java/org/alfresco/util/ConfigScheduler.java
new file mode 100644
index 0000000000..58d54ba976
--- /dev/null
+++ b/src/main/java/org/alfresco/util/ConfigScheduler.java
@@ -0,0 +1,223 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * 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 org.alfresco.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.quartz.CronExpression;
+import org.quartz.CronScheduleBuilder;
+import org.quartz.CronTrigger;
+import org.quartz.Job;
+import org.quartz.JobBuilder;
+import org.quartz.JobDataMap;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.quartz.Scheduler;
+import org.quartz.TriggerBuilder;
+import org.quartz.impl.StdSchedulerFactory;
+
+import java.io.IOException;
+import java.util.Date;
+
+/**
+ * Used to schedule reading of config. The config is assumed to change from time to time.
+ * Initially or on error the reading frequency is high but slower once no problems are reported.
+ * If the normal cron schedule is not set or is in the past, the config is read only once when
+ * {@link #run(boolean, Log, CronExpression, CronExpression)} is called.
+ *
+ * @author adavis
+ */
+public abstract class ConfigScheduler
+{
+ public static class ConfigSchedulerJob implements Job
+ {
+ @Override
+ public void execute(JobExecutionContext context) throws JobExecutionException
+ {
+ JobDataMap dataMap = context.getJobDetail().getJobDataMap();
+ ConfigScheduler configScheduler = (ConfigScheduler)dataMap.get(CONFIG_SCHEDULER);
+ boolean successReadingConfig = configScheduler.readConfigAndReplace();
+ configScheduler.changeScheduleOnStateChange(successReadingConfig);
+ }
+ }
+
+ public static final String CONFIG_SCHEDULER = "configScheduler";
+
+ private static final Log defaultLog = LogFactory.getLog(ConfigScheduler.class);
+ private static StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
+
+ private final String jobName;
+ private Log log;
+ private CronExpression cronExpression;
+ private CronExpression initialAndOnErrorCronExpression;
+
+ private Scheduler scheduler;
+ private boolean normalCronSchedule;
+
+ protected Data data;
+ private ThreadLocal threadData = ThreadLocal.withInitial(() -> data);
+
+ public ConfigScheduler(Object client)
+ {
+ jobName = client.getClass().getName()+"Job";
+ }
+
+ public abstract boolean readConfig() throws IOException;
+
+ public abstract Data createData();
+
+ public synchronized Data getData()
+ {
+ Data data = threadData.get();
+ if (data == null)
+ {
+ data = createData();
+ setData(data);
+ }
+ return data;
+ }
+
+ private synchronized void setData(Data data)
+ {
+ this.data = data;
+ threadData.set(data);
+ }
+
+ private synchronized void clearData()
+ {
+ this.data = null; // as run() should only be called multiple times in testing, it is okay to discard the
+ // previous data, as there should be no other Threads trying to read it, unless they are
+ // left over from previous tests.
+ threadData.remove(); // we need to pick up the initial value next time (whatever the data value is at that point)
+ }
+
+ /**
+ * This method should only be called once in production on startup generally from Spring afterPropertiesSet methods.
+ * In testing it is allowed to call this method multiple times, but in that case it is recommended to pass in a
+ * null cronExpression (or a cronExpression such as a date in the past) so the scheduler is not started. If this is
+ * done, the config is still read, but before the method returns.
+ */
+ public void run(boolean enabled, Log log, CronExpression cronExpression, CronExpression initialAndOnErrorCronExpression)
+ {
+ clearPreviousSchedule();
+ clearData();
+ if (enabled)
+ {
+ this.log = log == null ? ConfigScheduler.defaultLog : log;
+ Date now = new Date();
+ if (cronExpression != null &&
+ initialAndOnErrorCronExpression != null &&
+ cronExpression.getNextValidTimeAfter(now) != null &&
+ initialAndOnErrorCronExpression.getNextValidTimeAfter(now) != null)
+ {
+ this.cronExpression = cronExpression;
+ this.initialAndOnErrorCronExpression = initialAndOnErrorCronExpression;
+ schedule();
+ }
+ else
+ {
+ readConfigAndReplace();
+ }
+ }
+ }
+
+ private synchronized void schedule()
+ {
+ try
+ {
+ scheduler = schedulerFactory.getScheduler();
+
+ JobDetail job = JobBuilder.newJob()
+ .withIdentity(jobName)
+ .ofType(ConfigSchedulerJob.class)
+ .build();
+ job.getJobDataMap().put(CONFIG_SCHEDULER, this);
+ CronExpression cronExpression = normalCronSchedule ? this.cronExpression : initialAndOnErrorCronExpression;
+ CronTrigger trigger = TriggerBuilder.newTrigger()
+ .withIdentity(jobName+"Trigger", Scheduler.DEFAULT_GROUP)
+ .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
+ .build();
+ scheduler.startDelayed(0);
+ scheduler.scheduleJob(job, trigger);
+ }
+ catch (Exception e)
+ {
+ log.error("Error scheduling "+e.getMessage());
+ }
+ }
+
+ private void clearPreviousSchedule()
+ {
+ if (scheduler != null)
+ {
+ try
+ {
+ scheduler.clear();
+ }
+ catch (Exception e)
+ {
+ log.error("Error clearing previous schedule " + e.getMessage());
+ }
+ }
+ }
+
+ private boolean readConfigAndReplace()
+ {
+ boolean successReadingConfig;
+ log.debug("Config read started");
+ Data data = getData();
+ try
+ {
+ Data newData = createData();
+ threadData.set(newData);
+ successReadingConfig = readConfig();
+ data = newData;
+ log.debug("Config read finished "+data+
+ (successReadingConfig ? "" : ". Config replaced but there were problems"));
+ }
+ catch (Exception e)
+ {
+ successReadingConfig = false;
+ log.error("Config read failed. "+e.getMessage(), e);
+ }
+ setData(data);
+ return successReadingConfig;
+ }
+
+ private void changeScheduleOnStateChange(boolean successReadingConfig)
+ {
+ // Switch schedule sequence if we were on the normal schedule and we now have problems or if
+ // we are on the initial/error schedule and there were no errors.
+ if ( normalCronSchedule && !successReadingConfig ||
+ !normalCronSchedule && successReadingConfig)
+ {
+ normalCronSchedule = !normalCronSchedule;
+ clearPreviousSchedule();
+ schedule();
+ }
+ }
+}
diff --git a/src/main/java/org/alfresco/util/ResourceFinder.java b/src/main/java/org/alfresco/util/ResourceFinder.java
index 27f6cf2264..fc76816274 100644
--- a/src/main/java/org/alfresco/util/ResourceFinder.java
+++ b/src/main/java/org/alfresco/util/ResourceFinder.java
@@ -1,40 +1,40 @@
-/*
- * #%L
- * Alfresco Repository
- * %%
- * Copyright (C) 2005 - 2016 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%
- */
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2016 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 org.alfresco.util;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.context.support.ServletContextResourcePatternResolver;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
/**
* Can be used in Spring configuration to search for all resources matching an array of patterns.
*
diff --git a/src/main/resources/alfresco/rendition-services2-context.xml b/src/main/resources/alfresco/rendition-services2-context.xml
index b5430e9b9c..e291d6f0bf 100644
--- a/src/main/resources/alfresco/rendition-services2-context.xml
+++ b/src/main/resources/alfresco/rendition-services2-context.xml
@@ -147,9 +147,16 @@
+
+
+
+
+
+
+
@@ -157,108 +164,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/src/main/resources/alfresco/renditions/0100-baseRenditions.json b/src/main/resources/alfresco/renditions/0100-baseRenditions.json
new file mode 100644
index 0000000000..d828a0e8bd
--- /dev/null
+++ b/src/main/resources/alfresco/renditions/0100-baseRenditions.json
@@ -0,0 +1,69 @@
+{
+ "renditions": [
+ {
+ "renditionName": "medium",
+ "targetMediaType": "image/jpeg",
+ "options": [
+ {"name": "resizeWidth", "value": 100},
+ {"name": "resizeHeight", "value": 100},
+ {"name": "maintainAspectRatio", "value": true},
+ {"name": "thumbnail", "value": true}
+ ]
+ },
+ {
+ "renditionName": "doclib",
+ "targetMediaType": "image/png",
+ "options": [
+ {"name": "resizeWidth", "value": 100},
+ {"name": "resizeHeight", "value": 100},
+ {"name": "allowEnlargement", "value": false},
+ {"name": "maintainAspectRatio", "value": true},
+ {"name": "thumbnail", "value": true}
+ ]
+ },
+ {
+ "renditionName": "imgpreview",
+ "targetMediaType": "image/jpeg",
+ "options": [
+ {"name": "resizeWidth", "value": 960},
+ {"name": "resizeHeight", "value": 960},
+ {"name": "allowEnlargement", "value": false},
+ {"name": "maintainAspectRatio", "value": true},
+ {"name": "thumbnail", "value": true}
+ ]
+ },
+ {
+ "renditionName": "avatar",
+ "targetMediaType": "image/png",
+ "options": [
+ {"name": "resizeWidth", "value": 64},
+ {"name": "resizeHeight", "value": 64},
+ {"name": "allowEnlargement", "value": false},
+ {"name": "maintainAspectRatio", "value": true},
+ {"name": "thumbnail", "value": true}
+ ]
+ },
+ {
+ "renditionName": "avatar32",
+ "targetMediaType": "image/png",
+ "options": [
+ {"name": "resizeWidth", "value": 32},
+ {"name": "resizeHeight", "value": 32},
+ {"name": "allowEnlargement", "value": false},
+ {"name": "maintainAspectRatio", "value": true},
+ {"name": "thumbnail", "value": true}
+ ]
+ },
+ {
+ "renditionName": "webpreview",
+ "targetMediaType": "application/x-shockwave-flash",
+ "options": [
+ {"name": "flashVersion", "value": 9}
+ ]
+ },
+ {
+ "renditionName": "pdf",
+ "targetMediaType": "application/pdf"
+ }
+ ]
+}
diff --git a/src/main/resources/alfresco/repository.properties b/src/main/resources/alfresco/repository.properties
index f551df254a..9789e75dfe 100644
--- a/src/main/resources/alfresco/repository.properties
+++ b/src/main/resources/alfresco/repository.properties
@@ -1079,6 +1079,16 @@ people.search.honor.hint.useCQ=true
# Delays cron jobs after bootstrap to allow server to fully come up before jobs start
system.cronJob.startDelayMilliseconds=60000
+# Schedule for reading rendition config definitions dynamically. Initially checks every 10 seconds and then switches to
+# every 10 minutes after the configuration is read successfully. If there is a error later reading the config, the
+# checks return to every 10 seconds.
+rendition.config.cronExpression=0 0/10 * * * ?
+rendition.config.initialAndOnError.cronExpression=0/10 * * * * ?
+
+# Optional property to specify an external file or directory that will be read for rendition definitions from YAML
+# files (possibly added to a volume via k8 ConfigMaps).
+rendition.config.dir=
+
# Optional property to specify an external file or directory that will be read for transformer json config.
local.transform.pipeline.config.dir=
diff --git a/src/main/resources/alfresco/transformers/0150-officeToImageViaPdf.json b/src/main/resources/alfresco/transforms/0150-officeToImageViaPdf.json
similarity index 100%
rename from src/main/resources/alfresco/transformers/0150-officeToImageViaPdf.json
rename to src/main/resources/alfresco/transforms/0150-officeToImageViaPdf.json
diff --git a/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java b/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java
index 2fe276f72a..ec5c443599 100644
--- a/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java
+++ b/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java
@@ -53,6 +53,7 @@ import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.quartz.CronExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ResourceUtils;
@@ -119,6 +120,9 @@ public abstract class AbstractRenditionIntegrationTest extends BaseSpringTest
protected static final String ADMIN = "admin";
protected static final String DOC_LIB = "doclib";
+ private CronExpression origLocalTransCron;
+ private CronExpression origRenditionCron;
+
@BeforeClass
public static void before()
{
@@ -192,16 +196,25 @@ public abstract class AbstractRenditionIntegrationTest extends BaseSpringTest
legacyTransformServiceRegistry.setEnabled(Boolean.parseBoolean(System.getProperty("legacy.transform.service.enabled")));
legacyTransformServiceRegistry.afterPropertiesSet();
+ origLocalTransCron = localTransformServiceRegistry.getCronExpression();
+ localTransformServiceRegistry.setCronExpression(null);
localTransformServiceRegistry.setEnabled(Boolean.parseBoolean(System.getProperty("local.transform.service.enabled")));
localTransformServiceRegistry.afterPropertiesSet();
+ origRenditionCron = renditionDefinitionRegistry2.getCronExpression();
+ renditionDefinitionRegistry2.setCronExpression(null);
renditionDefinitionRegistry2.setTransformServiceRegistry(transformServiceRegistry);
+ renditionDefinitionRegistry2.afterPropertiesSet();
+
thumbnailRegistry.setTransformServiceRegistry(transformServiceRegistry);
}
@After
public void cleanUp()
{
+ localTransformServiceRegistry.setCronExpression(origLocalTransCron);
+ renditionDefinitionRegistry2.setCronExpression(origRenditionCron);
+
AuthenticationUtil.clearCurrentSecurityContext();
}
diff --git a/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionTest.java b/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionTest.java
index 2c1073ec03..3440824902 100644
--- a/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionTest.java
+++ b/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionTest.java
@@ -130,7 +130,7 @@ public abstract class AbstractRenditionTest extends AbstractRenditionIntegration
List thumbnailDefinitions = thumbnailRegistry.getThumbnailDefinitions(sourceMimetype, -1);
Set thumbnailNames = getThumbnailNames(thumbnailDefinitions);
assertEquals("There should be the same renditions ("+renditionNames+") as deprecated thumbnails ("+thumbnailNames+")",
- renditionNames, thumbnailNames);
+ thumbnailNames, renditionNames);
renditionCount += renditionNames.size();
for (String renditionName : renditionNames)
diff --git a/src/test/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistryIntegrationTest.java b/src/test/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistryIntegrationTest.java
index 5bc1eceacd..fff4914190 100644
--- a/src/test/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistryIntegrationTest.java
+++ b/src/test/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistryIntegrationTest.java
@@ -59,8 +59,16 @@ public class LegacyTransformServiceRegistryIntegrationTest extends LocalTransfor
AbstractRenditionIntegrationTest.after();
}
+ @Override
protected void setEnabled(boolean enabled)
{
legacyTransformServiceRegistry.setEnabled(enabled);
+ legacyTransformServiceRegistry.afterPropertiesSet();
+ }
+
+ @Override
+ protected boolean isEnabled()
+ {
+ return legacyTransformServiceRegistry.isEnabled();
}
}
diff --git a/src/test/java/org/alfresco/repo/rendition2/LocalTransformServiceRegistryIntegrationTest.java b/src/test/java/org/alfresco/repo/rendition2/LocalTransformServiceRegistryIntegrationTest.java
index fe0a2d39f4..4683c88907 100644
--- a/src/test/java/org/alfresco/repo/rendition2/LocalTransformServiceRegistryIntegrationTest.java
+++ b/src/test/java/org/alfresco/repo/rendition2/LocalTransformServiceRegistryIntegrationTest.java
@@ -27,11 +27,14 @@ package org.alfresco.repo.rendition2;
import org.alfresco.repo.content.transform.LocalTransformServiceRegistry;
import org.alfresco.transform.client.model.config.TransformServiceRegistry;
+import org.alfresco.transform.client.model.config.TransformServiceRegistryImpl;
+import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.quartz.CronExpression;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashMap;
@@ -45,6 +48,8 @@ import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_PDF;
*/
public class LocalTransformServiceRegistryIntegrationTest extends AbstractRenditionIntegrationTest
{
+ private static final String RENDITION_NAME = "pdf";
+
@Autowired
private LocalTransformServiceRegistry localTransformServiceRegistry;
@@ -65,6 +70,7 @@ public class LocalTransformServiceRegistryIntegrationTest extends AbstractRendit
AbstractRenditionIntegrationTest.after();
}
+ @Override
@Before
public void setUp() throws Exception
{
@@ -75,11 +81,16 @@ public class LocalTransformServiceRegistryIntegrationTest extends AbstractRendit
options = definition2.getTransformOptions();
}
- protected void setEnabled(boolean enabled)
+ protected void setEnabled(boolean enabled) throws Exception
{
localTransformServiceRegistry.setEnabled(enabled);
+ localTransformServiceRegistry.afterPropertiesSet();
+ }
+
+ protected boolean isEnabled()
+ {
+ return localTransformServiceRegistry.isEnabled();
}
- private static final String RENDITION_NAME = "pdf";
@Test
public void testIsSupported()
@@ -121,18 +132,22 @@ public class LocalTransformServiceRegistryIntegrationTest extends AbstractRendit
}
@Test
- public void testEnabledDisabled()
+ public void testEnabledDisabled() throws Exception
{
- Assert.assertTrue(transformServiceRegistry.isSupported(MIMETYPE_OPENXML_WORDPROCESSING, 1234, MIMETYPE_PDF, options, RENDITION_NAME));
+ boolean origEnabled = isEnabled(); // should be true
try
{
+ Assert.assertTrue(transformServiceRegistry.isSupported(MIMETYPE_OPENXML_WORDPROCESSING, 1234, MIMETYPE_PDF, options, RENDITION_NAME));
+
setEnabled(false);
Assert.assertFalse(transformServiceRegistry.isSupported(MIMETYPE_OPENXML_WORDPROCESSING, 1234, MIMETYPE_PDF, options, RENDITION_NAME));
+
+ setEnabled(true);
+ Assert.assertTrue(transformServiceRegistry.isSupported(MIMETYPE_OPENXML_WORDPROCESSING, 1234, MIMETYPE_PDF, options, RENDITION_NAME));
}
finally
{
- setEnabled(true);
+ setEnabled(origEnabled);
}
- Assert.assertTrue(transformServiceRegistry.isSupported(MIMETYPE_OPENXML_WORDPROCESSING, 1234, MIMETYPE_PDF, options, RENDITION_NAME));
}
}
diff --git a/src/test/java/org/alfresco/repo/rendition2/RenditionService2Test.java b/src/test/java/org/alfresco/repo/rendition2/RenditionService2Test.java
index cd67fae84f..60334f9080 100644
--- a/src/test/java/org/alfresco/repo/rendition2/RenditionService2Test.java
+++ b/src/test/java/org/alfresco/repo/rendition2/RenditionService2Test.java
@@ -25,6 +25,7 @@
*/
package org.alfresco.repo.rendition2;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.repo.policy.PolicyComponent;
@@ -38,16 +39,22 @@ import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
+import org.alfresco.transform.client.model.config.TransformServiceRegistryImpl;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
+import org.quartz.CronExpression;
+import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
@@ -68,6 +75,8 @@ import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class RenditionService2Test
{
+ private static final ObjectMapper JSON_OBJECT_MAPPER = new ObjectMapper();;
+
private RenditionService2Impl renditionService2;
private RenditionDefinitionRegistry2Impl renditionDefinitionRegistry2;
@@ -80,9 +89,10 @@ public class RenditionService2Test
@Mock private PolicyComponent policyComponent;
@Mock private BehaviourFilter behaviourFilter;
@Mock private RuleService ruleService;
+ @Mock private TransformServiceRegistryImpl transformServiceRegistry;
private NodeRef nodeRef = new NodeRef("workspace://spacesStore/test-id");
- private static final String IMGPREVIEW = "imgpreview";
+ private static final String TEST_RENDITION = "testRendition";
private static final String JPEG = "image/jpeg";
private String contentUrl = "test-content-url";
@@ -91,11 +101,11 @@ public class RenditionService2Test
{
renditionService2 = new RenditionService2Impl();
renditionDefinitionRegistry2 = new RenditionDefinitionRegistry2Impl();
-
- Map options = new HashMap<>();
- options.put("width", "960");
- options.put("height", "1024");
- new RenditionDefinition2Impl(IMGPREVIEW, JPEG, options, renditionDefinitionRegistry2);
+ renditionDefinitionRegistry2.setTransformServiceRegistry(transformServiceRegistry);
+ renditionDefinitionRegistry2.setRenditionConfigDir("");
+ renditionDefinitionRegistry2.setTimeoutDefault("120000");
+ renditionDefinitionRegistry2.setJsonObjectMapper(JSON_OBJECT_MAPPER);
+ renditionDefinitionRegistry2.setCronExpression(null); // just read it once
when(nodeService.exists(nodeRef)).thenReturn(true);
when(nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT)).thenReturn(contentData);
@@ -115,7 +125,14 @@ public class RenditionService2Test
renditionService2.setEnabled(true);
renditionService2.setThumbnailsEnabled(true);
renditionService2.setRenditionRequestSheduler(new RenditionRequestSchedulerMock());
+
+ renditionDefinitionRegistry2.afterPropertiesSet();
renditionService2.afterPropertiesSet();
+
+ Map options = new HashMap<>();
+ options.put("width", "960");
+ options.put("height", "1024");
+ new RenditionDefinition2Impl(TEST_RENDITION, JPEG, options, renditionDefinitionRegistry2);
}
private class RenditionRequestSchedulerMock extends PostTxnCallbackScheduler
@@ -138,20 +155,20 @@ public class RenditionService2Test
public void disabled()
{
renditionService2.setEnabled(false);
- renditionService2.render(nodeRef, IMGPREVIEW);
+ renditionService2.render(nodeRef, TEST_RENDITION);
}
@Test(expected = RenditionService2Exception.class)
public void thumbnailsDisabled()
{
renditionService2.setThumbnailsEnabled(false);
- renditionService2.render(nodeRef, IMGPREVIEW);
+ renditionService2.render(nodeRef, TEST_RENDITION);
}
@Test
public void useLocalTransform()
{
- renditionService2.render(nodeRef, IMGPREVIEW);
+ renditionService2.render(nodeRef, TEST_RENDITION);
verify(transformClient, times(1)).transform(any(), any(), anyString(), anyInt());
}
@@ -159,14 +176,14 @@ public class RenditionService2Test
public void noTransform()
{
doThrow(UnsupportedOperationException.class).when(transformClient).checkSupported(any(), any(), any(), anyLong(), any());
- renditionService2.render(nodeRef, IMGPREVIEW);
+ renditionService2.render(nodeRef, TEST_RENDITION);
}
@Test(expected = RenditionService2PreventedException.class)
public void checkSourceNodeForPreventionClass()
{
when(renditionPreventionRegistry.isContentClassRegistered((QName)any())).thenReturn(true);
- renditionService2.render(nodeRef, IMGPREVIEW);
+ renditionService2.render(nodeRef, TEST_RENDITION);
}
@Test(expected = IllegalArgumentException.class)
@@ -174,4 +191,16 @@ public class RenditionService2Test
{
renditionService2.render(nodeRef, "doesNotExist");
}
+
+ @Test
+ public void definitionExists() throws IOException
+ {
+ renditionDefinitionRegistry2.readConfig();
+
+ Set renditionNames = renditionDefinitionRegistry2.getRenditionNames();
+ for (String name: new String[] {"medium", "doclib", "imgpreview", "avatar", "avatar32", "webpreview", "pdf"})
+ {
+ assertTrue("Expected rendition "+name, renditionNames.contains(name));
+ }
+ }
}
diff --git a/src/test/java/org/alfresco/transform/client/model/config/LocalTransformServiceRegistryConfigTest.java b/src/test/java/org/alfresco/transform/client/model/config/LocalTransformServiceRegistryConfigTest.java
index 443216e3fe..ad0d5396ae 100644
--- a/src/test/java/org/alfresco/transform/client/model/config/LocalTransformServiceRegistryConfigTest.java
+++ b/src/test/java/org/alfresco/transform/client/model/config/LocalTransformServiceRegistryConfigTest.java
@@ -61,18 +61,18 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg
{
private class TestLocalTransformServiceRegistry extends LocalTransformServiceRegistry
{
- private boolean lastReadSucceed = false;
- private boolean mockSuccessReadingRemoteConfig = true;
+ private boolean mockSuccessReadingConfig = true;
+ LocalData dummyData = new LocalData();
- public synchronized boolean getMockSuccessReadingRemoteConfig()
+ public synchronized boolean getMockSuccessReadingConfig()
{
- return mockSuccessReadingRemoteConfig;
+ return mockSuccessReadingConfig;
}
- public synchronized void setMockSuccessReadingRemoteConfig(boolean mockSuccessReadingRemoteConfig)
+ public synchronized void setMockSuccessReadingConfig(boolean mockSuccessReadingConfig)
{
- System.out.println("\n"+getMs()+": set next mock read to "+(mockSuccessReadingRemoteConfig ? "success" : "failure"));
- this.mockSuccessReadingRemoteConfig = mockSuccessReadingRemoteConfig;
+ System.out.println("\n"+getMs()+": set next mock read to "+(mockSuccessReadingConfig ? "success" : "failure"));
+ this.mockSuccessReadingConfig = mockSuccessReadingConfig;
}
@Override
@@ -84,31 +84,36 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg
}
@Override
- protected TransformServiceRegistryImpl.Data readConfig() throws IOException
+ public boolean readConfig() throws IOException
{
readConfigCount++;
- data = createData();
- boolean mockSuccessReadingRemoteConfig = getMockSuccessReadingRemoteConfig();
- lastReadSucceed = mockSuccessReadingRemoteConfig;
- setSuccessReadingRemoteConfig(data, mockSuccessReadingRemoteConfig);
+ dummyData = new LocalData();
+ boolean mockSuccessReadingRemoteConfig = getMockSuccessReadingConfig();
System.out.println(getMs() + "readConfig() success="+mockSuccessReadingRemoteConfig+" reads="+readConfigCount);
- return data;
+ return mockSuccessReadingRemoteConfig;
}
- public Data assertDataChanged(Data data, String msg)
+ @Override
+ public synchronized LocalData getData()
+ {
+ return dummyData;
+ }
+
+ public Data assertDataChanged(Data prevData, String msg)
{
// If the data changes, there has been a read
System.out.println(getMs()+msg);
- assertNotEquals("The configuration data should have changed: "+msg, this.data, data);
- return this.data;
+ Data data = getData();
+ assertNotEquals("The configuration data should have changed: "+msg, data, prevData);
+ return data;
}
public Data assertDataUnchanged(Data data, String msg)
{
// If the data changes, there has been a read
System.out.println(getMs()+msg);
- assertEquals("The configuration data should be the same: "+msg, this.data, data);
- return this.data;
+ assertEquals("The configuration data should be the same: "+msg, getData(), data);
+ return getData();
}
}
@@ -134,7 +139,6 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg
private Map> libreofficeSupportedTransformation;
private Map> officeToImageViaPdfSupportedTransformation;
- private TransformServiceRegistryImpl.Data data;
private int readConfigCount;
private long startMs;
@@ -155,8 +159,8 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg
registry.setTransformerDebug(transformerDebug);
registry.setMimetypeService(mimetypeMap);
registry.setPipelineConfigDir("");
- registry.setCronExpression(new CronExpression("* * * * * ? 2099")); // not for a long time.
- registry.setInitialAndOnErrorCronExpression(new CronExpression("* * * * * ? 2099")); // not for a long time.
+ registry.setCronExpression(null); // just read it once
+ registry.afterPropertiesSet();
return registry;
}
@@ -416,22 +420,12 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg
{
CronExpression origCronExpression = registry.getCronExpression();
CronExpression origInitialAndOnErrorCronExpression = registry.getInitialAndOnErrorCronExpression();
-
String origPipelineConfigDir = registry.getPipelineConfigDir();
- Scheduler origScheduler = registry.getScheduler();
-
- if (origScheduler != null)
- {
- origScheduler.clear();
- }
try
{
- TransformServiceRegistryImpl.Data prevData;
- data = null;
readConfigCount = 0;
- registry.setScheduler(null);
registry.setInitialAndOnErrorCronExpression(new CronExpression(("0/2 * * ? * * *"))); // every 2 seconds rather than 10 seconds
registry.setCronExpression(new CronExpression(("0/4 * * ? * * *"))); // every 4 seconds rather than 10 mins
@@ -439,8 +433,9 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg
// It avoids having to work out schedule offsets and extra quick runs that can otherwise take place.
Thread.sleep(4000-System.currentTimeMillis()%4000);
startMs = System.currentTimeMillis();
- registry.setMockSuccessReadingRemoteConfig(false);
+ registry.setMockSuccessReadingConfig(false);
registry.afterPropertiesSet();
+ TransformServiceRegistryImpl.Data data = registry.getData();
Thread.sleep(1000); // 1 seconds
data = registry.assertDataChanged(data, "There should have been a read after a few milliseconds that fails");
@@ -456,7 +451,7 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg
// Should switch to normal 4s schedule after the next read, so the read at 12 seconds will be on that schedule.
// It is always possible that another quick one gets scheduled almost straight away after the next read.
- registry.setMockSuccessReadingRemoteConfig(true);
+ registry.setMockSuccessReadingConfig(true);
Thread.sleep(2000); // 9 seconds
data = registry.assertDataChanged(data, "There should have been a read after 8 seconds that succeeds");
@@ -467,7 +462,7 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg
data = registry.assertDataChanged(data, "There should have been a read after 12 seconds that succeeds");
// Should switch back to initial/error schedule after failure
- registry.setMockSuccessReadingRemoteConfig(false);
+ registry.setMockSuccessReadingConfig(false);
Thread.sleep(4000); // 17 seconds
data = registry.assertDataChanged(data, "There should have been a read after 16 seconds that fails");
@@ -476,15 +471,10 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg
}
finally
{
- registry.setMockSuccessReadingRemoteConfig(true);
-
- // Reset scheduler properties just in case another tests needs them in future.
- // We don't start the scheduler with registry.afterPropertiesSet() as this is
- // really just mocked up version of the registry.
+ registry.setMockSuccessReadingConfig(true);
registry.setCronExpression(origCronExpression);
registry.setInitialAndOnErrorCronExpression(origInitialAndOnErrorCronExpression);
registry.setPipelineConfigDir(origPipelineConfigDir);
- registry.setScheduler(null);
}
}
}
diff --git a/src/test/java/org/alfresco/transform/client/model/config/TransformServiceRegistryConfigTest.java b/src/test/java/org/alfresco/transform/client/model/config/TransformServiceRegistryConfigTest.java
index a1d4cb25eb..6abfecd002 100644
--- a/src/test/java/org/alfresco/transform/client/model/config/TransformServiceRegistryConfigTest.java
+++ b/src/test/java/org/alfresco/transform/client/model/config/TransformServiceRegistryConfigTest.java
@@ -33,6 +33,7 @@ import org.apache.log4j.LogManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.quartz.CronExpression;
import java.io.BufferedReader;
import java.io.File;
@@ -93,9 +94,9 @@ public class TransformServiceRegistryConfigTest
TransformServiceRegistryImpl registry = new TransformServiceRegistryImpl()
{
@Override
- protected Data readConfig() throws IOException
+ public boolean readConfig() throws IOException
{
- return createData(); // Empty config
+ return true;
}
@Override
@@ -105,6 +106,8 @@ public class TransformServiceRegistryConfigTest
}
};
registry.setJsonObjectMapper(JSON_OBJECT_MAPPER);
+ registry.setCronExpression(null); // just read once
+ registry.afterPropertiesSet();
return registry;
}
@@ -182,7 +185,7 @@ public class TransformServiceRegistryConfigTest
new SupportedSourceAndTarget(XLS, TXT, 1024000)));
registry = buildTransformServiceRegistryImpl();
- registry.register(registry.getData(), transformer, getBaseUrl(transformer), getClass().getName());
+ registry.register(transformer, getBaseUrl(transformer), getClass().getName());
assertTrue(registry.isSupported(XLS, 1024, TXT, Collections.emptyMap(), null));
assertTrue(registry.isSupported(XLS, 1024000, TXT, null, null));
@@ -223,7 +226,7 @@ public class TransformServiceRegistryConfigTest
registry = buildTransformServiceRegistryImpl();
for (Transformer transformer : transformers)
{
- registry.register(registry.getData(), transformer, getBaseUrl(transformer), getClass().getName());
+ registry.register(transformer, getBaseUrl(transformer), getClass().getName());
}
}
@@ -257,7 +260,7 @@ public class TransformServiceRegistryConfigTest
{
CombinedConfig combinedConfig = new CombinedConfig(log);
combinedConfig.addLocalConfig(path);
- combinedConfig.register(registry.getData(), registry);
+ combinedConfig.register(registry);
}
@Test
@@ -364,7 +367,7 @@ public class TransformServiceRegistryConfigTest
try (Reader reader = new BufferedReader(new FileReader(tempFile)))
{
- registry.register(registry.getData(), reader, getClass().getName());
+ registry.register(reader, getClass().getName());
// Check the count of transforms supported
assertEquals("The number of UNIQUE source to target mimetypes transforms has changed. Config change?",
42, countSupportedTransforms(true));
@@ -671,7 +674,7 @@ public class TransformServiceRegistryConfigTest
new SupportedSourceAndTarget(DOC, GIF, 102400),
new SupportedSourceAndTarget(MSG, GIF, -1)));
- registry.register(registry.getData(), transformer, getBaseUrl(transformer), getClass().getName());
+ registry.register(transformer, getBaseUrl(transformer), getClass().getName());
assertSupported(DOC, 1024, GIF, null, "doclib", "");
assertSupported(MSG, 1024, GIF, null, "doclib", "");