mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
ALF-14306: Merged DEV to HEAD (4.2)
Add priorities to transformers - Addition of a separate Transformers subsystem (holds configuration to allow JMX to be used to reset it on the fly) - Moved supported, unsupported and explicit transformation configuration from spring into transformers.properties in the subsystem - Moved all transformer limits configuration from spring and into transformers.properties with the exception of some added for thumbnails and the rendering service - not done as this code is known to be changing. - Added priority, errorTimes and thresholdCount to enable selection of transformers by priority. - Removed the concept of 'Explicit' transformation and replaced with priority and unsupported. - Added logging to aid in the creation of global properties and removal of spring configuration. - Implementation of spring pluggable transformation selector that uses priority. - Merging current state of code changes to allow other work in this area to take place. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@46719 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -30,6 +30,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.extensions.surf.util.ParameterCheck;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -47,7 +48,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractContentTransformer implements ContentTransformer
|
||||
public abstract class AbstractContentTransformer implements ContentTransformer, BeanNameAware
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(AbstractContentTransformer.class);
|
||||
|
||||
@@ -58,6 +59,9 @@ public abstract class AbstractContentTransformer implements ContentTransformer
|
||||
private double averageTime = 0.0;
|
||||
private long count = 0L;
|
||||
|
||||
/** The bean name. */
|
||||
private String beanName;
|
||||
|
||||
/**
|
||||
* All transformers start with an average transformation time of 0.0ms.
|
||||
*/
|
||||
@@ -408,6 +412,11 @@ public abstract class AbstractContentTransformer implements ContentTransformer
|
||||
return (long) averageTime;
|
||||
}
|
||||
|
||||
public long getTransformationTime(String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
return (long) averageTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records and updates the average transformation time for this transformer.
|
||||
* <p>
|
||||
@@ -433,4 +442,29 @@ public abstract class AbstractContentTransformer implements ContentTransformer
|
||||
double diffTime = ((double) transformationTime) - averageTime;
|
||||
averageTime += diffTime / (double) count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Spring bean name.
|
||||
*/
|
||||
@Override
|
||||
public void setBeanName(String beanName)
|
||||
{
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Spring bean name.
|
||||
*/
|
||||
public String getBeanName()
|
||||
{
|
||||
return beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns transformer name. Uses the Spring bean name, but if null uses the class name.
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return (beanName == null) ? getClass().getSimpleName() : beanName;
|
||||
}
|
||||
}
|
||||
|
@@ -19,7 +19,6 @@
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||
@@ -46,13 +45,20 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo
|
||||
private static final Log logger = LogFactory.getLog(AbstractContentTransformer2.class);
|
||||
|
||||
private ContentTransformerRegistry registry;
|
||||
private Properties properties;
|
||||
private double averageTime;
|
||||
private long count = 0L;
|
||||
|
||||
|
||||
private ThreadLocal<Integer> depth = new ThreadLocal<Integer>()
|
||||
{
|
||||
@Override
|
||||
protected Integer initialValue()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* All transformers start with an average transformation time of 0.0 ms,
|
||||
* unless there is an Alfresco global property {@code <beanName>.initialTime}.
|
||||
* unless there is an Alfresco global property {@code <beanName>.time}.
|
||||
* May also be set for given combinations of source and target mimetypes.
|
||||
*/
|
||||
protected AbstractContentTransformer2()
|
||||
{
|
||||
@@ -68,70 +74,12 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Alfresco global properties.
|
||||
*/
|
||||
public void setProperties(Properties properties)
|
||||
{
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the averageTime and count (if global properties were used to set the averageTime).
|
||||
* Both default to 0. The property names use the transformer bean name with a ".time"
|
||||
* or ".count" suffix. Spring bean configuration is not being used as we don't wish to
|
||||
* break existing transformers that know nothing about these properties.
|
||||
*/
|
||||
private void setAverageTimeFromAlfrescoGlobalProperties()
|
||||
{
|
||||
String beanName = getBeanName();
|
||||
averageTime = Long.valueOf(getPositiveLongProperty(beanName+".time", 0L));
|
||||
if (averageTime > 0.0)
|
||||
{
|
||||
// This normally is a large number so that it does not change much if used.
|
||||
count = Long.valueOf(getPositiveLongProperty(beanName+".count", 10000));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a positive long value from an optional Alfresco global property.
|
||||
* Invalid values are ignored but a log message is issued.
|
||||
* @param name of the property
|
||||
* @param defaultValue if the property does not exist or is negative
|
||||
* @return the value
|
||||
*/
|
||||
private long getPositiveLongProperty(String name, long defaultValue)
|
||||
{
|
||||
long value = defaultValue;
|
||||
if (properties != null)
|
||||
{
|
||||
String property = properties.getProperty(name);
|
||||
if (property != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
value = Long.valueOf(property);
|
||||
if (value < 0)
|
||||
{
|
||||
value = defaultValue;
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
logger.warn("Alfresco global property "+name+" is must be a positive Java long value. Using "+defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(this.getClass().getSimpleName())
|
||||
.append("[ average=").append((long)averageTime).append("ms")
|
||||
.append("[ average=").append(transformerConfig.getStatistics(this, null, null).getAverageTime()).append("ms")
|
||||
.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -140,10 +88,12 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo
|
||||
* Registers this instance with the {@link #setRegistry(ContentTransformerRegistry) registry}
|
||||
* if it is present.
|
||||
*
|
||||
* THIS IS A CUSTOME SPRING INIT METHOD
|
||||
* THIS IS A CUSTOM SPRING INIT METHOD
|
||||
*/
|
||||
public void register()
|
||||
{
|
||||
super.register();
|
||||
|
||||
if (registry == null)
|
||||
{
|
||||
logger.warn("Property 'registry' has not been set. Ignoring auto-registration: \n" +
|
||||
@@ -151,8 +101,6 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo
|
||||
return;
|
||||
}
|
||||
|
||||
setAverageTimeFromAlfrescoGlobalProperties();
|
||||
|
||||
// register this instance for the fallback case
|
||||
registry.addTransformer(this);
|
||||
}
|
||||
@@ -211,115 +159,127 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo
|
||||
public final void transform(ContentReader reader, ContentWriter writer, TransformationOptions options)
|
||||
throws ContentIOException
|
||||
{
|
||||
// begin timing
|
||||
long before = System.currentTimeMillis();
|
||||
|
||||
// check options map
|
||||
if (options == null)
|
||||
{
|
||||
options = new TransformationOptions();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (transformerDebug.isEnabled())
|
||||
depth.set(depth.get()+1);
|
||||
|
||||
// begin timing
|
||||
long before = System.currentTimeMillis();
|
||||
|
||||
String sourceMimetype = reader.getMimetype();
|
||||
String targetMimetype = writer.getMimetype();
|
||||
|
||||
// check options map
|
||||
if (options == null)
|
||||
{
|
||||
transformerDebug.pushTransform(this, reader.getContentUrl(), reader.getMimetype(),
|
||||
writer.getMimetype(), reader.getSize(), options);
|
||||
options = new TransformationOptions();
|
||||
}
|
||||
|
||||
// Check the transformability
|
||||
checkTransformable(reader, writer, options);
|
||||
|
||||
// Pass on any limits to the reader
|
||||
setReaderLimits(reader, writer, options);
|
||||
try
|
||||
{
|
||||
if (transformerDebug.isEnabled())
|
||||
{
|
||||
transformerDebug.pushTransform(this, reader.getContentUrl(), sourceMimetype,
|
||||
targetMimetype, reader.getSize(), options);
|
||||
}
|
||||
|
||||
// Check the transformability
|
||||
checkTransformable(reader, writer, options);
|
||||
|
||||
// Pass on any limits to the reader
|
||||
setReaderLimits(reader, writer, options);
|
||||
|
||||
// Transform
|
||||
transformInternal(reader, writer, options);
|
||||
}
|
||||
catch (ContentServiceTransientException cste)
|
||||
{
|
||||
// A transient failure has occurred within the content transformer.
|
||||
// This should not be interpreted as a failure and therefore we should not
|
||||
// update the transformer's average time.
|
||||
// Transform
|
||||
transformInternal(reader, writer, options);
|
||||
}
|
||||
catch (ContentServiceTransientException cste)
|
||||
{
|
||||
// A transient failure has occurred within the content transformer.
|
||||
// This should not be interpreted as a failure and therefore we should not
|
||||
// update the transformer's average time.
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Transformation has been transiently declined: \n" +
|
||||
" reader: " + reader + "\n" +
|
||||
" writer: " + writer + "\n" +
|
||||
" options: " + options + "\n" +
|
||||
" transformer: " + this);
|
||||
}
|
||||
// the finally block below will still perform tidyup. Otherwise we're done.
|
||||
// We rethrow the exception
|
||||
throw cste;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// Make sure that this transformation gets set back i.t.o. time taken.
|
||||
// This will ensure that transformers that compete for the same transformation
|
||||
// will be prejudiced against transformers that tend to fail
|
||||
recordError(sourceMimetype, targetMimetype);
|
||||
|
||||
// Ask Tika to detect the document, and report back on if
|
||||
// the current mime type is plausible
|
||||
String differentType = getMimetypeService().getMimetypeIfNotMatches(reader.getReader());
|
||||
|
||||
// Report the error
|
||||
if(differentType == null)
|
||||
{
|
||||
transformerDebug.debug(" Failed", e);
|
||||
throw new ContentIOException("Content conversion failed: \n" +
|
||||
" reader: " + reader + "\n" +
|
||||
" writer: " + writer + "\n" +
|
||||
" options: " + options.toString(false) + "\n" +
|
||||
" limits: " + getLimits(reader, writer, options),
|
||||
e);
|
||||
}
|
||||
else
|
||||
{
|
||||
transformerDebug.debug(" Failed: Mime type was '"+differentType+"'", e);
|
||||
throw new ContentIOException("Content conversion failed: \n" +
|
||||
" reader: " + reader + "\n" +
|
||||
" writer: " + writer + "\n" +
|
||||
" options: " + options.toString(false) + "\n" +
|
||||
" limits: " + getLimits(reader, writer, options) + "\n" +
|
||||
" claimed mime type: " + reader.getMimetype() + "\n" +
|
||||
" detected mime type: " + differentType,
|
||||
e);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
transformerDebug.popTransform();
|
||||
|
||||
// check that the reader and writer are both closed
|
||||
if (reader.isChannelOpen())
|
||||
{
|
||||
logger.error("Content reader not closed by transformer: \n" +
|
||||
" reader: " + reader + "\n" +
|
||||
" transformer: " + this);
|
||||
}
|
||||
if (writer.isChannelOpen())
|
||||
{
|
||||
logger.error("Content writer not closed by transformer: \n" +
|
||||
" writer: " + writer + "\n" +
|
||||
" transformer: " + this);
|
||||
}
|
||||
}
|
||||
|
||||
// record time
|
||||
long after = System.currentTimeMillis();
|
||||
recordTime(sourceMimetype, targetMimetype, after - before);
|
||||
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Transformation has been transiently declined: \n" +
|
||||
logger.debug("Completed transformation: \n" +
|
||||
" reader: " + reader + "\n" +
|
||||
" writer: " + writer + "\n" +
|
||||
" options: " + options + "\n" +
|
||||
" transformer: " + this);
|
||||
}
|
||||
// the finally block below will still perform tidyup. Otherwise we're done.
|
||||
// We rethrow the exception
|
||||
throw cste;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// Make sure that this transformation gets set back i.t.o. time taken.
|
||||
// This will ensure that transformers that compete for the same transformation
|
||||
// will be prejudiced against transformers that tend to fail
|
||||
recordTime(60 * 1000); // 1 minute, i.e. rubbish
|
||||
|
||||
// Ask Tika to detect the document, and report back on if
|
||||
// the current mime type is plausible
|
||||
String differentType = getMimetypeService().getMimetypeIfNotMatches(reader.getReader());
|
||||
|
||||
// Report the error
|
||||
if(differentType == null)
|
||||
{
|
||||
transformerDebug.debug(" Failed", e);
|
||||
throw new ContentIOException("Content conversion failed: \n" +
|
||||
" reader: " + reader + "\n" +
|
||||
" writer: " + writer + "\n" +
|
||||
" options: " + options.toString(false) + "\n" +
|
||||
" limits: " + getLimits(reader, writer, options),
|
||||
e);
|
||||
}
|
||||
else
|
||||
{
|
||||
transformerDebug.debug(" Failed: Mime type was '"+differentType+"'", e);
|
||||
throw new ContentIOException("Content conversion failed: \n" +
|
||||
" reader: " + reader + "\n" +
|
||||
" writer: " + writer + "\n" +
|
||||
" options: " + options.toString(false) + "\n" +
|
||||
" limits: " + getLimits(reader, writer, options) + "\n" +
|
||||
" claimed mime type: " + reader.getMimetype() + "\n" +
|
||||
" detected mime type: " + differentType,
|
||||
e);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
transformerDebug.popTransform();
|
||||
|
||||
// check that the reader and writer are both closed
|
||||
if (reader.isChannelOpen())
|
||||
{
|
||||
logger.error("Content reader not closed by transformer: \n" +
|
||||
" reader: " + reader + "\n" +
|
||||
" transformer: " + this);
|
||||
}
|
||||
if (writer.isChannelOpen())
|
||||
{
|
||||
logger.error("Content writer not closed by transformer: \n" +
|
||||
" writer: " + writer + "\n" +
|
||||
" transformer: " + this);
|
||||
}
|
||||
}
|
||||
|
||||
// record time
|
||||
long after = System.currentTimeMillis();
|
||||
recordTime(after - before);
|
||||
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Completed transformation: \n" +
|
||||
" reader: " + reader + "\n" +
|
||||
" writer: " + writer + "\n" +
|
||||
" options: " + options + "\n" +
|
||||
" transformer: " + this);
|
||||
depth.set(depth.get()+1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +296,23 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo
|
||||
*/
|
||||
public synchronized long getTransformationTime()
|
||||
{
|
||||
return (long) averageTime;
|
||||
return transformerConfig.getStatistics(this, null, null).getAverageTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the calculated running average of the current transformations
|
||||
*/
|
||||
public synchronized long getTransformationTime(String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
return transformerConfig.getStatistics(this, sourceMimetype, targetMimetype).getAverageTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use method with mimetypes.
|
||||
*/
|
||||
protected final synchronized void recordTime(long transformationTime)
|
||||
{
|
||||
recordTime(TransformerConfig.ANY, TransformerConfig.ANY, transformationTime);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,20 +324,33 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo
|
||||
* This method is thread-safe. The time spent in this method is negligible
|
||||
* so the impact will be minor.
|
||||
*
|
||||
* @param sourceMimetype
|
||||
* @param targetMimetype
|
||||
* @param transformationTime the time it took to perform the transformation.
|
||||
* The value may be 0.
|
||||
*/
|
||||
protected final synchronized void recordTime(long transformationTime)
|
||||
protected final synchronized void recordTime(String sourceMimetype, String targetMimetype,
|
||||
long transformationTime)
|
||||
{
|
||||
if (count == Long.MAX_VALUE)
|
||||
transformerConfig.getStatistics(this, sourceMimetype, targetMimetype).recordTime(transformationTime);
|
||||
if (depth.get() == 1)
|
||||
{
|
||||
// we have reached the max count - reduce it by half
|
||||
// the average fluctuation won't be extreme
|
||||
count /= 2L;
|
||||
transformerConfig.getStatistics(null, sourceMimetype, targetMimetype).recordTime(transformationTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Records an error and updates the average time as if the transformation took a
|
||||
* long time, so that it is less likely to be called again.
|
||||
* @param sourceMimetype
|
||||
* @param targetMimetype
|
||||
*/
|
||||
protected final synchronized void recordError(String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
transformerConfig.getStatistics(this, sourceMimetype, targetMimetype).recordError();
|
||||
if (depth.get() == 1)
|
||||
{
|
||||
transformerConfig.getStatistics(null, sourceMimetype, targetMimetype).recordError();
|
||||
}
|
||||
// adjust the average
|
||||
count++;
|
||||
double diffTime = ((double) transformationTime) - averageTime;
|
||||
averageTime += diffTime / (double) count;
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -18,14 +18,22 @@
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import static org.alfresco.service.cmr.repository.TransformationOptionLimits.OPT_MAX_PAGES;
|
||||
import static org.alfresco.service.cmr.repository.TransformationOptionLimits.OPT_MAX_SOURCE_SIZE_K_BYTES;
|
||||
import static org.alfresco.service.cmr.repository.TransformationOptionLimits.OPT_PAGE_LIMIT;
|
||||
import static org.alfresco.service.cmr.repository.TransformationOptionLimits.OPT_READ_LIMIT_K_BYTES;
|
||||
import static org.alfresco.service.cmr.repository.TransformationOptionLimits.OPT_READ_LIMIT_TIME_MS;
|
||||
import static org.alfresco.service.cmr.repository.TransformationOptionLimits.OPT_TIMEOUT_MS;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.alfresco.repo.content.AbstractContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptionLimits;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
|
||||
/**
|
||||
* Provides transformation limits for {@link org.alfresco.repo.content.transform.ContentTransformer}
|
||||
@@ -38,26 +46,14 @@ import org.springframework.beans.factory.BeanNameAware;
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public abstract class AbstractContentTransformerLimits extends ContentTransformerHelper implements ContentTransformer, BeanNameAware
|
||||
public abstract class AbstractContentTransformerLimits extends ContentTransformerHelper implements ContentTransformer
|
||||
{
|
||||
/** Transformer wide Time, KBytes and page limits */
|
||||
private TransformationOptionLimits limits = new TransformationOptionLimits();
|
||||
|
||||
/**
|
||||
* Time, KBytes and page limits by source and target mimetype combination.
|
||||
* The first map's key is the source mimetype. The second map's key is the
|
||||
* target mimetype and the value are the limits. */
|
||||
private Map<String, Map<String, TransformationOptionLimits>> mimetypeLimits;
|
||||
|
||||
/** Indicates if 'page' limits are supported. */
|
||||
private boolean pageLimitsSupported;
|
||||
|
||||
/** For debug **/
|
||||
protected TransformerDebug transformerDebug;
|
||||
|
||||
/** The bean name. Used in debug only. */
|
||||
private String beanName;
|
||||
|
||||
/**
|
||||
* Indicates if 'page' limits are supported.
|
||||
* @return false by default.
|
||||
@@ -172,21 +168,17 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme
|
||||
*/
|
||||
protected long getTimeoutMs()
|
||||
{
|
||||
return limits.getTimeoutMs();
|
||||
return getLimits().getTimeoutMs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a timeout (ms) on the InputStream after which an IOExecption is thrown
|
||||
* to terminate very slow transformations or to terminate (kill) a subprocess.
|
||||
* @param timeoutMs in milliseconds. If less than or equal to zero (the default)
|
||||
* there is no timeout.
|
||||
* If greater than zero the {@code readLimitTimeMs} must not be set.
|
||||
* @deprecated transformation limits are now set with global properties rather than spring configuration.
|
||||
*/
|
||||
public void setTimeoutMs(long timeoutMs)
|
||||
{
|
||||
limits.setTimeoutMs(timeoutMs);
|
||||
deprecatedSetter(OPT_TIMEOUT_MS+'='+timeoutMs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the limit in terms of the amount of data read (by time) to limit transformations where
|
||||
* only the start of the content is needed. After this limit is reached the InputStream reports
|
||||
@@ -195,19 +187,15 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme
|
||||
*/
|
||||
protected long getReadLimitTimeMs()
|
||||
{
|
||||
return limits.getReadLimitTimeMs();
|
||||
return getLimits().getReadLimitTimeMs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a limit in terms of the amount of data read (by time) to limit transformations where
|
||||
* only the start of the content is needed. After this limit is reached the InputStream reports
|
||||
* end of file.
|
||||
* @param readLimitBytes if less than or equal to zero (the default) there is no limit.
|
||||
* If greater than zero the {@code timeoutMs} must not be set.
|
||||
* @deprecated transformation limits are now set with global properties rather than spring configuration.
|
||||
*/
|
||||
public void setReadLimitTimeMs(long readLimitTimeMs)
|
||||
{
|
||||
limits.setReadLimitTimeMs(readLimitTimeMs);
|
||||
deprecatedSetter(OPT_READ_LIMIT_TIME_MS+'='+readLimitTimeMs);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,19 +206,15 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme
|
||||
*/
|
||||
protected long getMaxSourceSizeKBytes()
|
||||
{
|
||||
return limits.getMaxSourceSizeKBytes();
|
||||
return getLimits().getMaxSourceSizeKBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a maximum source content size, to skip transformations where
|
||||
* the source is just too large to expect it to perform. If the source is larger
|
||||
* the transformer indicates it is not available.
|
||||
* @param maxSourceSizeKBytes if less than or equal to zero (the default) there is no limit.
|
||||
* If greater than zero the {@code readLimitKBytes} must not be set.
|
||||
* @deprecated transformation limits are now set with global properties rather than spring configuration.
|
||||
*/
|
||||
public void setMaxSourceSizeKBytes(long maxSourceSizeKBytes)
|
||||
{
|
||||
limits.setMaxSourceSizeKBytes(maxSourceSizeKBytes);
|
||||
deprecatedSetter(OPT_MAX_SOURCE_SIZE_K_BYTES+'='+maxSourceSizeKBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,19 +225,15 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme
|
||||
*/
|
||||
protected long getReadLimitKBytes()
|
||||
{
|
||||
return limits.getReadLimitKBytes();
|
||||
return getLimits().getReadLimitKBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a limit in terms of the about of data read to limit transformations where
|
||||
* only the start of the content is needed. After this limit is reached the InputStream reports
|
||||
* end of file.
|
||||
* @param readLimitKBytes if less than or equal to zero (the default) there is no limit.
|
||||
* If greater than zero the {@code maxSourceSizeKBytes} must not be set.
|
||||
* @deprecated transformation limits are now set with global properties rather than spring configuration.
|
||||
*/
|
||||
public void setReadLimitKBytes(long readLimitKBytes)
|
||||
{
|
||||
limits.setReadLimitKBytes(readLimitKBytes);
|
||||
deprecatedSetter(OPT_READ_LIMIT_K_BYTES+'='+readLimitKBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -262,18 +242,15 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme
|
||||
*/
|
||||
protected int getMaxPages()
|
||||
{
|
||||
return limits.getMaxPages();
|
||||
return getLimits().getMaxPages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of pages read from the source before an exception is thrown.
|
||||
*
|
||||
* @param maxPages the number of pages to be read from the source. If less than or equal to zero
|
||||
* (the default) no limit is applied.
|
||||
* @deprecated transformation limits are now set with global properties rather than spring configuration.
|
||||
*/
|
||||
public void setMaxPages(int maxPages)
|
||||
{
|
||||
limits.setMaxPages(maxPages);
|
||||
deprecatedSetter(OPT_MAX_PAGES+'='+maxPages);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -282,18 +259,15 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme
|
||||
*/
|
||||
protected int getPageLimit()
|
||||
{
|
||||
return limits.getPageLimit();
|
||||
return getLimits().getPageLimit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of pages read from the source before returning EOF.
|
||||
*
|
||||
* @param pageLimit the number of pages to be read from the source. If less
|
||||
* than or equal to zero (the default) no limit is applied.
|
||||
* @deprecated transformation limits are now set with global properties rather than spring configuration.
|
||||
*/
|
||||
public void setPageLimit(int pageLimit)
|
||||
{
|
||||
limits.setPageLimit(pageLimit);
|
||||
deprecatedSetter(OPT_PAGE_LIMIT+'='+pageLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -301,33 +275,57 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme
|
||||
*/
|
||||
protected TransformationOptionLimits getLimits()
|
||||
{
|
||||
return limits;
|
||||
return transformerConfig.getLimits(this, null, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets max and limit values for time, size and pages in a single operation.
|
||||
* @deprecated transformation limits are now set with global properties rather than spring configuration.
|
||||
*/
|
||||
public void setLimits(TransformationOptionLimits limits)
|
||||
{
|
||||
this.limits = limits;
|
||||
deprecatedLimitsSetter("", limits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the max and limit values for time, size and pages per source and target mimetype
|
||||
* combination.
|
||||
*/
|
||||
protected Map<String, Map<String, TransformationOptionLimits>> getMimetypeLimits()
|
||||
{
|
||||
return mimetypeLimits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the max and limit values for time, size and pages per source and target mimetype
|
||||
* combination.
|
||||
* @deprecated transformation limits are now set with global properties rather than spring configuration.
|
||||
*/
|
||||
public void setMimetypeLimits(Map<String, Map<String, TransformationOptionLimits>> mimetypeLimits)
|
||||
{
|
||||
this.mimetypeLimits = mimetypeLimits;
|
||||
for (Entry<String, Map<String, TransformationOptionLimits>> source: mimetypeLimits.entrySet())
|
||||
{
|
||||
String sourceExt = getExtensionOrAny(source.getKey());
|
||||
for (Entry<String, TransformationOptionLimits> target: source.getValue().entrySet())
|
||||
{
|
||||
String targetExt = getExtensionOrAny(target.getKey());
|
||||
TransformationOptionLimits limits = target.getValue();
|
||||
String mimetypeSuffix = TransformerConfig.MIMETYPES_SEPARATOR.substring(1)+sourceExt+'.'+targetExt;
|
||||
|
||||
deprecatedLimitsSetter(mimetypeSuffix, limits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void deprecatedLimitsSetter(String mimetypeSuffix, TransformationOptionLimits limits)
|
||||
{
|
||||
if (limits.supported())
|
||||
{
|
||||
// Ignore limit pairs that are not specified
|
||||
for (String limit: new String[] {
|
||||
limits.getTimePair().toString(OPT_TIMEOUT_MS, OPT_READ_LIMIT_TIME_MS),
|
||||
limits.getKBytesPair().toString(OPT_MAX_SOURCE_SIZE_K_BYTES, OPT_READ_LIMIT_K_BYTES),
|
||||
limits.getPagesPair().toString(OPT_MAX_PAGES, OPT_PAGE_LIMIT)
|
||||
})
|
||||
{
|
||||
if (limit != null)
|
||||
{
|
||||
deprecatedSetter(mimetypeSuffix+'.'+limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
deprecatedSetter(mimetypeSuffix+TransformerConfig.SUPPORTED+"=false");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -339,7 +337,7 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme
|
||||
TransformationOptions options)
|
||||
{
|
||||
return (reader == null || writer == null)
|
||||
? limits.combine(options.getLimits())
|
||||
? getLimits().combine(options.getLimits())
|
||||
: getLimits(reader.getMimetype(), writer.getMimetype(), options);
|
||||
}
|
||||
|
||||
@@ -351,63 +349,8 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme
|
||||
protected TransformationOptionLimits getLimits(String sourceMimetype, String targetMimetype,
|
||||
TransformationOptions options)
|
||||
{
|
||||
// Get the limits for the source and target mimetypes
|
||||
TransformationOptionLimits mimetypeLimits = null;
|
||||
if (this.mimetypeLimits != null)
|
||||
{
|
||||
boolean anySource = false;
|
||||
Map<String, TransformationOptionLimits> targetLimits =
|
||||
this.mimetypeLimits.get(sourceMimetype);
|
||||
if (targetLimits == null)
|
||||
{
|
||||
targetLimits = this.mimetypeLimits.get("*");
|
||||
anySource = true;
|
||||
}
|
||||
if (targetLimits != null)
|
||||
{
|
||||
mimetypeLimits = targetLimits.get(targetMimetype);
|
||||
if (mimetypeLimits == null)
|
||||
{
|
||||
mimetypeLimits = targetLimits.get("*");
|
||||
|
||||
// Allow for the case where have specific source and target mimetype limits
|
||||
// and general source limits (avoid having to repeat the general values in
|
||||
// each specific source definition)
|
||||
if (mimetypeLimits == null && !anySource)
|
||||
{
|
||||
targetLimits = this.mimetypeLimits.get("*");
|
||||
if (targetLimits != null)
|
||||
{
|
||||
mimetypeLimits = targetLimits.get(targetMimetype);
|
||||
if (mimetypeLimits == null)
|
||||
{
|
||||
mimetypeLimits = targetLimits.get("*");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TransformationOptionLimits combined = (mimetypeLimits == null) ? limits : limits.combine(mimetypeLimits);
|
||||
return (options == null) ? combined : combined.combine(options.getLimits());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Spring bean name - only for use in debug.
|
||||
*/
|
||||
@Override
|
||||
public void setBeanName(String beanName)
|
||||
{
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Spring bean name - only for use in debug.
|
||||
*/
|
||||
public String getBeanName()
|
||||
{
|
||||
return beanName;
|
||||
TransformationOptionLimits limits = transformerConfig.getLimits(this, sourceMimetype, targetMimetype);
|
||||
return (options == null) ? limits : limits.combine(options.getLimits());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -28,6 +28,7 @@ import java.util.Map;
|
||||
import org.alfresco.repo.content.AbstractContentReader;
|
||||
import org.alfresco.repo.content.ContentMinimalContextTestSuite;
|
||||
import org.alfresco.repo.content.AbstractContentReaderLimitTest.DummyAbstractContentReader;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
@@ -43,9 +44,9 @@ import org.springframework.context.ApplicationContext;
|
||||
*/
|
||||
public class AbstractContentTransformerLimitsTest
|
||||
{
|
||||
private static final String A = "a";
|
||||
private static final String B = "b";
|
||||
private static final String C = "c";
|
||||
private static final String A = MimetypeMap.MIMETYPE_XML;
|
||||
private static final String B = MimetypeMap.MIMETYPE_HTML;
|
||||
private static final String C = MimetypeMap.MIMETYPE_PDF;
|
||||
|
||||
private AbstractContentTransformerLimits transformer;
|
||||
private TransformationOptionLimits limits;
|
||||
@@ -59,6 +60,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
MimetypeService mimetypeService = serviceRegistry.getMimetypeService();
|
||||
TransformerDebug transformerDebug = (TransformerDebug) ctx.getBean("transformerDebug");
|
||||
TransformerConfig transformerConfig = (TransformerConfig) ctx.getBean("transformerConfig");
|
||||
|
||||
transformer = new AbstractContentTransformer2()
|
||||
{
|
||||
@@ -77,6 +79,8 @@ public class AbstractContentTransformerLimitsTest
|
||||
};
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
transformer.setBeanName("transformer.test"+System.currentTimeMillis()%100000);
|
||||
|
||||
limits = new TransformationOptionLimits();
|
||||
options = new TransformationOptions();
|
||||
@@ -104,6 +108,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
{
|
||||
long value = 1234;
|
||||
transformer.setTimeoutMs(value);
|
||||
transformer.register();
|
||||
long actual = transformer.getTimeoutMs();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
}
|
||||
@@ -113,6 +118,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
{
|
||||
long value = 1234;
|
||||
transformer.setReadLimitTimeMs(value);
|
||||
transformer.register();
|
||||
long actual = transformer.getReadLimitTimeMs();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
}
|
||||
@@ -122,6 +128,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
{
|
||||
long value = 1234;
|
||||
transformer.setMaxSourceSizeKBytes(value);
|
||||
transformer.register();
|
||||
long actual = transformer.getMaxSourceSizeKBytes();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
}
|
||||
@@ -131,6 +138,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
{
|
||||
long value = 1234;
|
||||
transformer.setReadLimitKBytes(value);
|
||||
transformer.register();
|
||||
long actual = transformer.getReadLimitKBytes();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
}
|
||||
@@ -140,6 +148,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
{
|
||||
int value = 1234;
|
||||
transformer.setMaxPages(value);
|
||||
transformer.register();
|
||||
int actual = transformer.getMaxPages();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
}
|
||||
@@ -149,6 +158,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
{
|
||||
int value = 1234;
|
||||
transformer.setPageLimit(value);
|
||||
transformer.register();
|
||||
int actual = transformer.getPageLimit();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
}
|
||||
@@ -161,6 +171,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
addMimetypeLimits(A, B, limits);
|
||||
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
transformer.register();
|
||||
long actual = transformer.getLimits(A, B, options).getMaxSourceSizeKBytes();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
|
||||
@@ -176,6 +187,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
addMimetypeLimits(A, "*", limits);
|
||||
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
transformer.register();
|
||||
long actual = transformer.getLimits(A, B, options).getMaxSourceSizeKBytes();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
|
||||
@@ -191,6 +203,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
addMimetypeLimits("*", B, limits);
|
||||
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
transformer.register();
|
||||
long actual = transformer.getLimits(A, B, options).getMaxSourceSizeKBytes();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
|
||||
@@ -206,6 +219,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
addMimetypeLimits(A, B, limits);
|
||||
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
transformer.register();
|
||||
long actual = transformer.getLimits(A, B, options).getMaxSourceSizeKBytes();
|
||||
assertEquals("Getter did not return set value", value+1, actual);
|
||||
|
||||
@@ -228,6 +242,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
limits.setMaxSourceSizeKBytes(kValue);
|
||||
addMimetypeLimits(A, B, limits);
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
transformer.register();
|
||||
|
||||
assertEquals("Expected to have set value returned", kValue,
|
||||
transformer.getMaxSourceSizeKBytes(A, B, options));
|
||||
@@ -235,51 +250,115 @@ public class AbstractContentTransformerLimitsTest
|
||||
// With a mimetype that does not have any specific limits
|
||||
assertEquals("Expected to have -1 (unlimited) returned", -1,
|
||||
transformer.getMaxSourceSizeKBytes(C, B, options));
|
||||
}
|
||||
|
||||
@Test
|
||||
// Combination using just transformer limit to start with
|
||||
public void testGetMaxSourceSizeKBytesCombination() throws Exception
|
||||
{
|
||||
long kValue = 12;
|
||||
long byteValue = kValue*1024;
|
||||
|
||||
|
||||
// Clear the mimetype limits and double check
|
||||
limits.setMaxSourceSizeKBytes(-1);
|
||||
|
||||
assertEquals("Expected to have -1 (unlimited) returned", -1,
|
||||
transformer.getMaxSourceSizeKBytes(A, B, options));
|
||||
// Not set mimetype limits yet
|
||||
assertTrue("No limits so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
|
||||
// Check for combinations with transformer limits
|
||||
|
||||
// a) Using just transformer limit to start with
|
||||
transformer.setMaxSourceSizeKBytes(kValue);
|
||||
transformer.register();
|
||||
assertEquals("Expected to have transformer set value returned", kValue,
|
||||
transformer.getMaxSourceSizeKBytes(A, B, options));
|
||||
}
|
||||
|
||||
// b) combination where transformer limit is used
|
||||
@Test
|
||||
// Combination where transformer limit is used
|
||||
public void testGetMaxSourceSizeKBytesCombinationTransUsed() throws Exception
|
||||
{
|
||||
long kValue = 12;
|
||||
long byteValue = kValue*1024;
|
||||
|
||||
// Not set mimetype limits yet
|
||||
assertTrue("No limits so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
|
||||
transformer.setMaxSourceSizeKBytes(kValue);
|
||||
limits.setMaxSourceSizeKBytes(kValue+1);
|
||||
addMimetypeLimits(A, B, limits);
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
transformer.register();
|
||||
assertEquals("Expected to have transformer set value returned", kValue,
|
||||
transformer.getMaxSourceSizeKBytes(A, B, options));
|
||||
|
||||
// c) combination where mimetype limit is used
|
||||
}
|
||||
|
||||
@Test
|
||||
// Combination where mimetype limit is used
|
||||
public void testGetMaxSourceSizeKBytesCombinationMimetypeUsed() throws Exception
|
||||
{
|
||||
long kValue = 12;
|
||||
long byteValue = kValue*1024;
|
||||
|
||||
// Not set mimetype limits yet
|
||||
assertTrue("No limits so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
|
||||
transformer.setMaxSourceSizeKBytes(kValue+1);
|
||||
limits.setMaxSourceSizeKBytes(kValue);
|
||||
addMimetypeLimits(A, B, limits);
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
transformer.register();
|
||||
assertEquals("Expected to have transformer set value returned", kValue,
|
||||
transformer.getMaxSourceSizeKBytes(A, B, options));
|
||||
}
|
||||
|
||||
@Test
|
||||
// Check no limit when page limit set on a transformer that does not support page limit
|
||||
// maxSourceSizeKbytes value should be ignored if a page limit is in use
|
||||
public void testGetMaxSourceSizeKBytesPageSupportsNot() throws Exception
|
||||
{
|
||||
long kValue = 12;
|
||||
long byteValue = kValue*1024;
|
||||
|
||||
// Check no limit when page limit set on a transformer that does not support page limit
|
||||
// Not set mimetype limits yet
|
||||
assertTrue("No limits so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
|
||||
transformer.setPageLimitsSuported(false);
|
||||
transformer.setMaxSourceSizeKBytes(kValue);
|
||||
limits.setMaxSourceSizeKBytes(kValue+1);
|
||||
limits.setPageLimit(1);
|
||||
addMimetypeLimits(A, B, limits);
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
transformer.register();
|
||||
assertEquals("Expected to ignore the page limit as the transformer does not support it", kValue,
|
||||
transformer.getMaxSourceSizeKBytes(A, B, options));
|
||||
}
|
||||
@Test
|
||||
// Check no limit when page limit set on a transformer that does support page limit
|
||||
// maxSourceSizeKbytes value should be ignored if a page limit is in use
|
||||
public void testGetMaxSourceSizeKBytesPageSupports() throws Exception
|
||||
{
|
||||
long kValue = 12;
|
||||
long byteValue = kValue*1024;
|
||||
|
||||
// Check no limit when page limit set on a transformer that does support page limit
|
||||
// Not set mimetype limits yet
|
||||
assertTrue("No limits so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
|
||||
transformer.setPageLimitsSuported(true);
|
||||
transformer.setMaxSourceSizeKBytes(kValue);
|
||||
limits.setMaxSourceSizeKBytes(kValue+1);
|
||||
transformer.setPageLimitsSuported(true);
|
||||
limits.setPageLimit(1);
|
||||
addMimetypeLimits(A, B, limits);
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
transformer.register();
|
||||
assertEquals("Expected to have -1 (unlimited) returned when there are page limits", -1,
|
||||
transformer.getMaxSourceSizeKBytes(A, B, options));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsTransformableSize() throws Exception
|
||||
// Using limit on a mimetype
|
||||
public void testIsTransformableSizeMimetype() throws Exception
|
||||
{
|
||||
long kValue = 12;
|
||||
long byteValue = kValue*1024;
|
||||
@@ -292,12 +371,13 @@ public class AbstractContentTransformerLimitsTest
|
||||
limits.setMaxSourceSizeKBytes(kValue);
|
||||
addMimetypeLimits(A, B, limits);
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
transformer.register();
|
||||
|
||||
assertTrue("Size is less than limit so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue-1, B, options));
|
||||
assertTrue("Size is equal to limit so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue, B, options));
|
||||
assertFalse("Size is greater than limit so should not have failed",
|
||||
assertFalse("Size is greater than limit so should have failed",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
|
||||
// With a mimetype that does not have any specific limits
|
||||
@@ -307,36 +387,68 @@ public class AbstractContentTransformerLimitsTest
|
||||
transformer.isTransformableSize(A, byteValue+1, C, options));
|
||||
assertTrue("No limits so should have been ok",
|
||||
transformer.isTransformableSize(C, byteValue+1, C, options));
|
||||
|
||||
// Clear the mimetype limits and double check
|
||||
limits.setMaxSourceSizeKBytes(-1);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
// Using limit on transformer as a whole
|
||||
public void testIsTransformableSizeTrans() throws Exception
|
||||
{
|
||||
long kValue = 12;
|
||||
long byteValue = kValue*1024;
|
||||
|
||||
// Not set mimetype limits yet
|
||||
assertTrue("No limits so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
|
||||
// Check for combinations with transformer limits
|
||||
|
||||
// a) Using just transformer limit to start with
|
||||
transformer.setMaxSourceSizeKBytes(kValue);
|
||||
transformer.register();
|
||||
assertTrue("Size is equal to limit so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue, B, options));
|
||||
assertFalse("Size is greater than limit so should not have failed",
|
||||
assertFalse("Size is greater than limit so should have failed",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
}
|
||||
|
||||
// b) combination where transformer limit is used
|
||||
@Test
|
||||
// Combination where transformer limit is used
|
||||
public void testIsTransformableSizeCombinationTransUsed() throws Exception
|
||||
{
|
||||
long kValue = 12;
|
||||
long byteValue = kValue*1024;
|
||||
|
||||
// Not set mimetype limits yet
|
||||
assertTrue("No limits so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
|
||||
transformer.setMaxSourceSizeKBytes(kValue);
|
||||
limits.setMaxSourceSizeKBytes(kValue+1);
|
||||
addMimetypeLimits(A, B, limits);
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
transformer.register();
|
||||
assertTrue("Size is equal to limit so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue, B, options));
|
||||
assertFalse("Size is greater than limit so should not have failed",
|
||||
assertFalse("Size is greater than limit so should have failed",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
}
|
||||
|
||||
// c) combination where mimetype limit is used
|
||||
@Test
|
||||
// Combination where mimetype limit is used
|
||||
public void testIsTransformableSizeCombinationMimetypeUsed() throws Exception
|
||||
{
|
||||
long kValue = 12;
|
||||
long byteValue = kValue*1024;
|
||||
|
||||
// Not set mimetype limits yet
|
||||
assertTrue("No limits so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
|
||||
transformer.setMaxSourceSizeKBytes(kValue+1);
|
||||
limits.setMaxSourceSizeKBytes(kValue);
|
||||
addMimetypeLimits(A, B, limits);
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
transformer.register();
|
||||
assertTrue("Size is equal to limit so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue, B, options));
|
||||
assertFalse("Size is greater than limit so should not have failed",
|
||||
assertFalse("Size is greater than limit so should have failed",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
}
|
||||
|
||||
@@ -348,6 +460,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
|
||||
transformer.setMaxSourceSizeKBytes(kValue);
|
||||
transformer.setPageLimitsSuported(true);
|
||||
transformer.register();
|
||||
|
||||
// Test works as normal before setting the pageLimit
|
||||
assertTrue("Size is less than limit so should have been ok",
|
||||
@@ -370,6 +483,7 @@ public class AbstractContentTransformerLimitsTest
|
||||
|
||||
long value = 1234;
|
||||
transformer.setTimeoutMs(value);
|
||||
transformer.register();
|
||||
|
||||
assertEquals("Limit should not have been set in the reader", null, reader.getLimits());
|
||||
|
||||
|
@@ -70,6 +70,7 @@ public abstract class AbstractContentTransformerTest extends TestCase
|
||||
protected ServiceRegistry serviceRegistry;
|
||||
protected MimetypeService mimetypeService;
|
||||
protected TransformerDebug transformerDebug;
|
||||
protected TransformerConfig transformerConfig;
|
||||
|
||||
/**
|
||||
* Fetches a transformer to test for a given transformation. The transformer
|
||||
@@ -97,6 +98,8 @@ public abstract class AbstractContentTransformerTest extends TestCase
|
||||
serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
mimetypeService = serviceRegistry.getMimetypeService();
|
||||
transformerDebug = (TransformerDebug) ctx.getBean("transformerDebug");
|
||||
transformerConfig = (TransformerConfig) ctx.getBean("transformerConfig");
|
||||
|
||||
// perform a little cleaning up
|
||||
long now = System.currentTimeMillis();
|
||||
TempFileProvider.TempFileCleanerJob.removeFiles(now);
|
||||
|
@@ -40,6 +40,7 @@ public class AppleIWorksContentTransformerTest extends AbstractContentTransforme
|
||||
|
||||
// Ugly cast just to set the MimetypeService
|
||||
((ContentTransformerHelper)transformer).setMimetypeService(mimetypeService);
|
||||
((ContentTransformerHelper)transformer).setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -47,6 +47,7 @@ public class ArchiveContentTransformerTest extends AbstractContentTransformerTes
|
||||
transformer = new ArchiveContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype)
|
||||
|
@@ -38,6 +38,7 @@ public class BinaryPassThroughContentTransformerTest extends AbstractContentTran
|
||||
transformer = new BinaryPassThroughContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -267,7 +267,7 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple
|
||||
transformer = transformerIterator.next();
|
||||
if (transformer != null)
|
||||
{
|
||||
if (transformer.isTransformableMimetype(sourceMimetype, targetMimetype, options))
|
||||
if (transformer.isTransformable(sourceMimetype, -1, targetMimetype, options))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -306,7 +306,7 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple
|
||||
}
|
||||
else
|
||||
{
|
||||
if (transformer.isTransformableMimetype(currentSourceMimetype, currentTargetMimetype, options) == false)
|
||||
if (transformer.isTransformable(currentSourceMimetype, -1, currentTargetMimetype, options) == false)
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
|
@@ -63,6 +63,7 @@ public class ComplexContentTransformerTest extends AbstractContentTransformerTes
|
||||
transformer = new ComplexContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
// set the transformer list
|
||||
List<ContentTransformer> transformers = new ArrayList<ContentTransformer>(2);
|
||||
transformers.add(unoTransformer);
|
||||
|
@@ -78,29 +78,39 @@ public interface ContentTransformer extends ContentWorker
|
||||
public long getMaxSourceSizeKBytes(String sourceMimetype, String targetMimetype, TransformationOptions options);
|
||||
|
||||
/**
|
||||
* Indicates whether given the provided transformation parmaters this transformer can prvide an explict
|
||||
* @deprecated Use transformer priority and unsupported transformer properties.
|
||||
*
|
||||
* Indicates whether given the provided transformation parameters this transformer can provide an explicit
|
||||
* transformation.
|
||||
*
|
||||
* An explict transformation indicates that the transformation happens directly and not as a result of
|
||||
* another transformation process. Explict transformation always take presidence over normal transformations.
|
||||
* An explicit transformation indicates that the transformation happens directly and not as a result of
|
||||
* another transformation process. Explicit transformation always take presidency over normal transformations.
|
||||
*
|
||||
* @param sourceMimetype the source mimetype
|
||||
* @param targetMimetype the target mimetype
|
||||
* @param options the transformation options
|
||||
* @return boolean true if it is an explicit transformation, flase otherwise
|
||||
* @return boolean true if it is an explicit transformation, false otherwise
|
||||
*/
|
||||
public boolean isExplicitTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options);
|
||||
|
||||
/**
|
||||
* @deprecated use mimetype specific version.
|
||||
*/
|
||||
public long getTransformationTime();
|
||||
|
||||
/**
|
||||
* Provides an estimate, usually a worst case guess, of how long a transformation
|
||||
* will take.
|
||||
* will take. Null mimetype values provide the overall value for the transformer.
|
||||
* <p>
|
||||
* This method is used to determine, up front, which of a set of
|
||||
* equally reliant transformers will be used for a specific transformation.
|
||||
*
|
||||
* @param sourceMimetype the source mimetype
|
||||
* @param targetMimetype the target mimetype
|
||||
*
|
||||
* @return Returns the approximate number of milliseconds per transformation
|
||||
*/
|
||||
public long getTransformationTime();
|
||||
public long getTransformationTime(String sourceMimetype, String targetMimetype);
|
||||
|
||||
/**
|
||||
* @see #transform(ContentReader, ContentWriter, TransformationOptions)
|
||||
@@ -157,4 +167,9 @@ public interface ContentTransformer extends ContentWorker
|
||||
*/
|
||||
public void transform(ContentReader reader, ContentWriter contentWriter, TransformationOptions options)
|
||||
throws ContentIOException;
|
||||
|
||||
/**
|
||||
* Returns transformer's name used in configuration.
|
||||
*/
|
||||
public String getName();
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -18,37 +18,36 @@
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import java.util.Collections;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.ANY;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.service.cmr.repository.ContentAccessor;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
|
||||
/**
|
||||
* A class providing basic functionality shared by both {@link ContentTransformer}s and {@link ContentTransformerWorker}
|
||||
* s.
|
||||
* A class providing basic functionality shared by both {@link ContentTransformer}s and {@link ContentTransformerWorker}s.
|
||||
*
|
||||
* @author dward
|
||||
*/
|
||||
public class ContentTransformerHelper
|
||||
public class ContentTransformerHelper implements BeanNameAware
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(ContentTransformerHelper.class);
|
||||
|
||||
private MimetypeService mimetypeService;
|
||||
private List<ExplictTransformationDetails> explicitTransformations;
|
||||
private List<SupportedTransformation> supportedTransformations;
|
||||
private List<SupportedTransformation> unsupportedTransformations;
|
||||
protected TransformerConfig transformerConfig;
|
||||
|
||||
private List<String> deprecatedSetterMessages;
|
||||
private static boolean firstDeprecatedSetter = true;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public ContentTransformerHelper()
|
||||
{
|
||||
setExplicitTransformations(Collections.<ExplictTransformationDetails> emptyList());
|
||||
setSupportedTransformations(null);
|
||||
setUnsupportedTransformations(null);
|
||||
}
|
||||
/** The bean name. */
|
||||
private String beanName;
|
||||
|
||||
/**
|
||||
* Helper setter of the mimetype service. This is not always required.
|
||||
@@ -69,37 +68,35 @@ public class ContentTransformerHelper
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies transformations that are considered to be 'exceptional' so
|
||||
* should be used in preference to other transformers that can perform
|
||||
* the same transformation.
|
||||
* @deprecated supported transformations are now set with global properties rather than spring configuration.
|
||||
*/
|
||||
public void setExplicitTransformations(List<ExplictTransformationDetails> explicitTransformations)
|
||||
{
|
||||
this.explicitTransformations = explicitTransformations;
|
||||
deprecatedSupportedTransformations(explicitTransformations, null);
|
||||
// TODO Should suggest properties that indicate lower priority transformers should be unsupported.
|
||||
// This is for completeness rather than needed as the priority will avoid the non explicit
|
||||
// transformers from being used. Explicit transformers are given a priority of 5 rather than 10.
|
||||
}
|
||||
|
||||
/**
|
||||
* Restricts the transformations that may be performed even though the transformer
|
||||
* may perform other transformations. An null value applies no additional restrictions.
|
||||
* Even if a list is specified, the
|
||||
* {@link ContentTransformer#isTransformableMimetype(String, String, TransformationOptions)}
|
||||
* method will still be called.
|
||||
* @deprecated supported transformations are now set with global properties rather than spring configuration.
|
||||
*/
|
||||
public void setSupportedTransformations(List<SupportedTransformation> supportedTransformations)
|
||||
{
|
||||
this.supportedTransformations = supportedTransformations;
|
||||
deprecatedSupportedTransformations(supportedTransformations, "true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Restricts the transformations that may be performed even though the transformer
|
||||
* may claim to perform the transformations. An null value applies no additional restrictions.
|
||||
* Even if a list is specified, the
|
||||
* {@link ContentTransformer#isTransformableMimetype(String, String, TransformationOptions)}
|
||||
* method will still be called.
|
||||
* @deprecated supported transformations are now set with global properties rather than spring configuration.
|
||||
*/
|
||||
public void setUnsupportedTransformations(List<SupportedTransformation> unsupportedTransformations)
|
||||
{
|
||||
this.unsupportedTransformations = unsupportedTransformations;
|
||||
deprecatedSupportedTransformations(unsupportedTransformations, "false");
|
||||
}
|
||||
|
||||
public void setTransformerConfig(TransformerConfig transformerConfig)
|
||||
{
|
||||
this.transformerConfig = transformerConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,58 +120,138 @@ public class ContentTransformerHelper
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation, override if need to extend logic
|
||||
* @deprecated Should now use priority and unsupported transformer properties.
|
||||
*
|
||||
* @see org.alfresco.repo.content.transform.ContentTransformer#isExplicitTransformation(java.lang.String,
|
||||
* java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions)
|
||||
*/
|
||||
public boolean isExplicitTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
boolean result = false;
|
||||
for (ExplictTransformationDetails explicitTransformation : this.explicitTransformations)
|
||||
{
|
||||
if (sourceMimetype.equals(explicitTransformation.getSourceMimetype()) == true
|
||||
&& targetMimetype.equals(explicitTransformation.getTargetMimetype()) == true)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return transformerConfig.getPriority(((ContentTransformer)this), sourceMimetype, targetMimetype) == TransformerConfig.PRIORITY_EXPLICIT;
|
||||
}
|
||||
|
||||
public boolean isSupportedTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
boolean supported = true;
|
||||
if (supportedTransformations != null)
|
||||
return transformerConfig.isSupportedTransformation(((ContentTransformer)this), sourceMimetype, targetMimetype, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Spring bean name.
|
||||
*/
|
||||
@Override
|
||||
public void setBeanName(String beanName)
|
||||
{
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* THIS IS A CUSTOM SPRING INIT METHOD
|
||||
*/
|
||||
public void register()
|
||||
{
|
||||
logDeprecatedSetter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Spring bean name.
|
||||
*/
|
||||
public String getBeanName()
|
||||
{
|
||||
return beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns transformer name. Uses the Spring bean name, but if null uses the class name.
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return (beanName == null) ? getClass().getSimpleName() : beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by deprecated property setter methods that should no longer be called
|
||||
* by Spring configuration as the values are now set using global properties.
|
||||
* @param suffixAndValue that should have been used. The first part of the
|
||||
* property name "content.transformer.<name>." should not be included.
|
||||
* The reason is that the setter methods might be called before the bean
|
||||
* name is set.
|
||||
*/
|
||||
protected void deprecatedSetter(String suffixAndValue)
|
||||
{
|
||||
if (deprecatedSetterMessages == null)
|
||||
{
|
||||
supported = false;
|
||||
for (SupportedTransformation suportedTransformation : supportedTransformations)
|
||||
deprecatedSetterMessages = new ArrayList<String>();
|
||||
}
|
||||
deprecatedSetterMessages.add(suffixAndValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the bean name is set after all the deprecated setters to log
|
||||
* INFO messages with the Alfresco global properties that should now be set
|
||||
* (if no set) to replace Spring configuration.
|
||||
*/
|
||||
private void logDeprecatedSetter()
|
||||
{
|
||||
if (deprecatedSetterMessages != null)
|
||||
{
|
||||
for (String suffixAndValue: deprecatedSetterMessages)
|
||||
{
|
||||
String supportedSourceMimetype = suportedTransformation.getSourceMimetype();
|
||||
String supportedTargetMimetype = suportedTransformation.getTargetMimetype();
|
||||
if ((supportedSourceMimetype == null || sourceMimetype.equals(supportedSourceMimetype)) &&
|
||||
(supportedTargetMimetype == null || targetMimetype.equals(supportedTargetMimetype)))
|
||||
String propertyNameAndValue = TransformerConfig.CONTENT+beanName+'.'+suffixAndValue;
|
||||
String propertyName = propertyNameAndValue.replaceAll("=.*", "");
|
||||
if (transformerConfig.getProperty(propertyName) == null)
|
||||
{
|
||||
supported = true;
|
||||
break;
|
||||
if (firstDeprecatedSetter)
|
||||
{
|
||||
firstDeprecatedSetter = false;
|
||||
logger.error("In order to support dynamic setting of transformer options, Spring XML configuration");
|
||||
logger.error("is no longer used to initialise these options.");
|
||||
logger.error(" ");
|
||||
logger.error("Your system appears to contains custom Spring configuration which should be replace by");
|
||||
logger.error("the following Alfresco global properties. In the case of the Enterprise edition these");
|
||||
logger.error("values may then be dynamically changed via JMX.");
|
||||
logger.error(" ");
|
||||
// Note: Cannot set these automatically because, an MBean reset would clear them.
|
||||
}
|
||||
logger.error(propertyNameAndValue);
|
||||
|
||||
// Add them to the subsystem's properties anyway (even though an MBean reset would clear them),
|
||||
// so that existing unit tests work.
|
||||
transformerConfig.setProperty(propertyNameAndValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn(propertyNameAndValue+" is set, but spring config still exists");
|
||||
}
|
||||
}
|
||||
deprecatedSetterMessages = null;
|
||||
}
|
||||
if (supported && unsupportedTransformations != null)
|
||||
}
|
||||
|
||||
private void deprecatedSupportedTransformations(List<? extends SupportedTransformation> transformations, String value)
|
||||
{
|
||||
if (transformations != null)
|
||||
{
|
||||
for (SupportedTransformation unsuportedTransformation : unsupportedTransformations)
|
||||
for (SupportedTransformation transformation: transformations)
|
||||
{
|
||||
String unsupportedSourceMimetype = unsuportedTransformation.getSourceMimetype();
|
||||
String unsupportedTargetMimetype = unsuportedTransformation.getTargetMimetype();
|
||||
if ((unsupportedSourceMimetype == null || sourceMimetype.equals(unsupportedSourceMimetype)) &&
|
||||
(unsupportedTargetMimetype == null || targetMimetype.equals(unsupportedTargetMimetype)))
|
||||
{
|
||||
supported = false;
|
||||
break;
|
||||
}
|
||||
String sourceMimetype = transformation.getSourceMimetype();
|
||||
String targetMimetype = transformation.getTargetMimetype();
|
||||
String sourceExt = getExtensionOrAny(sourceMimetype);
|
||||
String targetExt = getExtensionOrAny(targetMimetype);
|
||||
deprecatedSetter(TransformerConfig.MIMETYPES_SEPARATOR.substring(1)+sourceExt+'.'+targetExt+
|
||||
(value == null // same as: transformation instanceof ExplictTransformationDetails
|
||||
? TransformerConfig.PRIORITY+"="+TransformerConfig.PRIORITY_EXPLICIT
|
||||
: TransformerConfig.SUPPORTED+"="+value));
|
||||
}
|
||||
}
|
||||
return supported;
|
||||
}
|
||||
|
||||
protected String getExtensionOrAny(String mimetype)
|
||||
{
|
||||
return mimetype == null || ANY.equals(mimetype) ? ANY : mimetypeService.getExtension(mimetype);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getName();
|
||||
}
|
||||
}
|
@@ -57,7 +57,7 @@ public class ContentTransformerRegistry
|
||||
public ContentTransformerRegistry(TransformerSelector transformerSelector)
|
||||
{
|
||||
this.transformerSelector = transformerSelector;
|
||||
this.transformers = new ArrayList<ContentTransformer>(10);
|
||||
this.transformers = new ArrayList<ContentTransformer>(70);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,7 +114,7 @@ public class ContentTransformerRegistry
|
||||
public List<ContentTransformer> getActiveTransformers(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
// Get the list of transformers
|
||||
List<ContentTransformer> transformers = transformerSelector.selectTransformers(this.transformers, sourceMimetype, sourceSize, targetMimetype, options);
|
||||
List<ContentTransformer> transformers = transformerSelector.selectTransformers(sourceMimetype, sourceSize, targetMimetype, options);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Searched for transformer: \n" +
|
||||
|
@@ -52,6 +52,12 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
private ContentReader reader;
|
||||
private ContentWriter writer;
|
||||
|
||||
private DummyTransformer ad20;
|
||||
private DummyTransformer ad30;
|
||||
private DummyTransformer ad10;
|
||||
private DummyTransformer ad25a;
|
||||
private DummyTransformer ad25b;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
@@ -70,19 +76,23 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
bytes[i] = (byte)i;
|
||||
}
|
||||
// create the dummyRegistry
|
||||
dummyRegistry = new ContentTransformerRegistry(new TransformerSelectorImpl());
|
||||
TransformerSelectorImpl transformerSelector = new TransformerSelectorImpl();
|
||||
transformerSelector.setTransformerConfig(transformerConfig);
|
||||
transformerSelector.setContentTransformerRegistry(dummyRegistry);
|
||||
dummyRegistry = new ContentTransformerRegistry(transformerSelector);
|
||||
transformerSelector.setContentTransformerRegistry(dummyRegistry);
|
||||
// create some dummy transformers for reliability tests
|
||||
new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, B, 10L);
|
||||
new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, B, 10L);
|
||||
new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, C, 10L);
|
||||
new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, C, 10L);
|
||||
new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, B, C, 10L);
|
||||
new DummyTransformer(mimetypeService, "transformer.testAB10a", transformerDebug, transformerConfig, dummyRegistry, A, B, 10L);
|
||||
new DummyTransformer(mimetypeService, "transformer.testAB10b", transformerDebug, transformerConfig, dummyRegistry, A, B, 10L);
|
||||
new DummyTransformer(mimetypeService, "transformer.testAC10a", transformerDebug, transformerConfig, dummyRegistry, A, C, 10L);
|
||||
new DummyTransformer(mimetypeService, "transformer.testAC10b", transformerDebug, transformerConfig, dummyRegistry, A, C, 10L);
|
||||
new DummyTransformer(mimetypeService, "transformer.testBC10", transformerDebug, transformerConfig, dummyRegistry, B, C, 10L);
|
||||
// create some dummy transformers for speed tests
|
||||
new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, D, 20L);
|
||||
new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, D, 30L);
|
||||
new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, D, 10L); // the fast one
|
||||
new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, D, 25L);
|
||||
new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, D, 25L);
|
||||
ad20 = new DummyTransformer(mimetypeService, "transformer.testAD20", transformerDebug, transformerConfig, dummyRegistry, A, D, 20L);
|
||||
ad30 = new DummyTransformer(mimetypeService, "transformer.testAD30", transformerDebug, transformerConfig, dummyRegistry, A, D, 30L);
|
||||
ad10 = new DummyTransformer(mimetypeService, "transformer.testAD10", transformerDebug, transformerConfig, dummyRegistry, A, D, 10L); // the fast one
|
||||
ad25a = new DummyTransformer(mimetypeService, "transformer.testAD25a", transformerDebug, transformerConfig, dummyRegistry, A, D, 25L);
|
||||
ad25b = new DummyTransformer(mimetypeService, "transformer.testAD25b", transformerDebug, transformerConfig, dummyRegistry, A, D, 25L);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,20 +141,45 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
*/
|
||||
public void testPerformanceRetrieval() throws Exception
|
||||
{
|
||||
// Until the threshold (3) is reached by each transformer with the same priority it will
|
||||
// be tried that many times in the order defined. 20, 30, 10, 25, 25
|
||||
for (int i=1; i<=3; i++)
|
||||
{
|
||||
long expectedTime = i == 1 ? 0L : 20L;
|
||||
ContentTransformer transformer1 = dummyRegistry.getTransformer(A, -1, D, OPTIONS);
|
||||
assertEquals(i+" incorrect transformation time", expectedTime, transformer1.getTransformationTime(A, D));
|
||||
ad20.transformInternal(null, null, null);
|
||||
}
|
||||
for (int i=1; i<=3; i++)
|
||||
{
|
||||
long expectedTime = i == 1 ? 0L : 30L;
|
||||
ContentTransformer transformer1 = dummyRegistry.getTransformer(A, -1, D, OPTIONS);
|
||||
assertEquals(i+" incorrect transformation time", expectedTime, transformer1.getTransformationTime(A, D));
|
||||
ad30.transformInternal(null, null, null);
|
||||
}
|
||||
for (int i=1; i<=3; i++)
|
||||
{
|
||||
ad10.transformInternal(null, null, null);
|
||||
ad25a.transformInternal(null, null, null);
|
||||
ad25b.transformInternal(null, null, null);
|
||||
}
|
||||
|
||||
// Now the average times are set up, it should find the fastest one
|
||||
|
||||
// A -> D expect 1.0, 10ms
|
||||
ContentTransformer transformer1 = dummyRegistry.getTransformer(A, -1, D, OPTIONS);
|
||||
assertTrue("Incorrect reliability", transformer1.isTransformable(A, -1, D, OPTIONS));
|
||||
assertFalse("Incorrect reliability", transformer1.isTransformable(D, -1, A, OPTIONS));
|
||||
assertEquals("Incorrect transformation time", 10L, transformer1.getTransformationTime());
|
||||
assertEquals("Incorrect transformation time", 10L, transformer1.getTransformationTime(A, D));
|
||||
|
||||
// A -> D has 10, 20, 25, 25, 30
|
||||
List<ContentTransformer> activeTransformers = dummyRegistry.getActiveTransformers(A, -1, D, OPTIONS);
|
||||
assertEquals("Not all found", 5, activeTransformers.size());
|
||||
assertEquals("Incorrect order", 10L, activeTransformers.get(0).getTransformationTime());
|
||||
assertEquals("Incorrect order", 20L, activeTransformers.get(1).getTransformationTime());
|
||||
assertEquals("Incorrect order", 25L, activeTransformers.get(2).getTransformationTime());
|
||||
assertEquals("Incorrect order", 25L, activeTransformers.get(3).getTransformationTime());
|
||||
assertEquals("Incorrect order", 30L, activeTransformers.get(4).getTransformationTime());
|
||||
assertEquals("Incorrect order", 10L, activeTransformers.get(0).getTransformationTime(A, D));
|
||||
assertEquals("Incorrect order", 20L, activeTransformers.get(1).getTransformationTime(A, D));
|
||||
assertEquals("Incorrect order", 25L, activeTransformers.get(2).getTransformationTime(A, D));
|
||||
assertEquals("Incorrect order", 25L, activeTransformers.get(3).getTransformationTime(A, D));
|
||||
assertEquals("Incorrect order", 30L, activeTransformers.get(4).getTransformationTime(A, D));
|
||||
|
||||
// Disable two of them, and re-test
|
||||
((DummyTransformer)activeTransformers.get(2)).disable();
|
||||
@@ -152,9 +187,9 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
|
||||
activeTransformers = dummyRegistry.getActiveTransformers(A, -1, D, OPTIONS);
|
||||
assertEquals("Not all found", 3, activeTransformers.size());
|
||||
assertEquals("Incorrect order", 10L, activeTransformers.get(0).getTransformationTime());
|
||||
assertEquals("Incorrect order", 20L, activeTransformers.get(1).getTransformationTime());
|
||||
assertEquals("Incorrect order", 25L, activeTransformers.get(2).getTransformationTime());
|
||||
assertEquals("Incorrect order", 10L, activeTransformers.get(0).getTransformationTime(A, D));
|
||||
assertEquals("Incorrect order", 20L, activeTransformers.get(1).getTransformationTime(A, D));
|
||||
assertEquals("Incorrect order", 25L, activeTransformers.get(2).getTransformationTime(A, D));
|
||||
}
|
||||
|
||||
public void testScoredRetrieval() throws Exception
|
||||
@@ -180,9 +215,9 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
{
|
||||
AbstractContentTransformer2 dummyTransformer = new DummyTransformer(
|
||||
mimetypeService,
|
||||
transformerDebug,
|
||||
dummyRegistry, MimetypeMap.MIMETYPE_FLASH,
|
||||
MimetypeMap.MIMETYPE_EXCEL, 12345);
|
||||
"transformer.testExplicit",
|
||||
transformerDebug, transformerConfig,
|
||||
dummyRegistry, MimetypeMap.MIMETYPE_FLASH, MimetypeMap.MIMETYPE_EXCEL, 12345);
|
||||
// set an explicit transformation
|
||||
ExplictTransformationDetails key =
|
||||
new ExplictTransformationDetails(
|
||||
@@ -212,25 +247,23 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
|
||||
public DummyTransformer(
|
||||
MimetypeService mimetypeService,
|
||||
TransformerDebug transformerDebug,
|
||||
ContentTransformerRegistry registry, String sourceMimetype,
|
||||
String targetMimetype, long transformationTime)
|
||||
String name,
|
||||
TransformerDebug transformerDebug, TransformerConfig transformerConfig,
|
||||
ContentTransformerRegistry registry, String sourceMimetype, String targetMimetype, long transformationTime)
|
||||
{
|
||||
super.setMimetypeService(mimetypeService);
|
||||
super.setTransformerDebug(transformerDebug);
|
||||
super.setTransformerConfig(transformerConfig);
|
||||
super.setRegistry(registry);
|
||||
this.sourceMimetype = sourceMimetype;
|
||||
this.targetMimetype = targetMimetype;
|
||||
this.transformationTime = transformationTime;
|
||||
setBeanName(name+'.'+System.currentTimeMillis()%100000);
|
||||
|
||||
// register
|
||||
register();
|
||||
}
|
||||
|
||||
protected void enable()
|
||||
{
|
||||
disable = false;
|
||||
}
|
||||
|
||||
protected void disable()
|
||||
{
|
||||
disable = true;
|
||||
@@ -262,16 +295,16 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
TransformationOptions options) throws Exception
|
||||
{
|
||||
// just update the transformation time
|
||||
super.recordTime(transformationTime);
|
||||
super.recordTime(sourceMimetype, targetMimetype, transformationTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the fixed dummy average transformation time
|
||||
*/
|
||||
public synchronized long getTransformationTime()
|
||||
{
|
||||
return transformationTime;
|
||||
}
|
||||
// /**
|
||||
// * @return Returns the fixed dummy average transformation time
|
||||
// */
|
||||
// public synchronized long getTransformationTime(String sourceMimetype, String targetMimetype)
|
||||
// {
|
||||
// return transformationTime;
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
|
125
source/java/org/alfresco/repo/content/transform/DoubleMap.java
Normal file
125
source/java/org/alfresco/repo/content/transform/DoubleMap.java
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Provides simple get and put access to a Map like object with a double key that allows
|
||||
* either or both keys to be a wild card that matches any value. May not contain null
|
||||
* keys or values.<p>
|
||||
*
|
||||
* Originally created for mapping source and target mimetypes to transformer configuration data.<p>
|
||||
*
|
||||
* For example:
|
||||
* <pre>
|
||||
* DoubleMap<String, String, String> foodLikes = new DoubleMap<String, String, String>("*", "*");
|
||||
*
|
||||
* foodLikes.put("cat", "mouse", "likes");
|
||||
*
|
||||
* foodLikes.get("cat", "mouse"); // returns "likes"
|
||||
* foodLikes.get("cat", "meat"); // returns null
|
||||
*
|
||||
* foodLikes.put("dog", "meat", "likes");
|
||||
* foodLikes.put("dog", "stick", "unsure");
|
||||
* foodLikes.put("child", "olive", "dislikes");
|
||||
* foodLikes.put("bird", "*", "worms only");
|
||||
* foodLikes.put("*", "meat", "unknown");
|
||||
* foodLikes.put("*", "*", "no idea at all");
|
||||
*
|
||||
* foodLikes.get("cat", "mouse"); // returns "likes"
|
||||
* foodLikes.get("cat", "meat"); // returns "unknown"
|
||||
* foodLikes.get("cat", "tea"); // returns "unknown"
|
||||
* foodLikes.get("*", "mouse"); // returns "no idea at all"
|
||||
* foodLikes.get("dog", "*"); // returns "no idea at all"
|
||||
* foodLikes.get("bird","*"); // returns "worms only"
|
||||
* foodLikes.get("bird","tea"); // returns "worms only"
|
||||
* </pre>
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public class DoubleMap<K1, K2, V>
|
||||
{
|
||||
private final Map<K1, Map<K2, V>> mapMap = new ConcurrentHashMap<K1, Map<K2, V>>();
|
||||
private final K1 anyKey1;
|
||||
private final K2 anyKey2;
|
||||
|
||||
public DoubleMap(K1 anyKey1, K2 anyKey2)
|
||||
{
|
||||
this.anyKey1 = anyKey1;
|
||||
this.anyKey2 = anyKey2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value for the given keys.
|
||||
*/
|
||||
public V get(K1 key1, K2 key2)
|
||||
{
|
||||
V value = null;
|
||||
|
||||
Map<K2, V> map = mapMap.get(key1);
|
||||
boolean anySource = false;
|
||||
if (map == null)
|
||||
{
|
||||
map = mapMap.get(anyKey1);
|
||||
anySource = true;
|
||||
}
|
||||
if (map != null)
|
||||
{
|
||||
value = map.get(key2);
|
||||
if (value == null)
|
||||
{
|
||||
value = map.get(anyKey2);
|
||||
|
||||
// Handle the case were there is no match using an non wildcarded key1 and
|
||||
// key2 but is a match if key1 is wildcarded.
|
||||
if (value == null && !anySource)
|
||||
{
|
||||
map = mapMap.get(anyKey1);
|
||||
if (map != null)
|
||||
{
|
||||
value = map.get(key2);
|
||||
if (value == null)
|
||||
{
|
||||
value = map.get(anyKey2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a value for the given keys.
|
||||
*/
|
||||
public void put(K1 key1, K2 key2, V t)
|
||||
{
|
||||
Map<K2, V> map = mapMap.get(key1);
|
||||
if (map == null)
|
||||
{
|
||||
map = new ConcurrentHashMap<K2, V>();
|
||||
mapMap.put(key1, map);
|
||||
}
|
||||
|
||||
map.put(key2, t);
|
||||
}
|
||||
}
|
@@ -50,6 +50,7 @@ public class EMLTransformerTest extends AbstractContentTransformerTest
|
||||
transformer = new EMLTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -57,6 +57,7 @@ public class FailoverContentTransformerTest extends AbstractContentTransformerTe
|
||||
transformer = (FailoverContentTransformer) failoverAppContext.getBean("transformer.failover.Test-FailThenSucceed");
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -42,6 +42,7 @@ public class HtmlParserContentTransformerTest extends AbstractContentTransformer
|
||||
transformer = new HtmlParserContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype)
|
||||
|
@@ -45,6 +45,7 @@ public class MailContentTransformerTest extends AbstractContentTransformerTest
|
||||
transformer = new MailContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -70,6 +70,7 @@ public class MediaWikiContentTransformerTest extends AbstractContentTransformerT
|
||||
transformer = new MediaWikiContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype)
|
||||
|
@@ -50,6 +50,7 @@ public class OpenOfficeContentTransformerTest extends AbstractContentTransformer
|
||||
transformer = new ProxyContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
transformer.setWorker(this.worker);
|
||||
}
|
||||
|
||||
|
@@ -38,6 +38,7 @@ public class PdfBoxContentTransformerTest extends AbstractContentTransformerTest
|
||||
transformer = new PdfBoxContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -38,6 +38,7 @@ public class PoiContentTransformerTest extends AbstractContentTransformerTest
|
||||
transformer = new PoiContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -46,6 +46,7 @@ public class PoiHssfContentTransformerTest extends TikaPoweredContentTransformer
|
||||
transformer = new PoiHssfContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -38,6 +38,7 @@ public class PoiOOXMLContentTransformerTest extends AbstractContentTransformerTe
|
||||
transformer = new PoiOOXMLContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -74,10 +74,12 @@ public class RuntimeExecutableContentTransformerTest extends BaseAlfrescoTestCas
|
||||
worker.afterPropertiesSet();
|
||||
|
||||
TransformerDebug transformerDebug = (TransformerDebug) ctx.getBean("transformerDebug");
|
||||
TransformerConfig transformerConfig = (TransformerConfig) ctx.getBean("transformerConfig");
|
||||
|
||||
ProxyContentTransformer transformer = new ProxyContentTransformer();
|
||||
transformer.setMimetypeService(serviceRegistry.getMimetypeService());
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
transformer.setWorker(worker);
|
||||
this.transformer = transformer;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -169,19 +169,7 @@ public class RuntimeExecutableContentTransformerWorker extends ContentTransforme
|
||||
*/
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
if (!available)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isExplicitTransformation(sourceMimetype, targetMimetype, options))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return available;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -68,6 +68,7 @@ public class StringExtractingContentTransformerTest extends AbstractContentTrans
|
||||
transformer = new StringExtractingContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
targetWriter = new FileContentWriter(getTempFile());
|
||||
targetWriter.setMimetype("text/plain");
|
||||
targetWriter.setEncoding("UTF-8");
|
||||
|
@@ -46,6 +46,7 @@ public class TextMiningContentTransformerTest extends AbstractContentTransformer
|
||||
transformer = new TextMiningContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -50,9 +50,11 @@ public class TextToPdfContentTransformerTest extends AbstractContentTransformerT
|
||||
transformer = new TextToPdfContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
transformer.setStandardFont("Times-Roman");
|
||||
transformer.setFontSize(20);
|
||||
transformer.setPageLimit(-1);
|
||||
transformer.register();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,7 +122,9 @@ public class TextToPdfContentTransformerTest extends AbstractContentTransformerT
|
||||
|
||||
private void transformTextAndCheckPageLength(int pageLimit) throws IOException
|
||||
{
|
||||
transformer.setBeanName("transformer.test"+System.currentTimeMillis()%100000);
|
||||
transformer.setPageLimit(pageLimit);
|
||||
transformer.register();
|
||||
|
||||
int pageLength = 32;
|
||||
int lines = (pageLength+10) * ((pageLimit > 0) ? pageLimit : 1);
|
||||
|
@@ -43,6 +43,7 @@ public class TikaAutoContentTransformerTest extends TikaPoweredContentTransforme
|
||||
transformer = new TikaAutoContentTransformer( config );
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setTransformerConfig(transformerConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.alfresco.service.cmr.repository.TransformationOptionLimits;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
|
||||
/**
|
||||
* Provides access to transformer configuration and current performance data.
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public interface TransformerConfig
|
||||
{
|
||||
/**
|
||||
* Wild card mimetype and mimetype extension.
|
||||
*/
|
||||
public static final String ANY = "*";
|
||||
|
||||
/**
|
||||
* Prefix before the transformer name of all property names that contain transformer
|
||||
* information
|
||||
*/
|
||||
static final String CONTENT = "content.";
|
||||
|
||||
/**
|
||||
* Prefix for all transformer names
|
||||
*/
|
||||
static final String TRANSFORMER = "transformer.";
|
||||
|
||||
/**
|
||||
* The combined content and transformer name prefix of for all property names that contain
|
||||
* transformer information
|
||||
*/
|
||||
static final String PREFIX = CONTENT+TRANSFORMER;
|
||||
|
||||
/**
|
||||
* The 'transformer name' for system wide defaults for all transformers
|
||||
*/
|
||||
static final String DEFAULT_TRANSFORMER = TRANSFORMER+"default";
|
||||
|
||||
/**
|
||||
* Name given to the 'SUMMARY' dummy (does not exist) transformer that gathers data
|
||||
* from all root level transformations
|
||||
*/
|
||||
static final String SUMMARY_TRANSFORMER_NAME = "SUMMARY";
|
||||
|
||||
/**
|
||||
* The separator between the transformer name and two mimetype extensions in a property name.
|
||||
*/
|
||||
static final String MIMETYPES_SEPARATOR = ".mimetypes.";
|
||||
|
||||
/**
|
||||
* The suffix to property names for supported and unsupported combinations.
|
||||
*/
|
||||
static final String SUPPORTED = ".supported";
|
||||
|
||||
/**
|
||||
* The suffix to property names for the priority.
|
||||
*/
|
||||
static final String PRIORITY = ".priority";
|
||||
|
||||
/**
|
||||
* The suffix to property names for the threshold count.
|
||||
*/
|
||||
static final String THRESHOLD_COUNT = ".thresholdCount";
|
||||
|
||||
/**
|
||||
* The suffix to property names for the error time.
|
||||
*/
|
||||
static final String ERROR_TIME = ".errorTime";
|
||||
|
||||
/**
|
||||
* The suffix to property names for the the average time. Only used in the initial setup of
|
||||
* TransformerData. This is a historical property used by the 'Transformation Server' to set
|
||||
* an effective priority.
|
||||
*/
|
||||
static final String INITIAL_TIME = ".time";
|
||||
|
||||
/**
|
||||
* The suffix to property names for the the average count. Only used in the initial setup of
|
||||
* TransformerData. This is a historical property used by the 'Transformation Server' to set
|
||||
* an effective priority.
|
||||
*/
|
||||
static final String INITIAL_COUNT = ".count";
|
||||
|
||||
/**
|
||||
* To support the historical concept of EXPLICIT transformers, all such transformers
|
||||
* are given a {@link PRIORITY_EXPLICIT} (5). By default transformers have a default of 10.
|
||||
* A value of 5 allows better transformers to be added later.
|
||||
*/
|
||||
public int PRIORITY_EXPLICIT = 5;
|
||||
|
||||
/**
|
||||
* Suffixes to property names used to define transformation limits
|
||||
*/
|
||||
static final Collection<String> LIMIT_SUFFIXES = Arrays.asList(new String [] {
|
||||
'.'+TransformationOptionLimits.OPT_MAX_SOURCE_SIZE_K_BYTES,
|
||||
'.'+TransformationOptionLimits.OPT_TIMEOUT_MS,
|
||||
'.'+TransformationOptionLimits.OPT_MAX_PAGES,
|
||||
'.'+TransformationOptionLimits.OPT_READ_LIMIT_K_BYTES,
|
||||
'.'+TransformationOptionLimits.OPT_READ_LIMIT_TIME_MS,
|
||||
'.'+TransformationOptionLimits.OPT_PAGE_LIMIT
|
||||
});
|
||||
|
||||
/**
|
||||
* No suffixes to property names used to define transformer settings.
|
||||
*/
|
||||
public static final Collection<String> NO_SUFFIXES = Collections.singletonList("");
|
||||
|
||||
/**
|
||||
* Returns a transformer property value.
|
||||
* @param name of the property.
|
||||
* @return a transformer property or {@code null} if not set.
|
||||
*/
|
||||
String getProperty(String name);
|
||||
|
||||
/**
|
||||
* Sets a transformer property value. This will be stored in the database but on an MBean
|
||||
* reset would be cleared.
|
||||
*
|
||||
* @param propertyNameAndValue
|
||||
*/
|
||||
void setProperty(String propertyNameAndValue);
|
||||
|
||||
/**
|
||||
* Returns and creates if needed the {@link TransformerStatistics} object for the combination of
|
||||
* transformer, sourceMimetype and targetMimetype. When transformer is null this is the
|
||||
* system wide summary object for a combination of sourceMimetype and targetMimetype.
|
||||
* When both sourceMimetype and targetMimetype are null this is the transformer's summary
|
||||
* object. When all three parameters are null this is the system wide summary for all
|
||||
* transformers.
|
||||
* @param transformer the transformer for which data is being recorded.
|
||||
* @param sourceMimetype the source mimetype.
|
||||
* @param targetMimetype the source mimetype.
|
||||
* @return the requested {@link TransformerStatistics}.
|
||||
*/
|
||||
public TransformerStatistics getStatistics(ContentTransformer transformer, String sourceMimetype, String targetMimetype);
|
||||
|
||||
/**
|
||||
* Returns the limits defined for the combination of transformer, sourceMimetype and targetMimetype.
|
||||
* When the transformer is null, this is a default value. When both sourceMimetype and targetMimetype
|
||||
* are null this is a default for the specified transformer.
|
||||
* @param transformer
|
||||
* @param sourceMimetype
|
||||
* @param targetMimetype
|
||||
* @return the combined (takes into account defaults from higher levels) limits for the combination.
|
||||
*/
|
||||
public TransformationOptionLimits getLimits(ContentTransformer transformer, String sourceMimetype, String targetMimetype);
|
||||
|
||||
/**
|
||||
* Returns true if the supplied mimetype transformation pair is allowed by the list of supported
|
||||
* and unsupported transformations.
|
||||
* @param transformer
|
||||
* @param sourceMimetype
|
||||
* @param targetMimetype
|
||||
* @param options not currently used
|
||||
*/
|
||||
public boolean isSupportedTransformation(ContentTransformer transformer, String sourceMimetype,
|
||||
String targetMimetype, TransformationOptions options);
|
||||
|
||||
/**
|
||||
* Returns the priority of the specified transformer for the the combination of source and target mimetype.
|
||||
* @param transformer
|
||||
* @param sourceMimetype
|
||||
* @param targetMimetype
|
||||
* @return the priority. To support the historical concept of EXPLICIT transformers, all such transformers
|
||||
* are given a {@link PRIORITY_EXPLICIT} (5). By default transformers have a default of 10.
|
||||
*/
|
||||
public int getPriority(ContentTransformer contentTransformerHelper,
|
||||
String sourceMimetype, String targetMimetype);
|
||||
|
||||
/**
|
||||
* Returns the threshold of the transformer. It is only after this number of transformation attempts
|
||||
* that the average time is used.
|
||||
* @param transformer
|
||||
* @param sourceMimetype
|
||||
* @param targetMimetype
|
||||
* @return the threshold.
|
||||
*/
|
||||
|
||||
public int getThresholdCount(ContentTransformer contentTransformerHelper, String sourceMimetype,
|
||||
String targetMimetype);
|
||||
}
|
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptionLimits;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
||||
|
||||
/**
|
||||
* Provides access to transformer configuration and current performance data.
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public class TransformerConfigImpl extends AbstractLifecycleBean implements TransformerConfig
|
||||
{
|
||||
/** The logger. */
|
||||
private static Log logger = LogFactory.getLog(TransformerConfigImpl.class);
|
||||
|
||||
private MimetypeService mimetypeService;
|
||||
|
||||
// Holds statistics about each transformer, sourceMimeType and targetMimetype combination.
|
||||
// A null transformer is the system wide value. Null sourceMimeType and targetMimetype values are
|
||||
// transformer wide summaries.
|
||||
private TransformerConfigStatistics statistics;
|
||||
|
||||
// Transformer limits.
|
||||
private TransformerConfigLimits limits;
|
||||
|
||||
// Supported and unsupported transformations.
|
||||
private TransformerConfigSupported supported;
|
||||
|
||||
// Priorities
|
||||
private TransformerConfigProperty priorities;
|
||||
|
||||
// Threshold counts - Initially there will only be the system wide value, but
|
||||
// having this structure provides flexibility.
|
||||
private TransformerConfigProperty thresholdCounts;
|
||||
|
||||
// Times to be recorded if there is an error - Initially there will only be the system wide value, but
|
||||
// having this structure provides flexibility.
|
||||
private TransformerConfigProperty errorTimes;
|
||||
|
||||
// For backward compatibility where priority could not be set, with AMPs that need to have their
|
||||
// transformer used rather than an inbuilt one. Achieved by making the inbuilt transformers look
|
||||
// poor. Generally contains no entries, other than the system wide 0 values.
|
||||
private TransformerConfigProperty initialAverageTimes;
|
||||
private TransformerConfigProperty initialCounts;
|
||||
|
||||
// Needed to read properties.
|
||||
private ChildApplicationContextFactory subsystemFactory;
|
||||
|
||||
/**
|
||||
* Sets of the mimetype service.
|
||||
*
|
||||
* @param mimetypeService
|
||||
*/
|
||||
public void setMimetypeService(MimetypeService mimetypeService)
|
||||
{
|
||||
this.mimetypeService = mimetypeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by spring after bean is initialised.
|
||||
*/
|
||||
public void initialise()
|
||||
{
|
||||
statistics= new TransformerConfigStatistics(this, mimetypeService);
|
||||
limits = new TransformerConfigLimits(getSubsystem(), mimetypeService);
|
||||
supported = new TransformerConfigSupported(getSubsystem(), mimetypeService);
|
||||
priorities = new TransformerConfigProperty(getSubsystem(), mimetypeService, PRIORITY);
|
||||
thresholdCounts = new TransformerConfigProperty(getSubsystem(), mimetypeService, THRESHOLD_COUNT);
|
||||
errorTimes = new TransformerConfigProperty(getSubsystem(), mimetypeService, ERROR_TIME);
|
||||
initialAverageTimes = new TransformerConfigProperty(getSubsystem(), mimetypeService, INITIAL_TIME);
|
||||
initialCounts = new TransformerConfigProperty(getSubsystem(), mimetypeService, INITIAL_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the 'transformers' subsystem which among other things holds transformer properties.
|
||||
*/
|
||||
private synchronized ChildApplicationContextFactory getSubsystem()
|
||||
{
|
||||
if (subsystemFactory == null)
|
||||
{
|
||||
subsystemFactory = getApplicationContext().getBean("Transformers", ChildApplicationContextFactory.class);
|
||||
}
|
||||
return subsystemFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getProperty(String name)
|
||||
{
|
||||
return getSubsystem().getProperty(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setProperty(String propertyNameAndValue)
|
||||
{
|
||||
int i = propertyNameAndValue.indexOf('=');
|
||||
String name = i != -1 ? propertyNameAndValue.substring(0, i) : propertyNameAndValue;
|
||||
String value = i != -1 ? propertyNameAndValue.substring(i+1) : "";
|
||||
getSubsystem().setProperty(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public TransformerStatistics getStatistics(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
return statistics.getStatistics(transformer, sourceMimetype, targetMimetype);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public TransformationOptionLimits getLimits(ContentTransformer transformer, String sourceMimetype,
|
||||
String targetMimetype)
|
||||
{
|
||||
return limits.getLimits(transformer, sourceMimetype, targetMimetype);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean isSupportedTransformation(ContentTransformer transformer, String sourceMimetype,
|
||||
String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
return supported.isSupportedTransformation(transformer, sourceMimetype, targetMimetype, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int getPriority(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
return priorities.getInt(transformer, sourceMimetype, targetMimetype);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int getThresholdCount(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
return thresholdCounts.getInt(transformer, sourceMimetype, targetMimetype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time to be recorded if there is an error.
|
||||
*/
|
||||
long getErrorTime(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
return errorTimes.getLong(transformer, sourceMimetype, targetMimetype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the initial average time to be set for a transformer. Used historically to set the priority of transformers in AMPs.
|
||||
* The initial count value may also obtained via {@link #getInitialCount(ContentTransformer, String, String)}.
|
||||
*/
|
||||
long getInitialAverageTime(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
return initialAverageTimes.getLong(transformer, sourceMimetype, targetMimetype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the initial transformer count to be set for a transformer. Used historically to set the priority of transformers in AMPs.
|
||||
* Only called if {@link #getInitialAverageTime(ContentTransformer, String, String)} returns a value larger than 0.
|
||||
*/
|
||||
int getInitialCount(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
return initialCounts.getInt(transformer, sourceMimetype, targetMimetype);
|
||||
}
|
||||
}
|
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.ANY;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.CONTENT;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.DEFAULT_TRANSFORMER;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.LIMIT_SUFFIXES;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.MIMETYPES_SEPARATOR;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptionLimits;
|
||||
import org.alfresco.util.Triple;
|
||||
|
||||
/**
|
||||
* Provides access to transformer limits defined via properties.
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public class TransformerConfigLimits extends TransformerPropertyNameExtractor
|
||||
{
|
||||
// Holds configured (entries only exist if configured rather than for all possible combinations)
|
||||
// limits for for transformer, sourceMimeType and targetMimetype combination.
|
||||
// A null transformer is the system wide value. SourceMimeType and targetMimetype may be 'ANY'
|
||||
// values to act as wild cards.
|
||||
private Map<String, DoubleMap<String, String, TransformationOptionLimits>> limits;
|
||||
|
||||
public TransformerConfigLimits(ChildApplicationContextFactory subsystem, MimetypeService mimetypeService)
|
||||
{
|
||||
setLimits(subsystem, mimetypeService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transformer limits created from system properties.
|
||||
*/
|
||||
private void setLimits(ChildApplicationContextFactory subsystem, MimetypeService mimetypeService)
|
||||
{
|
||||
limits = new HashMap<String, DoubleMap<String, String, TransformationOptionLimits>>();
|
||||
|
||||
// Gets all the transformer, source and target combinations in properties that define limits.
|
||||
Set<Triple<String, String, String>> transformerNamesAndExt =
|
||||
getTransformerNamesAndExt(MIMETYPES_SEPARATOR, LIMIT_SUFFIXES, true, subsystem, mimetypeService);
|
||||
|
||||
// Add the system wide default just in case it is not included, as we always need this one
|
||||
transformerNamesAndExt.add(new Triple<String,String,String>(DEFAULT_TRANSFORMER, ANY, ANY));
|
||||
|
||||
// Populate the transformer limits
|
||||
for (Triple<String, String, String> triple: transformerNamesAndExt)
|
||||
{
|
||||
String transformerName = triple.getFirst();
|
||||
String sourceExt = triple.getSecond();
|
||||
String targetExt = triple.getThird();
|
||||
String sourceMimetype = ANY.equals(sourceExt) ? ANY : mimetypeService.getMimetype(sourceExt);
|
||||
String targetMimetype = ANY.equals(targetExt) ? ANY : mimetypeService.getMimetype(targetExt);
|
||||
|
||||
TransformationOptionLimits limits = newTransformationOptionLimits(transformerName, sourceExt, targetExt, subsystem);
|
||||
|
||||
DoubleMap<String, String, TransformationOptionLimits> mimetypeLimits =
|
||||
this.limits.get(transformerName);
|
||||
if (mimetypeLimits == null)
|
||||
{
|
||||
mimetypeLimits = new DoubleMap<String, String, TransformationOptionLimits>(ANY, ANY);
|
||||
this.limits.put(transformerName, mimetypeLimits);
|
||||
}
|
||||
mimetypeLimits.put(sourceMimetype, targetMimetype, limits);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a TransformationOptionLimits object using property values.
|
||||
* @param transformerName
|
||||
* @param sourceExt is null for overall transformer options rather than for a specific mimetype pair
|
||||
* @param targetExt is null for overall transformer options rather than for a specific mimetype pair
|
||||
* @return a TransformationOptionLimits object or null if not created
|
||||
*/
|
||||
private TransformationOptionLimits newTransformationOptionLimits(String transformerName,
|
||||
String sourceExt, String targetExt, ChildApplicationContextFactory subsystem)
|
||||
{
|
||||
TransformationOptionLimits limits = new TransformationOptionLimits();
|
||||
|
||||
// The overall values can be defined in two ways
|
||||
if (ANY.equals(sourceExt) && ANY.equals(targetExt))
|
||||
{
|
||||
setTransformationOptionsFromProperties(limits, transformerName, null, null, subsystem);
|
||||
}
|
||||
setTransformationOptionsFromProperties(limits, transformerName, sourceExt, targetExt, subsystem);
|
||||
|
||||
return limits;
|
||||
}
|
||||
|
||||
private void setTransformationOptionsFromProperties(TransformationOptionLimits limits,
|
||||
String transformerName, String sourceExt, String targetExt, ChildApplicationContextFactory subsystem)
|
||||
{
|
||||
String propertyNameRoot = CONTENT+transformerName+
|
||||
(sourceExt == null ? "" : MIMETYPES_SEPARATOR+sourceExt+'.'+targetExt);
|
||||
int i = 0;
|
||||
for (String suffix: LIMIT_SUFFIXES)
|
||||
{
|
||||
String value = subsystem.getProperty(propertyNameRoot+suffix);
|
||||
if (value != null)
|
||||
{
|
||||
long l = Long.parseLong(value);
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
limits.setMaxSourceSizeKBytes(l);
|
||||
break;
|
||||
case 1:
|
||||
limits.setTimeoutMs(l);
|
||||
break;
|
||||
case 2:
|
||||
limits.setMaxPages((int)l);
|
||||
break;
|
||||
case 3:
|
||||
limits.setReadLimitKBytes(l);
|
||||
break;
|
||||
case 4:
|
||||
limits.setReadLimitTimeMs(l);
|
||||
break;
|
||||
case 5:
|
||||
limits.setPageLimit((int)l);
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link TransformerConfig#getLimits(ContentTransformer, String, String)}.
|
||||
*/
|
||||
public TransformationOptionLimits getLimits(ContentTransformer transformer, String sourceMimetype,
|
||||
String targetMimetype)
|
||||
{
|
||||
if (sourceMimetype == null)
|
||||
{
|
||||
sourceMimetype = ANY;
|
||||
}
|
||||
|
||||
if (targetMimetype == null)
|
||||
{
|
||||
targetMimetype = ANY;
|
||||
}
|
||||
|
||||
String name = (transformer == null) ? DEFAULT_TRANSFORMER : transformer.getName();
|
||||
|
||||
DoubleMap<String, String, TransformationOptionLimits> transformerLimits = limits.get(name);
|
||||
|
||||
TransformationOptionLimits limits = (transformerLimits == null) ? null : transformerLimits.get(sourceMimetype, targetMimetype);
|
||||
|
||||
// Individual transformer limits might not exist.
|
||||
TransformationOptionLimits transformerWideLimits = (transformerLimits == null) ? null : transformerLimits.get(ANY, ANY);
|
||||
limits = (limits == null) ? transformerWideLimits : transformerWideLimits == null ? limits : transformerWideLimits.combine(limits);
|
||||
|
||||
// If a non recursive call
|
||||
if (transformer != null)
|
||||
{
|
||||
// System wide 'default' limits should exist.
|
||||
TransformationOptionLimits systemWideLimits = getLimits(null, sourceMimetype, targetMimetype);
|
||||
limits = (limits == null) ? systemWideLimits : systemWideLimits.combine(limits);
|
||||
}
|
||||
|
||||
return limits;
|
||||
}
|
||||
}
|
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.ANY;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.CONTENT;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.DEFAULT_TRANSFORMER;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.MIMETYPES_SEPARATOR;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.util.Triple;
|
||||
|
||||
/**
|
||||
* Provides access to single transformer configuration property depending on the
|
||||
* transformer and source and target mimetypes, falling back to defaults.
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public class TransformerConfigProperty extends TransformerPropertyNameExtractor
|
||||
{
|
||||
private Map<String, DoubleMap<String, String, String>> values;
|
||||
|
||||
public TransformerConfigProperty(ChildApplicationContextFactory subsystem,
|
||||
MimetypeService mimetypeService, String propertySuffix)
|
||||
{
|
||||
setValues(subsystem, mimetypeService, propertySuffix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transformer values created from system properties.
|
||||
*/
|
||||
private void setValues(ChildApplicationContextFactory subsystem, MimetypeService mimetypeService, String propertySuffix)
|
||||
{
|
||||
values = new HashMap<String, DoubleMap<String, String, String>>();
|
||||
|
||||
// Gets all the transformer, source and target combinations in properties that define
|
||||
// this value.
|
||||
Set<Triple<String, String, String>> transformerNamesAndMimetypes =
|
||||
getTransformerNamesAndExt(MIMETYPES_SEPARATOR, Collections.singletonList(propertySuffix), true, subsystem, mimetypeService);
|
||||
|
||||
// Add the system wide default just in case it is not included, as we always need this one
|
||||
transformerNamesAndMimetypes.add(new Triple<String,String,String>(DEFAULT_TRANSFORMER, ANY, ANY));
|
||||
|
||||
// Populate the transformer values
|
||||
for (Triple<String, String, String> triple: transformerNamesAndMimetypes)
|
||||
{
|
||||
String transformerName = triple.getFirst();
|
||||
String sourceExt = triple.getSecond();
|
||||
String targetExt = triple.getThird();
|
||||
String sourceMimetype = ANY.equals(sourceExt) ? ANY : mimetypeService.getMimetype(sourceExt);
|
||||
String targetMimetype = ANY.equals(targetExt) ? ANY : mimetypeService.getMimetype(targetExt);
|
||||
|
||||
String value = newTransformerValue(transformerName, sourceExt, targetExt, subsystem, propertySuffix);
|
||||
|
||||
DoubleMap<String, String, String> mimetypeLimits = this.values.get(transformerName);
|
||||
if (mimetypeLimits == null)
|
||||
{
|
||||
mimetypeLimits = new DoubleMap<String, String, String>(ANY, ANY);
|
||||
this.values.put(transformerName, mimetypeLimits);
|
||||
}
|
||||
mimetypeLimits.put(sourceMimetype, targetMimetype, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String object using property values.
|
||||
* @param transformerName
|
||||
* @param sourceExt is null for overall transformer options rather than for a specific mimetype pair
|
||||
* @param targetExt is null for overall transformer options rather than for a specific mimetype pair
|
||||
* @return a String object or null if not created
|
||||
*/
|
||||
private String newTransformerValue(String transformerName, String sourceExt, String targetExt,
|
||||
ChildApplicationContextFactory subsystem, String propertySuffix)
|
||||
{
|
||||
String value = getValueFromProperties(transformerName, sourceExt, targetExt, subsystem, propertySuffix);
|
||||
|
||||
// The overall values can be defined in another way
|
||||
if (value == null && ANY.equals(sourceExt) && ANY.equals(targetExt))
|
||||
{
|
||||
value = getValueFromProperties(transformerName, null, null, subsystem, propertySuffix);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private String getValueFromProperties(String transformerName, String sourceExt, String targetExt,
|
||||
ChildApplicationContextFactory subsystem, String propertySuffix)
|
||||
{
|
||||
String propertyName = CONTENT+transformerName+
|
||||
(sourceExt == null ? "" : MIMETYPES_SEPARATOR+sourceExt+'.'+targetExt)+
|
||||
propertySuffix;
|
||||
String value = subsystem.getProperty(propertyName);
|
||||
return value;
|
||||
}
|
||||
|
||||
private String getString(ContentTransformer transformer, String sourceMimetype,
|
||||
String targetMimetype)
|
||||
{
|
||||
if (sourceMimetype == null)
|
||||
{
|
||||
sourceMimetype = ANY;
|
||||
}
|
||||
|
||||
if (targetMimetype == null)
|
||||
{
|
||||
targetMimetype = ANY;
|
||||
}
|
||||
|
||||
String name = (transformer == null) ? DEFAULT_TRANSFORMER : transformer.getName();
|
||||
|
||||
DoubleMap<String, String, String> mimetypeLimits = values.get(name);
|
||||
|
||||
String value = (mimetypeLimits == null) ? null : mimetypeLimits.get(sourceMimetype, targetMimetype);
|
||||
|
||||
if (value == null && transformer != null)
|
||||
{
|
||||
// System wide 'default' limits should exist, but individual transformer values might not.
|
||||
value = getString(null, sourceMimetype, targetMimetype);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public long getLong(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
return Long.parseLong(getString(transformer, sourceMimetype, targetMimetype));
|
||||
}
|
||||
|
||||
public int getInt(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
return Integer.parseInt(getString(transformer, sourceMimetype, targetMimetype));
|
||||
}
|
||||
}
|
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.ANY;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.SUMMARY_TRANSFORMER_NAME;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
|
||||
/**
|
||||
* Provides a place to store and access statistics about transformers, source and target mimetypes combinations.
|
||||
* It also provides summaries for transformers as a whole and the system as a whole.
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public class TransformerConfigStatistics
|
||||
{
|
||||
private TransformerConfigImpl transformerConfigImpl;
|
||||
private MimetypeService mimetypeService;
|
||||
|
||||
// Holds statistics about each transformer, sourceMimeType and targetMimetype combination.
|
||||
// A null transformer is the system wide value. Null sourceMimeType and targetMimetype values are
|
||||
// transformer wide summaries.
|
||||
private Map<String, DoubleMap<String, String, TransformerStatistics>> statistics =
|
||||
new HashMap<String, DoubleMap<String, String, TransformerStatistics>>();
|
||||
|
||||
public TransformerConfigStatistics(TransformerConfigImpl transformerConfigImpl,
|
||||
MimetypeService mimetypeService)
|
||||
{
|
||||
this.transformerConfigImpl = transformerConfigImpl;
|
||||
this.mimetypeService = mimetypeService;
|
||||
}
|
||||
|
||||
public TransformerStatistics getStatistics(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
if (sourceMimetype == null)
|
||||
{
|
||||
sourceMimetype = ANY;
|
||||
}
|
||||
|
||||
if (targetMimetype == null)
|
||||
{
|
||||
targetMimetype = ANY;
|
||||
}
|
||||
|
||||
TransformerStatistics transformerStatistics;
|
||||
|
||||
String name = (transformer == null) ? SUMMARY_TRANSFORMER_NAME : transformer.getName();
|
||||
DoubleMap<String, String, TransformerStatistics> mimetypeStatistics = statistics.get(name);
|
||||
|
||||
if (mimetypeStatistics == null)
|
||||
{
|
||||
// Create the summary for the transformer as a whole
|
||||
mimetypeStatistics = new DoubleMap<String, String, TransformerStatistics>(ANY, ANY);
|
||||
statistics.put(name, mimetypeStatistics);
|
||||
transformerStatistics = newTransformerStatistics(transformer, ANY, ANY, null);
|
||||
mimetypeStatistics.put(ANY, ANY, transformerStatistics);
|
||||
}
|
||||
|
||||
if (ANY.equals(sourceMimetype) && ANY.equals(targetMimetype))
|
||||
{
|
||||
transformerStatistics = mimetypeStatistics.get(ANY, ANY);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not looking for the summary, so will have to create if not found or the summary is returned
|
||||
transformerStatistics = mimetypeStatistics.get(sourceMimetype, targetMimetype);
|
||||
if (transformerStatistics == null || transformerStatistics.isSummary())
|
||||
{
|
||||
// Create individual mimetype to mimetype transformation by this transformer
|
||||
transformerStatistics = newTransformerStatistics(transformer, sourceMimetype, targetMimetype, mimetypeStatistics.get(ANY, ANY));
|
||||
mimetypeStatistics.put(sourceMimetype, targetMimetype, transformerStatistics);
|
||||
}
|
||||
}
|
||||
|
||||
return transformerStatistics;
|
||||
}
|
||||
|
||||
private TransformerStatistics newTransformerStatistics(ContentTransformer transformer,
|
||||
String sourceMimetype, String targetMimetype, TransformerStatistics parent)
|
||||
{
|
||||
long initialAverageTime = transformerConfigImpl.getInitialAverageTime(transformer, sourceMimetype, targetMimetype);
|
||||
long initialCount = initialAverageTime <= 0
|
||||
? 0
|
||||
: transformerConfigImpl.getInitialCount(transformer, sourceMimetype, targetMimetype);
|
||||
long errorTime = transformerConfigImpl.getErrorTime(transformer, sourceMimetype, targetMimetype);
|
||||
|
||||
TransformerStatistics transformerStatistics = new TransformerStatisticsImpl(mimetypeService, sourceMimetype, targetMimetype,
|
||||
transformer, parent, errorTime, initialAverageTime, initialCount);
|
||||
|
||||
return transformerStatistics;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.ANY;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.CONTENT;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.MIMETYPES_SEPARATOR;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.SUPPORTED;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
import org.alfresco.util.Triple;
|
||||
|
||||
/**
|
||||
* Provides access to the lists of supported and unsupported mimetype transformations
|
||||
* defined via properties for all transformers.
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public class TransformerConfigSupported extends TransformerPropertyNameExtractor
|
||||
{
|
||||
// Holds configured (entries only exist if configured rather than for all possible combinations)
|
||||
// of supported and unsupported mimetypes transformations for a transformer.
|
||||
// SourceMimetype and targetMimetype may be 'ANY' values to act as wild cards.
|
||||
private Map<String, SupportedAndUnsupportedTransformations> supported;
|
||||
|
||||
public TransformerConfigSupported(ChildApplicationContextFactory subsystem, MimetypeService mimetypeService)
|
||||
{
|
||||
setSupported(subsystem, mimetypeService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the supported/unsupported mimetype transformations created from system properties.
|
||||
*/
|
||||
private void setSupported(ChildApplicationContextFactory subsystem, MimetypeService mimetypeService)
|
||||
{
|
||||
supported = new HashMap<String, SupportedAndUnsupportedTransformations>();
|
||||
|
||||
// Gets all the supported and unsupported transformer, source and target combinations
|
||||
Set<Triple<String, String, String>> transformerNamesAndMimetypes =
|
||||
getTransformerNamesAndExt(MIMETYPES_SEPARATOR, Collections.singletonList(SUPPORTED), false, subsystem, mimetypeService);
|
||||
|
||||
|
||||
|
||||
|
||||
// Populate the transformer values
|
||||
for (Triple<String, String, String> triple: transformerNamesAndMimetypes)
|
||||
{
|
||||
String transformerName = triple.getFirst();
|
||||
String sourceExt = triple.getSecond();
|
||||
String targetExt = triple.getThird();
|
||||
String sourceMimetype = ANY.equals(sourceExt) ? ANY : mimetypeService.getMimetype(sourceExt);
|
||||
String targetMimetype = ANY.equals(targetExt) ? ANY : mimetypeService.getMimetype(targetExt);
|
||||
|
||||
SupportedAndUnsupportedTransformations supportedBytransformer = this.supported.get(transformerName);
|
||||
|
||||
if (supportedBytransformer == null)
|
||||
{
|
||||
supportedBytransformer = new SupportedAndUnsupportedTransformations();
|
||||
this.supported.put(transformerName, supportedBytransformer);
|
||||
}
|
||||
boolean supported = getValueFromProperties(transformerName, sourceExt, targetExt, subsystem, SUPPORTED);
|
||||
supportedBytransformer.put(sourceMimetype, targetMimetype, supported);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getValueFromProperties(String transformerName, String sourceExt, String targetExt,
|
||||
ChildApplicationContextFactory subsystem, String propertySuffix)
|
||||
{
|
||||
String propertyName = CONTENT+transformerName+
|
||||
(sourceExt == null ? "" : MIMETYPES_SEPARATOR+sourceExt+'.'+targetExt)+
|
||||
propertySuffix;
|
||||
String value = subsystem.getProperty(propertyName);
|
||||
return value == null || value.equalsIgnoreCase("true");
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link TransformerConfig#isSupportedTransformation(ContentTransformer, String, String, TransformationOptions)}.
|
||||
*/
|
||||
public boolean isSupportedTransformation(ContentTransformer transformer, String sourceMimetype,
|
||||
String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
if (sourceMimetype == null)
|
||||
{
|
||||
sourceMimetype = ANY;
|
||||
}
|
||||
|
||||
if (targetMimetype == null)
|
||||
{
|
||||
targetMimetype = ANY;
|
||||
}
|
||||
|
||||
boolean isSupported = true;
|
||||
String name = transformer.getName();
|
||||
SupportedAndUnsupportedTransformations supportedBytransformer = supported.get(name);
|
||||
if (supportedBytransformer != null)
|
||||
{
|
||||
isSupported = supportedBytransformer.isSupported(sourceMimetype, targetMimetype);
|
||||
}
|
||||
return isSupported;
|
||||
}
|
||||
|
||||
// Class contains both supported and unsupported combinations to avoid having to
|
||||
// add in an extra ANY to ANY combination which could be true or false. Having an
|
||||
// extra combination might reduce understandability.
|
||||
private class SupportedAndUnsupportedTransformations
|
||||
{
|
||||
DoubleMap<String, String, Boolean> supportedTransformations;
|
||||
DoubleMap<String, String, Boolean> unsupportedTransformations;
|
||||
|
||||
boolean isSupported(String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
boolean isSupported = true;
|
||||
if (supportedTransformations != null)
|
||||
{
|
||||
Boolean sup = supportedTransformations.get(sourceMimetype, targetMimetype);
|
||||
isSupported = sup != null;
|
||||
}
|
||||
if (isSupported && unsupportedTransformations != null)
|
||||
{
|
||||
Boolean sup = unsupportedTransformations.get(sourceMimetype, targetMimetype);
|
||||
isSupported = sup == null;
|
||||
}
|
||||
return isSupported;
|
||||
}
|
||||
|
||||
public void put(String sourceMimetype, String targetMimetype, boolean supported)
|
||||
{
|
||||
if (supported)
|
||||
{
|
||||
if (supportedTransformations == null)
|
||||
{
|
||||
supportedTransformations = new DoubleMap<String, String, Boolean>(ANY, ANY);
|
||||
}
|
||||
supportedTransformations.put(sourceMimetype, targetMimetype, supported);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unsupportedTransformations == null)
|
||||
{
|
||||
unsupportedTransformations = new DoubleMap<String, String, Boolean>(ANY, ANY);
|
||||
}
|
||||
unsupportedTransformations.put(sourceMimetype, targetMimetype, supported);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -118,6 +118,7 @@ public class TransformerDebug
|
||||
private final long start;
|
||||
|
||||
private Call callType;
|
||||
private Frame parent;
|
||||
private int childId;
|
||||
private Set<UnavailableTransformer> unavailableTransformers;
|
||||
private String failureReason;
|
||||
@@ -127,7 +128,8 @@ public class TransformerDebug
|
||||
private Frame(Frame parent, String transformerName, String fromUrl, String sourceMimetype, String targetMimetype,
|
||||
long sourceSize, TransformationOptions options, Call pushCall, boolean origDebugOutput)
|
||||
{
|
||||
this.id = parent == null ? -1 : ++parent.childId;
|
||||
this.id = -1;
|
||||
this.parent = parent;
|
||||
this.fromUrl = fromUrl;
|
||||
this.transformerName = transformerName;
|
||||
this.sourceMimetype = sourceMimetype;
|
||||
@@ -143,8 +145,8 @@ public class TransformerDebug
|
||||
{
|
||||
if (id == -1)
|
||||
{
|
||||
id = uniqueId.getAndIncrement();
|
||||
}
|
||||
id = parent == null ? uniqueId.getAndIncrement() : ++parent.childId;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -223,14 +225,16 @@ public class TransformerDebug
|
||||
|
||||
private final NodeService nodeService;
|
||||
private final MimetypeService mimetypeService;
|
||||
private final TransformerConfig transformerConfig;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TransformerDebug(NodeService nodeService, MimetypeService mimetypeService)
|
||||
public TransformerDebug(NodeService nodeService, MimetypeService mimetypeService, TransformerConfig transformerConfig)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
this.mimetypeService = mimetypeService;
|
||||
this.transformerConfig = transformerConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -373,8 +377,10 @@ public class TransformerDebug
|
||||
long maxSourceSizeKBytes = trans.getMaxSourceSizeKBytes(frame.sourceMimetype, frame.targetMimetype, frame.options);
|
||||
String size = maxSourceSizeKBytes > 0 ? "< "+fileSize(maxSourceSizeKBytes*1024) : "";
|
||||
int padSize = 10 - size.length();
|
||||
log((c == 'a' ? "**" : " ") + (c++) + ") " + name + spaces(padName) +
|
||||
size + spaces(padSize) + ms(trans.getTransformationTime()));
|
||||
String priority = Integer.toString(transformerConfig.getPriority(trans, frame.sourceMimetype, frame.targetMimetype));
|
||||
priority = spaces(2-priority.length())+priority;
|
||||
log((c == 'a' ? "**" : " ") + (c++) + ") " + priority + ' ' + name + spaces(padName) +
|
||||
size + spaces(padSize) + ms(trans.getTransformationTime(frame.sourceMimetype, frame.targetMimetype)));
|
||||
}
|
||||
if (frame.unavailableTransformers != null)
|
||||
{
|
||||
@@ -382,7 +388,7 @@ public class TransformerDebug
|
||||
{
|
||||
int pad = longestNameLength - unavailable.name.length();
|
||||
String reason = "> "+fileSize(unavailable.maxSourceSizeKBytes*1024);
|
||||
log("--" + (c++) + ") " + unavailable.name + spaces(pad+1) + reason, unavailable.debug);
|
||||
log("--" + (c++) + ") " + unavailable.name + spaces(pad+1) + reason, unavailable.debug);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -390,7 +396,7 @@ public class TransformerDebug
|
||||
|
||||
public void inactiveTransformer(ContentTransformer transformer)
|
||||
{
|
||||
log(getName(transformer)+' '+ms(transformer.getTransformationTime())+" INACTIVE");
|
||||
log(getName(transformer)+' '+ms(transformer.getTransformationTime(null, null))+" INACTIVE");
|
||||
}
|
||||
|
||||
public void activeTransformer(int mimetypePairCount, ContentTransformer transformer, String sourceMimetype,
|
||||
@@ -398,7 +404,7 @@ public class TransformerDebug
|
||||
{
|
||||
if (firstMimetypePair)
|
||||
{
|
||||
log(getName(transformer)+' '+ms(transformer.getTransformationTime()));
|
||||
log(getName(transformer)+' '+ms(transformer.getTransformationTime(sourceMimetype, targetMimetype)));
|
||||
}
|
||||
String i = Integer.toString(mimetypePairCount);
|
||||
log(spaces(5-i.length())+mimetypePairCount+") "+getMimetypeExt(sourceMimetype)+getMimetypeExt(targetMimetype)+
|
||||
@@ -416,7 +422,7 @@ public class TransformerDebug
|
||||
: spaces(10);
|
||||
char c = (char)('a'+transformerCount);
|
||||
log(mimetypes+
|
||||
" "+c+") "+getName(transformer)+' '+ms(transformer.getTransformationTime())+
|
||||
" "+c+") "+getName(transformer)+' '+ms(transformer.getTransformationTime(sourceMimetype, targetMimetype))+
|
||||
' '+fileSize((maxSourceSizeKBytes > 0) ? maxSourceSizeKBytes*1024 : maxSourceSizeKBytes)+
|
||||
(maxSourceSizeKBytes == 0 || (explicit != null && !explicit) ? " disabled" : "")+
|
||||
(explicit == null ? "" : explicit ? " EXPLICIT" : " not explicit"));
|
||||
@@ -593,8 +599,8 @@ public class TransformerDebug
|
||||
(fileName == null ? "" : fileName) +
|
||||
(sourceSize >= 0 ? ' '+fileSize(sourceSize) : "") +
|
||||
(transformerName == null ? "" : ' '+transformerName) +
|
||||
(failureReason == null ? "" : ' '+failureReason) +
|
||||
' '+ms;
|
||||
' '+ms +
|
||||
(failureReason == null ? "" : '\n'+failureReason.trim());
|
||||
info.log(message, debug);
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.ANY;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.CONTENT;
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.PREFIX;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.util.Triple;
|
||||
|
||||
/**
|
||||
* Provides access to transformer property names and values.
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public abstract class TransformerPropertyNameExtractor
|
||||
{
|
||||
/**
|
||||
* Returns a set of transformer names, source extensions and target mimetype extensions
|
||||
* from property names that defined transformation limits.
|
||||
* @param separator after the transformer name and the source mimetype extension.
|
||||
* Must start and end in a '.'.
|
||||
* @param suffixes possible endings to the property names after the target mimetype extension.
|
||||
* Must start with a '.' if there is a suffix.
|
||||
* @param includeSummary if true will also look for property names without the separator,
|
||||
* source mimetype and target mimetype.
|
||||
* @param subsystem that provides the properties
|
||||
* @param mimetypeService
|
||||
*/
|
||||
protected Set<Triple<String,String,String>> getTransformerNamesAndExt(String separator, Collection<String> suffixes, boolean includeSummary,
|
||||
ChildApplicationContextFactory subsystem, MimetypeService mimetypeService)
|
||||
{
|
||||
Set<Triple<String,String,String>> transformerNamesAndExtensions =
|
||||
new HashSet<Triple<String,String,String>>();
|
||||
|
||||
for (String propertyName: subsystem.getPropertyNames())
|
||||
{
|
||||
if (propertyName.startsWith(PREFIX))
|
||||
{
|
||||
for (String suffix: suffixes)
|
||||
{
|
||||
if (propertyName.endsWith(suffix))
|
||||
{
|
||||
String name = propertyName.substring(CONTENT.length(), propertyName.length()-suffix.length());
|
||||
int i = name.lastIndexOf(separator);
|
||||
if (i != -1)
|
||||
{
|
||||
String[] ext = name.substring(i+separator.length()).split("\\.");
|
||||
if (ext.length == 2)
|
||||
{
|
||||
name = name.substring(0, i);
|
||||
transformerNamesAndExtensions.add(
|
||||
new Triple<String,String,String>(name, ext[0], ext[1]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (includeSummary)
|
||||
{
|
||||
transformerNamesAndExtensions.add(new Triple<String,String,String>(name, ANY, ANY));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return transformerNamesAndExtensions;
|
||||
}
|
||||
}
|
@@ -33,15 +33,12 @@ public interface TransformerSelector
|
||||
/**
|
||||
* Returns a sorted list of transformers that identifies the order in which transformers
|
||||
* should be tried.
|
||||
* @param transformers an unordered list of all transformers. This
|
||||
* list may be modified.
|
||||
* @param sourceMimetype
|
||||
* @param sourceSize
|
||||
* @param targetMimetype
|
||||
* @param options transformation options
|
||||
* @return a sorted list of transformers, with the best one first.
|
||||
*/
|
||||
List<ContentTransformer> selectTransformers(List<ContentTransformer> transformers,
|
||||
String sourceMimetype, long sourceSize, String targetMimetype,
|
||||
TransformationOptions options);
|
||||
List<ContentTransformer> selectTransformers(String sourceMimetype, long sourceSize,
|
||||
String targetMimetype, TransformationOptions options);
|
||||
}
|
||||
|
@@ -28,94 +28,127 @@ import java.util.Map;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
|
||||
/**
|
||||
* Implementation of a transformer selector that matches the code that was in place
|
||||
* before a selector was introduced. It is expected that this code will be replaced.
|
||||
* Default transformer selector implementation, which sorts by priority and then
|
||||
* by average transform time. The transform time is only used once a threshold
|
||||
* (number of transforms) has been reached. This average is maintained for each
|
||||
* source target mimetype pair.<p>
|
||||
*
|
||||
* Prior to the introduction of this class the transformation time was only kept
|
||||
* for each transformer. There was no threshold and there was a concept of
|
||||
* 'Explicit' transformers, which would cause all other transformers to be discarded.
|
||||
* It is still possible to disable transformers by giving adding unsupported mappings
|
||||
* as has been done for transformers that would not have been used in the past as
|
||||
* there existed one or more 'explicit' transformers (a concept not used by this
|
||||
* TransformerSelector). By default a transformer has a priority of {@code 10}.
|
||||
* Old 'Explicit' transformers have been given a priority of {@code 5}.
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public class TransformerSelectorImpl implements TransformerSelector
|
||||
{
|
||||
private TransformerConfig transformerConfig;
|
||||
private ContentTransformerRegistry contentTransformerRegistry;
|
||||
|
||||
public void setTransformerConfig(TransformerConfig transformerConfig)
|
||||
{
|
||||
this.transformerConfig = transformerConfig;
|
||||
}
|
||||
|
||||
public void setContentTransformerRegistry(ContentTransformerRegistry contentTransformerRegistry)
|
||||
{
|
||||
this.contentTransformerRegistry = contentTransformerRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ContentTransformer> selectTransformers(List<ContentTransformer> transformers,
|
||||
String sourceMimetype, long sourceSize, String targetMimetype,
|
||||
TransformationOptions options)
|
||||
public List<ContentTransformer> selectTransformers(String sourceMimetype, long sourceSize,
|
||||
String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
transformers = findTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options);
|
||||
transformers = discardNonExplicitTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options);
|
||||
transformers = sortTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options);
|
||||
return transformers;
|
||||
// TODO cache results for reuse. This was a heavy operation in the past and still is.
|
||||
|
||||
List<ContentTransformer> transformers = contentTransformerRegistry.getTransformers();
|
||||
List<TransformerSortData> possibleTransformers = findTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options);
|
||||
return sortTransformers(possibleTransformers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces the list of transformers down to only those capable of doing the transformation.
|
||||
* Returns the list of possible transformers for the transformation.
|
||||
*/
|
||||
private List<ContentTransformer> findTransformers(List<ContentTransformer> allTransformers, String sourceMimetype,
|
||||
private List<TransformerSortData> findTransformers(List<ContentTransformer> allTransformers, String sourceMimetype,
|
||||
long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
List<ContentTransformer> transformers = new ArrayList<ContentTransformer>(2);
|
||||
|
||||
List<TransformerSortData> transformers = new ArrayList<TransformerSortData>(8);
|
||||
for (ContentTransformer transformer : allTransformers)
|
||||
{
|
||||
if (transformer.isTransformable(sourceMimetype, sourceSize, targetMimetype, options) == true)
|
||||
int priority = transformerConfig.getPriority(transformer, sourceMimetype, targetMimetype);
|
||||
if (priority > 0 &&
|
||||
transformer.isTransformable(sourceMimetype, sourceSize, targetMimetype, options) == true)
|
||||
|
||||
{
|
||||
transformers.add(transformer);
|
||||
transformers.add(new TransformerSortData(transformer, sourceMimetype, targetMimetype, priority));
|
||||
}
|
||||
}
|
||||
return transformers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discards non explicit transformers if there are any explicit ones.
|
||||
* Returns a sorted list of transformers by priority and then average time (ignored if the threshold
|
||||
* has not been reached).
|
||||
*/
|
||||
private List<ContentTransformer> discardNonExplicitTransformers(List<ContentTransformer> allTransformers, String sourceMimetype,
|
||||
long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
private List<ContentTransformer> sortTransformers(List<TransformerSortData> possibleTransformers)
|
||||
{
|
||||
List<ContentTransformer> transformers = new ArrayList<ContentTransformer>(2);
|
||||
boolean foundExplicit = false;
|
||||
Collections.sort(possibleTransformers);
|
||||
|
||||
for (ContentTransformer transformer : allTransformers)
|
||||
List<ContentTransformer> transformers = new ArrayList<ContentTransformer>(possibleTransformers.size());
|
||||
for (TransformerSortData possibleTransformer: possibleTransformers)
|
||||
{
|
||||
if (transformer.isExplicitTransformation(sourceMimetype, targetMimetype, options) == true)
|
||||
{
|
||||
if (foundExplicit == false)
|
||||
{
|
||||
transformers.clear();
|
||||
foundExplicit = true;
|
||||
}
|
||||
transformers.add(transformer);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (foundExplicit == false)
|
||||
{
|
||||
transformers.add(transformer);
|
||||
}
|
||||
}
|
||||
transformers.add(possibleTransformer.transformer);
|
||||
}
|
||||
return transformers;
|
||||
}
|
||||
|
||||
// sort by performance (quicker is "better")
|
||||
private List<ContentTransformer> sortTransformers(List<ContentTransformer> transformers,
|
||||
String sourceMimetype, long sourceSize, String targetMimetype,
|
||||
TransformationOptions options)
|
||||
|
||||
private class TransformerSortData implements Comparable<TransformerSortData>
|
||||
{
|
||||
final Map<ContentTransformer,Long> activeTransformers = new HashMap<ContentTransformer, Long>();
|
||||
for (ContentTransformer transformer : transformers)
|
||||
private final ContentTransformer transformer;
|
||||
private final int priority;
|
||||
private long averageTime = -1;
|
||||
|
||||
TransformerSortData(ContentTransformer transformer, String sourceMimetype, String targetMimetype, int priority)
|
||||
{
|
||||
long transformationTime = transformer.getTransformationTime();
|
||||
activeTransformers.put(transformer, transformationTime);
|
||||
this.transformer = transformer;
|
||||
this.priority = priority;
|
||||
|
||||
TransformerStatistics stats = transformerConfig.getStatistics(transformer, sourceMimetype, targetMimetype);
|
||||
long threashold = transformerConfig.getThresholdCount(transformer, sourceMimetype, targetMimetype);
|
||||
averageTime = (stats.getCount() < threashold) ? 0 : stats.getAverageTime();
|
||||
}
|
||||
|
||||
List<ContentTransformer> sorted = new ArrayList<ContentTransformer>(activeTransformers.keySet());
|
||||
Collections.sort(sorted, new Comparator<ContentTransformer>() {
|
||||
@Override
|
||||
public int compare(ContentTransformer a, ContentTransformer b)
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (int) (averageTime ^ (averageTime >>> 32));
|
||||
result = prime * result + priority;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
return transformer == ((TransformerSortData) obj).transformer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(TransformerSortData that)
|
||||
{
|
||||
int relativePriority = priority - that.priority;
|
||||
if (relativePriority != 0)
|
||||
{
|
||||
return activeTransformers.get(a).compareTo(activeTransformers.get(b));
|
||||
return relativePriority;
|
||||
}
|
||||
});
|
||||
return sorted;
|
||||
|
||||
long relativeTime = averageTime - that.averageTime;
|
||||
return relativeTime > 0L ? 1 : relativeTime < 0L ? -1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
|
||||
/**
|
||||
* Implementation of a transformer selector that matches the code that was in place
|
||||
* before a selector was introduced. Class is not used but exists to allow customers
|
||||
* to maintain the previous approach if they really wish.
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public class TransformerSelectorImplOriginal implements TransformerSelector
|
||||
{
|
||||
private ContentTransformerRegistry contentTransformerRegistry;
|
||||
|
||||
public void setContentTransformerRegistry(ContentTransformerRegistry contentTransformerRegistry)
|
||||
{
|
||||
this.contentTransformerRegistry = contentTransformerRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ContentTransformer> selectTransformers( String sourceMimetype, long sourceSize,
|
||||
String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
List<ContentTransformer> transformers = contentTransformerRegistry.getTransformers();
|
||||
transformers = findTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options);
|
||||
transformers = discardNonExplicitTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options);
|
||||
transformers = sortTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options);
|
||||
return transformers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces the list of transformers down to only those capable of doing the transformation.
|
||||
*/
|
||||
private List<ContentTransformer> findTransformers(List<ContentTransformer> allTransformers, String sourceMimetype,
|
||||
long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
List<ContentTransformer> transformers = new ArrayList<ContentTransformer>(2);
|
||||
|
||||
for (ContentTransformer transformer : allTransformers)
|
||||
{
|
||||
if (transformer.isTransformable(sourceMimetype, sourceSize, targetMimetype, options) == true)
|
||||
{
|
||||
transformers.add(transformer);
|
||||
}
|
||||
}
|
||||
return transformers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discards non explicit transformers if there are any explicit ones.
|
||||
*/
|
||||
private List<ContentTransformer> discardNonExplicitTransformers(List<ContentTransformer> allTransformers, String sourceMimetype,
|
||||
long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
List<ContentTransformer> transformers = new ArrayList<ContentTransformer>(2);
|
||||
boolean foundExplicit = false;
|
||||
|
||||
for (ContentTransformer transformer : allTransformers)
|
||||
{
|
||||
if (transformer.isExplicitTransformation(sourceMimetype, targetMimetype, options) == true)
|
||||
{
|
||||
if (foundExplicit == false)
|
||||
{
|
||||
transformers.clear();
|
||||
foundExplicit = true;
|
||||
}
|
||||
transformers.add(transformer);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (foundExplicit == false)
|
||||
{
|
||||
transformers.add(transformer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return transformers;
|
||||
}
|
||||
|
||||
// sort by performance (quicker is "better")
|
||||
private List<ContentTransformer> sortTransformers(List<ContentTransformer> transformers,
|
||||
String sourceMimetype, long sourceSize, String targetMimetype,
|
||||
TransformationOptions options)
|
||||
{
|
||||
final Map<ContentTransformer,Long> activeTransformers = new HashMap<ContentTransformer, Long>();
|
||||
for (ContentTransformer transformer : transformers)
|
||||
{
|
||||
long transformationTime = transformer.getTransformationTime(sourceMimetype, targetMimetype);
|
||||
activeTransformers.put(transformer, transformationTime);
|
||||
}
|
||||
|
||||
List<ContentTransformer> sorted = new ArrayList<ContentTransformer>(activeTransformers.keySet());
|
||||
Collections.sort(sorted, new Comparator<ContentTransformer>() {
|
||||
@Override
|
||||
public int compare(ContentTransformer a, ContentTransformer b)
|
||||
{
|
||||
return activeTransformers.get(a).compareTo(activeTransformers.get(b));
|
||||
}
|
||||
});
|
||||
return sorted;
|
||||
}
|
||||
}
|
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
|
||||
/**
|
||||
* Interface to obtain the configuration and performance data for every
|
||||
* source, target and transformer combination.
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public interface TransformerStatistics
|
||||
{
|
||||
/**
|
||||
* @return the extension of the source mimetype of the transformer.
|
||||
*/
|
||||
public String getSourceExt();
|
||||
|
||||
/**
|
||||
* @return the extension of the target mimetype of the transformer.
|
||||
*/
|
||||
public String getTargetExt();
|
||||
|
||||
/**
|
||||
* @return the name of the parent transformer.
|
||||
*/
|
||||
public String getTransformerName();
|
||||
|
||||
/**
|
||||
* @return the number of time the transformer has been called.
|
||||
*/
|
||||
public long getCount();
|
||||
|
||||
/**
|
||||
* @param count overrides the number of time the transformer has been called.
|
||||
*/
|
||||
public void setCount(long count);
|
||||
|
||||
/**
|
||||
* @return the number of time the transformer has failed.
|
||||
*/
|
||||
public long getErrorCount();
|
||||
|
||||
/**
|
||||
* @param errorCount overrides the number of time the transformer has failed.
|
||||
*/
|
||||
public void setErrorCount(long errorCount);
|
||||
|
||||
/**
|
||||
* @return the average time taken by the the transformer.
|
||||
*/
|
||||
public long getAverageTime();
|
||||
|
||||
/**
|
||||
* @param averageTime overrides the average time taken by the the transformer.
|
||||
*/
|
||||
public void setAverageTime(long averageTime);
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if this is the summary of all transformations done
|
||||
* by a transformer rather than just between two specific mimetypes.
|
||||
*/
|
||||
public boolean isSummary();
|
||||
|
||||
/**
|
||||
* @param transformationTime to be added to this TransformationData and its parents.
|
||||
*/
|
||||
public void recordTime(long transformationTime);
|
||||
|
||||
/**
|
||||
* Adds 1 to the error count of this TransformationData and its parents.
|
||||
*/
|
||||
public void recordError();
|
||||
}
|
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import static org.alfresco.repo.content.transform.TransformerConfig.ANY;
|
||||
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptionLimits;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of a {@link TransformerStatistics}.
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
// TODO These values should be made visible via JMX.
|
||||
public class TransformerStatisticsImpl implements TransformerStatistics
|
||||
{
|
||||
private final MimetypeService mimetypeService;
|
||||
private final String sourceMimetype;
|
||||
private final String targetMimetype;
|
||||
private final ContentTransformer transformer;
|
||||
private final TransformerStatistics parent;
|
||||
private final long errorTime;
|
||||
|
||||
private double averageTime;
|
||||
private long count = 0L;
|
||||
private long errorCount = 0L;
|
||||
|
||||
public TransformerStatisticsImpl(MimetypeService mimetypeService, String sourceMimetype, String targetMimetype,
|
||||
ContentTransformer transformer, TransformerStatistics parent, long errorTime,
|
||||
long initialAverageTime, long initialCount)
|
||||
{
|
||||
this.mimetypeService = mimetypeService;
|
||||
this.sourceMimetype = sourceMimetype;
|
||||
this.targetMimetype = targetMimetype;
|
||||
this.transformer = transformer;
|
||||
this.parent = parent;
|
||||
this.errorTime = errorTime;
|
||||
|
||||
averageTime = initialAverageTime;
|
||||
count = initialCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceExt()
|
||||
{
|
||||
return ANY.equals(sourceMimetype) ? ANY : mimetypeService.getExtension(sourceMimetype);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTargetExt()
|
||||
{
|
||||
return ANY.equals(targetMimetype) ? ANY : mimetypeService.getExtension(targetMimetype);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTransformerName()
|
||||
{
|
||||
return transformer == null ? TransformerConfig.SUMMARY_TRANSFORMER_NAME : transformer.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void recordTime(long transformationTime)
|
||||
{
|
||||
if (count == Long.MAX_VALUE)
|
||||
{
|
||||
// we have reached the max count - reduce it by half
|
||||
// the average fluctuation won't be extreme
|
||||
count /= 2L;
|
||||
}
|
||||
// adjust the average
|
||||
count++;
|
||||
double diffTime = ((double) transformationTime) - averageTime;
|
||||
averageTime += diffTime / (double) count;
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
parent.recordTime(transformationTime);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void recordError()
|
||||
{
|
||||
if (errorCount < Long.MAX_VALUE)
|
||||
{
|
||||
errorCount++;
|
||||
}
|
||||
if (errorTime > 0)
|
||||
{
|
||||
recordTime(errorTime);
|
||||
}
|
||||
if (parent != null)
|
||||
{
|
||||
parent.recordError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCount()
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCount(long count)
|
||||
{
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getErrorCount()
|
||||
{
|
||||
return errorCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setErrorCount(long errorCount)
|
||||
{
|
||||
this.errorCount = errorCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAverageTime()
|
||||
{
|
||||
return (long)averageTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAverageTime(long averageTime)
|
||||
{
|
||||
this.averageTime = (double)averageTime;
|
||||
}
|
||||
|
||||
public boolean isSummary()
|
||||
{
|
||||
return TransformerConfig.ANY.equals(sourceMimetype) && TransformerConfig.ANY.equals(targetMimetype);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////// TODO Split into summary class ///////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// private enum Property
|
||||
// {
|
||||
// priority(true)
|
||||
// {
|
||||
// String getValue(TransformerData bean)
|
||||
// {
|
||||
// return Integer.toString(bean.getPriority());
|
||||
// }
|
||||
// void setValue(TransformerData bean, String value)
|
||||
// {
|
||||
// bean.setPriority(Integer.valueOf(value));
|
||||
// }
|
||||
// },
|
||||
//
|
||||
// averageTime(false)
|
||||
// {
|
||||
// String getValue(TransformerData bean)
|
||||
// {
|
||||
// return Integer.toString(bean.getPriority());
|
||||
// }
|
||||
// },
|
||||
//
|
||||
// count(false)
|
||||
// {
|
||||
// String getValue(TransformerData bean)
|
||||
// {
|
||||
// return Integer.toString(bean.getPriority());
|
||||
// }
|
||||
// },
|
||||
//
|
||||
// errors(false)
|
||||
// {
|
||||
// String getValue(TransformerData bean)
|
||||
// {
|
||||
// return Integer.toString(bean.getPriority());
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// private final boolean updatable;
|
||||
//
|
||||
// Property(boolean updatable)
|
||||
// {
|
||||
// this.updatable = updatable;
|
||||
// }
|
||||
//
|
||||
// abstract String getValue(TransformerData bean);
|
||||
//
|
||||
// void setValue(TransformerData bean, String value)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// public boolean isUpdatable()
|
||||
// {
|
||||
// return updatable;
|
||||
// }
|
||||
//
|
||||
// public static Set<String> getNames()
|
||||
// {
|
||||
// Set<String> names = new HashSet<String>();
|
||||
// for (Property property: Property.class.getEnumConstants())
|
||||
// {
|
||||
// names.add(property.name());
|
||||
// }
|
||||
// return names;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// public List<String> getId()
|
||||
// {
|
||||
// List<String> id = super.getId();
|
||||
//
|
||||
// id.add(transformerName);
|
||||
//
|
||||
// if (TransformerConfig.ANY.equals(sourceExt))
|
||||
// {
|
||||
// id.add(sourceExt);
|
||||
// }
|
||||
//
|
||||
// if (TransformerConfig.ANY.equals(targetExt))
|
||||
// {
|
||||
// id.add(targetExt);
|
||||
// }
|
||||
//
|
||||
// return id;
|
||||
// }
|
||||
//
|
||||
// public boolean isUpdateable(String name)
|
||||
// {
|
||||
// return Enum.valueOf(Property.class, name).isUpdatable();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected PropertyBackedBeanState createInitialState() throws IOException
|
||||
// {
|
||||
// return new PropertyBackedBeanState()
|
||||
// {
|
||||
//
|
||||
// @Override
|
||||
// public Set<String> getPropertyNames()
|
||||
// {
|
||||
// return Property.getNames();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getProperty(String name)
|
||||
// {
|
||||
// return Enum.valueOf(Property.class, name).getValue(TransformerDataImpl.this);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void setProperty(String name, String value)
|
||||
// {
|
||||
// Enum.valueOf(Property.class, name).setValue(TransformerDataImpl.this, value);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void start()
|
||||
// {
|
||||
// ;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void stop()
|
||||
// {
|
||||
// ;
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
}
|
Reference in New Issue
Block a user