Transformation service changes to support thumbnail service, shell of thumbnail service API

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@8658 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2008-04-02 11:28:39 +00:00
parent dca8be14dd
commit e5bfb7e8fa
58 changed files with 2032 additions and 718 deletions

View File

@@ -35,6 +35,8 @@ import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.ParameterCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -45,14 +47,19 @@ import org.apache.commons.logging.LogFactory;
* This class maintains the performance measures for the transformers as well, making sure that
* there is an extra penalty for transformers that fail regularly.
*
* @deprecated
* Deprecated since 3.0. The abstract base class org.alfresco.repo.content.transform.AbstractContentTransformer2 should now be used instead.
*
* @author Derek Hulley
*/
@Deprecated
public abstract class AbstractContentTransformer implements ContentTransformer
{
private static final Log logger = LogFactory.getLog(AbstractContentTransformer.class);
private MimetypeService mimetypeService;
private ContentTransformerRegistry registry;
@SuppressWarnings("deprecation")
private List<ContentTransformerRegistry.TransformationKey> explicitTransformations;
private double averageTime = 0.0;
private long count = 0L;
@@ -60,6 +67,7 @@ public abstract class AbstractContentTransformer implements ContentTransformer
/**
* All transformers start with an average transformation time of 0.0ms.
*/
@SuppressWarnings("deprecation")
protected AbstractContentTransformer()
{
averageTime = 0.0;
@@ -97,6 +105,7 @@ public abstract class AbstractContentTransformer implements ContentTransformer
/**
* @return Returns the explicit transformations that were enabled for this transformer
*/
@SuppressWarnings("deprecation")
protected List<ContentTransformerRegistry.TransformationKey> getExplicitTransformations()
{
return explicitTransformations;
@@ -108,6 +117,7 @@ public abstract class AbstractContentTransformer implements ContentTransformer
*
* @param explicitTransformations explicit key mappings
*/
@SuppressWarnings("deprecation")
public void setExplicitTransformations(List<ContentTransformerRegistry.TransformationKey> explicitTransformations)
{
this.explicitTransformations = explicitTransformations;
@@ -136,13 +146,13 @@ public abstract class AbstractContentTransformer implements ContentTransformer
return;
}
// first register any explicit transformations
if (explicitTransformations != null)
{
for (ContentTransformerRegistry.TransformationKey key : explicitTransformations)
{
registry.addExplicitTransformer(key, this);
}
}
//if (explicitTransformations != null)
//{
// for (ContentTransformerRegistry.TransformationKey key : explicitTransformations)
// / {
// registry.addExplicitTransformer(key, this);
// }
//}
// register this instance for the fallback case
registry.addTransformer(this);
}
@@ -165,6 +175,15 @@ public abstract class AbstractContentTransformer implements ContentTransformer
return mimetype;
}
/**
* Added for backward compatibility of existing content transformers
*
* @param sourceMimetype the source mimetype
* @param targetMimetype the target mimetype
* @return double the reliability value of the content transformer ranging from 0 to 1
*/
protected abstract double getReliability(String sourceMimetype, String targetMimetype);
/**
* Convenience method to check the reliability of a transformation
*
@@ -185,7 +204,48 @@ public abstract class AbstractContentTransformer implements ContentTransformer
}
// it all checks out OK
}
/**
* @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)
{
ParameterCheck.mandatoryString("sourceMimetype", sourceMimetype);
ParameterCheck.mandatoryString("targetMimetype", targetMimetype);
double reliability = getReliability(sourceMimetype, targetMimetype);
boolean result = true;
if (reliability <= 0.0)
{
result = false;
}
return result;
}
/**
* @see org.alfresco.repo.content.transform.ContentTransformer#isTransformable(java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions)
*/
@SuppressWarnings("deprecation")
public boolean isExplicitTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
boolean result = false;
if (this.explicitTransformations != null)
{
for (ContentTransformerRegistry.TransformationKey transformationKey : this.explicitTransformations)
{
if (transformationKey.getSourceMimetype().equals(sourceMimetype) == true &&
transformationKey.getTargetMimetype().equals(targetMimetype) == true)
{
result = true;
break;
}
}
}
return result;
}
/**
* Method to be implemented by subclasses wishing to make use of the common infrastructural code
* provided by this class.
@@ -207,7 +267,18 @@ public abstract class AbstractContentTransformer implements ContentTransformer
*/
public final void transform(ContentReader reader, ContentWriter writer) throws ContentIOException
{
transform(reader, writer, null);
Map<String, Object> optionsMap = null;
transform(reader, writer, optionsMap);
}
/**
* @see org.alfresco.repo.content.transform.ContentTransformer#transform(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter, org.alfresco.service.cmr.repository.TransformationOptions)
*/
public final void transform(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws ContentIOException
{
Map<String, Object> optionsMap = options.toMap();
transform(reader, writer, optionsMap);
}
/**
@@ -223,6 +294,7 @@ public abstract class AbstractContentTransformer implements ContentTransformer
* <p>
* If the options provided are null, then an empty map will be created.
*/
@SuppressWarnings("deprecation")
public final void transform(
ContentReader reader,
ContentWriter writer,

View File

@@ -0,0 +1,326 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.content.transform;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.ContentAccessor;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Provides basic services for {@link org.alfresco.repo.content.transform.ContentTransformer}
* implementations.
* <p>
* This class maintains the performance measures for the transformers as well, making sure that
* there is an extra penalty for transformers that fail regularly.
*
* @author Derek Hulley
* @author Roy Wetherall
*/
public abstract class AbstractContentTransformer2 implements ContentTransformer
{
private static final Log logger = LogFactory.getLog(AbstractContentTransformer2.class);
private MimetypeService mimetypeService;
private ContentTransformerRegistry registry;
private List<ExplictTransformationDetails> explicitTransformations;
private double averageTime = 0.0;
private long count = 0L;
/**
* All transformers start with an average transformation time of 0.0ms.
*/
protected AbstractContentTransformer2()
{
averageTime = 0.0;
explicitTransformations = new ArrayList<ExplictTransformationDetails>(0);
}
/**
* The registry to auto-register with
*
* @param registry the transformer registry
*/
public void setRegistry(ContentTransformerRegistry registry)
{
this.registry = registry;
}
/**
* Helper setter of the mimetype service. This is not always required.
*
* @param mimetypeService
*/
public void setMimetypeService(MimetypeService mimetypeService)
{
this.mimetypeService = mimetypeService;
}
/**
* @return Returns the mimetype helper
*/
protected MimetypeService getMimetypeService()
{
return mimetypeService;
}
public void setExplicitTransformations(List<ExplictTransformationDetails> explicitTransformations)
{
this.explicitTransformations = explicitTransformations;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append(this.getClass().getSimpleName())
.append("[ average=").append((long)averageTime).append("ms")
.append("]");
return sb.toString();
}
/**
* Registers this instance with the {@link #setRegistry(ContentTransformerRegistry) registry}
* if it is present.
*/
public void register()
{
if (registry == null)
{
logger.warn("Property 'registry' has not been set. Ignoring auto-registration: \n" +
" transformer: " + this);
return;
}
// register this instance for the fallback case
registry.addTransformer(this);
}
/**
* Convenience to fetch and check the mimetype for the given content
*
* @param content the reader/writer for the content
* @return Returns the mimetype for the content
* @throws AlfrescoRuntimeException if the content doesn't have a mimetype
*/
protected String getMimetype(ContentAccessor content)
{
String mimetype = content.getMimetype();
if (mimetype == null)
{
throw new AlfrescoRuntimeException("Mimetype is mandatory for transformation: " + content);
}
// done
return mimetype;
}
/**
* Convenience method to check the transformability of a transformation
*
* @param reader content reader
* @param writer content writer
* @param options transformation options
* @throws AlfrescoRuntimeException if the the transformation isn't supported
*/
protected void checkTransformable(ContentReader reader, ContentWriter writer, TransformationOptions options)
{
String sourceMimetype = getMimetype(reader);
String targetMimetype = getMimetype(writer);
boolean transformable = isTransformable(sourceMimetype, targetMimetype, options);
if (transformable == false)
{
throw new AlfrescoRuntimeException("Unsuported transformation attempted: \n" +
" reader: " + reader + "\n" +
" writer: " + writer);
}
// it all checks out OK
}
/**
* Method to be implemented by subclasses wishing to make use of the common infrastructural code
* provided by this class.
*
* @param reader the source of the content to transform
* @param writer the target to which to write the transformed content
* @param options a map of options to use when performing the transformation. The map
* will never be null.
* @throws Exception exceptions will be handled by this class - subclasses can throw anything
*/
protected abstract void transformInternal(
ContentReader reader,
ContentWriter writer,
TransformationOptions options) throws Exception;
/**
* @see #transform(ContentReader, ContentWriter, Map)
* @see #transformInternal(ContentReader, ContentWriter, Map)
*/
public final void transform(ContentReader reader, ContentWriter writer) throws ContentIOException
{
transform(reader, writer, new TransformationOptions());
}
/**
* @see org.alfresco.repo.content.transform.ContentTransformer#transform(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter, org.alfresco.service.cmr.repository.TransformationOptions)
*/
public final void transform(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws ContentIOException
{
// begin timing
long before = System.currentTimeMillis();
// check options map
if (options == null)
{
options = new TransformationOptions();
}
try
{
// Check the transformability
checkTransformable(reader, writer, options);
// Transform
transformInternal(reader, writer, options);
}
catch (Throwable e)
{
// Make sure that this transformation gets set back i.t.o. time taken.
// This will ensure that transformers that compete for the same transformation
// will be prejudiced against transformers that tend to fail
recordTime(10000); // 10 seconds, i.e. rubbish
throw new ContentIOException("Content conversion failed: \n" +
" reader: " + reader + "\n" +
" writer: " + writer + "\n" +
" options: " + options,
e);
}
finally
{
// check that the reader and writer are both closed
if (reader.isChannelOpen())
{
logger.error("Content reader not closed by transformer: \n" +
" reader: " + reader + "\n" +
" transformer: " + this);
}
if (writer.isChannelOpen())
{
logger.error("Content writer not closed by transformer: \n" +
" writer: " + writer + "\n" +
" transformer: " + this);
}
}
// record time
long after = System.currentTimeMillis();
recordTime(after - before);
// done
if (logger.isDebugEnabled())
{
logger.debug("Completed transformation: \n" +
" reader: " + reader + "\n" +
" writer: " + writer + "\n" +
" options: " + options + "\n" +
" transformer: " + this);
}
}
@SuppressWarnings("deprecation")
public final void transform(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws ContentIOException
{
this.transform(reader, writer, new TransformationOptions(options));
}
/**
* Default implementation, override if need to extend logic
*
* @see org.alfresco.repo.content.transform.ContentTransformer#isExplicitTransformation(java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions)
*/
public boolean isExplicitTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
boolean result = false;
for (ExplictTransformationDetails explicitTransformation : this.explicitTransformations)
{
if (sourceMimetype.equals(explicitTransformation.getSourceMimetype()) == true &&
targetMimetype.equals(explicitTransformation.getTargetMimetype()) == true)
{
result = true;
break;
}
}
return result;
}
/**
* @return Returns the calculated running average of the current transformations
*/
public synchronized long getTransformationTime()
{
return (long) averageTime;
}
/**
* Records and updates the average transformation time for this transformer.
* <p>
* Subclasses should call this after every transformation in order to keep
* the running average of the transformation times up to date.
* <p>
* This method is thread-safe. The time spent in this method is negligible
* so the impact will be minor.
*
* @param transformationTime the time it took to perform the transformation.
* The value may be 0.
*/
protected final synchronized void recordTime(long transformationTime)
{
if (count == Long.MAX_VALUE)
{
// we have reached the max count - reduce it by half
// the average fluctuation won't be extreme
count /= 2L;
}
// adjust the average
count++;
double diffTime = ((double) transformationTime) - averageTime;
averageTime += diffTime / (double) count;
}
}

View File

@@ -170,7 +170,7 @@ public abstract class AbstractContentTransformerTest extends TestCase
// must we test the transformation?
ContentTransformer transformer = getTransformer(sourceMimetype, targetMimetype);
if (transformer == null || transformer.getReliability(sourceMimetype, targetMimetype) <= 0.0)
if (transformer == null || transformer.isTransformable(sourceMimetype, targetMimetype, null) == false)
{
// no transformer
continue;

View File

@@ -24,10 +24,9 @@
*/
package org.alfresco.repo.content.transform;
import java.util.Map;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -42,41 +41,38 @@ import org.apache.commons.logging.LogFactory;
*
* @author Derek Hulley
*/
public class BinaryPassThroughContentTransformer extends AbstractContentTransformer
public class BinaryPassThroughContentTransformer extends AbstractContentTransformer2
{
@SuppressWarnings("unused")
private static final Log logger = LogFactory.getLog(BinaryPassThroughContentTransformer.class);
/**
* @return Returns 1.0 if the formats are identical and not text
*/
public double getReliability(String sourceMimetype, String targetMimetype)
@Override
protected void transformInternal(ContentReader reader,
ContentWriter writer, TransformationOptions options)
throws Exception
{
// just stream it
writer.putContent(reader.getContentInputStream());
}
public boolean isTransformable(String sourceMimetype,
String targetMimetype, TransformationOptions options)
{
if (sourceMimetype.startsWith(StringExtractingContentTransformer.PREFIX_TEXT))
{
// we can only stream binary content through
return 0.0;
return false;
}
else if (!sourceMimetype.equals(targetMimetype))
{
// no transformation is possible so formats must be exact
return 0.0;
return false;
}
else
{
// formats are the same and are not text
return 1.0;
return true;
}
}
/**
* Performs a direct stream provided the preconditions are met
*/
public void transformInternal(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws Exception
{
// just stream it
writer.putContent(reader.getContentInputStream());
}
}

View File

@@ -25,6 +25,7 @@
package org.alfresco.repo.content.transform;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* @see org.alfresco.repo.content.transform.BinaryPassThroughContentTransformer
@@ -51,16 +52,18 @@ public class BinaryPassThroughContentTransformerTest extends AbstractContentTran
return transformer;
}
public void testReliability() throws Exception
public void testIsTransformable() throws Exception
{
double reliability = 0.0;
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_TEXT_PLAIN);
assertEquals("Mimetype should not be supported", 0.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_XML, MimetypeMap.MIMETYPE_XML);
assertEquals("Mimetype should not be supported", 0.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_WORD);
assertEquals("Mimetype should be supported", 1.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_EXCEL);
assertEquals("Mimetype should be supported", 1.0, reliability);
TransformationOptions options = new TransformationOptions();
boolean reliability = false;
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_TEXT_PLAIN, options);
assertFalse("Mimetype should not be supported", reliability);
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_XML, MimetypeMap.MIMETYPE_XML, options);
assertFalse("Mimetype should not be supported", reliability);
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_WORD, options);
assertTrue("Mimetype should be supported", reliability);
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_EXCEL, options);
assertTrue("Mimetype should be supported", reliability);
}
}

