mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
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:
@@ -211,8 +211,6 @@ public abstract class AbstractContentTransformer2 extends ContentTransformerHelp
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public final void transform(
|
||||
ContentReader reader,
|
||||
ContentWriter writer,
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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>
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -102,8 +102,8 @@ public class PdfToImageContentTransformer extends AbstractContentTransformer2
|
||||
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
|
||||
int width=(int)page.getBBox().getWidth();
|
||||
int height=(int)page.getBBox().getHeight();
|
||||
|
Reference in New Issue
Block a user