Merged V3.2 to HEAD

17502: Merged V3.1 to V3.2 (Fixes ETHREEOH-3155 & ETHREEOH-2653)
      17501: Merged V2.2 to V3.1
         17358: Improved debugging in Schema2XForms utility to help with resolving of repeating switch support for ETWOTWO-490
         17488: Fix for ETWOTWO-1006: xforms.js DEBUG output can cause performance issues with web forms
         17491: More XForms debugging improvements
   17503: Failover content transformer
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /alfresco/BRANCHES/V2.2:r17358,17488,17491
   Merged /alfresco/BRANCHES/V3.1:r17501
   Merged /alfresco/BRANCHES/V3.2:r17502-17503


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18146 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2010-01-19 14:51:40 +00:00
parent af8f250c13
commit a650eb2a1c
7 changed files with 522 additions and 6 deletions

View File

@@ -239,6 +239,21 @@
</property> </property>
</bean> </bean>
<!-- These transformers are not used alone but only as part of a failover sequence -->
<!-- For this reason they do not extend the baseContentTransformer bean and so will not be registered. -->
<bean id="failover.transformer.PdfRenderer.PdfToImage"
class="org.alfresco.repo.content.transform.PdfToImageContentTransformer" >
<property name="mimetypeService">
<ref bean="mimetypeService"/>
</property>
</bean>
<bean id="failover.transformer.PdfBox.PdfToImage"
class="org.alfresco.repo.content.transform.PdfBoxPdfToImageContentTransformer" >
<property name="mimetypeService">
<ref bean="mimetypeService"/>
</property>
</bean>
<!-- Content Transformations --> <!-- Content Transformations -->
<bean id="transformer.StringExtracter" <bean id="transformer.StringExtracter"
class="org.alfresco.repo.content.transform.StringExtractingContentTransformer" class="org.alfresco.repo.content.transform.StringExtractingContentTransformer"
@@ -262,8 +277,14 @@
</bean> </bean>
<bean id="transformer.PdfToImage" <bean id="transformer.PdfToImage"
class="org.alfresco.repo.content.transform.PdfToImageContentTransformer" class="org.alfresco.repo.content.transform.FailoverContentTransformer"
parent="baseContentTransformer" > parent="baseContentTransformer" >
<property name="transformers">
<list>
<ref bean="failover.transformer.PdfRenderer.PdfToImage"/>
<ref bean="failover.transformer.PdfBox.PdfToImage"/>
</list>
</property>
</bean> </bean>
<bean id="transformer.complex.PDF.Image" <bean id="transformer.complex.PDF.Image"

View File