View File

@@ -3,12 +3,12 @@ package org.alfresco.repo.content.transform;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
import org.springframework.beans.factory.InitializingBean;
@@ -18,7 +18,7 @@ import org.springframework.beans.factory.InitializingBean;
*
* @author Derek Hulley
*/
public class ComplexContentTransformer extends AbstractContentTransformer implements InitializingBean
public class ComplexContentTransformer extends AbstractContentTransformer2 implements InitializingBean
{
private List<ContentTransformer> transformers;
private List<String> intermediateMimetypes;
@@ -74,13 +74,15 @@ public class ComplexContentTransformer extends AbstractContentTransformer implem
throw new AlfrescoRuntimeException("'mimetypeService' is a required property");
}
}
/**
* @return Returns the multiple of the reliabilities of the chain of transformers
* Check we can transform all the way along the chain of mimetypes
*
* @see org.alfresco.repo.content.transform.ContentTransformer#isTransformable(java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions)
*/
public double getReliability(String sourceMimetype, String targetMimetype)
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
double reliability = 1.0;
boolean result = true;
String currentSourceMimetype = sourceMimetype;
Iterator<ContentTransformer> transformerIterator = transformers.iterator();
@@ -99,20 +101,29 @@ public class ComplexContentTransformer extends AbstractContentTransformer implem
// use an intermediate transformation mimetype
currentTargetMimetype = intermediateMimetypeIterator.next();
}
// the reliability is a multiple
reliability *= transformer.getReliability(currentSourceMimetype, currentTargetMimetype);
// move the source on
// check we can tranform the current stage
if (transformer.isTransformable(currentSourceMimetype, currentTargetMimetype, options) == false)
{
result = false;
break;
}
// move on
currentSourceMimetype = currentTargetMimetype;
}
// done
return reliability;
return result;
}
/**
* @see org.alfresco.repo.content.transform.AbstractContentTransformer2#transformInternal(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter, org.alfresco.service.cmr.repository.TransformationOptions)
*/
@Override
public void transformInternal(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws Exception
TransformationOptions options) throws Exception
{
ContentReader currentReader = reader;
@@ -145,5 +156,5 @@ public class ComplexContentTransformer extends AbstractContentTransformer implem
currentReader = currentWriter.getReader();
}
// done
}
}
}

View File

@@ -29,6 +29,7 @@ import java.util.Collections;
import java.util.List;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* Tests a transformation from Powerpoint->PDF->Text.
@@ -50,12 +51,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.getReliability(MimetypeMap.MIMETYPE_PPT, MimetypeMap.MIMETYPE_PDF) == 0.0)
if (unoTransformer.isTransformable(MimetypeMap.MIMETYPE_PPT, MimetypeMap.MIMETYPE_PDF, new TransformationOptions()) == false)
{
isAvailable = false;
return;
}
else if (pdfBoxTransformer.getReliability(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_TEXT_PLAIN) == 0.0)
else if (pdfBoxTransformer.isTransformable(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()) == false)
{
isAvailable = false;
return;
@@ -91,10 +92,9 @@ public class ComplexContentTransformerTest extends AbstractContentTransformerTes
{
return;
}
double reliability = 0.0;
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_PPT, MimetypeMap.MIMETYPE_PDF);
assertEquals("Mimetype should not be supported", 0.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_PPT, MimetypeMap.MIMETYPE_TEXT_PLAIN);
assertEquals("Mimetype should be supported", 1.0, reliability);
boolean reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_PPT, 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());
assertEquals("Mimetype should be supported", true, reliability);
}
}

View File

