mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
ALF-12273: Merge V4.0-BUG-FIX to HEAD
33119: Merge V3.4-BUG-FIX (3.4.8) to V4.0-BUG-FIX (4.0.1) 33099: ALF-10412 Nonreducing 100% CPU Uploading Large Files to Share Site Document Library ALF-10976 Excel files bigger than 2mb cause soffice.exe to take 100% of one CPU for more than 2 minutes in previews. - Polish TransformerDebug - Better config for txt and xlsx to swf 33095: ALF-10412 Nonreducing 100% CPU Uploading Large Files to Share Site Document Library ALF-10976 Excel files bigger than 2mb cause soffice.exe to take 100% of one CPU for more than 2 minutes in previews. - Improvements to TransformerDebug so that calls to getTransformers use trace rather than debug level logging allowing one to see the wood for the trees 33016: ALF-10412 Nonreducing 100% CPU Uploading Large Files to Share Site Document Library ALF-10976 Excel files bigger than 2mb cause soffice.exe to take 100% of one CPU for more than 2 minutes in previews. - fix build errors - may not get all of them as not tested on Linux 33005: ALF-10412 Nonreducing 100% CPU Uploading Large Files to Share Site Document Library ALF-10976 Excel files bigger than 2mb cause soffice.exe to take 100% of one CPU for more than 2 minutes in previews. - Disable transformers if the source txt or xlsx is too large - avoids transforms that don't finish txt limit is 5MB xlsx limit is 1MB - Added a general 2 minute timeout added (ignored by JOD transformers - which already have a 2 minute timeout and OpenOffice transformers - would require more work) - Previous commit already limited txt -> pdf -> png so that only the 1st pdf page was created when creating a doclib icon - Earlier commit already reduced the priority of the background Thread used for transformations so that user interaction did not suffer. 33004: ALF-10412 Nonreducing 100% CPU Uploading Large Files to Share Site Document Library ALF-10976 Excel files bigger than 2mb cause soffice.exe to take 100% of one CPU for more than 2 minutes in previews. - Added time, size and page limits to transformer configuration to allow one to avoid costly transformations and to stop them if they do occur. Limits avoid a transformer being selected if the source is too large, or make it throw and Exception or discard data after a given time, KBytes read or pages created. - Page limits currently only used by TextToPdfContentTransformer for thumbnail (icon) creation. - Time, Size and Page limits are currently ignored by JodContentTransformer and OpenOfficeContentTransformerWorker once running but the max source size limits may be used to avoid the selection of the transformer in the first place. - TransformerDebug added to be able to see what is going on. A real eye opener! log4j org.alfresco.repo.content.transform.TransformerDebug 32136: ALF-10412 Nonreducing 100% CPU Uploading Large Files to Share Site Document Library Reducing the priority of the async thread pool that is used to perform the transformations so that normal activity (and even garbage collection) is not interrupted by transformations. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@33223 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -198,9 +198,21 @@ public abstract class AbstractContentTransformer implements ContentTransformer
|
||||
}
|
||||
// it all checks out OK
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}<p>
|
||||
*
|
||||
* Implementation calls the deprecated overloaded method without the sourceSize parameter.
|
||||
* Note: source size checked has not been added to this deprecated class.
|
||||
*/
|
||||
@Override
|
||||
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
return isTransformable(sourceMimetype, targetMimetype, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.content.transform.ContentTransformer#isTransformable(java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions)
|
||||
* @deprecated use version with extra sourceSize parameter.
|
||||
*/
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -38,7 +38,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
* @author Derek Hulley
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public abstract class AbstractContentTransformer2 extends ContentTransformerHelper implements ContentTransformer
|
||||
public abstract class AbstractContentTransformer2 extends AbstractContentTransformerLimits
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(AbstractContentTransformer2.class);
|
||||
|
||||
@@ -103,12 +103,14 @@ public abstract class AbstractContentTransformer2 extends ContentTransformerHelp
|
||||
{
|
||||
String sourceMimetype = getMimetype(reader);
|
||||
String targetMimetype = getMimetype(writer);
|
||||
boolean transformable = isTransformable(sourceMimetype, targetMimetype, options);
|
||||
long sourceSize = reader.getSize();
|
||||
boolean transformable = isTransformable(sourceMimetype, sourceSize, targetMimetype, options);
|
||||
if (transformable == false)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unsuported transformation attempted: \n" +
|
||||
AlfrescoRuntimeException e = new AlfrescoRuntimeException("Unsuported transformation attempted: \n" +
|
||||
" reader: " + reader + "\n" +
|
||||
" writer: " + writer);
|
||||
throw transformerDebug.setCause(e);
|
||||
}
|
||||
// it all checks out OK
|
||||
}
|
||||
@@ -154,8 +156,16 @@ public abstract class AbstractContentTransformer2 extends ContentTransformerHelp
|
||||
|
||||
try
|
||||
{
|
||||
if (transformerDebug.isEnabled())
|
||||
{
|
||||
transformerDebug.pushTransform(this, reader.getContentUrl(), reader.getMimetype(), writer.getMimetype(), reader.getSize());
|
||||
}
|
||||
|
||||
// Check the transformability
|
||||
checkTransformable(reader, writer, options);
|
||||
|
||||
// Pass on any limits to the reader
|
||||
setReaderLimits(reader, writer, options);
|
||||
|
||||
// Transform
|
||||
transformInternal(reader, writer, options);
|
||||
@@ -174,18 +184,22 @@ public abstract class AbstractContentTransformer2 extends ContentTransformerHelp
|
||||
// Report the error
|
||||
if(differentType == null)
|
||||
{
|
||||
throw new ContentIOException("Content conversion failed: \n" +
|
||||
transformerDebug.debug("Failed", e);
|
||||
throw new ContentIOException("Content conversion failed: \n" +
|
||||
" reader: " + reader + "\n" +
|
||||
" writer: " + writer + "\n" +
|
||||
" options: " + options,
|
||||
" 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 + "\n" +
|
||||
" options: " + options.toString(false) + "\n" +
|
||||
" limits: " + getLimits(reader, writer, options) + "\n" +
|
||||
" claimed mime type: " + reader.getMimetype() + "\n" +
|
||||
" detected mime type: " + differentType,
|
||||
e);
|
||||
@@ -193,6 +207,8 @@ public abstract class AbstractContentTransformer2 extends ContentTransformerHelp
|
||||
}
|
||||
finally
|
||||
{
|
||||
transformerDebug.popTransform();
|
||||
|
||||
// check that the reader and writer are both closed
|
||||
if (reader.isChannelOpen())
|
||||
{
|
||||
|
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 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 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.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}
|
||||
* implementations.
|
||||
* <p>
|
||||
* This class maintains the limits and provides methods that combine limits:
|
||||
* a) for the transformer as a whole
|
||||
* b) for specific combinations if source and target mimetypes
|
||||
* c) for the {@link TransformationOptions} provided for a specific transform.
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public abstract class AbstractContentTransformerLimits extends ContentTransformerHelper implements ContentTransformer, BeanNameAware
|
||||
{
|
||||
/** 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.
|
||||
*/
|
||||
protected boolean isPageLimitSupported()
|
||||
{
|
||||
return pageLimitsSupported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if 'page' limits are supported.
|
||||
*/
|
||||
public void setPageLimitsSuported(boolean pageLimitsSupported)
|
||||
{
|
||||
this.pageLimitsSupported = pageLimitsSupported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper setter of the transformer debug.
|
||||
* @param transformerDebug
|
||||
*/
|
||||
public void setTransformerDebug(TransformerDebug transformerDebug)
|
||||
{
|
||||
this.transformerDebug = transformerDebug;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}<p>
|
||||
*
|
||||
* Implementation calls the deprecated overloaded method without the sourceSize parameter
|
||||
* and then {@link #isTransformableSize(String, long, String, TransformationOptions)}.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
return
|
||||
isTransformable(sourceMimetype, targetMimetype, options) &&
|
||||
isTransformableSize(sourceMimetype, sourceSize, targetMimetype, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this transformer is able to transform the given {@code sourceSize}.
|
||||
* The {@code maxSourceSizeKBytes} property may indicate that only small source files
|
||||
* may be transformed.
|
||||
* @param sourceSize size in bytes of the source. If negative, the source size is unknown.
|
||||
* @return {@code true} if the source is transformable.
|
||||
*/
|
||||
protected boolean isTransformableSize(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
boolean sizeOkay = true;
|
||||
if (sourceSize >= 0)
|
||||
{
|
||||
TransformationOptionLimits limits = getLimits(sourceMimetype, targetMimetype, options);
|
||||
|
||||
// The maxSourceSizeKbytes value is ignored if this transformer is able to use
|
||||
// page limits and the limits include a pageLimit. Normally used in the creation
|
||||
// of icons. Note the readLimitKBytes value is not checked as the combined limits
|
||||
// only have the max or limit kbytes value set (the smaller value is returned).
|
||||
if (!isPageLimitSupported() || limits.getPageLimit() <= 0)
|
||||
{
|
||||
// if maxSourceSizeKBytes == 0 this implies the transformation is disabled
|
||||
long maxSourceSizeKBytes = limits.getMaxSourceSizeKBytes();
|
||||
sizeOkay = maxSourceSizeKBytes < 0 || (maxSourceSizeKBytes > 0 && sourceSize <= maxSourceSizeKBytes*1024);
|
||||
if (!sizeOkay && transformerDebug.isEnabled())
|
||||
{
|
||||
transformerDebug.unavailableTransformer(this, maxSourceSizeKBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sizeOkay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the timeout (ms) on the InputStream after which an IOExecption is thrown
|
||||
* to terminate very slow transformations or a subprocess is terminated (killed).
|
||||
* @return timeoutMs in milliseconds. If less than or equal to zero (the default)
|
||||
* there is no timeout.
|
||||
*/
|
||||
protected long getTimeoutMs()
|
||||
{
|
||||
return limits.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.
|
||||
*/
|
||||
public void setTimeoutMs(long timeoutMs)
|
||||
{
|
||||
limits.setTimeoutMs(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
|
||||
* end of file.
|
||||
* @return readLimitBytes if less than or equal to zero (the default) there is no limit.
|
||||
*/
|
||||
protected long getReadLimitTimeMs()
|
||||
{
|
||||
return limits.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.
|
||||
*/
|
||||
public void setReadLimitTimeMs(long readLimitTimeMs)
|
||||
{
|
||||
limits.setReadLimitTimeMs(readLimitTimeMs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the 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.
|
||||
* @return maxSourceSizeKBytes if less than or equal to zero (the default) there is no limit.
|
||||
*/
|
||||
protected long getMaxSourceSizeKBytes()
|
||||
{
|
||||
return limits.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.
|
||||
*/
|
||||
public void setMaxSourceSizeKBytes(long maxSourceSizeKBytes)
|
||||
{
|
||||
limits.setMaxSourceSizeKBytes(maxSourceSizeKBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the 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.
|
||||
* @return readLimitKBytes if less than or equal to zero (the default) no limit should be applied.
|
||||
*/
|
||||
protected long getReadLimitKBytes()
|
||||
{
|
||||
return limits.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.
|
||||
*/
|
||||
public void setReadLimitKBytes(long readLimitKBytes)
|
||||
{
|
||||
limits.setReadLimitKBytes(readLimitKBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum number of pages read before an exception is thrown.
|
||||
* @return If less than or equal to zero (the default) no limit should be applied.
|
||||
*/
|
||||
protected int getMaxPages()
|
||||
{
|
||||
return limits.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.
|
||||
*/
|
||||
public void setMaxPages(int maxPages)
|
||||
{
|
||||
limits.setMaxPages(maxPages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the page limit before returning EOF.
|
||||
* @return If less than or equal to zero (the default) no limit should be applied.
|
||||
*/
|
||||
protected int getPageLimit()
|
||||
{
|
||||
return limits.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.
|
||||
*/
|
||||
public void setPageLimit(int pageLimit)
|
||||
{
|
||||
limits.setPageLimit(pageLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns max and limit values for time, size and pages in a single operation.
|
||||
*/
|
||||
protected TransformationOptionLimits getLimits()
|
||||
{
|
||||
return limits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets max and limit values for time, size and pages in a single operation.
|
||||
*/
|
||||
public void setLimits(TransformationOptionLimits limits)
|
||||
{
|
||||
this.limits = 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.
|
||||
*/
|
||||
public void setMimetypeLimits(Map<String, Map<String, TransformationOptionLimits>> mimetypeLimits)
|
||||
{
|
||||
this.mimetypeLimits = mimetypeLimits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns max and limit values for time, size and pages for a specified source and
|
||||
* target mimetypes, combined with this Transformer's general limits and optionally
|
||||
* the supplied transformation option's limits.
|
||||
*/
|
||||
protected TransformationOptionLimits getLimits(ContentReader reader, ContentWriter writer,
|
||||
TransformationOptions options)
|
||||
{
|
||||
return (reader == null || writer == null)
|
||||
? limits.combine(options.getLimits())
|
||||
: getLimits(reader.getMimetype(), writer.getMimetype(), options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns max and limit values for time, size and pages for a specified source and
|
||||
* target mimetypes, combined with this Transformer's general limits and optionally
|
||||
* the supplied transformation option's limits.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
Map<String, TransformationOptionLimits> targetLimits =
|
||||
this.mimetypeLimits.get(sourceMimetype);
|
||||
if (targetLimits == null)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass on any limits to the reader. Will only do so if the reader is an
|
||||
* {@link AbstractContentReader}.
|
||||
* @param reader passed to {@link #transform(ContentReader, ContentWriter, TransformationOptions).
|
||||
* @param writer passed to {@link #transform(ContentReader, ContentWriter, TransformationOptions).
|
||||
* @param options passed to {@link #transform(ContentReader, ContentWriter, TransformationOptions).
|
||||
*/
|
||||
protected void setReaderLimits(ContentReader reader, ContentWriter writer,
|
||||
TransformationOptions options)
|
||||
{
|
||||
if (reader instanceof AbstractContentReader)
|
||||
{
|
||||
AbstractContentReader abstractContentReader = (AbstractContentReader)reader;
|
||||
TransformationOptionLimits limits = getLimits(reader, writer, options);
|
||||
abstractContentReader.setLimits(limits);
|
||||
abstractContentReader.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 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.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.HashMap;
|
||||
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.service.ServiceRegistry;
|
||||
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.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* Test methods that control limits in {@link AbstractContentTransformerLimits}
|
||||
*/
|
||||
public class AbstractContentTransformerLimitsTest
|
||||
{
|
||||
private static final String A = "a";
|
||||
private static final String B = "b";
|
||||
private static final String C = "c";
|
||||
|
||||
private AbstractContentTransformerLimits transformer;
|
||||
private TransformationOptionLimits limits;
|
||||
private Map<String, Map<String, TransformationOptionLimits>> mimetypeLimits;
|
||||
private TransformationOptions options;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
ApplicationContext ctx = ContentMinimalContextTestSuite.getContext();
|
||||
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
MimetypeService mimetypeService = serviceRegistry.getMimetypeService();
|
||||
TransformerDebug transformerDebug = (TransformerDebug) ctx.getBean("transformerDebug");
|
||||
|
||||
transformer = new AbstractContentTransformer2()
|
||||
{
|
||||
@Override
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype,
|
||||
TransformationOptions options)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void transformInternal(ContentReader reader, ContentWriter writer,
|
||||
TransformationOptions options) throws Exception
|
||||
{
|
||||
}
|
||||
};
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
|
||||
limits = new TransformationOptionLimits();
|
||||
options = new TransformationOptions();
|
||||
}
|
||||
|
||||
private void addMimetypeLimits(String source, String target, TransformationOptionLimits limits)
|
||||
{
|
||||
if (mimetypeLimits == null)
|
||||
{
|
||||
mimetypeLimits = new HashMap<String, Map<String, TransformationOptionLimits>>();
|
||||
}
|
||||
|
||||
Map<String, TransformationOptionLimits> targetLimits = mimetypeLimits.get(source);
|
||||
if (targetLimits == null)
|
||||
{
|
||||
targetLimits = new HashMap<String, TransformationOptionLimits>();
|
||||
mimetypeLimits.put(source, targetLimits);
|
||||
}
|
||||
|
||||
targetLimits.put(target, limits);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeoutMs() throws Exception
|
||||
{
|
||||
long value = 1234;
|
||||
transformer.setTimeoutMs(value);
|
||||
long actual = transformer.getTimeoutMs();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadLimitTimeMs() throws Exception
|
||||
{
|
||||
long value = 1234;
|
||||
transformer.setReadLimitTimeMs(value);
|
||||
long actual = transformer.getReadLimitTimeMs();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxSourceSizeKBytes() throws Exception
|
||||
{
|
||||
long value = 1234;
|
||||
transformer.setMaxSourceSizeKBytes(value);
|
||||
long actual = transformer.getMaxSourceSizeKBytes();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadLimitKBytes() throws Exception
|
||||
{
|
||||
long value = 1234;
|
||||
transformer.setReadLimitKBytes(value);
|
||||
long actual = transformer.getReadLimitKBytes();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxPages() throws Exception
|
||||
{
|
||||
int value = 1234;
|
||||
transformer.setMaxPages(value);
|
||||
int actual = transformer.getMaxPages();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPageLimit() throws Exception
|
||||
{
|
||||
int value = 1234;
|
||||
transformer.setPageLimit(value);
|
||||
int actual = transformer.getPageLimit();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMimetypeLimit() throws Exception
|
||||
{
|
||||
long value = 1234;
|
||||
limits.setMaxSourceSizeKBytes(value);
|
||||
addMimetypeLimits(A, B, limits);
|
||||
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
long actual = transformer.getLimits(A, B, options).getMaxSourceSizeKBytes();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
|
||||
actual = transformer.getLimits(A, C, options).getMaxSourceSizeKBytes();
|
||||
assertEquals("Other values should not be set", -1, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMimetypeLimitTargetWildcard() throws Exception
|
||||
{
|
||||
long value = 1234;
|
||||
limits.setMaxSourceSizeKBytes(value);
|
||||
addMimetypeLimits(A, "*", limits);
|
||||
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
long actual = transformer.getLimits(A, B, options).getMaxSourceSizeKBytes();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
|
||||
actual = transformer.getLimits(B, A, options).getMaxSourceSizeKBytes();
|
||||
assertEquals("Other values should not be set", -1, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMimetypeLimitSourceWildcard() throws Exception
|
||||
{
|
||||
long value = 1234;
|
||||
limits.setMaxSourceSizeKBytes(value);
|
||||
addMimetypeLimits("*", B, limits);
|
||||
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
long actual = transformer.getLimits(A, B, options).getMaxSourceSizeKBytes();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
|
||||
actual = transformer.getLimits(B, A, options).getMaxSourceSizeKBytes();
|
||||
assertEquals("Other values should not be set", -1, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPassedInOptions() throws Exception
|
||||
{
|
||||
long value = 1234;
|
||||
limits.setMaxSourceSizeKBytes(value+1);
|
||||
addMimetypeLimits(A, B, limits);
|
||||
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
long actual = transformer.getLimits(A, B, options).getMaxSourceSizeKBytes();
|
||||
assertEquals("Getter did not return set value", value+1, actual);
|
||||
|
||||
options.setMaxSourceSizeKBytes(value);
|
||||
actual = transformer.getLimits(A, B, options).getMaxSourceSizeKBytes();
|
||||
assertEquals("Getter did not return set value", value, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsTransformableSize() 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));
|
||||
|
||||
// Set limit for A to B mimetypes and test
|
||||
limits.setMaxSourceSizeKBytes(kValue);
|
||||
addMimetypeLimits(A, B, limits);
|
||||
transformer.setMimetypeLimits(mimetypeLimits);
|
||||
|
||||
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",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
|
||||
// With a mimetype that does not have any specific limits
|
||||
assertTrue("No limits so should have been ok",
|
||||
transformer.isTransformableSize(C, byteValue+1, B, options));
|
||||
assertTrue("No limits so should have been ok",
|
||||
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);
|
||||
|
||||
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);
|
||||
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",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
|
||||
// b) combination where transformer limit is used
|
||||
transformer.setMaxSourceSizeKBytes(kValue+1);
|
||||
limits.setMaxSourceSizeKBytes(kValue);
|
||||
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",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
|
||||
// c) combination where mimetype limit is used
|
||||
transformer.setMaxSourceSizeKBytes(kValue);
|
||||
limits.setMaxSourceSizeKBytes(kValue+1);
|
||||
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",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsTransformableSizeWithPageLimit() throws Exception
|
||||
{
|
||||
long kValue = 12;
|
||||
long byteValue = kValue*1024;
|
||||
|
||||
transformer.setMaxSourceSizeKBytes(kValue);
|
||||
transformer.setPageLimitsSuported(true);
|
||||
|
||||
// Test works as normal before setting the pageLimit
|
||||
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",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
|
||||
// test with pageLimit set
|
||||
options.getLimits().setPageLimit(1);
|
||||
assertTrue("Size is greater than limit BUT pageLimit is set so should have been ok",
|
||||
transformer.isTransformableSize(A, byteValue+1, B, options));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetReaderLimits() throws Exception
|
||||
{
|
||||
AbstractContentReader reader = new DummyAbstractContentReader(0, 0);
|
||||
|
||||
long value = 1234;
|
||||
transformer.setTimeoutMs(value);
|
||||
|
||||
assertEquals("Limit should not have been set in the reader", null, reader.getLimits());
|
||||
|
||||
transformer.setReaderLimits(reader, null, options);
|
||||
assertEquals("Limit should have been set in the reader", value, reader.getLimits().getTimeoutMs());
|
||||
|
||||
options.setTimeoutMs(--value);
|
||||
transformer.setReaderLimits(reader, null, options);
|
||||
assertEquals("Limit should have been set in the reader", value, reader.getLimits().getTimeoutMs());
|
||||
}
|
||||
}
|
@@ -68,6 +68,7 @@ public abstract class AbstractContentTransformerTest extends TestCase
|
||||
|
||||
protected ServiceRegistry serviceRegistry;
|
||||
protected MimetypeService mimetypeService;
|
||||
protected TransformerDebug transformerDebug;
|
||||
|
||||
/**
|
||||
* Fetches a transformer to test for a given transformation. The transformer
|
||||
@@ -94,6 +95,7 @@ public abstract class AbstractContentTransformerTest extends TestCase
|
||||
// Grab other useful beans
|
||||
serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
mimetypeService = serviceRegistry.getMimetypeService();
|
||||
transformerDebug = (TransformerDebug) ctx.getBean("transformerDebug");
|
||||
// perform a little cleaning up
|
||||
long now = System.currentTimeMillis();
|
||||
TempFileProvider.TempFileCleanerJob.removeFiles(now);
|
||||
@@ -212,7 +214,14 @@ public abstract class AbstractContentTransformerTest extends TestCase
|
||||
{
|
||||
// attempt to get a source file for each mimetype
|
||||
String[] quickFiles = getQuickFilenames(sourceMimetype);
|
||||
sb.append(" Source Files: ").append(quickFiles).append("\n");
|
||||
sb.append(" Source Files: ");
|
||||
for (String quickFile: quickFiles)
|
||||
{
|
||||
sb.append(quickFile);
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append("\n");
|
||||
|
||||
|
||||
for (String quickFile : quickFiles)
|
||||
{
|
||||
@@ -232,7 +241,7 @@ public abstract class AbstractContentTransformerTest extends TestCase
|
||||
|
||||
// must we test the transformation?
|
||||
ContentTransformer transformer = getTransformer(sourceMimetype, targetMimetype);
|
||||
if (transformer == null || transformer.isTransformable(sourceMimetype, targetMimetype, null) == false)
|
||||
if (transformer == null || transformer.isTransformable(sourceMimetype, -1, targetMimetype, null) == false)
|
||||
{
|
||||
// no transformer
|
||||
continue;
|
||||
|
@@ -45,6 +45,8 @@ public class ArchiveContentTransformerTest extends AbstractContentTransformerTes
|
||||
super.setUp();
|
||||
|
||||
transformer = new ArchiveContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
|
||||
protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype)
|
||||
@@ -54,9 +56,9 @@ public class ArchiveContentTransformerTest extends AbstractContentTransformerTes
|
||||
|
||||
public void testIsTransformable() throws Exception
|
||||
{
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_ZIP, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable("application/x-tar", MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable("application/x-gtar", MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_ZIP, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable("application/x-tar", -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable("application/x-gtar", -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -28,7 +28,7 @@ import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
*/
|
||||
public class BinaryPassThroughContentTransformerTest extends AbstractContentTransformerTest
|
||||
{
|
||||
private ContentTransformer transformer;
|
||||
private BinaryPassThroughContentTransformer transformer;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
@@ -36,6 +36,8 @@ public class BinaryPassThroughContentTransformerTest extends AbstractContentTran
|
||||
super.setUp();
|
||||
|
||||
transformer = new BinaryPassThroughContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,13 +53,13 @@ public class BinaryPassThroughContentTransformerTest extends AbstractContentTran
|
||||
TransformationOptions options = new TransformationOptions();
|
||||
boolean reliability = false;
|
||||
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_TEXT_PLAIN, options);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, options);
|
||||
assertFalse("Mimetype should not be supported", reliability);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_XML, MimetypeMap.MIMETYPE_XML, options);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_XML, -1, MimetypeMap.MIMETYPE_XML, options);
|
||||
assertFalse("Mimetype should not be supported", reliability);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_WORD, options);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, -1, MimetypeMap.MIMETYPE_WORD, options);
|
||||
assertTrue("Mimetype should be supported", reliability);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_EXCEL, options);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, -1, MimetypeMap.MIMETYPE_EXCEL, options);
|
||||
assertTrue("Mimetype should be supported", reliability);
|
||||
}
|
||||
}
|
||||
|
@@ -130,7 +130,7 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple
|
||||
*
|
||||
* @see org.alfresco.repo.content.transform.ContentTransformer#isTransformable(java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions)
|
||||
*/
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
boolean result = true;
|
||||
String currentSourceMimetype = sourceMimetype;
|
||||
@@ -178,6 +178,7 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple
|
||||
}
|
||||
}
|
||||
|
||||
boolean first = true;
|
||||
Iterator<ContentTransformer> transformerIterator = transformers.iterator();
|
||||
Iterator<String> intermediateMimetypeIterator = intermediateMimetypes.iterator();
|
||||
while (transformerIterator.hasNext())
|
||||
@@ -195,8 +196,9 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple
|
||||
currentTargetMimetype = intermediateMimetypeIterator.next();
|
||||
}
|
||||
|
||||
// check we can tranform the current stage
|
||||
if (transformer.isTransformable(currentSourceMimetype, currentTargetMimetype, options) == false)
|
||||
// check we can tranform the current stage (using -1 if not the first stage as we can't know the size)
|
||||
long size = first ? sourceSize : -1;
|
||||
if (transformer.isTransformable(currentSourceMimetype, size, currentTargetMimetype, options) == false)
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
@@ -204,6 +206,12 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple
|
||||
|
||||
// move on
|
||||
currentSourceMimetype = currentTargetMimetype;
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (result && !isTransformableSize(sourceMimetype, sourceSize, targetMimetype, options))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -255,4 +263,15 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple
|
||||
{
|
||||
return Collections.unmodifiableList(intermediateMimetypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method should no longer be called as the overloaded method
|
||||
* that calls it has the overridden.
|
||||
*/
|
||||
@Override
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype,
|
||||
TransformationOptions options)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -45,12 +45,12 @@ public class ComplexContentTransformerTest extends AbstractContentTransformerTes
|
||||
ContentTransformer unoTransformer = (ContentTransformer) ctx.getBean("transformer.OpenOffice");
|
||||
ContentTransformer pdfBoxTransformer = (ContentTransformer) ctx.getBean("transformer.PdfBox");
|
||||
// make sure that they are working for this test
|
||||
if (unoTransformer.isTransformable(MimetypeMap.MIMETYPE_PPT, MimetypeMap.MIMETYPE_PDF, new TransformationOptions()) == false)
|
||||
if (unoTransformer.isTransformable(MimetypeMap.MIMETYPE_PPT, -1, MimetypeMap.MIMETYPE_PDF, new TransformationOptions()) == false)
|
||||
{
|
||||
isAvailable = false;
|
||||
return;
|
||||
}
|
||||
else if (pdfBoxTransformer.isTransformable(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()) == false)
|
||||
else if (pdfBoxTransformer.isTransformable(MimetypeMap.MIMETYPE_PDF, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()) == false)
|
||||
{
|
||||
isAvailable = false;
|
||||
return;
|
||||
@@ -62,6 +62,7 @@ public class ComplexContentTransformerTest extends AbstractContentTransformerTes
|
||||
|
||||
transformer = new ComplexContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
// set the transformer list
|
||||
List<ContentTransformer> transformers = new ArrayList<ContentTransformer>(2);
|
||||
transformers.add(unoTransformer);
|
||||
@@ -86,9 +87,9 @@ public class ComplexContentTransformerTest extends AbstractContentTransformerTes
|
||||
{
|
||||
return;
|
||||
}
|
||||
boolean reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_PPT, MimetypeMap.MIMETYPE_PDF, new TransformationOptions());
|
||||
boolean reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_PPT, -1, MimetypeMap.MIMETYPE_PDF, new TransformationOptions());
|
||||
assertEquals("Mimetype should not be supported", false, reliability);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_PPT, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_PPT, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
|
||||
assertEquals("Mimetype should be supported", true, reliability);
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -33,16 +33,22 @@ import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
*/
|
||||
public interface ContentTransformer extends ContentWorker
|
||||
{
|
||||
/**
|
||||
* @deprecated use version with extra sourceSize parameter.
|
||||
*/
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options);
|
||||
|
||||
/**
|
||||
* Indicates whether the provided source mimetype can be transformed into the target mimetype with
|
||||
* the options specified by this content transformer.
|
||||
*
|
||||
* @param sourceMimetype the source mimetype
|
||||
* @param destinationMimetype the destination mimetype
|
||||
* @param sourceSize the size (bytes) of the source. If negative it is unknown.
|
||||
* @param targetMimetype the target mimetype
|
||||
* @param options the transformation options
|
||||
* @return boolean true if this content transformer can satify the mimetypes and options specified, false otherwise
|
||||
*/
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options);
|
||||
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options);
|
||||
|
||||
/**
|
||||
* Indicates whether given the provided transformation parmaters this transformer can prvide an explict
|
||||
|
@@ -71,13 +71,21 @@ public class ContentTransformerRegistry
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the best transformer possible. This is a combination of the most reliable
|
||||
* and the most performant transformer.
|
||||
* @deprecated use overloaded version with sourceSize parameter.
|
||||
*/
|
||||
public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
return getTransformer(sourceMimetype, -1, targetMimetype, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the best transformer possible. This is a combination of the most reliable
|
||||
* and the most performant transformer.
|
||||
*/
|
||||
public ContentTransformer getTransformer(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
// Get the sorted list of transformers
|
||||
List<ContentTransformer> transformers = getActiveTransformers(sourceMimetype, targetMimetype, options);
|
||||
List<ContentTransformer> transformers = getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options);
|
||||
|
||||
// select the most performant transformer
|
||||
ContentTransformer bestTransformer = null;
|
||||
@@ -92,10 +100,10 @@ public class ContentTransformerRegistry
|
||||
/**
|
||||
* @since 3.5
|
||||
*/
|
||||
public List<ContentTransformer> getActiveTransformers(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
public List<ContentTransformer> getActiveTransformers(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
// Get the list of transformers
|
||||
List<ContentTransformer> transformers = findTransformers(sourceMimetype, targetMimetype, options);
|
||||
List<ContentTransformer> transformers = findTransformers(sourceMimetype, sourceSize, targetMimetype, options);
|
||||
|
||||
final Map<ContentTransformer,Long> activeTransformers = new HashMap<ContentTransformer, Long>();
|
||||
|
||||
@@ -103,7 +111,7 @@ public class ContentTransformerRegistry
|
||||
for (ContentTransformer transformer : transformers)
|
||||
{
|
||||
// Transformability can be dynamic, i.e. it may have become unusable
|
||||
if (transformer.isTransformable(sourceMimetype, targetMimetype, options) == false)
|
||||
if (transformer.isTransformable(sourceMimetype, sourceSize, targetMimetype, options) == false)
|
||||
{
|
||||
// It is unreliable now.
|
||||
continue;
|
||||
@@ -135,10 +143,10 @@ public class ContentTransformerRegistry
|
||||
* @return Returns best transformer for the translation - null if all
|
||||
* score 0.0 on reliability
|
||||
*/
|
||||
private List<ContentTransformer> findTransformers(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
private List<ContentTransformer> findTransformers(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
// search for a simple transformer that can do the job
|
||||
List<ContentTransformer> transformers = findDirectTransformers(sourceMimetype, targetMimetype, options);
|
||||
List<ContentTransformer> transformers = findDirectTransformers(sourceMimetype, sourceSize, targetMimetype, options);
|
||||
// get the complex transformers that can do the job
|
||||
List<ContentTransformer> complexTransformers = findComplexTransformer(sourceMimetype, targetMimetype, options);
|
||||
transformers.addAll(complexTransformers);
|
||||
@@ -161,7 +169,7 @@ public class ContentTransformerRegistry
|
||||
* @return Returns the most reliable transformers for the translation - empty list if there
|
||||
* are none.
|
||||
*/
|
||||
private List<ContentTransformer> findDirectTransformers(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
private List<ContentTransformer> findDirectTransformers(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
//double maxReliability = 0.0;
|
||||
|
||||
@@ -171,7 +179,7 @@ public class ContentTransformerRegistry
|
||||
// loop through transformers
|
||||
for (ContentTransformer transformer : this.transformers)
|
||||
{
|
||||
if (transformer.isTransformable(sourceMimetype, targetMimetype, options) == true)
|
||||
if (transformer.isTransformable(sourceMimetype, sourceSize, targetMimetype, options) == true)
|
||||
{
|
||||
if (transformer.isExplicitTransformation(sourceMimetype, targetMimetype, options) == true)
|
||||
{
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -72,17 +72,17 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
// create the dummyRegistry
|
||||
dummyRegistry = new ContentTransformerRegistry();
|
||||
// create some dummy transformers for reliability tests
|
||||
new DummyTransformer(mimetypeService, dummyRegistry, A, B, 10L);
|
||||
new DummyTransformer(mimetypeService, dummyRegistry, A, B, 10L);
|
||||
new DummyTransformer(mimetypeService, dummyRegistry, A, C, 10L);
|
||||
new DummyTransformer(mimetypeService, dummyRegistry, A, C, 10L);
|
||||
new DummyTransformer(mimetypeService, dummyRegistry, B, C, 10L);
|
||||
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);
|
||||
// create some dummy transformers for speed tests
|
||||
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 20L);
|
||||
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 30L);
|
||||
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 10L); // the fast one
|
||||
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 25L);
|
||||
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 25L);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,17 +99,17 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
*/
|
||||
protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
return registry.getTransformer(sourceMimetype, targetMimetype, options);
|
||||
return registry.getTransformer(sourceMimetype, -1, targetMimetype, options);
|
||||
}
|
||||
|
||||
public void testNullRetrieval() throws Exception
|
||||
{
|
||||
ContentTransformer transformer = null;
|
||||
transformer = dummyRegistry.getTransformer(C, B, OPTIONS);
|
||||
transformer = dummyRegistry.getTransformer(C, -1, B, OPTIONS);
|
||||
assertNull("No transformer expected", transformer);
|
||||
transformer = dummyRegistry.getTransformer(C, A, OPTIONS);
|
||||
transformer = dummyRegistry.getTransformer(C, -1, A, OPTIONS);
|
||||
assertNull("No transformer expected", transformer);
|
||||
transformer = dummyRegistry.getTransformer(B, A, OPTIONS);
|
||||
transformer = dummyRegistry.getTransformer(B, -1, A, OPTIONS);
|
||||
assertNull("No transformer expected", transformer);
|
||||
}
|
||||
|
||||
@@ -117,11 +117,11 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
{
|
||||
ContentTransformer transformer = null;
|
||||
// B -> C expect true
|
||||
transformer = dummyRegistry.getTransformer(B, C, OPTIONS);
|
||||
transformer = dummyRegistry.getTransformer(B, -1, C, OPTIONS);
|
||||
//transformer = dummyRegistry.getTransformer(B, C, OPTIONS);
|
||||
assertNotNull("No transformer found", transformer);
|
||||
assertTrue("Incorrect reliability", transformer.isTransformable(B, C, OPTIONS));
|
||||
assertFalse("Incorrect reliability", transformer.isTransformable(C, B, OPTIONS));
|
||||
assertTrue("Incorrect reliability", transformer.isTransformable(B, -1, C, OPTIONS));
|
||||
assertFalse("Incorrect reliability", transformer.isTransformable(C, -1, B, OPTIONS));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,13 +132,13 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
public void testPerformanceRetrieval() throws Exception
|
||||
{
|
||||
// A -> D expect 1.0, 10ms
|
||||
ContentTransformer transformer1 = dummyRegistry.getTransformer(A, D, OPTIONS);
|
||||
assertTrue("Incorrect reliability", transformer1.isTransformable(A, D, OPTIONS));
|
||||
assertFalse("Incorrect reliability", transformer1.isTransformable(D, A, OPTIONS));
|
||||
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());
|
||||
|
||||
// A -> D has 10, 20, 25, 25, 30
|
||||
List<ContentTransformer> activeTransformers = dummyRegistry.getActiveTransformers(A, D, OPTIONS);
|
||||
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());
|
||||
@@ -150,7 +150,7 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
((DummyTransformer)activeTransformers.get(2)).disable();
|
||||
((DummyTransformer)activeTransformers.get(4)).disable();
|
||||
|
||||
activeTransformers = dummyRegistry.getActiveTransformers(A, D, OPTIONS);
|
||||
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());
|
||||
@@ -161,15 +161,15 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
{
|
||||
ContentTransformer transformer = null;
|
||||
// A -> B expect 0.6
|
||||
transformer = dummyRegistry.getTransformer(A, B, OPTIONS);
|
||||
transformer = dummyRegistry.getTransformer(A, -1, B, OPTIONS);
|
||||
assertNotNull("No transformer found", transformer);
|
||||
assertTrue("Incorrect reliability", transformer.isTransformable(A, B, OPTIONS));
|
||||
assertFalse("Incorrect reliability", transformer.isTransformable(B, A, OPTIONS));
|
||||
assertTrue("Incorrect reliability", transformer.isTransformable(A, -1, B, OPTIONS));
|
||||
assertFalse("Incorrect reliability", transformer.isTransformable(B, -1, A, OPTIONS));
|
||||
// A -> C expect 1.0
|
||||
transformer = dummyRegistry.getTransformer(A, C, OPTIONS);
|
||||
transformer = dummyRegistry.getTransformer(A, -1, C, OPTIONS);
|
||||
assertNotNull("No transformer found", transformer);
|
||||
assertTrue("Incorrect reliability", transformer.isTransformable(A, C, OPTIONS));
|
||||
assertFalse("Incorrect reliability", transformer.isTransformable(C, A, OPTIONS));
|
||||
assertTrue("Incorrect reliability", transformer.isTransformable(A, -1, C, OPTIONS));
|
||||
assertFalse("Incorrect reliability", transformer.isTransformable(C, -1, A, OPTIONS));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -180,9 +180,9 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
{
|
||||
AbstractContentTransformer2 dummyTransformer = new DummyTransformer(
|
||||
mimetypeService,
|
||||
dummyRegistry,
|
||||
MimetypeMap.MIMETYPE_FLASH, MimetypeMap.MIMETYPE_EXCEL,
|
||||
12345);
|
||||
transformerDebug,
|
||||
dummyRegistry, MimetypeMap.MIMETYPE_FLASH,
|
||||
MimetypeMap.MIMETYPE_EXCEL, 12345);
|
||||
// set an explicit transformation
|
||||
ExplictTransformationDetails key =
|
||||
new ExplictTransformationDetails(
|
||||
@@ -193,7 +193,7 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
dummyTransformer.register();
|
||||
|
||||
// get the appropriate transformer for the bizarre mapping
|
||||
ContentTransformer checkTransformer = dummyRegistry.getTransformer(MimetypeMap.MIMETYPE_FLASH, MimetypeMap.MIMETYPE_EXCEL, OPTIONS);
|
||||
ContentTransformer checkTransformer = dummyRegistry.getTransformer(MimetypeMap.MIMETYPE_FLASH, -1, MimetypeMap.MIMETYPE_EXCEL, OPTIONS);
|
||||
|
||||
assertNotNull("No explicit transformer found", checkTransformer);
|
||||
assertTrue("Expected explicit transformer", dummyTransformer == checkTransformer);
|
||||
@@ -212,11 +212,12 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
|
||||
|
||||
public DummyTransformer(
|
||||
MimetypeService mimetypeService,
|
||||
ContentTransformerRegistry registry,
|
||||
String sourceMimetype, String targetMimetype,
|
||||
long transformationTime)
|
||||
TransformerDebug transformerDebug,
|
||||
ContentTransformerRegistry registry, String sourceMimetype,
|
||||
String targetMimetype, long transformationTime)
|
||||
{
|
||||
super.setMimetypeService(mimetypeService);
|
||||
super.setTransformerDebug(transformerDebug);
|
||||
super.setRegistry(registry);
|
||||
this.sourceMimetype = sourceMimetype;
|
||||
this.targetMimetype = targetMimetype;
|
||||
|
@@ -80,9 +80,9 @@ public class FailoverContentTransformer extends AbstractContentTransformer2 impl
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.alfresco.repo.content.transform.ContentTransformer#isTransformable(java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions)
|
||||
* @see org.alfresco.repo.content.transform.ContentTransformer#isTransformable(java.lang.String, long sourceSize, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions)
|
||||
*/
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
// For this transformer to be considered operational, there must be at least one transformer
|
||||
// in the chain that can perform for us.
|
||||
@@ -90,15 +90,27 @@ public class FailoverContentTransformer extends AbstractContentTransformer2 impl
|
||||
|
||||
for (ContentTransformer ct : this.transformers)
|
||||
{
|
||||
if (ct.isTransformable(sourceMimetype, targetMimetype, options))
|
||||
if (ct.isTransformable(sourceMimetype, sourceSize, targetMimetype, options))
|
||||
{
|
||||
result = true;
|
||||
// There may be size limits on this transformer as well as those it contains.
|
||||
result = isTransformableSize(sourceMimetype, sourceSize, targetMimetype, options);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method should no longer be called as the overloaded method
|
||||
* that calls it has the overridden.
|
||||
*/
|
||||
@Override
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype,
|
||||
TransformationOptions options)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isExplicitTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
@@ -130,7 +142,7 @@ public class FailoverContentTransformer extends AbstractContentTransformer2 impl
|
||||
// then move on to the next transformer. In the event that they all fail, we will throw
|
||||
// the final exception.
|
||||
Exception transformationException = null;
|
||||
|
||||
|
||||
for (int i = 0; i < transformers.size(); i++)
|
||||
{
|
||||
int oneBasedCount = i + 1;
|
||||
@@ -198,6 +210,7 @@ public class FailoverContentTransformer extends AbstractContentTransformer2 impl
|
||||
// At this point we have tried all transformers in the sequence without apparent success.
|
||||
if (transformationException != null)
|
||||
{
|
||||
transformerDebug.debug("No more transformations to failover to");
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("All transformations were unsuccessful. Throwing latest exception.", transformationException);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -56,6 +56,7 @@ public class FailoverContentTransformerTest extends AbstractContentTransformerTe
|
||||
|
||||
transformer = (FailoverContentTransformer) failoverAppContext.getBean("transformer.failover.Test-FailThenSucceed");
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,7 +71,7 @@ public class FailoverContentTransformerTest extends AbstractContentTransformerTe
|
||||
{
|
||||
// The MIME types here are rather arbitrary
|
||||
|
||||
boolean reliability = transformer.isTransformable(sourceMimeType, targetMimeType, new TransformationOptions());
|
||||
boolean reliability = transformer.isTransformable(sourceMimeType, -1, targetMimeType, new TransformationOptions());
|
||||
assertEquals("Mimetype should be supported", true, reliability);
|
||||
}
|
||||
}
|
||||
|
@@ -28,13 +28,15 @@ import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
*/
|
||||
public class HtmlParserContentTransformerTest extends AbstractContentTransformerTest
|
||||
{
|
||||
private ContentTransformer transformer;
|
||||
private HtmlParserContentTransformer transformer;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
transformer = new HtmlParserContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
|
||||
protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype)
|
||||
@@ -50,11 +52,11 @@ public class HtmlParserContentTransformerTest extends AbstractContentTransformer
|
||||
public void checkIsTransformable() throws Exception
|
||||
{
|
||||
// check reliability
|
||||
boolean reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_HTML, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
|
||||
boolean reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_HTML, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
|
||||
assertTrue(reliability); // plain text to plain text is supported
|
||||
|
||||
// check other way around
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_HTML, new TransformationOptions());
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions());
|
||||
assertFalse(reliability); // plain text to plain text is not supported
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -35,7 +35,7 @@ import org.alfresco.util.TempFileProvider;
|
||||
*/
|
||||
public class MailContentTransformerTest extends AbstractContentTransformerTest
|
||||
{
|
||||
private ContentTransformer transformer;
|
||||
private MailContentTransformer transformer;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
@@ -43,6 +43,8 @@ public class MailContentTransformerTest extends AbstractContentTransformerTest
|
||||
super.setUp();
|
||||
|
||||
transformer = new MailContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,8 +57,8 @@ public class MailContentTransformerTest extends AbstractContentTransformerTest
|
||||
|
||||
public void testIsTransformable() throws Exception
|
||||
{
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_OUTLOOK_MSG, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OUTLOOK_MSG, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_OUTLOOK_MSG, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OUTLOOK_MSG, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -39,7 +39,7 @@ import de.schlichtherle.io.FileOutputStream;
|
||||
*/
|
||||
public class MediaWikiContentTransformerTest extends AbstractContentTransformerTest
|
||||
{
|
||||
private ContentTransformer transformer;
|
||||
private MediaWikiContentTransformer transformer;
|
||||
|
||||
private static final String WIKI_TEXT =
|
||||
"== This is a title ==\n" +
|
||||
@@ -69,6 +69,8 @@ public class MediaWikiContentTransformerTest extends AbstractContentTransformerT
|
||||
{
|
||||
super.setUp();
|
||||
transformer = new MediaWikiContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
|
||||
protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype)
|
||||
@@ -84,8 +86,8 @@ public class MediaWikiContentTransformerTest extends AbstractContentTransformerT
|
||||
public void testIsTransformable() throws Exception
|
||||
{
|
||||
// check reliability
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_MEDIAWIKI, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_HTML, MimetypeMap.MIMETYPE_TEXT_MEDIAWIKI, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_MEDIAWIKI, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_HTML, -1, MimetypeMap.MIMETYPE_TEXT_MEDIAWIKI, new TransformationOptions()));
|
||||
}
|
||||
|
||||
public void testMediaWikiToHTML() throws Exception
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -39,7 +39,7 @@ public class OpenOfficeContentTransformerTest extends AbstractContentTransformer
|
||||
private static String MIMETYPE_RUBBISH = "text/rubbish";
|
||||
|
||||
private ContentTransformerWorker worker;
|
||||
private ContentTransformer transformer;
|
||||
private ProxyContentTransformer transformer;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
@@ -47,10 +47,10 @@ public class OpenOfficeContentTransformerTest extends AbstractContentTransformer
|
||||
super.setUp();
|
||||
|
||||
this.worker = (ContentTransformerWorker) ctx.getBean("transformer.worker.OpenOffice");
|
||||
ProxyContentTransformer transformer = new ProxyContentTransformer();
|
||||
transformer = new ProxyContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setWorker(this.worker);
|
||||
this.transformer = transformer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,15 +74,15 @@ public class OpenOfficeContentTransformerTest extends AbstractContentTransformer
|
||||
// no connection
|
||||
return;
|
||||
}
|
||||
boolean reliability = transformer.isTransformable(MIMETYPE_RUBBISH, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
|
||||
boolean reliability = transformer.isTransformable(MIMETYPE_RUBBISH, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
|
||||
assertEquals("Mimetype should not be supported", false, reliability);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MIMETYPE_RUBBISH, new TransformationOptions());
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MIMETYPE_RUBBISH, new TransformationOptions());
|
||||
assertEquals("Mimetype should not be supported", false, reliability);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_XHTML, new TransformationOptions());
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_XHTML, new TransformationOptions());
|
||||
assertEquals("Mimetype should not be supported", false, reliability);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_WORD, new TransformationOptions());
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_WORD, new TransformationOptions());
|
||||
assertEquals("Mimetype should be supported", true, reliability);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
|
||||
assertEquals("Mimetype should be supported", true, reliability);
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -28,7 +28,7 @@ import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
*/
|
||||
public class PdfBoxContentTransformerTest extends AbstractContentTransformerTest
|
||||
{
|
||||
private ContentTransformer transformer;
|
||||
private PdfBoxContentTransformer transformer;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
@@ -36,6 +36,8 @@ public class PdfBoxContentTransformerTest extends AbstractContentTransformerTest
|
||||
super.setUp();
|
||||
|
||||
transformer = new PdfBoxContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,9 +50,9 @@ public class PdfBoxContentTransformerTest extends AbstractContentTransformerTest
|
||||
|
||||
public void testIsTransformable() throws Exception
|
||||
{
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_PDF, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_PDF, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
}
|
||||
}
|
||||
|
@@ -36,7 +36,7 @@ import org.alfresco.util.TempFileProvider;
|
||||
*/
|
||||
public class PdfBoxPdfToImageContentTransformerTest extends AbstractContentTransformerTest
|
||||
{
|
||||
private ContentTransformer transformer;
|
||||
private PdfBoxPdfToImageContentTransformer transformer;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
@@ -44,7 +44,8 @@ public class PdfBoxPdfToImageContentTransformerTest extends AbstractContentTrans
|
||||
super.setUp();
|
||||
|
||||
transformer = new PdfBoxPdfToImageContentTransformer();
|
||||
((ContentTransformerHelper)transformer).setMimetypeService(mimetypeService);
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +58,7 @@ public class PdfBoxPdfToImageContentTransformerTest extends AbstractContentTrans
|
||||
|
||||
public void testIsTransformable() throws Exception
|
||||
{
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_IMAGE_PNG, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, -1, MimetypeMap.MIMETYPE_IMAGE_PNG, new TransformationOptions()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -28,7 +28,7 @@ import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
*/
|
||||
public class PoiContentTransformerTest extends AbstractContentTransformerTest
|
||||
{
|
||||
private ContentTransformer transformer;
|
||||
private PoiContentTransformer transformer;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
@@ -36,6 +36,8 @@ public class PoiContentTransformerTest extends AbstractContentTransformerTest
|
||||
super.setUp();
|
||||
|
||||
transformer = new PoiContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,22 +50,22 @@ public class PoiContentTransformerTest extends AbstractContentTransformerTest
|
||||
|
||||
public void testIsTransformable() throws Exception
|
||||
{
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_WORD, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_WORD, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_PPT, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PPT, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PPT, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PPT, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_PPT, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PPT, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PPT, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PPT, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_OUTLOOK_MSG, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OUTLOOK_MSG, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OUTLOOK_MSG, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OUTLOOK_MSG, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_OUTLOOK_MSG, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OUTLOOK_MSG, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OUTLOOK_MSG, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OUTLOOK_MSG, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
|
||||
// Doesn't claim excel
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
}
|
||||
}
|
||||
|
@@ -72,19 +72,30 @@ public class PoiHssfContentTransformer extends TikaPoweredContentTransformer
|
||||
* We support transforming to HTML, XML, Text or CSV
|
||||
*/
|
||||
@Override
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
if(sourceMimeTypes.contains(sourceMimetype) &&
|
||||
MimetypeMap.MIMETYPE_TEXT_CSV.equals(targetMimetype))
|
||||
{
|
||||
// Special case for CSV
|
||||
return true;
|
||||
// Special case for CSV
|
||||
return isTransformableSize(sourceMimetype, sourceSize, targetMimetype, options);
|
||||
}
|
||||
|
||||
// Otherwise fall back on the default Tika rules
|
||||
return super.isTransformable(sourceMimetype, targetMimetype, options);
|
||||
return super.isTransformable(sourceMimetype, sourceSize, targetMimetype, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method should no longer be called as the overloaded method
|
||||
* that calls it has been overridden.
|
||||
*/
|
||||
@Override
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype,
|
||||
TransformationOptions options)
|
||||
{
|
||||
return isTransformable(sourceMimetype, -1, targetMimetype, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we win over openoffice when it comes to producing
|
||||
* HTML
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -36,7 +36,7 @@ import org.alfresco.util.TempFileProvider;
|
||||
*/
|
||||
public class PoiHssfContentTransformerTest extends TikaPoweredContentTransformerTest
|
||||
{
|
||||
private ContentTransformer transformer;
|
||||
private PoiHssfContentTransformer transformer;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
@@ -44,6 +44,8 @@ public class PoiHssfContentTransformerTest extends TikaPoweredContentTransformer
|
||||
super.setUp();
|
||||
|
||||
transformer = new PoiHssfContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,11 +65,11 @@ public class PoiHssfContentTransformerTest extends TikaPoweredContentTransformer
|
||||
|
||||
public void testIsTransformable() throws Exception
|
||||
{
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_EXCEL, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_TEXT_CSV, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_EXCEL, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, -1, MimetypeMap.MIMETYPE_TEXT_CSV, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
}
|
||||
|
||||
public void testCsvOutput() throws Exception
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -28,7 +28,7 @@ import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
*/
|
||||
public class PoiOOXMLContentTransformerTest extends AbstractContentTransformerTest
|
||||
{
|
||||
private ContentTransformer transformer;
|
||||
private PoiOOXMLContentTransformer transformer;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
@@ -36,6 +36,8 @@ public class PoiOOXMLContentTransformerTest extends AbstractContentTransformerTe
|
||||
super.setUp();
|
||||
|
||||
transformer = new PoiOOXMLContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,19 +50,19 @@ public class PoiOOXMLContentTransformerTest extends AbstractContentTransformerTe
|
||||
|
||||
public void testIsTransformable() throws Exception
|
||||
{
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_OPENXML_PRESENTATION, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_PRESENTATION, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_PRESENTATION, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_PRESENTATION, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_OPENXML_PRESENTATION, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_PRESENTATION, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_PRESENTATION, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_PRESENTATION, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
}
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ import net.sf.jooreports.converter.DocumentFormatRegistry;
|
||||
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptionLimits;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
|
||||
/**
|
||||
@@ -65,6 +66,18 @@ public class ProxyContentTransformer extends AbstractContentTransformer2
|
||||
protected void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options)
|
||||
throws Exception
|
||||
{
|
||||
this.worker.transform(reader, writer, options);
|
||||
}
|
||||
TransformationOptionLimits original = options.getLimits();
|
||||
try
|
||||
{
|
||||
// Combine the transformer's limit values into the options so they are available to the worker
|
||||
options.setLimits(getLimits(reader, writer, options));
|
||||
|
||||
// Perform the transformation
|
||||
this.worker.transform(reader, writer, options);
|
||||
}
|
||||
finally
|
||||
{
|
||||
options.setLimits(original);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -73,8 +73,11 @@ public class RuntimeExecutableContentTransformerTest extends BaseAlfrescoTestCas
|
||||
// initialise so that it doesn't score 0
|
||||
worker.afterPropertiesSet();
|
||||
|
||||
TransformerDebug transformerDebug = (TransformerDebug) ctx.getBean("transformerDebug");
|
||||
|
||||
ProxyContentTransformer transformer = new ProxyContentTransformer();
|
||||
transformer.setMimetypeService(serviceRegistry.getMimetypeService());
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setWorker(worker);
|
||||
this.transformer = transformer;
|
||||
}
|
||||
|
@@ -256,10 +256,11 @@ public class RuntimeExecutableContentTransformerWorker extends ContentTransforme
|
||||
reader.getContent(sourceFile);
|
||||
|
||||
// execute the transformation command
|
||||
long timeoutMs = options.getTimeoutMs();
|
||||
ExecutionResult result = null;
|
||||
try
|
||||
{
|
||||
result = transformCommand.execute(properties);
|
||||
result = transformCommand.execute(properties, timeoutMs);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
|
@@ -118,7 +118,7 @@ public class StringExtractingContentTransformer extends AbstractContentTransform
|
||||
charWriter = new OutputStreamWriter(writer.getContentOutputStream(), writer.getEncoding());
|
||||
}
|
||||
// copy from the one to the other
|
||||
char[] buffer = new char[1024];
|
||||
char[] buffer = new char[8192];
|
||||
int readCount = 0;
|
||||
while (readCount > -1)
|
||||
{
|
||||
|
@@ -56,7 +56,7 @@ public class StringExtractingContentTransformerTest extends AbstractContentTrans
|
||||
}
|
||||
}
|
||||
|
||||
private ContentTransformer transformer;
|
||||
private StringExtractingContentTransformer transformer;
|
||||
/** the final destination of transformations */
|
||||
private ContentWriter targetWriter;
|
||||
|
||||
@@ -66,6 +66,8 @@ public class StringExtractingContentTransformerTest extends AbstractContentTrans
|
||||
super.setUp();
|
||||
|
||||
transformer = new StringExtractingContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
targetWriter = new FileContentWriter(getTempFile());
|
||||
targetWriter.setMimetype("text/plain");
|
||||
targetWriter.setEncoding("UTF-8");
|
||||
@@ -112,7 +114,7 @@ public class StringExtractingContentTransformerTest extends AbstractContentTrans
|
||||
ContentReader reader = writeContent("text/plain", "MacDingbat");
|
||||
|
||||
// check transformability
|
||||
assertTrue(transformer.isTransformable(reader.getMimetype(), targetWriter.getMimetype(), new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(reader.getMimetype(), -1, targetWriter.getMimetype(), new TransformationOptions()));
|
||||
|
||||
// transform
|
||||
transformer.transform(reader, targetWriter);
|
||||
@@ -128,7 +130,7 @@ public class StringExtractingContentTransformerTest extends AbstractContentTrans
|
||||
ContentReader reader = writeContent("text/xml", "MacDingbat");
|
||||
|
||||
// check transformability
|
||||
assertTrue(transformer.isTransformable(reader.getMimetype(), targetWriter.getMimetype(), new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(reader.getMimetype(), -1, targetWriter.getMimetype(), new TransformationOptions()));
|
||||
|
||||
// transform
|
||||
transformer.transform(reader, targetWriter);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -36,7 +36,7 @@ import org.alfresco.util.TempFileProvider;
|
||||
*/
|
||||
public class TextMiningContentTransformerTest extends AbstractContentTransformerTest
|
||||
{
|
||||
private ContentTransformer transformer;
|
||||
private TextMiningContentTransformer transformer;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
@@ -44,6 +44,8 @@ public class TextMiningContentTransformerTest extends AbstractContentTransformer
|
||||
super.setUp();
|
||||
|
||||
transformer = new TextMiningContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,8 +65,8 @@ public class TextMiningContentTransformerTest extends AbstractContentTransformer
|
||||
|
||||
public void testIsTransformable() throws Exception
|
||||
{
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_WORD, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_WORD, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -18,24 +18,31 @@
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptionLimits;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptionPair;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptionPair.Action;
|
||||
import org.alfresco.service.cmr.repository.TransformationOptions;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.pdfbox.TextToPDF;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
||||
import org.apache.tika.io.IOUtils;
|
||||
|
||||
/**
|
||||
* Makes use of the {@link http://www.pdfbox.org/ PDFBox} library's <code>TextToPDF</code> utility.
|
||||
*
|
||||
@@ -46,11 +53,12 @@ public class TextToPdfContentTransformer extends AbstractContentTransformer2
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(TextToPdfContentTransformer.class);
|
||||
|
||||
private TextToPDF transformer;
|
||||
private PagedTextToPDF transformer;
|
||||
|
||||
public TextToPdfContentTransformer()
|
||||
{
|
||||
transformer = new TextToPDF();
|
||||
setPageLimitsSuported(true);
|
||||
transformer = new PagedTextToPDF();
|
||||
}
|
||||
|
||||
public void setStandardFont(String fontName)
|
||||
@@ -92,7 +100,7 @@ public class TextToPdfContentTransformer extends AbstractContentTransformer2
|
||||
/**
|
||||
* Only supports Text to PDF
|
||||
*/
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
if ( (!MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(sourceMimetype) &&
|
||||
!MimetypeMap.MIMETYPE_TEXT_CSV.equals(sourceMimetype) &&
|
||||
@@ -104,10 +112,21 @@ public class TextToPdfContentTransformer extends AbstractContentTransformer2
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
return isTransformableSize(sourceMimetype, sourceSize, targetMimetype, options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method should no longer be called as the overloaded method
|
||||
* that calls it has the overridden.
|
||||
*/
|
||||
@Override
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype,
|
||||
TransformationOptions options)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void transformInternal(
|
||||
ContentReader reader,
|
||||
@@ -122,8 +141,11 @@ public class TextToPdfContentTransformer extends AbstractContentTransformer2
|
||||
{
|
||||
is = reader.getContentInputStream();
|
||||
ir = buildReader(is, reader.getEncoding(), reader.getContentUrl());
|
||||
|
||||
pdf = transformer.createPDFFromText(ir);
|
||||
|
||||
TransformationOptionLimits limits = getLimits(reader, writer, options);
|
||||
TransformationOptionPair pageLimits = limits.getPagesPair();
|
||||
pdf = transformer.createPDFFromText(ir, pageLimits, reader.getContentUrl());
|
||||
|
||||
// dump it all to the writer
|
||||
os = writer.getContentOutputStream();
|
||||
pdf.save(os);
|
||||
@@ -174,4 +196,124 @@ public class TextToPdfContentTransformer extends AbstractContentTransformer2
|
||||
logger.debug("Processing plain text using system default encoding");
|
||||
return new InputStreamReader(is);
|
||||
}
|
||||
|
||||
private class PagedTextToPDF extends TextToPDF
|
||||
{
|
||||
// The following code is based on the code in TextToPDF with the addition of
|
||||
// checks for page limits
|
||||
public PDDocument createPDFFromText(Reader text, TransformationOptionPair pageLimits,
|
||||
String contentUrl) throws IOException
|
||||
{
|
||||
int pageLimit = (int)pageLimits.getValue();
|
||||
PDDocument doc = null;
|
||||
int pageCount = 0;
|
||||
try
|
||||
{
|
||||
final int margin = 40;
|
||||
float height = getFont().getFontDescriptor().getFontBoundingBox().getHeight()/1000;
|
||||
|
||||
//calculate font height and increase by 5 percent.
|
||||
height = height*getFontSize()*1.05f;
|
||||
doc = new PDDocument();
|
||||
BufferedReader data = new BufferedReader( text );
|
||||
String nextLine = null;
|
||||
PDPage page = new PDPage();
|
||||
PDPageContentStream contentStream = null;
|
||||
float y = -1;
|
||||
float maxStringLength = page.getMediaBox().getWidth() - 2*margin;
|
||||
|
||||
// There is a special case of creating a PDF document from an empty string.
|
||||
boolean textIsEmpty = true;
|
||||
|
||||
outer:
|
||||
while( (nextLine = data.readLine()) != null )
|
||||
{
|
||||
|
||||
// The input text is nonEmpty. New pages will be created and added
|
||||
// to the PDF document as they are needed, depending on the length of
|
||||
// the text.
|
||||
textIsEmpty = false;
|
||||
|
||||
String[] lineWords = nextLine.trim().split( " " );
|
||||
int lineIndex = 0;
|
||||
while( lineIndex < lineWords.length )
|
||||
{
|
||||
StringBuffer nextLineToDraw = new StringBuffer();
|
||||
float lengthIfUsingNextWord = 0;
|
||||
do
|
||||
{
|
||||
nextLineToDraw.append( lineWords[lineIndex] );
|
||||
nextLineToDraw.append( " " );
|
||||
lineIndex++;
|
||||
if( lineIndex < lineWords.length )
|
||||
{
|
||||
String lineWithNextWord = nextLineToDraw.toString() + lineWords[lineIndex];
|
||||
lengthIfUsingNextWord =
|
||||
(getFont().getStringWidth( lineWithNextWord )/1000) * getFontSize();
|
||||
}
|
||||
}
|
||||
while( lineIndex < lineWords.length &&
|
||||
lengthIfUsingNextWord < maxStringLength );
|
||||
if( y < margin )
|
||||
{
|
||||
if (pageLimit > 0 && pageCount++ >= pageLimit)
|
||||
{
|
||||
pageLimits.getAction().throwIOExceptionIfRequired("Page limit ("+pageLimit+
|
||||
") reached.", transformerDebug);
|
||||
break outer;
|
||||
}
|
||||
|
||||
// We have crossed the end-of-page boundary and need to extend the
|
||||
// document by another page.
|
||||
page = new PDPage();
|
||||
doc.addPage( page );
|
||||
if( contentStream != null )
|
||||
{
|
||||
contentStream.endText();
|
||||
contentStream.close();
|
||||
}
|
||||
contentStream = new PDPageContentStream(doc, page);
|
||||
contentStream.setFont(getFont(), getFontSize());
|
||||
contentStream.beginText();
|
||||
y = page.getMediaBox().getHeight() - margin + height;
|
||||
contentStream.moveTextPositionByAmount(
|
||||
margin, y );
|
||||
}
|
||||
//System.out.println( "Drawing string at " + x + "," + y );
|
||||
|
||||
if( contentStream == null )
|
||||
{
|
||||
throw new IOException( "Error:Expected non-null content stream." );
|
||||
}
|
||||
contentStream.moveTextPositionByAmount( 0, -height);
|
||||
y -= height;
|
||||
contentStream.drawString( nextLineToDraw.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
// If the input text was the empty string, then the above while loop will have short-circuited
|
||||
// and we will not have added any PDPages to the document.
|
||||
// So in order to make the resultant PDF document readable by Adobe Reader etc, we'll add an empty page.
|
||||
if (textIsEmpty)
|
||||
{
|
||||
doc.addPage(page);
|
||||
}
|
||||
|
||||
if( contentStream != null )
|
||||
{
|
||||
contentStream.endText();
|
||||
contentStream.close();
|
||||
}
|
||||
}
|
||||
catch( IOException io )
|
||||
{
|
||||
if( doc != null )
|
||||
{
|
||||
doc.close();
|
||||
}
|
||||
throw io;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -19,6 +19,7 @@
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
@@ -47,8 +48,11 @@ public class TextToPdfContentTransformerTest extends AbstractContentTransformerT
|
||||
super.setUp();
|
||||
|
||||
transformer = new TextToPdfContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setStandardFont("Times-Roman");
|
||||
transformer.setFontSize(20);
|
||||
transformer.setPageLimit(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,11 +66,11 @@ public class TextToPdfContentTransformerTest extends AbstractContentTransformerT
|
||||
|
||||
public void testReliability() throws Exception
|
||||
{
|
||||
boolean reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
|
||||
boolean reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
|
||||
assertEquals("Mimetype should not be supported", false, reliability);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_PDF, new TransformationOptions());
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_PDF, new TransformationOptions());
|
||||
assertEquals("Mimetype should be supported", true, reliability);
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_XML, MimetypeMap.MIMETYPE_PDF, new TransformationOptions());
|
||||
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_XML, -1, MimetypeMap.MIMETYPE_PDF, new TransformationOptions());
|
||||
assertEquals("Mimetype should be supported", true, reliability);
|
||||
}
|
||||
|
||||
@@ -82,44 +86,90 @@ public class TextToPdfContentTransformerTest extends AbstractContentTransformerT
|
||||
String european = "En français où les choses sont accentués\n" +
|
||||
"En español, así";
|
||||
|
||||
ContentReader reader;
|
||||
for(String text : new String[] {allAscii, european})
|
||||
{
|
||||
for(String encoding : new String[] {"ISO-8859-1", "UTF-8", "UTF-16"})
|
||||
{
|
||||
// Get a reader for the text
|
||||
reader = buildContentReader(text, Charset.forName(encoding));
|
||||
|
||||
// And a temp writer
|
||||
File out = TempFileProvider.createTempFile("AlfrescoTest_", ".pdf");
|
||||
ContentWriter writer = new FileContentWriter(out);
|
||||
writer.setMimetype("application/pdf");
|
||||
|
||||
// Transform to PDF
|
||||
transformer.transform(reader, writer);
|
||||
|
||||
// Read back in the PDF and check it
|
||||
PDDocument doc = PDDocument.load(out);
|
||||
PDFTextStripper textStripper = new PDFTextStripper();
|
||||
StringWriter textWriter = new StringWriter();
|
||||
textStripper.writeText(doc, textWriter);
|
||||
doc.close();
|
||||
|
||||
// Newlines etc may be different, so zap them
|
||||
String checkText = clean(text);
|
||||
String roundTrip = clean(textWriter.toString());
|
||||
|
||||
// Now check it
|
||||
// System.err.println("== " + encoding + " ==");
|
||||
// System.err.println(roundTrip);
|
||||
// System.err.println("====");
|
||||
assertEquals(
|
||||
"Incorrect text in PDF when starting from text in " + encoding,
|
||||
checkText, roundTrip
|
||||
);
|
||||
|
||||
transformTextAndCheck(text, encoding, checkText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnlimitedPages() throws Exception
|
||||
{
|
||||
transformTextAndCheckPageLength(-1);
|
||||
}
|
||||
|
||||
public void testLimitedTo1Page() throws Exception
|
||||
{
|
||||
transformTextAndCheckPageLength(1);
|
||||
}
|
||||
|
||||
public void testLimitedTo2Pages() throws Exception
|
||||
{
|
||||
transformTextAndCheckPageLength(2);
|
||||
}
|
||||
|
||||
public void testLimitedTo50Pages() throws Exception
|
||||
{
|
||||
transformTextAndCheckPageLength(50);
|
||||
}
|
||||
|
||||
private void transformTextAndCheckPageLength(int pageLimit) throws IOException
|
||||
{
|
||||
transformer.setPageLimit(pageLimit);
|
||||
|
||||
int pageLength = 32;
|
||||
int lines = (pageLength+10) * ((pageLimit > 0) ? pageLimit : 1);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String checkText = null;
|
||||
int cutoff = pageLimit * pageLength;
|
||||
for (int i=1; i<=lines; i++)
|
||||
{
|
||||
sb.append(i);
|
||||
sb.append(" I must not talk in class or feed my homework to my cat.\n");
|
||||
if (i == cutoff)
|
||||
checkText = sb.toString();
|
||||
}
|
||||
sb.append("\nBart\n");
|
||||
String text = sb.toString();
|
||||
checkText = (checkText == null) ? clean(text) : clean(checkText);
|
||||
|
||||
transformTextAndCheck(text, "UTF-8", checkText);
|
||||
}
|
||||
|
||||
private void transformTextAndCheck(String text, String encoding, String checkText)
|
||||
throws IOException
|
||||
{
|
||||
// Get a reader for the text
|
||||
ContentReader reader = buildContentReader(text, Charset.forName(encoding));
|
||||
|
||||
// And a temp writer
|
||||
File out = TempFileProvider.createTempFile("AlfrescoTest_", ".pdf");
|
||||
ContentWriter writer = new FileContentWriter(out);
|
||||
writer.setMimetype("application/pdf");
|
||||
|
||||
// Transform to PDF
|
||||
transformer.transform(reader, writer);
|
||||
|
||||
// Read back in the PDF and check it
|
||||
PDDocument doc = PDDocument.load(out);
|
||||
PDFTextStripper textStripper = new PDFTextStripper();
|
||||
StringWriter textWriter = new StringWriter();
|
||||
textStripper.writeText(doc, textWriter);
|
||||
doc.close();
|
||||
|
||||
String roundTrip = clean(textWriter.toString());
|
||||
|
||||
assertEquals(
|
||||
"Incorrect text in PDF when starting from text in " + encoding,
|
||||
checkText, roundTrip
|
||||
);
|
||||
}
|
||||
|
||||
private String clean(String text)
|
||||
{
|
||||
text = text.replaceAll("\\s+\\r", "");
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -32,7 +32,7 @@ import org.apache.tika.config.TikaConfig;
|
||||
*/
|
||||
public class TikaAutoContentTransformerTest extends TikaPoweredContentTransformerTest
|
||||
{
|
||||
private ContentTransformer transformer;
|
||||
private TikaAutoContentTransformer transformer;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
@@ -41,6 +41,8 @@ public class TikaAutoContentTransformerTest extends TikaPoweredContentTransforme
|
||||
|
||||
TikaConfig config = (TikaConfig)ctx.getBean("tikaConfig");
|
||||
transformer = new TikaAutoContentTransformer( config );
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,36 +60,36 @@ public class TikaAutoContentTransformerTest extends TikaPoweredContentTransforme
|
||||
public void testIsTransformable() throws Exception
|
||||
{
|
||||
// Excel (but this isn't normally used)
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_EXCEL, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_EXCEL, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
|
||||
// Word
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_WORD, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_WORD, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
|
||||
// PDF
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_PDF, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_PDF, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
|
||||
// Open Office
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, -1, MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
|
||||
// We don't do images
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_IMAGE_JPEG, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_IMAGE_JPEG, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_IMAGE_JPEG, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_IMAGE_JPEG, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_IMAGE_JPEG, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_IMAGE_JPEG, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
// Ditto music
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_MP3, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_MP3, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_MP3, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_MP3, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_MP3, -1, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
|
||||
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_MP3, -1, MimetypeMap.MIMETYPE_XML, new TransformationOptions()));
|
||||
}
|
||||
}
|
||||
|
@@ -87,7 +87,7 @@ public abstract class TikaPoweredContentTransformer extends AbstractContentTrans
|
||||
* Can we do the requested transformation via Tika?
|
||||
* We support transforming to HTML, XML or Text
|
||||
*/
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
|
||||
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
|
||||
{
|
||||
if(! sourceMimeTypes.contains(sourceMimetype))
|
||||
{
|
||||
@@ -101,7 +101,8 @@ public abstract class TikaPoweredContentTransformer extends AbstractContentTrans
|
||||
MimetypeMap.MIMETYPE_XML.equals(targetMimetype))
|
||||
{
|
||||
// We can output to this
|
||||
return true;
|
||||
// But there may be size limits on this transformer.
|
||||
return isTransformableSize(sourceMimetype, sourceSize, targetMimetype, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -109,6 +110,17 @@ public abstract class TikaPoweredContentTransformer extends AbstractContentTrans
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method should no longer be called as the overloaded method
|
||||
* that calls it has been overridden.
|
||||
*/
|
||||
@Override
|
||||
public boolean isTransformable(String sourceMimetype, String targetMimetype,
|
||||
TransformationOptions options)
|
||||
{
|
||||
return isTransformable(sourceMimetype, -1, targetMimetype, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an appropriate Tika ContentHandler for the
|
||||
|
@@ -0,0 +1,570 @@
|
||||
/*
|
||||
* 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.text.DecimalFormat;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.Formatter;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Debugs transformers selection and activity.<p>
|
||||
*
|
||||
* As transformations are frequently composed of lower level transformations, log
|
||||
* messages include a prefix to identify the transformation. A numeric dot notation
|
||||
* is used (such as {@code 123.1.2} indicating the second third level transformation
|
||||
* of the 123rd top level transformation).<p>
|
||||
*
|
||||
* In order to track of the nesting of transforms, this class has a stack to represent
|
||||
* the Transformers. Each Transformer calls {@link #pushTransform} at the start of a
|
||||
* transform and {@link #popTransform} at the end. However the top level transform may
|
||||
* be selected from a list of available transformers. To record this activity,
|
||||
* {@link #pushAvailable}, {@link #unavailableTransformer} (to record the reason a
|
||||
* transformer is rejected), {@link #availableTransformers} (to record the available
|
||||
* transformers) and {@link #popAvailable} are called.<p>
|
||||
*
|
||||
* @author Alan Davis
|
||||
*/
|
||||
public class TransformerDebug
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(TransformerDebug.class);
|
||||
|
||||
private enum Call
|
||||
{
|
||||
AVAILABLE,
|
||||
TRANSFORM,
|
||||
AVAILABLE_AND_TRANSFORM
|
||||
};
|
||||
|
||||
private static class ThreadInfo
|
||||
{
|
||||
private static final ThreadLocal<ThreadInfo> threadInfo = new ThreadLocal<ThreadInfo>()
|
||||
{
|
||||
@Override
|
||||
protected ThreadInfo initialValue()
|
||||
{
|
||||
return new ThreadInfo();
|
||||
}
|
||||
};
|
||||
|
||||
private final Deque<Frame> stack = new ArrayDeque<Frame>();
|
||||
private boolean debugOutput = true;
|
||||
|
||||
public static Deque<Frame> getStack()
|
||||
{
|
||||
return threadInfo.get().stack;
|
||||
}
|
||||
|
||||
public static boolean getDebug()
|
||||
{
|
||||
return threadInfo.get().debugOutput;
|
||||
}
|
||||
|
||||
public static boolean setDebugOutput(boolean debugOutput)
|
||||
{
|
||||
ThreadInfo thisThreadInfo = threadInfo.get();
|
||||
boolean orig = thisThreadInfo.debugOutput;
|
||||
thisThreadInfo.debugOutput = debugOutput;
|
||||
return orig;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Frame
|
||||
{
|
||||
private static final AtomicInteger uniqueId = new AtomicInteger(0);
|
||||
|
||||
private final int id;
|
||||
private final String fromUrl;
|
||||
private final String sourceMimetype;
|
||||
private final String targetMimetype;
|
||||
private final long start;
|
||||
|
||||
private Call callType;
|
||||
private int childId;
|
||||
private Set<UnavailableTransformer> unavailableTransformers;
|
||||
// See debug(String, Throwable) as to why this is commented out
|
||||
// private Throwable lastThrowable;
|
||||
|
||||
private Frame(Frame parent, String fromUrl, String sourceMimetype, String targetMimetype, Call pushCall)
|
||||
{
|
||||
this.id = parent == null ? uniqueId.getAndIncrement() : ++parent.childId;
|
||||
this.fromUrl = fromUrl;
|
||||
this.sourceMimetype = sourceMimetype;
|
||||
this.targetMimetype = targetMimetype;
|
||||
this.callType = pushCall;
|
||||
start = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
private class UnavailableTransformer
|
||||
{
|
||||
private final String name;
|
||||
private final String reason;
|
||||
private final transient boolean debug;
|
||||
|
||||
UnavailableTransformer(String name, String reason, boolean debug)
|
||||
{
|
||||
this.name = name;
|
||||
this.reason = reason;
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hashCode = 37 * name.hashCode();
|
||||
hashCode += 37 * reason.hashCode();
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (obj instanceof UnavailableTransformer)
|
||||
{
|
||||
UnavailableTransformer that = (UnavailableTransformer) obj;
|
||||
return
|
||||
EqualsHelper.nullSafeEquals(name, that.name) &&
|
||||
EqualsHelper.nullSafeEquals(reason, that.reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final MimetypeService mimetypeService;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TransformerDebug(MimetypeService mimetypeService)
|
||||
{
|
||||
this.mimetypeService = mimetypeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called prior to working out what transformers are available.
|
||||
*/
|
||||
public void pushAvailable(String fromUrl, String sourceMimetype, String targetMimetype)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
push(null, fromUrl, sourceMimetype, targetMimetype, -1, Call.AVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called prior to performing a transform.
|
||||
*/
|
||||
public void pushTransform(ContentTransformer transformer, String fromUrl, String sourceMimetype, String targetMimetype, long sourceSize)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
push(getName(transformer), fromUrl, sourceMimetype, targetMimetype, sourceSize, Call.TRANSFORM);
|
||||
}
|
||||
}
|
||||
|
||||
private void push(String name, String fromUrl, String sourceMimetype, String targetMimetype, long sourceSize, Call callType)
|
||||
{
|
||||
Deque<Frame> ourStack = ThreadInfo.getStack();
|
||||
Frame frame = ourStack.peek();
|
||||
|
||||
if (callType == Call.TRANSFORM && frame != null && frame.callType == Call.AVAILABLE)
|
||||
{
|
||||
frame.callType = Call.AVAILABLE_AND_TRANSFORM;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame = new Frame(frame, fromUrl, sourceMimetype, targetMimetype, callType);
|
||||
ourStack.push(frame);
|
||||
|
||||
if (callType == Call.TRANSFORM)
|
||||
{
|
||||
// Log the basic info about this transformation
|
||||
logBasicDetails(frame, sourceSize, name, (ourStack.size() == 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to identify a transformer that cannot be used during working out
|
||||
* available transformers.
|
||||
*/
|
||||
public void unavailableTransformer(ContentTransformer transformer, long maxSourceSizeKBytes)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
Deque<Frame> ourStack = ThreadInfo.getStack();
|
||||
Frame frame = ourStack.peek();
|
||||
|
||||
if (frame != null)
|
||||
{
|
||||
String name = getName(transformer);
|
||||
String reason = String.format("> %,dK", maxSourceSizeKBytes);
|
||||
boolean debug = (maxSourceSizeKBytes != 0);
|
||||
if (ourStack.size() == 1)
|
||||
{
|
||||
if (frame.unavailableTransformers == null)
|
||||
{
|
||||
frame.unavailableTransformers = new HashSet<UnavailableTransformer>();
|
||||
}
|
||||
frame.unavailableTransformers.add(new UnavailableTransformer(name, reason, debug));
|
||||
}
|
||||
else
|
||||
{
|
||||
log("-- " + name + ' ' + reason, debug);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called once all available transformers have been identified.
|
||||
*/
|
||||
public void availableTransformers(List<ContentTransformer> transformers, long sourceSize, String calledFrom)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
Deque<Frame> ourStack = ThreadInfo.getStack();
|
||||
Frame frame = ourStack.peek();
|
||||
|
||||
// Log the basic info about this transformation
|
||||
logBasicDetails(frame, sourceSize,
|
||||
calledFrom + ((transformers.size() == 0) ? " NO transformers" : ""),
|
||||
(ourStack.size() == 1));
|
||||
|
||||
// Report available and unavailable transformers
|
||||
char c = 'a';
|
||||
int longestNameLength = getLongestTransformerNameLength(transformers, frame);
|
||||
for (ContentTransformer trans : transformers)
|
||||
{
|
||||
String name = getName(trans);
|
||||
int pad = longestNameLength - name.length();
|
||||
log((c == 'a' ? "**" : " ") + (c++) + ") " +
|
||||
name + spaces(pad+1) + trans.getTransformationTime() + " ms");
|
||||
}
|
||||
if (frame.unavailableTransformers != null)
|
||||
{
|
||||
for (UnavailableTransformer unavailable: frame.unavailableTransformers)
|
||||
{
|
||||
int pad = longestNameLength - unavailable.name.length();
|
||||
log("--" + (c++) + ") " + unavailable.name + spaces(pad+1) + unavailable.reason,
|
||||
unavailable.debug);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getLongestTransformerNameLength(List<ContentTransformer> transformers,
|
||||
Frame frame)
|
||||
{
|
||||
int longestNameLength = 0;
|
||||
for (ContentTransformer trans : transformers)
|
||||
{
|
||||
int length = getName(trans).length();
|
||||
if (longestNameLength < length)
|
||||
longestNameLength = length;
|
||||
}
|
||||
if (frame.unavailableTransformers != null)
|
||||
{
|
||||
for (UnavailableTransformer unavailable: frame.unavailableTransformers)
|
||||
{
|
||||
int length = unavailable.name.length();
|
||||
if (longestNameLength < length)
|
||||
longestNameLength = length;
|
||||
}
|
||||
}
|
||||
return longestNameLength;
|
||||
}
|
||||
|
||||
private void logBasicDetails(Frame frame, long sourceSize, String message, boolean firstLevel)
|
||||
{
|
||||
// Log the source URL, but there is no point if the parent has logged it
|
||||
if (frame.fromUrl != null && (firstLevel || frame.id != 1))
|
||||
{
|
||||
log(frame.fromUrl, firstLevel);
|
||||
}
|
||||
|
||||
log(getMimetypeExt(frame.sourceMimetype)+getMimetypeExt(frame.targetMimetype) + String.format("%,dK ", (sourceSize/1024)) + message);
|
||||
|
||||
log(frame.sourceMimetype+' '+frame.targetMimetype, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after working out what transformers are available and any
|
||||
* resulting transform has been called.
|
||||
*/
|
||||
public void popAvailable()
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
pop(Call.AVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after performing a transform.
|
||||
*/
|
||||
public void popTransform()
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
pop(Call.TRANSFORM);
|
||||
}
|
||||
}
|
||||
|
||||
private void pop(Call callType)
|
||||
{
|
||||
Deque<Frame> ourStack = ThreadInfo.getStack();
|
||||
if (!ourStack.isEmpty())
|
||||
{
|
||||
Frame frame = ourStack.peek();
|
||||
if ((frame.callType == callType) ||
|
||||
(frame.callType == Call.AVAILABLE_AND_TRANSFORM && callType == Call.AVAILABLE))
|
||||
{
|
||||
if (ourStack.size() == 1 || logger.isTraceEnabled())
|
||||
{
|
||||
boolean topFrame = ourStack.size() == 1;
|
||||
log("Finished in " +
|
||||
(System.currentTimeMillis() - frame.start) + " ms" +
|
||||
(frame.callType == Call.AVAILABLE ? " Transformer NOT called" : "") +
|
||||
(topFrame ? "\n" : ""),
|
||||
topFrame);
|
||||
}
|
||||
|
||||
ourStack.pop();
|
||||
|
||||
// See debug(String, Throwable) as to why this is commented out
|
||||
// if (ourStack.size() >= 1)
|
||||
// {
|
||||
// ourStack.peek().lastThrowable = frame.lastThrowable;
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if any logging is required.
|
||||
*/
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return
|
||||
(logger.isDebugEnabled() && ThreadInfo.getDebug()) ||
|
||||
logger.isTraceEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable debug log output. Normally used to hide calls to
|
||||
* getTransformer as trace rather than debug level log messages. There
|
||||
* are lots of these and it makes it hard to see what is going on.
|
||||
* @param debugOutput if {@code true} both debug and trace is generated. Otherwise all output is trace.
|
||||
* @return the original value.
|
||||
*/
|
||||
public static boolean setDebugOutput(boolean debugOutput)
|
||||
{
|
||||
return ThreadInfo.setDebugOutput(debugOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message prefixed with the current transformation reference.
|
||||
* @param message
|
||||
*/
|
||||
public void debug(String message)
|
||||
{
|
||||
if (isEnabled() && message != null)
|
||||
{
|
||||
log(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message prefixed with the current transformation reference
|
||||
* and include a exception, suppressing the stack trace if repeated
|
||||
* as we return up the stack of transformers.
|
||||
* @param message
|
||||
*/
|
||||
public void debug(String message, Throwable t)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
log(message + ' ' + t.getMessage());
|
||||
|
||||
// // Generally the full stack is not needed as transformer
|
||||
// // Exceptions get logged as a Error higher up, so including
|
||||
// // the stack trace has been found not to be needed. Keeping
|
||||
// // the following code and code that sets lastThrowable just
|
||||
// // in case we need it after all.
|
||||
//
|
||||
// Frame frame = ThreadInfo.getStack().peek();
|
||||
// boolean newThrowable = isNewThrowable(frame.lastThrowable, t);
|
||||
// frame.lastThrowable = t;
|
||||
//
|
||||
// if (newThrowable)
|
||||
// {
|
||||
// log(message, t, true);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// log(message + ' ' + t.getMessage());
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// private boolean isNewThrowable(Throwable lastThrowable, Throwable t)
|
||||
// {
|
||||
// while (t != null)
|
||||
// {
|
||||
// if (lastThrowable == t)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// t = t.getCause();
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
private void log(String message)
|
||||
{
|
||||
log(message, true);
|
||||
}
|
||||
|
||||
private void log(String message, boolean debug)
|
||||
{
|
||||
log(message, null, debug);
|
||||
}
|
||||
|
||||
private void log(String message, Throwable t, boolean debug)
|
||||
{
|
||||
if (debug && ThreadInfo.getDebug())
|
||||
{
|
||||
logger.debug(getReference()+message, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.trace(getReference()+message, t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cause of a transformation failure, so that only the
|
||||
* message of the Throwable is reported later rather than the full
|
||||
* stack trace over and over.
|
||||
*/
|
||||
public <T extends Throwable> T setCause(T t)
|
||||
{
|
||||
// See debug(String, Throwable) as to why this is commented out
|
||||
// if (isEnabled())
|
||||
// {
|
||||
// Deque<Frame> ourStack = ThreadInfo.getStack();
|
||||
// if (!ourStack.isEmpty())
|
||||
// {
|
||||
// ourStack.peek().lastThrowable = t;
|
||||
// }
|
||||
// }
|
||||
return t;
|
||||
}
|
||||
|
||||
private String getReference()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("");
|
||||
Frame frame = null;
|
||||
Iterator<Frame> iterator = ThreadInfo.getStack().descendingIterator();
|
||||
int lengthOfFirstId = 0;
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
frame = iterator.next();
|
||||
if (sb.length() == 0)
|
||||
{
|
||||
sb.append(frame.id);
|
||||
lengthOfFirstId = sb.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append('.');
|
||||
sb.append(frame.id);
|
||||
}
|
||||
}
|
||||
if (frame != null)
|
||||
{
|
||||
sb.append(spaces(9-sb.length()+lengthOfFirstId)); // Try to pad to level 5
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getName(ContentTransformer transformer)
|
||||
{
|
||||
return
|
||||
(transformer instanceof AbstractContentTransformer2
|
||||
? ((AbstractContentTransformerLimits)transformer).getBeanName()
|
||||
: transformer.getClass().getSimpleName())+
|
||||
|
||||
(transformer instanceof ComplexContentTransformer
|
||||
? "<<Complex>>"
|
||||
: transformer instanceof FailoverContentTransformer
|
||||
? "<<Failover>>"
|
||||
: transformer instanceof ProxyContentTransformer
|
||||
? (((ProxyContentTransformer)transformer).getWorker() instanceof RuntimeExecutableContentTransformerWorker)
|
||||
? "<<Runtime>>"
|
||||
: "<<Proxy>>"
|
||||
: "");
|
||||
}
|
||||
|
||||
private String getMimetypeExt(String mimetype)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("");
|
||||
if (mimetypeService == null)
|
||||
{
|
||||
sb.append(mimetype);
|
||||
sb.append(' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
String mimetypeExt = mimetypeService.getExtension(mimetype);
|
||||
sb.append(mimetypeExt);
|
||||
sb.append(spaces(5-mimetypeExt.length())); // Pad to normal max ext (4) plus 1
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String spaces(int i)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("");
|
||||
while (--i >= 0)
|
||||
{
|
||||
sb.append(' ');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -35,7 +35,7 @@ import org.alfresco.util.exec.RuntimeExec;
|
||||
public class ImageMagickContentTransformerTest extends AbstractContentTransformerTest
|
||||
{
|
||||
private ImageMagickContentTransformerWorker worker;
|
||||
private ContentTransformer transformer;
|
||||
private ProxyContentTransformer transformer;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
@@ -51,11 +51,10 @@ public class ImageMagickContentTransformerTest extends AbstractContentTransforme
|
||||
worker.setExecuter(executer);
|
||||
worker.afterPropertiesSet();
|
||||
|
||||
ProxyContentTransformer transformer = new ProxyContentTransformer();
|
||||
transformer = new ProxyContentTransformer();
|
||||
transformer.setMimetypeService(mimetypeService);
|
||||
transformer.setTransformerDebug(transformerDebug);
|
||||
transformer.setWorker(worker);
|
||||
this.transformer = transformer;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,10 +72,10 @@ public class ImageMagickContentTransformerTest extends AbstractContentTransforme
|
||||
return;
|
||||
}
|
||||
boolean reliability = transformer.isTransformable(
|
||||
MimetypeMap.MIMETYPE_IMAGE_GIF, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
|
||||
MimetypeMap.MIMETYPE_IMAGE_GIF, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
|
||||
assertEquals("Mimetype should not be supported", false, reliability);
|
||||
reliability = transformer.isTransformable(
|
||||
MimetypeMap.MIMETYPE_IMAGE_GIF, MimetypeMap.MIMETYPE_IMAGE_JPEG, new TransformationOptions());
|
||||
MimetypeMap.MIMETYPE_IMAGE_GIF, -1, MimetypeMap.MIMETYPE_IMAGE_JPEG, new TransformationOptions());
|
||||
assertEquals("Mimetype should be supported", true, reliability);
|
||||
}
|
||||
}
|
||||
|
@@ -172,7 +172,8 @@ public class ImageMagickContentTransformerWorker extends AbstractImageMagickCont
|
||||
properties.put(VAR_TARGET, targetFile.getAbsolutePath());
|
||||
|
||||
// execute the statement
|
||||
RuntimeExec.ExecutionResult result = executer.execute(properties);
|
||||
long timeoutMs = options.getTimeoutMs();
|
||||
RuntimeExec.ExecutionResult result = executer.execute(properties, timeoutMs);
|
||||
if (result.getExitValue() != 0 && result.getStdErr() != null && result.getStdErr().length() > 0)
|
||||
{
|
||||
throw new ContentIOException("Failed to perform ImageMagick transformation: \n" + result);
|
||||
|
Reference in New Issue
Block a user