@@ -211,8 +211,6 @@ public abstract class AbstractContentTransformer2 extends ContentTransformerHelp
} }
} }
@SuppressWarnings("deprecation")
public final void transform( public final void transform(
ContentReader reader, ContentReader reader,
ContentWriter writer, ContentWriter writer,

View File

@@ -0,0 +1,214 @@
/*
* Copyright (C) 2005-2009 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 received 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.List;
import org.alfresco.error.AlfrescoRuntimeException;
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.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;
import org.springframework.beans.factory.InitializingBean;
/**
* This class is a transformer which contains a fixed sequence of delegate transformers.
* Requests to transform a document will be passed to the first transformer in the sequence.
* If that transformer successfully transforms the document then the process is complete. However
* should it fail, the transformation will be passed on to the next transformer in the sequence and
* so on.
* <P/>Transformers are considered to have failed of they throw an exception.
*
* @author Neil McErlean
*/
public class FailoverContentTransformer extends AbstractContentTransformer2 implements InitializingBean
{
private static Log logger = LogFactory.getLog(FailoverContentTransformer.class);
private List<ContentTransformer> transformers;
public FailoverContentTransformer()
{
// Intentionally empty
}
/**
* The list of transformers to use. There must be at least one, but for failover behaviour to work
* there should be at least two.
*
* @param transformers list of transformers.
*/
public void setTransformers(List<ContentTransformer> transformers)
{
this.transformers = transformers;
}
/**
* Ensures that required properties have been set
*/
public void afterPropertiesSet() throws Exception
{
if (transformers == null || transformers.size() == 0)
{
throw new AlfrescoRuntimeException("At least one inner transformer must be supplied: " + this);
}
if (getMimetypeService() == null)
{
throw new AlfrescoRuntimeException("'mimetypeService' is a required property");
}
}
/**
*
* @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)
{
// For this transformer to be considered operational, there must be at least one transformer
// in the chain that can perform for us.
boolean result = false;
for (ContentTransformer ct : this.transformers)
{
if (ct.isTransformable(sourceMimetype, targetMimetype, options))
{
result = true;
break;
}
}
return result;
}
public boolean isExplicitTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
boolean result = true;
for (ContentTransformer ct : this.transformers)
{
if (ct.isExplicitTransformation(sourceMimetype, targetMimetype, options) == false)
{
result = false;
}
}
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,
TransformationOptions options) throws Exception
{
final String outputMimetype = writer.getMimetype();
final String outputFileExt = getMimetypeService().getExtension(outputMimetype);
// We need to keep a reference to thrown exceptions as we're going to catch them and
// then move on to the next transformer. In the event that they all fail, we will throw
// the final exception.
Exception transformationException = null;
for (int i = 0; i < transformers.size(); i++)
{
int oneBasedCount = i + 1;
ContentTransformer transf = transformers.get(i);
ContentWriter currentWriter = null;
File tempFile = null;
try
{
if (logger.isDebugEnabled())
{
logger.debug("Transformation attempt " + oneBasedCount + " of " + transformers.size() + ": " + transf);
}
// We can't know in advance which transformer in the sequence will work - if any.
// Therefore we can't write into the ContentWriter stream.
// So make a temporary file writer with the current transformer name.
tempFile = TempFileProvider.createTempFile(
"FailoverTransformer_intermediate_" + transf.getClass().getSimpleName() + "_",
"." + outputFileExt);
currentWriter = new FileContentWriter(tempFile);
currentWriter.setMimetype(outputMimetype);
currentWriter.setEncoding(writer.getEncoding());
// attempt to transform
transf.transform(reader, currentWriter, options);
// TODO Could add a check for zero-length output and treat that as a failure
// final long writtenSize = currentWriter.getSize();
}
catch (Exception are)
{
transformationException = are;
if (logger.isDebugEnabled())
{
logger.debug("Transformation " + oneBasedCount + " was unsuccessful.");
if (i != transformers.size() - 1)
{
// We don't log the last exception as we're going to throw it.
logger.debug("The below exception is provided for information purposes only.", are);
}
}
// Set a new reader to refresh the input stream.
reader = reader.getReader();
// and move to the next transformer
continue;
}
// No need to close input or output streams
// At this point the current transformation was successful i.e. it did not throw an exception.
// Now we must copy the content from the temporary file into the ContentWriter stream.
if (tempFile != null)
{
writer.putContent(tempFile);
}
if (logger.isInfoEnabled())
{
logger.info("Transformation was successful");
}
return;
}
// At this point we have tried all transformers in the sequence without apparent success.
if (transformationException != null)
{
if (logger.isDebugEnabled())
{
logger.debug("All transformations were unsuccessful. Throwing latest exception.", transformationException);
}
throw transformationException;
}
}
}

View File

@@ -0,0 +1,31 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<bean id="transformer.Test-PdfToText-AlwaysFails"
class="org.alfresco.repo.content.transform.DummyTestContentTransformer"
parent="baseContentTransformer" >
<property name="alwaysFail">
<value>true</value>
</property>
</bean>
<bean id="transformer.Test-PdfToText-AlwaysSucceeds"
class="org.alfresco.repo.content.transform.DummyTestContentTransformer"
parent="baseContentTransformer" >
<property name="alwaysFail">
<value>false</value>
</property>
</bean>
<bean id="transformer.failover.Test-FailThenSucceed"
class="org.alfresco.repo.content.transform.FailoverContentTransformer"
parent="baseContentTransformer" >
<property name="transformers">
<list>
<ref bean="transformer.Test-PdfToText-AlwaysFails"/>
<ref bean="transformer.Test-PdfToText-AlwaysSucceeds"/>
</list>
</property>
</bean>
</beans>

View File

@@ -0,0 +1,138 @@
/*
* Copyright (C) 2005-2009 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.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.alfresco.util.ApplicationContextHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Tests the FailoverContentTransformer.
*
* @see org.alfresco.repo.content.transform.FailoverContentTransformer
*
* @author Neil McErlean
*/
public class FailoverContentTransformerTest extends AbstractContentTransformerTest
{
private static final String sourceMimeType = MimetypeMap.MIMETYPE_PDF;
private static final String targetMimeType = MimetypeMap.MIMETYPE_IMAGE_PNG;
private static ApplicationContext failoverAppContext =
new ClassPathXmlApplicationContext(new String[] {"classpath:org/alfresco/repo/content/transform/FailoverContentTransformerTest-context.xml"},
ApplicationContextHelper.getApplicationContext());
private FailoverContentTransformer transformer;
@Override
public void setUp() throws Exception
{
super.setUp();
ApplicationContextHelper.getApplicationContext();
transformer = (FailoverContentTransformer) failoverAppContext.getBean("transformer.failover.Test-FailThenSucceed");
transformer.setMimetypeService(mimetypeService);
}
/**
* @return Returns the same transformer regardless - it is allowed
*/
protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype)
{
return transformer;
}
public void testReliability() throws Exception
{
// The MIME types here are rather arbitrary
boolean reliability = transformer.isTransformable(sourceMimeType, targetMimeType, new TransformationOptions());
assertEquals("Mimetype should be supported", true, reliability);
}
}
/**
* This dummy class is used only for test purposes within this source file.
*
* @author Neil McErlean
*/
class DummyTestContentTransformer extends AbstractContentTransformer2 implements BeanNameAware
{
private static Log logger = LogFactory.getLog(DummyTestContentTransformer.class);
/** Bean name for logging */
private String springBeanName;
private boolean alwaysFail;
public void setAlwaysFail(boolean value)
{
this.alwaysFail = value;
}
@Override
protected void transformInternal(ContentReader reader,
ContentWriter writer, TransformationOptions options)
throws Exception
{
// Do not actually perform any transformation. The test above is only interested in whether
// an exception is thrown and handled.
if (logger.isInfoEnabled())
{
logger.info(springBeanName + " is attempting a transformation");
}
reader.getContentString();
if (alwaysFail)
{
throw new AlfrescoRuntimeException("Test code intentionally failed method call.");
}
else
{
return;
}
}
public boolean isTransformable(String sourceMimetype,
String targetMimetype, TransformationOptions options)
{
// We'll arbitrarily claim to be able to transform PDF to PNG
return (MimetypeMap.MIMETYPE_PDF.equals(sourceMimetype) &&
MimetypeMap.MIMETYPE_IMAGE_PNG.equals(targetMimetype));
}
public void setBeanName(String name)
{
this.springBeanName = name;
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2005-2009 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 received 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.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import javax.imageio.ImageIO;
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.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
/**
* Makes use of the {@link http://www.pdfbox.org/ PDFBox} library to
* perform conversions from PDF files to images.
*
* @author Neil McErlean
*/
public class PdfBoxPdfToImageContentTransformer extends AbstractContentTransformer2
{
private static Log logger = LogFactory.getLog(PdfBoxPdfToImageContentTransformer.class);
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
// only support PDF -> PNG
return (MimetypeMap.MIMETYPE_PDF.equals(sourceMimetype) == true &&
MimetypeMap.MIMETYPE_IMAGE_PNG.equals(targetMimetype) == true);
}
@SuppressWarnings("unchecked")
protected void transformInternal(
ContentReader reader,
ContentWriter writer,
TransformationOptions options) throws Exception
{
PDDocument document = null;
try
{
File file = TempFileProvider.createTempFile("pdfToImage", ".pdf");
reader.getContent(file);
document = PDDocument.load(file);
if (document.isEncrypted())
{
String msg = "PDF document is encrypted.";
if (logger.isInfoEnabled())
{
logger.info(msg);
}
throw new AlfrescoRuntimeException(msg);
}
final int resolution = 16; //TODO A rather arbitrary number for resolution (DPI) here.
List pages = document.getDocumentCatalog().getAllPages();
PDPage page = (PDPage)pages.get(0);
BufferedImage img = page.convertToImage(BufferedImage.TYPE_INT_ARGB, resolution);
File outputFile = TempFileProvider.createTempFile("pdfToImageOutput", ".png");
ImageIO.write(img, "png", outputFile);
writer.putContent(outputFile);
}
catch (FileNotFoundException e1)
{
throw new AlfrescoRuntimeException("Unable to create image from pdf file.", e1);
}
catch (IOException e)
{
throw new AlfrescoRuntimeException("Unable to create image from pdf file.", e);
}
finally
{
if( document != null )
{
document.close();
}
}
}
}

View File

@@ -102,8 +102,8 @@ public class PdfToImageContentTransformer extends AbstractContentTransformer2
logger.info(msg.toString()); logger.info(msg.toString());
} }
PDFPage page = pdffile.getPage(0); PDFPage page = pdffile.getPage(0, true);
//get the width and height for the doc at the default zoom //get the width and height for the doc at the default zoom
int width=(int)page.getBBox().getWidth(); int width=(int)page.getBBox().getWidth();
int height=(int)page.getBBox().getHeight(); int height=(int)page.getBBox().getHeight();