@@ -1,256 +0,0 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.content.transform;
import java.io.File;
import java.util.LinkedList;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* A chain of transformations that is able to produce non-zero reliability
* transformation from one mimetype to another.
* <p>
* The reliability of the chain is the product of all the individual
* transformations.
*
* @author Derek Hulley
*/
public class CompoundContentTransformer implements ContentTransformer
{
private static final Log logger = LogFactory.getLog(CompoundContentTransformer.class);
/** a sequence of transformers to apply */
private LinkedList<Transformation> chain;
/** the combined reliability of all the transformations in the chain */
private double reliability;
public CompoundContentTransformer()
{
chain = new LinkedList<Transformation>();
reliability = 1.0;
}
/**
* Adds a transformation to the chain. The reliability of each transformation
* added must be greater than 0.0.
*
* @param sourceMimetype
* @param targetMimetype
* @param transformer the transformer that will transform from the source to
* the target mimetype
*/
public void addTransformation(String sourceMimetype, String targetMimetype, ContentTransformer transformer)
{
// create a transformation that aggregates the transform info
Transformation transformation = new Transformation(
transformer,
sourceMimetype,
targetMimetype);
// add to the chain
chain.add(transformation);
// recalculate combined reliability
double transformerReliability = transformer.getReliability(sourceMimetype, targetMimetype);
if (transformerReliability <= 0.0 || transformerReliability > 1.0)
{
throw new AlfrescoRuntimeException(
"Reliability of transformer must be between 0.0 and 1.0: \n" +
" transformer: " + transformer + "\n" +
" source: " + sourceMimetype + "\n" +
" target: " + targetMimetype + "\n" +
" reliability: " + transformerReliability);
}
this.reliability *= transformerReliability;
}
/**
* In order to score anything, the source mimetype must match the source
* mimetype of the first transformer and the target mimetype must match
* the target mimetype of the last transformer in the chain.
*
* @return Returns the product of the individual reliability scores of the
* transformations in the chain
*/
public double getReliability(String sourceMimetype, String targetMimetype)
{
if (chain.size() == 0)
{
// no transformers therefore no transformation possible
return 0.0;
}
Transformation first = chain.getFirst();
Transformation last = chain.getLast();
if (!first.getSourceMimetype().equals(sourceMimetype)
&& last.getTargetMimetype().equals(targetMimetype))
{
// the source type of the first transformation must match the source
// the target type of the last transformation must match the target
return 0.0;
}
return reliability;
}
/**
* @return Returns 0 if there are no transformers in the chain otherwise
* returns the sum of all the individual transformation times
*/
public long getTransformationTime()
{
long transformationTime = 0L;
for (Transformation transformation : chain)
{
ContentTransformer transformer = transformation.transformer;
transformationTime += transformer.getTransformationTime();
}
return transformationTime;
}
/**
*
*/
public void transform(ContentReader reader, ContentWriter writer) throws ContentIOException
{
transform(reader, writer, null);
}
/**
* Executes each transformer in the chain, passing the content between them
*/
public void transform(ContentReader reader, ContentWriter writer, Map<String, Object> options)
throws ContentIOException
{
if (chain.size() == 0)
{
throw new AlfrescoRuntimeException("No transformations present in chain");
}
// check that the mimetypes of the transformation are valid for the chain
String sourceMimetype = reader.getMimetype();
String targetMimetype = writer.getMimetype();
Transformation firstTransformation = chain.getFirst();
Transformation lastTransformation = chain.getLast();
if (!firstTransformation.getSourceMimetype().equals(sourceMimetype)
&& lastTransformation.getTargetMimetype().equals(targetMimetype))
{
throw new AlfrescoRuntimeException("Attempting to perform unreliable transformation: \n" +
" reader: " + reader + "\n" +
" writer: " + writer);
}
ContentReader currentReader = reader;
ContentWriter currentWriter = null;
int currentIndex = 0;
for (Transformation transformation : chain)
{
boolean last = (currentIndex == chain.size() - 1);
if (last)
{
// we are on the last transformation so use the final output writer
currentWriter = writer;
}
else
{
// have to create an intermediate writer - just use a file writer
File tempFile = TempFileProvider.createTempFile("transform", ".tmp");
currentWriter = new FileContentWriter(tempFile);
// set the writer's mimetype to conform to the transformation we are using
currentWriter.setMimetype(transformation.getTargetMimetype());
}
// transform from the current reader to the current writer
transformation.execute(currentReader, currentWriter, options);
if (!currentWriter.isClosed())
{
throw new AlfrescoRuntimeException("Writer not closed by transformation: \n" +
" transformation: " + transformation + "\n" +
" writer: " + currentWriter);
}
// if we have more transformations, then use the written content
// as the next source
if (!last)
{
currentReader = currentWriter.getReader();
}
}
// done
if (logger.isDebugEnabled())
{
logger.debug("Executed complex transformation: \n" +
" chain: " + chain + "\n" +
" reader: " + reader + "\n" +
" writer: " + writer);
}
}
/**
* A transformation that contains the transformer as well as the
* transformation mimetypes to be used
*/
public static class Transformation extends ContentTransformerRegistry.TransformationKey
{
private ContentTransformer transformer;
public Transformation(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
{
super(sourceMimetype, targetMimetype);
this.transformer = transformer;
}
/**
* Executs the transformation
*
* @param reader the reader from which to read the content
* @param writer the writer to write content to
* @param options the options to execute with
* @throws ContentIOException if the transformation fails
*/
public void execute(ContentReader reader, ContentWriter writer, Map<String, Object> options)
throws ContentIOException
{
String sourceMimetype = getSourceMimetype();
String targetMimetype = getTargetMimetype();
// check that the source and target mimetypes of the reader and writer match
if (!sourceMimetype.equals(reader.getMimetype()))
{
throw new AlfrescoRuntimeException("The source mimetype doesn't match the reader's mimetype: \n" +
" source mimetype: " + sourceMimetype + "\n" +
" reader: " + reader);
}
if (!targetMimetype.equals(writer.getMimetype()))
{
throw new AlfrescoRuntimeException("The target mimetype doesn't match the writer's mimetype: \n" +
" target mimetype: " + targetMimetype + "\n" +
" writer: " + writer);
}
transformer.transform(reader, writer, options);
}
}
}

View File

@@ -30,6 +30,7 @@ import org.alfresco.repo.content.ContentWorker;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* Interface for class that allow content transformation from one mimetype to another.
@@ -45,8 +46,8 @@ public interface ContentTransformer extends ContentWorker
* options are used, but they should be considered optional and their absence
* should not interfere with the execution of the transformer.
*/
public static final String OPT_SOURCE_NODEREF = "sourceNodeRef";
public static final String OPT_DESTINATION_NODEREF = "destinationNodeRef";
//public static final String OPT_SOURCE_NODEREF = "sourceNodeRef";
//public static final String OPT_DESTINATION_NODEREF = "destinationNodeRef";
/**
* Provides the approximate accuracy with which this transformer can
@@ -61,7 +62,27 @@ public interface ContentTransformer extends ContentWorker
* transformation cannot be performed at all. 1.0 indicates that
* the transformation can be performed perfectly.
*/
public double getReliability(String sourceMimetype, String targetMimetype);
//public double getReliability(String sourceMimetype, String targetMimetype);
/**
* 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 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);
/**
*
* @param sourceMimetype
* @param targetMimetype
* @param options
* @return
*/
public boolean isExplicitTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options);
/**
* Provides an estimate, usually a worst case guess, of how long a transformation
@@ -75,7 +96,7 @@ public interface ContentTransformer extends ContentWorker
public long getTransformationTime();
/**
* @see #transform(ContentReader, ContentWriter, Map)
* @see #transform(ContentReader, ContentWriter, TransformationOptions)
*/
public void transform(ContentReader reader, ContentWriter writer) throws ContentIOException;
@@ -97,9 +118,36 @@ public interface ContentTransformer extends ContentWorker
* @param options options to pass to the transformer. These are transformer dependent
* and may be null.
* @throws ContentIOException if an IO exception occurs
*
* @deprecated
* Deprecated since 3.0. Options should now be provided as a TransformationOptions object.
*/
@Deprecated
public void transform(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws ContentIOException;
/**
* Transforms the content provided by the reader and source mimetype
* to the writer and target mimetype with the provided transformation options.
* <p>
* The transformation viability can be determined by an up front call
* to {@link #isTransformable(String, String, TransformationOptions)}.
* <p>
* The source and target mimetypes <b>must</b> be available on the
* {@link org.alfresco.service.cmr.repository.ContentAccessor#getMimetype()} methods of
* both the reader and the writer.
* <p>
* Both reader and writer will be closed after the transformation completes.
* <p>
* The provided options can be null.
*
* @param reader the source of the content
* @param contentWriter the destination of the transformed content
* @param options transformation options, these can be null
* @throws ContentIOException if an IO exception occurs
*/
public void transform(ContentReader reader, ContentWriter contentWriter, TransformationOptions options)
throws ContentIOException;
}

View File

