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:
Alan Davis
2012-01-13 17:25:32 +00:00
parent 0a5389a552
commit 819988c518
70 changed files with 4514 additions and 438 deletions

View File

@@ -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)
{

View File

@@ -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())
{

View File

@@ -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);
}
}
}

View File

@@ -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());
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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
}
}

View File

@@ -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()));
}
/**

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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()));
}
}

View File

@@ -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()));
}
/**

View File

@@ -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()));
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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()));
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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()));
}
/**

View File

@@ -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;
}
}
}

View File

@@ -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", "");

View File

@@ -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()));
}
}

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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);