@@ -26,13 +26,9 @@ package org.alfresco.repo.content.transform;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -52,12 +48,13 @@ public class ContentTransformerRegistry
private static final Log logger = LogFactory.getLog(ContentTransformerRegistry.class);
private List<ContentTransformer> transformers;
/** Cache of previously used transactions */
private Map<TransformationKey, List<ContentTransformer>> transformationCache;
//private Map<TransformationKey, List<ContentTransformer>> transformationCache;
/** Controls read access to the transformation cache */
private Lock transformationCacheReadLock;
//private Lock transformationCacheReadLock;
/** controls write access to the transformation cache */
private Lock transformationCacheWriteLock;
//private Lock transformationCacheWriteLock;
/**
* @param mimetypeMap all the mimetypes available to the system
@@ -65,12 +62,13 @@ public class ContentTransformerRegistry
public ContentTransformerRegistry()
{
this.transformers = new ArrayList<ContentTransformer>(10);
transformationCache = new HashMap<TransformationKey, List<ContentTransformer>>(17);
//transformationCache = new HashMap<TransformationKey, List<ContentTransformer>>(17);
// create lock objects for access to the cache
ReadWriteLock transformationCacheLock = new ReentrantReadWriteLock();
transformationCacheReadLock = transformationCacheLock.readLock();
transformationCacheWriteLock = transformationCacheLock.writeLock();
//ReadWriteLock transformationCacheLock = new ReentrantReadWriteLock();
//transformationCacheReadLock = transformationCacheLock.readLock();
//transformationCacheWriteLock = transformationCacheLock.writeLock();
}
/**
@@ -80,17 +78,17 @@ public class ContentTransformerRegistry
* @param key the mapping from one mimetype to the next
* @param transformer the content transformer
*/
public void addExplicitTransformer(TransformationKey key, ContentTransformer transformer)
{
transformationCache.put(key, Collections.singletonList(transformer));
//public void addExplicitTransformer(TransformationKey key, ContentTransformer transformer)
//{
// transformationCache.put(key, Collections.singletonList(transformer));
// done
if (logger.isDebugEnabled())
{
logger.debug("Registered explicit transformation: \n" +
" key: " + key + "\n" +
" transformer: " + transformer);
}
}
// if (logger.isDebugEnabled())
// {
// logger.debug("Registered explicit transformation: \n" +
// " key: " + key + "\n" +
// " transformer: " + transformer);
// }
// }
/**
* Registers an individual transformer that can be queried to check for applicability.
@@ -112,81 +110,75 @@ public class ContentTransformerRegistry
* Resets the transformation cache. This allows a fresh analysis of the best
* conversions based on actual average performance of the transformers.
*/
public void resetCache()
{
// get a write lock on the cache
transformationCacheWriteLock.lock();
try
{
transformationCache.clear();
}
finally
{
transformationCacheWriteLock.unlock();
}
// done
if (logger.isDebugEnabled())
{
logger.debug("Content transformation cache reset");
}
}
// public void resetCache()
// {
// // get a write lock on the cache
// transformationCacheWriteLock.lock();
// try
// {
// transformationCache.clear();
// }
// finally
// {
// transformationCacheWriteLock.unlock();
// }
// // done
// if (logger.isDebugEnabled())
// {
// logger.debug("Content transformation cache reset");
// }
// }
/**
* Gets the best transformer possible. This is a combination of the most reliable
* and the most performant transformer.
* <p>
* The result is cached for quicker access next time.
*
* @param sourceMimetype the source mimetype of the transformation
* @param targetMimetype the target mimetype of the transformation
* @return Returns a content transformer that can perform the desired
* transformation or null if no transformer could be found that would do it.
*
* TODO
*/
public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype)
public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
TransformationKey key = new TransformationKey(sourceMimetype, targetMimetype);
//TransformationKey key = new TransformationKey(sourceMimetype, targetMimetype);
List<ContentTransformer> transformers = null;
transformationCacheReadLock.lock();
try
{
if (transformationCache.containsKey(key))
{
//transformationCacheReadLock.lock();
//try
//{
// if (transformationCache.containsKey(key))
// {
// the translation has been requested before
// it might have been null
transformers = transformationCache.get(key);
}
}
finally
{
transformationCacheReadLock.unlock();
}
// transformers = transformationCache.get(key);
// }
//}
// finally
// {
// transformationCacheReadLock.unlock();
// }
if (transformers == null)
{
// if (transformers == null)
// {
// the translation has not been requested before
// get a write lock on the cache
// no double check done as it is not an expensive task
transformationCacheWriteLock.lock();
try
{
// transformationCacheWriteLock.lock();
// try
// {
// find the most suitable transformer - may be empty list
transformers = findTransformers(sourceMimetype, targetMimetype);
transformers = findTransformers(sourceMimetype, targetMimetype, options);
// store the result even if it is null
transformationCache.put(key, transformers);
}
finally
{
transformationCacheWriteLock.unlock();
}
}
// transformationCache.put(key, transformers);
// }
// finally
// {
// transformationCacheWriteLock.unlock();
// }
//}
// select the most performant transformer
long bestTime = -1L;
ContentTransformer bestTransformer = null;
for (ContentTransformer transformer : transformers)
{
// Reliability can be dynamic, i.e. it may have become unreliable
double reliability = transformer.getReliability(sourceMimetype, targetMimetype);
if (reliability == 0.0)
// Transformability can be dynamic, i.e. it may have become unusable
if (transformer.isTransformable(sourceMimetype, targetMimetype, options) == false)
{
// It is unreliable now.
continue;
@@ -210,12 +202,12 @@ 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)
private List<ContentTransformer> findTransformers(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
// search for a simple transformer that can do the job
List<ContentTransformer> transformers = findDirectTransformers(sourceMimetype, targetMimetype);
List<ContentTransformer> transformers = findDirectTransformers(sourceMimetype, targetMimetype, options);
// get the complex transformers that can do the job
List<ContentTransformer> complexTransformers = findComplexTransformer(sourceMimetype, targetMimetype);
List<ContentTransformer> complexTransformers = findComplexTransformer(sourceMimetype, targetMimetype, options);
transformers.addAll(complexTransformers);
// done
if (logger.isDebugEnabled())
@@ -236,45 +228,68 @@ 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)
private List<ContentTransformer> findDirectTransformers(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
double maxReliability = 0.0;
List<ContentTransformer> bestTransformers = new ArrayList<ContentTransformer>(2);
//double maxReliability = 0.0;
List<ContentTransformer> transformers = new ArrayList<ContentTransformer>(2);
boolean foundExplicit = false;
// loop through transformers
for (ContentTransformer transformer : this.transformers)
{
double reliability = transformer.getReliability(sourceMimetype, targetMimetype);
if (reliability <= 0.0)
if (transformer.isTransformable(sourceMimetype, targetMimetype, options) == true)
{
// it is unusable
continue;
if (transformer.isExplicitTransformation(sourceMimetype, targetMimetype, options) == true)
{
if (foundExplicit == false)
{
transformers.clear();
foundExplicit = true;
}
transformers.add(transformer);
}
else
{
if (foundExplicit == false)
{
transformers.add(transformer);
}
}
}
else if (reliability < maxReliability)
{
// it is not the best one to use
continue;
}
else if (reliability == maxReliability)
{
// it is as reliable as a previous transformer
}
else
{
// it is better than any previous transformer - wipe them
bestTransformers.clear();
maxReliability = reliability;
}
// add the transformer to the list
bestTransformers.add(transformer);
// double reliability = transformer.getReliability(sourceMimetype, targetMimetype);
// if (reliability <= 0.0)
// {
// // it is unusable
// continue;
// }
// else if (reliability < maxReliability)
// {
// // it is not the best one to use
// continue;
// }
// else if (reliability == maxReliability)
// {
// // it is as reliable as a previous transformer
// }
// else
// {
// // it is better than any previous transformer - wipe them
// bestTransformers.clear();
// maxReliability = reliability;
// }
// // add the transformer to the list
// bestTransformers.add(transformer);
}
// done
return bestTransformers;
return transformers;
}
/**
* Uses a list of known mimetypes to build transformations from several direct transformations.
*/
private List<ContentTransformer> findComplexTransformer(String sourceMimetype, String targetMimetype)
private List<ContentTransformer> findComplexTransformer(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
// get a complete list of mimetypes
// TODO: Build complex transformers by searching for transformations by mimetype
@@ -296,7 +311,10 @@ public class ContentTransformerRegistry
/**
* A key for a combination of a source and target mimetype
*
* @Deprecated since 3.0
*/
@Deprecated
public static class TransformationKey
{
private final String sourceMimetype;

View File

@@ -25,7 +25,6 @@
package org.alfresco.repo.content.transform;
import java.util.Collections;
import java.util.Map;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentReader;
@@ -33,6 +32,7 @@ import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
/**
@@ -46,6 +46,8 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
private static final String B = MimetypeMap.MIMETYPE_XML;
private static final String C = MimetypeMap.MIMETYPE_WORD;
private static final String D = MimetypeMap.MIMETYPE_HTML;
private static final TransformationOptions OPTIONS = new TransformationOptions();
/** a real registry with real transformers */
private ContentTransformerRegistry registry;
@@ -75,17 +77,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, 0.3, 10L);
new DummyTransformer(mimetypeService, dummyRegistry, A, B, 0.6, 10L);
new DummyTransformer(mimetypeService, dummyRegistry, A, C, 0.5, 10L);
new DummyTransformer(mimetypeService, dummyRegistry, A, C, 1.0, 10L);
new DummyTransformer(mimetypeService, dummyRegistry, B, C, 0.2, 10L);
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);
// create some dummy transformers for speed tests
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 1.0, 20L);
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 1.0, 20L);
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 1.0, 10L); // the fast one
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 1.0, 20L);
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 1.0, 20L);
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 20L);
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 20L);
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 10L); // the fast one
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 20L);
new DummyTransformer(mimetypeService, dummyRegistry, A, D, 20L);
}
/**
@@ -100,31 +102,31 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
/**
* @return Returns the transformer provided by the <b>real</b> registry
*/
protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype)
protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
return registry.getTransformer(sourceMimetype, targetMimetype);
return registry.getTransformer(sourceMimetype, targetMimetype, options);
}
public void testNullRetrieval() throws Exception
{
ContentTransformer transformer = null;
transformer = dummyRegistry.getTransformer(C, B);
transformer = dummyRegistry.getTransformer(C, B, OPTIONS);
assertNull("No transformer expected", transformer);
transformer = dummyRegistry.getTransformer(C, A);
transformer = dummyRegistry.getTransformer(C, A, OPTIONS);
assertNull("No transformer expected", transformer);
transformer = dummyRegistry.getTransformer(B, A);
transformer = dummyRegistry.getTransformer(B, A, OPTIONS);
assertNull("No transformer expected", transformer);
}
public void testSimpleRetrieval() throws Exception
{
ContentTransformer transformer = null;
// B -> C expect 0.2
transformer = dummyRegistry.getTransformer(B, C);
transformer = dummyRegistry.getTransformer(B, C);
// B -> C expect true
transformer = dummyRegistry.getTransformer(B, C, OPTIONS);
//transformer = dummyRegistry.getTransformer(B, C, OPTIONS);
assertNotNull("No transformer found", transformer);
assertEquals("Incorrect reliability", 0.2, transformer.getReliability(B, C));
assertEquals("Incorrect reliability", 0.0, transformer.getReliability(C, B));
assertTrue("Incorrect reliability", transformer.isTransformable(B, C, OPTIONS));
assertFalse("Incorrect reliability", transformer.isTransformable(C, B, OPTIONS));
}
/**
@@ -135,9 +137,9 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
public void testPerformanceRetrieval() throws Exception
{
// A -> D expect 1.0, 10ms
ContentTransformer transformer1 = dummyRegistry.getTransformer(A, D);
assertEquals("Incorrect reliability", 1.0, transformer1.getReliability(A, D));
assertEquals("Incorrect reliability", 0.0, transformer1.getReliability(D, A));
ContentTransformer transformer1 = dummyRegistry.getTransformer(A, D, OPTIONS);
assertTrue("Incorrect reliability", transformer1.isTransformable(A, D, OPTIONS));
assertFalse("Incorrect reliability", transformer1.isTransformable(D, A, OPTIONS));
assertEquals("Incorrect transformation time", 10L, transformer1.getTransformationTime());
}
@@ -145,15 +147,15 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
{
ContentTransformer transformer = null;
// A -> B expect 0.6
transformer = dummyRegistry.getTransformer(A, B);
transformer = dummyRegistry.getTransformer(A, B, OPTIONS);
assertNotNull("No transformer found", transformer);
assertEquals("Incorrect reliability", 0.6, transformer.getReliability(A, B));
assertEquals("Incorrect reliability", 0.0, transformer.getReliability(B, A));
assertTrue("Incorrect reliability", transformer.isTransformable(A, B, OPTIONS));
assertFalse("Incorrect reliability", transformer.isTransformable(B, A, OPTIONS));
// A -> C expect 1.0
transformer = dummyRegistry.getTransformer(A, C);
transformer = dummyRegistry.getTransformer(A, C, OPTIONS);
assertNotNull("No transformer found", transformer);
assertEquals("Incorrect reliability", 1.0, transformer.getReliability(A, C));
assertEquals("Incorrect reliability", 0.0, transformer.getReliability(C, A));
assertTrue("Incorrect reliability", transformer.isTransformable(A, C, OPTIONS));
assertFalse("Incorrect reliability", transformer.isTransformable(C, A, OPTIONS));
}
/**
@@ -162,22 +164,22 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
*/
public void testExplicitTransformation()
{
AbstractContentTransformer dummyTransformer = new DummyTransformer(
AbstractContentTransformer2 dummyTransformer = new DummyTransformer(
mimetypeService,
dummyRegistry,
MimetypeMap.MIMETYPE_FLASH, MimetypeMap.MIMETYPE_EXCEL,
1.0, 12345);
12345);
// set an explicit transformation
ContentTransformerRegistry.TransformationKey key =
new ContentTransformerRegistry.TransformationKey(
MimetypeMap.MIMETYPE_FLASH, MimetypeMap.MIMETYPE_EXCEL);
ExplictTransformationDetails key =
new ExplictTransformationDetails(
MimetypeMap.MIMETYPE_FLASH,
MimetypeMap.MIMETYPE_EXCEL);
dummyTransformer.setExplicitTransformations(Collections.singletonList(key));
// register again
dummyTransformer.register();
// get the appropriate transformer for the bizarre mapping
ContentTransformer checkTransformer = dummyRegistry.getTransformer(
MimetypeMap.MIMETYPE_FLASH, MimetypeMap.MIMETYPE_EXCEL);
ContentTransformer checkTransformer = dummyRegistry.getTransformer(MimetypeMap.MIMETYPE_FLASH, MimetypeMap.MIMETYPE_EXCEL, OPTIONS);
assertNotNull("No explicit transformer found", checkTransformer);
assertTrue("Expected explicit transformer", dummyTransformer == checkTransformer);
@@ -187,39 +189,37 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
* Dummy transformer that does no transformation and scores exactly as it is
* told to in the constructor. It enables the tests to be sure of what to expect.
*/
private static class DummyTransformer extends AbstractContentTransformer
private static class DummyTransformer extends AbstractContentTransformer2
{
private String sourceMimetype;
private String targetMimetype;
private double reliability;
private long transformationTime;
public DummyTransformer(
MimetypeService mimetypeService,
ContentTransformerRegistry registry,
String sourceMimetype, String targetMimetype,
double reliability, long transformationTime)
long transformationTime)
{
super.setMimetypeService(mimetypeService);
super.setRegistry(registry);
this.sourceMimetype = sourceMimetype;
this.targetMimetype = targetMimetype;
this.reliability = reliability;
this.transformationTime = transformationTime;
// register
register();
}
public double getReliability(String sourceMimetype, String targetMimetype)
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (this.sourceMimetype.equals(sourceMimetype)
&& this.targetMimetype.equals(targetMimetype))
{
return reliability;
return true;
}
else
{
return 0.0;
return false;
}
}
@@ -229,7 +229,7 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
public void transformInternal(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws Exception
TransformationOptions options) throws Exception
{
// just update the transformation time
super.recordTime(transformationTime);
@@ -243,4 +243,11 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
return transformationTime;
}
}
@Override
protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype)
{
// TODO Auto-generated method stub
return null;
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.content.transform;
public class ExplictTransformationDetails
{
private String sourceMimetype;
private String targetMimetype;
public ExplictTransformationDetails()
{
}
public ExplictTransformationDetails(String sourceMimetype, String targetMimetype)
{
this.sourceMimetype = sourceMimetype;
this.targetMimetype = targetMimetype;
}
public void setSourceMimetype(String sourceMimetype)
{
this.sourceMimetype = sourceMimetype;
}
public String getSourceMimetype()
{
return sourceMimetype;
}
public void setTargetMimetype(String targetMimetype)
{
this.targetMimetype = targetMimetype;
}
public String getTargetMimetype()
{
return targetMimetype;
}
}

View File

@@ -25,11 +25,11 @@
package org.alfresco.repo.content.transform;
import java.io.File;
import java.util.Map;
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.TransformationOptions;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -41,28 +41,29 @@ import org.htmlparser.beans.StringBean;
*
* @author Derek Hulley
*/
public class HtmlParserContentTransformer extends AbstractContentTransformer
public class HtmlParserContentTransformer extends AbstractContentTransformer2
{
@SuppressWarnings("unused")
private static final Log logger = LogFactory.getLog(HtmlParserContentTransformer.class);
/**
* Only support HTML to TEXT.
*/
public double getReliability(String sourceMimetype, String targetMimetype)
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (!MimetypeMap.MIMETYPE_HTML.equals(sourceMimetype) ||
!MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(targetMimetype))
{
// only support HTML -> TEXT
return 0.0;
return false;
}
else
{
return 1.0;
return true;
}
}
public void transformInternal(ContentReader reader, ContentWriter writer, Map<String, Object> options)
public void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception
{
// we can only work from a file

View File

@@ -25,6 +25,7 @@
package org.alfresco.repo.content.transform;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* @see org.alfresco.repo.content.transform.HtmlParserContentTransformer
@@ -52,14 +53,14 @@ public class HtmlParserContentTransformerTest extends AbstractContentTransformer
assertNotNull(transformer);
}
public void checkReliability() throws Exception
public void checkIsTransformable() throws Exception
{
// check reliability
double reliability = transformer.getReliability(MimetypeMap.MIMETYPE_HTML, MimetypeMap.MIMETYPE_TEXT_PLAIN);
assertEquals("Reliability incorrect", 1.0, reliability); // plain text to plain text is 100%
boolean reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_HTML, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
assertTrue(reliability); // plain text to plain text is supported
// check other way around
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_HTML);
assertEquals("Reliability incorrect", 0.0, reliability); // plain text to plain text is 0%
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_HTML, new TransformationOptions());
assertFalse(reliability); // plain text to plain text is not supported
}
}

View File

@@ -26,12 +26,12 @@ package org.alfresco.repo.content.transform;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
@@ -44,7 +44,7 @@ import org.apache.poi.poifs.filesystem.DocumentInputStream;
*
* @author Kevin Roast
*/
public class MailContentTransformer extends AbstractContentTransformer
public class MailContentTransformer extends AbstractContentTransformer2
{
private static final Log logger = LogFactory.getLog(MailContentTransformer.class);
@@ -54,17 +54,17 @@ public class MailContentTransformer extends AbstractContentTransformer
/**
* Only support MSG to text
*/
public double getReliability(String sourceMimetype, String targetMimetype)
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (!MimetypeMap.MIMETYPE_RFC822.equals(sourceMimetype) ||
!MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(targetMimetype))
{
// only support MSG -> TEXT
return 0.0;
return false;
}
else
{
return 1.0;
return true;
}
}
@@ -72,7 +72,7 @@ public class MailContentTransformer extends AbstractContentTransformer
* @see org.alfresco.repo.content.transform.AbstractContentTransformer#transformInternal(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter, java.util.Map)
*/
@Override
protected void transformInternal(final ContentReader reader, ContentWriter writer, Map<String, Object> options)
protected void transformInternal(final ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception
{
final StringBuilder sb = new StringBuilder();

View File

@@ -31,6 +31,7 @@ import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
/**
@@ -58,13 +59,10 @@ public class MailContentTransformerTest extends AbstractContentTransformerTest
return transformer;
}
public void testReliability() throws Exception
public void testIsTransformable() throws Exception
{
double reliability = 0.0;
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_RFC822);
assertEquals("Mimetype should not be supported", 0.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_RFC822, MimetypeMap.MIMETYPE_TEXT_PLAIN);
assertEquals("Mimetype should be supported", 1.0, reliability);
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_RFC822, new TransformationOptions()));
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_RFC822, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
}
/**

View File

@@ -29,7 +29,6 @@ import info.bliki.wiki.model.WikiModel;
import info.bliki.wiki.tags.ATag;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.model.FileFolderService;
@@ -38,6 +37,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.htmlcleaner.ContentToken;
/**
@@ -47,7 +47,7 @@ import org.htmlcleaner.ContentToken;
*
* @author Roy Wetherall
*/
public class MediaWikiContentTransformer extends AbstractContentTransformer
public class MediaWikiContentTransformer extends AbstractContentTransformer2
{
/** The file folder service */
private FileFolderService fileFolderService;
@@ -76,35 +76,36 @@ public class MediaWikiContentTransformer extends AbstractContentTransformer
}
/**
* Only support MEDIAWIKI to HTML
*/
public double getReliability(String sourceMimetype, String targetMimetype)
* Only transform from mediawiki to html
*
* @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)
{
if (!MimetypeMap.MIMETYPE_TEXT_MEDIAWIKI.equals(sourceMimetype) ||
!MimetypeMap.MIMETYPE_HTML.equals(targetMimetype))
{
// only support MEDIAWIKI -> HTML
return 0.0;
return false;
}
else
{
return 1.0;
return true;
}
}
/**
* @see org.alfresco.repo.content.transform.AbstractContentTransformer#transformInternal(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter, java.util.Map)
*/
public void transformInternal(ContentReader reader, ContentWriter writer, Map<String, Object> options)
/**
* @see org.alfresco.repo.content.transform.AbstractContentTransformer2#transformInternal(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter, org.alfresco.service.cmr.repository.TransformationOptions)
*/
public void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception
{
String imageURL = "{$image}";
String pageURL = "${title}";
if (options.containsKey(ContentTransformer.OPT_DESTINATION_NODEREF) == true)
// If we have context about the destination of the transformation then use it
if (options.getTargetNodeRef() != null)
{
NodeRef destinationNodeRef = (NodeRef)options.get(ContentTransformer.OPT_DESTINATION_NODEREF);
NodeRef parentNodeRef = this.nodeService.getPrimaryParent(destinationNodeRef).getParentRef();
NodeRef parentNodeRef = this.nodeService.getPrimaryParent(options.getTargetNodeRef()).getParentRef();
StringBuffer folderPath = new StringBuffer(256);
List<FileInfo> fileInfos = this.fileFolderService.getNamePath(null, parentNodeRef);
@@ -124,6 +125,11 @@ public class MediaWikiContentTransformer extends AbstractContentTransformer
writer.putContent(wikiModel.render(reader.getContentString()));
}
/**
* Alfresco custom Wiki model used to generate links and image references
*
* @author Roy Wetherall
*/
private class AlfrescoWikiModel extends WikiModel
{
public AlfrescoWikiModel(String imageBaseURL, String linkBaseURL)

View File

@@ -33,6 +33,7 @@ import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import de.schlichtherle.io.FileOutputStream;
@@ -85,15 +86,11 @@ public class MediaWikiContentTransformerTest extends AbstractContentTransformerT
assertNotNull(transformer);
}
public void checkReliability() throws Exception
public void testIsTransformable() throws Exception
{
// check reliability
double reliability = transformer.getReliability(MimetypeMap.MIMETYPE_TEXT_MEDIAWIKI, MimetypeMap.MIMETYPE_HTML);
assertEquals("Reliability incorrect", 1.0, reliability); // plain text to html is 100%
// check other way around
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_HTML, MimetypeMap.MIMETYPE_TEXT_MEDIAWIKI);
assertEquals("Reliability incorrect", 0.0, reliability); // html to plain text is 0%
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_MEDIAWIKI, MimetypeMap.MIMETYPE_HTML, new TransformationOptions()));
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_HTML, MimetypeMap.MIMETYPE_TEXT_MEDIAWIKI, new TransformationOptions()));
}
public void testMediaWikiToHTML() throws Exception

View File

@@ -27,7 +27,6 @@ package org.alfresco.repo.content.transform;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import net.sf.jooreports.converter.DocumentFamily;
import net.sf.jooreports.converter.DocumentFormat;
@@ -43,6 +42,7 @@ import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.PropertyCheck;
import org.alfresco.util.TempFileProvider;
import org.springframework.core.io.DefaultResourceLoader;
@@ -53,7 +53,7 @@ import org.springframework.core.io.DefaultResourceLoader;
*
* @author Derek Hulley
*/
public class OpenOfficeContentTransformer extends AbstractContentTransformer
public class OpenOfficeContentTransformer extends AbstractContentTransformer2
{
private OpenOfficeConnection connection;
private OpenOfficeDocumentConverter converter;
@@ -119,22 +119,22 @@ public class OpenOfficeContentTransformer extends AbstractContentTransformer
/**
* @see DocumentFormatRegistry
*/
public double getReliability(String sourceMimetype, String targetMimetype)
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (!isConnected())
{
// The connection management is must take care of this
return 0.0;
return false;
}
// there are some conversions that fail, despite the converter believing them possible
if (targetMimetype.equals(MimetypeMap.MIMETYPE_XHTML))
{
return 0.0;
return false;
}
else if (targetMimetype.equals(MimetypeMap.MIMETYPE_WORDPERFECT))
{
return 0.0;
return false;
}
MimetypeService mimetypeService = getMimetypeService();
@@ -145,14 +145,14 @@ public class OpenOfficeContentTransformer extends AbstractContentTransformer
if (sourceFormat == null)
{
// no document format
return 0.0;
return false;
}
// query the registry for the target format
DocumentFormat targetFormat = formatRegistry.getFormatByFileExtension(targetExtension);
if (targetFormat == null)
{
// no document format
return 0.0;
return false;
}
// get the family of the target document
@@ -161,18 +161,18 @@ public class OpenOfficeContentTransformer extends AbstractContentTransformer
if (!targetFormat.isExportableFrom(sourceFamily))
{
// unable to export from source family of documents to the target format
return 0.0;
return false;
}
else
{
return 1.0;
return true;
}
}
protected void transformInternal(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws Exception
TransformationOptions options) throws Exception
{
String sourceMimetype = getMimetype(reader);
String targetMimetype = getMimetype(writer);

View File

@@ -33,6 +33,7 @@ import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
/**
@@ -81,17 +82,16 @@ public class OpenOfficeContentTransformerTest extends AbstractContentTransformer
// no connection
return;
}
double reliability = 0.0;
reliability = transformer.getReliability(MIMETYPE_RUBBISH, MimetypeMap.MIMETYPE_TEXT_PLAIN);
assertEquals("Mimetype should not be supported", 0.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN, MIMETYPE_RUBBISH);
assertEquals("Mimetype should not be supported", 0.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_XHTML);
assertEquals("Mimetype should not be supported", 0.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_WORD);
assertEquals("Mimetype should be supported", 1.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_TEXT_PLAIN);
assertEquals("Mimetype should be supported", 1.0, reliability);
boolean reliability = transformer.isTransformable(MIMETYPE_RUBBISH, 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());
assertEquals("Mimetype should not be supported", false, reliability);
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, 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());
assertEquals("Mimetype should be supported", true, reliability);
reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions());
assertEquals("Mimetype should be supported", true, reliability);
}
/**

View File

@@ -25,11 +25,11 @@
package org.alfresco.repo.content.transform;
import java.io.InputStream;
import java.util.Map;
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.TransformationOptions;
import org.pdfbox.pdmodel.PDDocument;
import org.pdfbox.util.PDFTextStripper;
@@ -39,12 +39,12 @@ import org.pdfbox.util.PDFTextStripper;
*
* @author Derek Hulley
*/
public class PdfBoxContentTransformer extends AbstractContentTransformer
public class PdfBoxContentTransformer extends AbstractContentTransformer2
{
/**
* Currently the only transformation performed is that of text extraction from PDF documents.
*/
public double getReliability(String sourceMimetype, String targetMimetype)
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
// TODO: Expand PDFBox usage to convert images to PDF and investigate other conversions
@@ -52,18 +52,18 @@ public class PdfBoxContentTransformer extends AbstractContentTransformer
!MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(targetMimetype))
{
// only support PDF -> Text
return 0.0;
return false;
}
else
{
return 1.0;
return true;
}
}
protected void transformInternal(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws Exception
TransformationOptions options) throws Exception
{
PDDocument pdf = null;
InputStream is = null;

View File

@@ -25,6 +25,7 @@
package org.alfresco.repo.content.transform;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* @see org.alfresco.repo.content.transform.PdfBoxContentTransformer
@@ -51,12 +52,9 @@ public class PdfBoxContentTransformerTest extends AbstractContentTransformerTest
return transformer;
}
public void testReliability() throws Exception
public void testIsTransformable() throws Exception
{
double reliability = 0.0;
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_PDF);
assertEquals("Mimetype should not be supported", 0.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_TEXT_PLAIN);
assertEquals("Mimetype should be supported", 1.0, reliability);
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_PDF, new TransformationOptions()));
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
}
}

View File

@@ -26,11 +26,11 @@ package org.alfresco.repo.content.transform;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
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.TransformationOptions;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
@@ -51,7 +51,7 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
*
* @author Derek Hulley
*/
public class PoiHssfContentTransformer extends AbstractContentTransformer
public class PoiHssfContentTransformer extends AbstractContentTransformer2
{
/**
* Windows carriage return line feed pair.
@@ -61,21 +61,21 @@ public class PoiHssfContentTransformer extends AbstractContentTransformer
/**
* Currently the only transformation performed is that of text extraction from XLS documents.
*/
public double getReliability(String sourceMimetype, String targetMimetype)
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (!MimetypeMap.MIMETYPE_EXCEL.equals(sourceMimetype) ||
!MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(targetMimetype))
{
// only support XLS -> Text
return 0.0;
return false;
}
else
{
return 1.0;
return true;
}
}
public void transformInternal(ContentReader reader, ContentWriter writer, Map<String, Object> options)
public void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception
{
InputStream is = reader.getContentInputStream();
@@ -135,6 +135,7 @@ public class PoiHssfContentTransformer extends AbstractContentTransformer
}
}
@SuppressWarnings("deprecation")
private void writeRow(OutputStream os, HSSFRow row, String encoding) throws Exception
{
short firstCellNum = row.getFirstCellNum();

View File

@@ -30,6 +30,7 @@ import java.io.InputStream;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
/**
@@ -57,13 +58,10 @@ public class PoiHssfContentTransformerTest extends AbstractContentTransformerTes
return transformer;
}
public void testReliability() throws Exception
public void testIsTransformable() throws Exception
{
double reliability = 0.0;
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_EXCEL);
assertEquals("Mimetype should not be supported", 0.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_TEXT_PLAIN);
assertEquals("Mimetype should be supported", 1.0, reliability);
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_EXCEL, new TransformationOptions()));
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_EXCEL, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
}
/**

View File

@@ -30,10 +30,10 @@ import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.transform.ContentTransformerRegistry.TransformationKey;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
import org.alfresco.util.exec.RuntimeExec;
import org.alfresco.util.exec.RuntimeExec.ExecutionResult;
@@ -67,7 +67,7 @@ import org.apache.commons.logging.LogFactory;
* @since 1.1
* @author Derek Hulley
*/
public class RuntimeExecutableContentTransformer extends AbstractContentTransformer
public class RuntimeExecutableContentTransformer extends AbstractContentTransformer2
{
public static final String VAR_SOURCE = "source";
public static final String VAR_TARGET = "target";
@@ -168,28 +168,20 @@ public class RuntimeExecutableContentTransformer extends AbstractContentTransfor
*
* @see AbstractContentTransformer#setExplicitTransformations(List)
*/
public double getReliability(String sourceMimetype, String targetMimetype)
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (!available)
{
return 0.0;
return false;
}
// check whether the transformation was one of the explicit transformations
TransformationKey transformationKey = new TransformationKey(sourceMimetype, targetMimetype);
List<TransformationKey> explicitTransformations = getExplicitTransformations();
if (explicitTransformations.size() == 0)
if (isExplicitTransformation(sourceMimetype, targetMimetype, options) == true)
{
logger.warn(
"Property 'explicitTransformations' should be set to enable this transformer: \n" +
" transformer: " + this);
}
if (explicitTransformations.contains(transformationKey))
{
return 1.0;
return true;
}
else
{
return 0.0;
return false;
}
}
@@ -202,7 +194,7 @@ public class RuntimeExecutableContentTransformer extends AbstractContentTransfor
protected final void transformInternal(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws Exception
TransformationOptions options) throws Exception
{
// get mimetypes
String sourceMimetype = getMimetype(reader);
@@ -230,11 +222,15 @@ public class RuntimeExecutableContentTransformer extends AbstractContentTransfor
Map<String, String> properties = new HashMap<String, String>(5);
// copy options over
for (Map.Entry<String, Object> entry : options.entrySet())
if (options instanceof RuntimeExecutableContentTransformerOptions)
{
String key = entry.getKey();
Object value = entry.getValue();
properties.put(key, (value == null ? null : value.toString()));
RuntimeExecutableContentTransformerOptions runtimeOptions = (RuntimeExecutableContentTransformerOptions)options;
for (Map.Entry<String, Object> entry : runtimeOptions.getPropertyValues().entrySet())
{
String key = entry.getKey();
Object value = entry.getValue();
properties.put(key, (value == null ? null : value.toString()));
}
}
// add the source and target properties
properties.put(VAR_SOURCE, sourceFile.getAbsolutePath());

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.content.transform;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* Transformation options for the runtime executable transformer.
* <p>
* Values set here are mapped to ${valueName} style strings in the tranformer
* execution string.
*
* @author Roy Wetherall
*/
public class RuntimeExecutableContentTransformerOptions extends TransformationOptions
{
/** Map of property values */
private Map<String, Object> propertyValues = new HashMap<String, Object>(1);
/**
* Sets the map of property values that are used when executing the transformer
*
* @param propertyValues property value
*/
public void setPropertyValues(Map<String, Object> propertyValues)
{
this.propertyValues = propertyValues;
}
/**
* Gets the map of property values that are used when executing the transformer
*
* @return Map<String, Object> property values
*/
public Map<String, Object> getPropertyValues()
{
return propertyValues;
}
}

View File

@@ -32,13 +32,11 @@ import java.util.Map;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.repo.content.transform.ContentTransformerRegistry.TransformationKey;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.util.BaseAlfrescoTestCase;
import org.alfresco.util.TempFileProvider;
import org.alfresco.util.exec.RuntimeExec;
import org.apache.xml.security.transforms.TransformationException;
/**
* @see org.alfresco.repo.content.transform.RuntimeExecutableContentTransformer
@@ -65,9 +63,9 @@ public class RuntimeExecutableContentTransformerTest extends BaseAlfrescoTestCas
transformer.setTransformCommand(transformCommand);
transformer.setMimetypeService(serviceRegistry.getMimetypeService());
// set the explicit transformations
List<TransformationKey> explicitTranformations = new ArrayList<TransformationKey>(1);
List<ExplictTransformationDetails> explicitTranformations = new ArrayList<ExplictTransformationDetails>(1);
explicitTranformations.add(
new TransformationKey(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_XML));
new ExplictTransformationDetails(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_XML));
transformer.setExplicitTransformations(explicitTranformations);
// initialise so that it doesn't score 0

View File

@@ -28,11 +28,11 @@ import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.Map;
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.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -43,7 +43,7 @@ import org.apache.commons.logging.LogFactory;
*
* @author Derek Hulley
*/
public class StringExtractingContentTransformer extends AbstractContentTransformer
public class StringExtractingContentTransformer extends AbstractContentTransformer2
{
public static final String PREFIX_TEXT = "text/";
@@ -56,28 +56,28 @@ public class StringExtractingContentTransformer extends AbstractContentTransform
* <p>
* Extraction of text from binary data is wholly unreliable.
*/
public double getReliability(String sourceMimetype, String targetMimetype)
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (!targetMimetype.equals(MimetypeMap.MIMETYPE_TEXT_PLAIN))
{
// can only convert to plain text
return 0.0;
return false;
}
else if (sourceMimetype.equals(MimetypeMap.MIMETYPE_TEXT_PLAIN) ||
sourceMimetype.equals(MimetypeMap.MIMETYPE_JAVASCRIPT))
{
// conversions from any plain text format are very reliable
return 1.0;
return true;
}
else if (sourceMimetype.startsWith(PREFIX_TEXT))
{
// the source is text, but probably with some kind of markup
return 0.1;
return true;
}
else
{
// extracting text from binary is not useful
return 0.0;
return false;
}
}
@@ -90,17 +90,17 @@ public class StringExtractingContentTransformer extends AbstractContentTransform
* be unformatted but valid.
*/
@Override
public void transformInternal(ContentReader reader, ContentWriter writer, Map<String, Object> options)
public void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception
{
// is this a straight text-text transformation
transformText(reader, writer);
transformText(reader, writer, options);
}
/**
* Transformation optimized for text-to-text conversion
*/
private void transformText(ContentReader reader, ContentWriter writer) throws Exception
private void transformText(ContentReader reader, ContentWriter writer, TransformationOptions options) throws Exception
{
// get a char reader and writer
Reader charReader = null;

View File

@@ -38,6 +38,7 @@ import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
/**
@@ -116,9 +117,8 @@ public class StringExtractingContentTransformerTest extends AbstractContentTrans
{
ContentReader reader = writeContent("text/plain", "MacDingbat");
// check reliability
double reliability = transformer.getReliability(reader.getMimetype(), targetWriter.getMimetype());
assertEquals("Reliability incorrect", 1.0, reliability); // plain text to plain text is 100%
// check transformability
assertTrue(transformer.isTransformable(reader.getMimetype(), targetWriter.getMimetype(), new TransformationOptions()));
// transform
transformer.transform(reader, targetWriter);
@@ -133,9 +133,8 @@ public class StringExtractingContentTransformerTest extends AbstractContentTrans
{
ContentReader reader = writeContent("text/xml", "MacDingbat");
// check reliability
double reliability = transformer.getReliability(reader.getMimetype(), targetWriter.getMimetype());
assertEquals("Reliability incorrect", 0.1, reliability); // markup to plain text not 100%
// check transformability
assertTrue(transformer.isTransformable(reader.getMimetype(), targetWriter.getMimetype(), new TransformationOptions()));
// transform
transformer.transform(reader, targetWriter);

View File

@@ -26,11 +26,11 @@ package org.alfresco.repo.content.transform;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
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.TransformationOptions;
import org.textmining.text.extraction.WordExtractor;
/**
@@ -39,7 +39,7 @@ import org.textmining.text.extraction.WordExtractor;
*
* @author Derek Hulley
*/
public class TextMiningContentTransformer extends AbstractContentTransformer
public class TextMiningContentTransformer extends AbstractContentTransformer2
{
private WordExtractor wordExtractor;
@@ -51,21 +51,21 @@ public class TextMiningContentTransformer extends AbstractContentTransformer
/**
* Currently the only transformation performed is that of text extraction from Word documents.
*/
public double getReliability(String sourceMimetype, String targetMimetype)
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (!MimetypeMap.MIMETYPE_WORD.equals(sourceMimetype) ||
!MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(targetMimetype))
{
// only support DOC -> Text
return 0.0;
return false;
}
else
{
return 1.0;
return true;
}
}
public void transformInternal(ContentReader reader, ContentWriter writer, Map<String, Object> options)
public void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception
{
InputStream is = null;

View File

@@ -30,6 +30,7 @@ import java.io.InputStream;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
/**
@@ -57,13 +58,10 @@ public class TextMiningContentTransformerTest extends AbstractContentTransformer
return transformer;
}
public void testReliability() throws Exception
public void testIsTransformable() throws Exception
{
double reliability = 0.0;
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_WORD);
assertEquals("Mimetype should not be supported", 0.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_TEXT_PLAIN);
assertEquals("Mimetype should be supported", 1.0, reliability);
assertFalse(transformer.isTransformable(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_WORD, new TransformationOptions()));
assertTrue(transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()));
}
/**

View File

@@ -27,12 +27,12 @@ package org.alfresco.repo.content.transform;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
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.TransformationOptions;
import org.pdfbox.TextToPDF;
import org.pdfbox.pdmodel.PDDocument;
import org.pdfbox.pdmodel.font.PDTrueTypeFont;
@@ -44,7 +44,7 @@ import org.pdfbox.pdmodel.font.PDType1Font;
* @author Derek Hulley
* @since 2.1.0
*/
public class TextToPdfContentTransformer extends AbstractContentTransformer
public class TextToPdfContentTransformer extends AbstractContentTransformer2
{
private TextToPDF transformer;
@@ -92,24 +92,24 @@ public class TextToPdfContentTransformer extends AbstractContentTransformer
/**
* Only supports Text to PDF
*/
public double getReliability(String sourceMimetype, String targetMimetype)
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (!MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(sourceMimetype) ||
!MimetypeMap.MIMETYPE_PDF.equals(targetMimetype))
{
// only support Text -> PDF
return 0.0;
return false;
}
else
{
return 1.0;
return true;
}
}
protected void transformInternal(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws Exception
TransformationOptions options) throws Exception
{
PDDocument pdf = null;
InputStream is = null;

View File

@@ -25,6 +25,7 @@
package org.alfresco.repo.content.transform;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* @see org.alfresco.repo.content.transform.TextToPdfContentTransformer
@@ -56,10 +57,9 @@ public class TextToPdfContentTransformerTest extends AbstractContentTransformerT
public void testReliability() throws Exception
{
double reliability = 0.0;
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_TEXT_PLAIN);
assertEquals("Mimetype should not be supported", 0.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_PDF);
assertEquals("Mimetype should be supported", 1.0, reliability);
boolean reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_PDF, 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());
assertEquals("Mimetype should be supported", true, reliability);
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.content.transform;
import org.alfresco.repo.content.transform.magick.ImageMagickContentTransformerTest;
import org.alfresco.repo.content.transform.magick.JMagickContentTransformerTest;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Version test suite
*
* @author Roy Wetherall
*/
public class TransformTestSuite extends TestSuite
{
/**
* Creates the test suite
*
* @return the test suite
*/
public static Test suite()
{
TestSuite suite = new TestSuite();
suite.addTestSuite(BinaryPassThroughContentTransformerTest.class);
suite.addTestSuite(ComplexContentTransformerTest.class);
suite.addTestSuite(ContentTransformerRegistryTest.class);
suite.addTestSuite(HtmlParserContentTransformerTest.class);
suite.addTestSuite(MailContentTransformerTest.class);
suite.addTestSuite(MediaWikiContentTransformerTest.class);
suite.addTestSuite(OpenOfficeContentTransformerTest.class);
suite.addTestSuite(PdfBoxContentTransformerTest.class);
suite.addTestSuite(PoiHssfContentTransformerTest.class);
suite.addTestSuite(RuntimeExecutableContentTransformerTest.class);
suite.addTestSuite(StringExtractingContentTransformerTest.class);
suite.addTestSuite(TextMiningContentTransformerTest.class);
suite.addTestSuite(TextToPdfContentTransformerTest.class);
suite.addTestSuite(ImageMagickContentTransformerTest.class);
suite.addTestSuite(JMagickContentTransformerTest.class);
return suite;
}
}

View File

@@ -26,16 +26,15 @@ package org.alfresco.repo.content.transform.magick;
import java.io.File;
import java.io.InputStream;
import java.util.Collections;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.repo.content.transform.AbstractContentTransformer;
import org.alfresco.repo.content.transform.AbstractContentTransformer2;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -45,7 +44,7 @@ import org.apache.commons.logging.LogFactory;
*
* @author Derek Hulley
*/
public abstract class AbstractImageMagickContentTransformer extends AbstractContentTransformer
public abstract class AbstractImageMagickContentTransformer extends AbstractContentTransformer2
{
/** the prefix for mimetypes supported by the transformer */
public static final String MIMETYPE_IMAGE_PREFIX = "image/";
@@ -111,8 +110,7 @@ public abstract class AbstractImageMagickContentTransformer extends AbstractCont
".png");
// execute it
Map<String, Object> options = Collections.emptyMap();
transformInternal(inputFile, outputFile, options);
transformInternal(inputFile, outputFile, new TransformationOptions());
// check that the file exists
if (!outputFile.exists())
@@ -167,21 +165,21 @@ public abstract class AbstractImageMagickContentTransformer extends AbstractCont
* Supports image to image conversion, but only if the JMagick library and required
* libraries are available.
*/
public double getReliability(String sourceMimetype, String targetMimetype)
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (!available)
{
return 0.0;
return false;
}
if (!AbstractImageMagickContentTransformer.isSupported(sourceMimetype) ||
!AbstractImageMagickContentTransformer.isSupported(targetMimetype))
{
// only support IMAGE -> IMAGE (excl. RGB)
return 0.0;
return false;
}
else
{
return 1.0;
return true;
}
}
@@ -191,7 +189,7 @@ public abstract class AbstractImageMagickContentTransformer extends AbstractCont
protected final void transformInternal(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws Exception
TransformationOptions options) throws Exception
{
// get mimetypes
String sourceMimetype = getMimetype(reader);
@@ -251,5 +249,5 @@ public abstract class AbstractImageMagickContentTransformer extends AbstractCont
protected abstract void transformInternal(
File sourceFile,
File targetFile,
Map<String, Object> options) throws Exception;
TransformationOptions options) throws Exception;
}

View File

@@ -30,6 +30,7 @@ import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.exec.RuntimeExec;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -41,14 +42,12 @@ import org.apache.commons.logging.LogFactory;
*/
public class ImageMagickContentTransformer extends AbstractImageMagickContentTransformer
{
/** the command options, such as <b>--resize</b>, etc. */
public static final String KEY_OPTIONS = "options";
/** options variable name */
private static final String KEY_OPTIONS = "options";
/** source variable name */
public static final String VAR_OPTIONS = "options";
/** source variable name */
public static final String VAR_SOURCE = "source";
private static final String VAR_SOURCE = "source";
/** target variable name */
public static final String VAR_TARGET = "target";
private static final String VAR_TARGET = "target";
private static final Log logger = LogFactory.getLog(ImageMagickContentTransformer.class);
@@ -95,11 +94,14 @@ public class ImageMagickContentTransformer extends AbstractImageMagickContentTra
/**
* Transform the image content from the source file to the target file
*/
protected void transformInternal(File sourceFile, File targetFile, Map<String, Object> options) throws Exception
protected void transformInternal(File sourceFile, File targetFile, TransformationOptions options) throws Exception
{
Map<String, String> properties = new HashMap<String, String>(5);
// set properties
properties.put(KEY_OPTIONS, (String) options.get(KEY_OPTIONS));
if (options instanceof ImageTransformationOptions)
{
properties.put(KEY_OPTIONS, (String) ((ImageTransformationOptions)options).getCommandOptions());
}
properties.put(VAR_SOURCE, sourceFile.getAbsolutePath());
properties.put(VAR_TARGET, targetFile.getAbsolutePath());

View File

@@ -29,6 +29,7 @@ import java.util.Collections;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
import org.alfresco.repo.content.transform.ContentTransformer;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.exec.RuntimeExec;
/**
@@ -69,10 +70,9 @@ public class ImageMagickContentTransformerTest extends AbstractContentTransforme
{
return;
}
double reliability = 0.0;
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_IMAGE_GIF, MimetypeMap.MIMETYPE_TEXT_PLAIN);
assertEquals("Mimetype should not be supported", 0.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_IMAGE_GIF, MimetypeMap.MIMETYPE_IMAGE_JPEG);
assertEquals("Mimetype should be supported", 1.0, reliability);
boolean reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_IMAGE_GIF, 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());
assertEquals("Mimetype should be supported", true, reliability);
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.content.transform.magick;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* @author Roy Wetherall
*/
public class ImageTransformationOptions extends TransformationOptions
{
private String commandOptions = "";
public void setCommandOptions(String commandOptions)
{
this.commandOptions = commandOptions;
}
public String getCommandOptions()
{
return commandOptions;
}
}

View File

@@ -25,11 +25,11 @@
package org.alfresco.repo.content.transform.magick;
import java.io.File;
import java.util.Map;
import magick.ImageInfo;
import magick.MagickImage;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -41,6 +41,7 @@ import org.apache.commons.logging.LogFactory;
*/
public class JMagickContentTransformer extends AbstractImageMagickContentTransformer
{
@SuppressWarnings("unused")
private static final Log logger = LogFactory.getLog(JMagickContentTransformer.class);
public JMagickContentTransformer()
@@ -55,7 +56,7 @@ public class JMagickContentTransformer extends AbstractImageMagickContentTransfo
* @throws Exception
*/
@Override
protected void transformInternal(File sourceFile, File targetFile, Map<String, Object> options) throws Exception
protected void transformInternal(File sourceFile, File targetFile, TransformationOptions options) throws Exception
{
ImageInfo imageInfo = new ImageInfo(sourceFile.getAbsolutePath());
MagickImage image = new MagickImage(imageInfo);

View File

@@ -27,6 +27,7 @@ package org.alfresco.repo.content.transform.magick;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
import org.alfresco.repo.content.transform.ContentTransformer;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* @see org.alfresco.repo.content.transform.magick.JMagickContentTransformer
@@ -61,10 +62,9 @@ public class JMagickContentTransformerTest extends AbstractContentTransformerTes
{
return;
}
double reliability = 0.0;
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_IMAGE_GIF, MimetypeMap.MIMETYPE_TEXT_PLAIN);
assertEquals("Mimetype should not be supported", 0.0, reliability);
reliability = transformer.getReliability(MimetypeMap.MIMETYPE_IMAGE_GIF, MimetypeMap.MIMETYPE_IMAGE_JPEG);
assertEquals("Mimetype should be supported", 1.0, reliability);
boolean reliability = transformer.isTransformable(MimetypeMap.MIMETYPE_IMAGE_GIF, 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());
assertEquals("Mimetype should be supported", true, reliability);
}
}