From ebb756825eb5ba04de584b7a5b209cc565691efd Mon Sep 17 00:00:00 2001 From: Dave Ward Date: Wed, 30 May 2012 08:27:10 +0000 Subject: [PATCH] Merged V4.0-BUG-FIX to HEAD 37121: ALF-12796: Ensure that only visible nodes are shown via Category search in Repository view when libraryRoot is changed from company home. 37124: ALF-14220: Parallel reviews now takes into account maximum percentage of approval rate possible when deciding to add new task 37128: Fixes: ALF-14322. Translation update from Gloria 37135: Fix for ALF-13993 It fails to find documents whose tag is longer than 255 characters - TAGS are truncated as QNAMES - default to 255. - TAGS longer then 255 characters can be created. - TAGS equal in the first 255 characters can not be created (as they would be treated as duplicates by search) 37181: Merged V3.4-BUG-FIX to V4.0-BUG-FIX Merge HEAD to V3.4-BUG-FIX 33880: ALF-12777 / ALF-14259: MMT should not install AMPs which override pre-existing files in the war file, unless -force is provided. The MMT is moving toward more of a validation phase (checks things, calculate changes) then an execution phase (makes the changes). 37192: Merged V3.4-BUG-FIX to V4.0-BUG-FIX 37081: ALF-13054 Rule action "Transform and copy image" fails if transformation cannot be performed by transformer.ImageMagick - (Problem 3 only) - TransformerDebug is now issued from ContentService.isTransformable(...) and ImageTransformActionExecuter.doTransform(...) 37088: ALF-10217: Updated parse-args.lib.js to support sites having two parent nodes. 37143: Fixes: ALF-14322: Translation update from Gloria. 37145: ALF-14303 Alfresco crashes when viewing doclib / previewing - PDF with CMap Adding temporary workaround: Modified fail over transformers for PDF to PNG to be PDFRenderer, ImageMagick (new) and the PDFBox. If Ghostscript is installed on the server, ImageMagick will be able to perform the transformation. If not installed, it fails with an unsupported transformation and fails over to PDFBox as it does today and will encounter this issue if the supplied PDF. If this issues takes place, install Ghostscript. 37190: Merged PATCHES/V3.4.6 to V3.4-BUG-FIX 37189: ALF-13404: Performance: 'Content I'm Editing' dashlet is slow to render when there is lots of data/sites - Additional query improvement by Pavel 37191: ALF-13379: Fix IsImmutableProperty to react to locks again and stop unit test from confusing a lock with a checkout 37193: Merged V4.0 to V4.0-BUG-FIX 37070: ALF-14310: alfresco-enterprise-webeditor-4.0.2.zip fails with HTTP Status 500 - Due to more incomplete dependency updates 37146: (RECORD ONLY) ALF-13745: Merged V3.4-BUG-FIX (3.4.10) to V4.0 (4.0.2) 37145: ALF-14303 Alfresco crashes when viewing doclib / previewing - PDF with CMap Adding temporary workaround: Modified fail over transformers for PDF to PNG to be PDFRenderer, ImageMagick (new) and the PDFBox. If Ghostscript is installed on the server, ImageMagick will be able to perform the transformation. If not installed, it fails with an unsupported transformation and fails over to PDFBox as it does today and will encounter this issue if the supplied PDF. If this issues takes place, install Ghostscript. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@37196 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/action-services-context.xml | 3 + config/alfresco/content-services-context.xml | 11 +- .../mapping/AbstractVersioningProperty.java | 9 +- .../cmis/mapping/CMISPropertyServiceTest.java | 6 +- .../cmis/mapping/IsImmutableProperty.java | 2 +- .../renditions/CMISRenditionServiceTest.java | 7 +- .../ImageTransformActionExecuter.java | 100 +++++++++++------- .../executer/TransformActionExecuter.java | 8 +- .../repo/content/ContentServiceImpl.java | 17 ++- .../FailoverPdfToImageContentTransformer.java | 35 ++++++ ...ctImageMagickContentTransformerWorker.java | 10 +- .../org/alfresco/repo/jscript/ScriptNode.java | 7 +- .../repo/template/BaseContentNode.java | 7 +- .../cmr/repository/ContentService.java | 21 +--- 14 files changed, 168 insertions(+), 75 deletions(-) create mode 100644 source/java/org/alfresco/repo/content/transform/FailoverPdfToImageContentTransformer.java diff --git a/config/alfresco/action-services-context.xml b/config/alfresco/action-services-context.xml index 8e72b96293..eb985bbc28 100644 --- a/config/alfresco/action-services-context.xml +++ b/config/alfresco/action-services-context.xml @@ -422,6 +422,9 @@ + + + diff --git a/config/alfresco/content-services-context.xml b/config/alfresco/content-services-context.xml index c30e87e247..9da13521b0 100644 --- a/config/alfresco/content-services-context.xml +++ b/config/alfresco/content-services-context.xml @@ -328,6 +328,14 @@ class="org.alfresco.repo.content.transform.PdfBoxPdfToImageContentTransformer" parent="unregisteredBaseContentTransformer" /> + + + + + + + diff --git a/source/java/org/alfresco/cmis/mapping/AbstractVersioningProperty.java b/source/java/org/alfresco/cmis/mapping/AbstractVersioningProperty.java index e5d9b9a1b5..69a5bec3b2 100644 --- a/source/java/org/alfresco/cmis/mapping/AbstractVersioningProperty.java +++ b/source/java/org/alfresco/cmis/mapping/AbstractVersioningProperty.java @@ -69,10 +69,13 @@ public abstract class AbstractVersioningProperty extends AbstractProperty return getServiceRegistry().getCheckOutCheckInService().isWorkingCopy(nodeRef); } + public boolean isImmutable(NodeRef nodeRef) + { + return getServiceRegistry().getLockService().getLockType(nodeRef) == LockType.READ_ONLY_LOCK; + } + public boolean hasWorkingCopy(NodeRef nodeRef) { - final ServiceRegistry serviceRegistry = getServiceRegistry(); - return serviceRegistry.getLockService().getLockType(nodeRef) == LockType.READ_ONLY_LOCK - && serviceRegistry.getCheckOutCheckInService().getWorkingCopy(nodeRef) != null; + return isImmutable(nodeRef) && getServiceRegistry().getCheckOutCheckInService().getWorkingCopy(nodeRef) != null; } } diff --git a/source/java/org/alfresco/cmis/mapping/CMISPropertyServiceTest.java b/source/java/org/alfresco/cmis/mapping/CMISPropertyServiceTest.java index f1d1a874ff..c7311c8a44 100644 --- a/source/java/org/alfresco/cmis/mapping/CMISPropertyServiceTest.java +++ b/source/java/org/alfresco/cmis/mapping/CMISPropertyServiceTest.java @@ -191,13 +191,13 @@ public class CMISPropertyServiceTest extends BaseCMISTest properties = cmisService.getProperties(content); assertEquals(properties.get(CMISDictionaryModel.PROP_IS_IMMUTABLE), true); - assertEquals(properties.get(CMISDictionaryModel.PROP_IS_LATEST_VERSION), false); + assertEquals(properties.get(CMISDictionaryModel.PROP_IS_LATEST_VERSION), true); assertEquals(properties.get(CMISDictionaryModel.PROP_IS_MAJOR_VERSION), false); assertEquals(properties.get(CMISDictionaryModel.PROP_IS_LATEST_MAJOR_VERSION), false); assertNotNull(properties.get(CMISDictionaryModel.PROP_VERSION_LABEL)); assertEquals(properties.get(CMISDictionaryModel.PROP_VERSION_SERIES_ID), content.toString()); - assertEquals(properties.get(CMISDictionaryModel.PROP_IS_VERSION_SERIES_CHECKED_OUT), true); - assertEquals(properties.get(CMISDictionaryModel.PROP_VERSION_SERIES_CHECKED_OUT_BY), authenticationComponent.getCurrentUserName()); + assertEquals(properties.get(CMISDictionaryModel.PROP_IS_VERSION_SERIES_CHECKED_OUT), false); + assertEquals(properties.get(CMISDictionaryModel.PROP_VERSION_SERIES_CHECKED_OUT_BY), null); assertEquals(properties.get(CMISDictionaryModel.PROP_VERSION_SERIES_CHECKED_OUT_ID), null); assertEquals(properties.get(CMISDictionaryModel.PROP_CHECKIN_COMMENT), null); diff --git a/source/java/org/alfresco/cmis/mapping/IsImmutableProperty.java b/source/java/org/alfresco/cmis/mapping/IsImmutableProperty.java index 7bfcb9e0de..5f93e91815 100644 --- a/source/java/org/alfresco/cmis/mapping/IsImmutableProperty.java +++ b/source/java/org/alfresco/cmis/mapping/IsImmutableProperty.java @@ -53,7 +53,7 @@ public class IsImmutableProperty extends AbstractVersioningProperty } if (getVersionSeries(nodeRef).equals(nodeRef)) { - return hasWorkingCopy(nodeRef); + return isImmutable(nodeRef); } return true; } diff --git a/source/java/org/alfresco/cmis/renditions/CMISRenditionServiceTest.java b/source/java/org/alfresco/cmis/renditions/CMISRenditionServiceTest.java index 28cbc25906..bac3447020 100644 --- a/source/java/org/alfresco/cmis/renditions/CMISRenditionServiceTest.java +++ b/source/java/org/alfresco/cmis/renditions/CMISRenditionServiceTest.java @@ -34,6 +34,7 @@ import org.alfresco.repo.content.transform.magick.ImageTransformationOptions; import org.alfresco.repo.thumbnail.ThumbnailDefinition; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NoTransformerException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.TransformationOptions; @@ -211,10 +212,14 @@ public class CMISRenditionServiceTest extends BaseCMISTest TransformationOptions options = new TransformationOptions(); options.setSourceNodeRef(textDocument); - if (contentService.isTransformable(contentReader, contentWriter, options)) + try { contentService.transform(contentReader, contentWriter, options); } + catch (NoTransformerException e) + { + // ignore + } fileFolderService.delete(textDocument); diff --git a/source/java/org/alfresco/repo/action/executer/ImageTransformActionExecuter.java b/source/java/org/alfresco/repo/action/executer/ImageTransformActionExecuter.java index 9801efe104..c54ed8c11f 100644 --- a/source/java/org/alfresco/repo/action/executer/ImageTransformActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/ImageTransformActionExecuter.java @@ -18,10 +18,12 @@ */ package org.alfresco.repo.action.executer; +import java.util.ArrayList; import java.util.List; import org.alfresco.repo.action.ParameterDefinitionImpl; import org.alfresco.repo.content.transform.ContentTransformer; +import org.alfresco.repo.content.transform.TransformerDebug; import org.alfresco.repo.content.transform.magick.ImageTransformationOptions; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ParameterDefinition; @@ -38,42 +40,50 @@ import org.alfresco.service.cmr.repository.NodeRef; */ public class ImageTransformActionExecuter extends TransformActionExecuter { + private TransformerDebug transformerDebug; + /** * Action constants */ - public static final String NAME = "transform-image"; - public static final String PARAM_CONVERT_COMMAND = "convert-command"; - - private ContentTransformer imageMagickContentTransformer; - - /** - * Set the image magick content transformer - * - * @param imageMagickContentTransformer the conten transformer - */ - public void setImageMagickContentTransformer(ContentTransformer imageMagickContentTransformer) - { - this.imageMagickContentTransformer = imageMagickContentTransformer; - } - - /** - * Add parameter definitions - */ - @Override - protected void addParameterDefinitions(List paramList) - { - super.addParameterDefinitions(paramList); - paramList.add(new ParameterDefinitionImpl(PARAM_CONVERT_COMMAND, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_CONVERT_COMMAND))); - } - - /** + public static final String NAME = "transform-image"; + public static final String PARAM_CONVERT_COMMAND = "convert-command"; + + private ContentTransformer imageMagickContentTransformer; + + /** + * Set the image magick content transformer + * + * @param imageMagickContentTransformer + * the conten transformer + */ + public void setImageMagickContentTransformer(ContentTransformer imageMagickContentTransformer) + { + this.imageMagickContentTransformer = imageMagickContentTransformer; + } + + /** + * Add parameter definitions + */ + @Override + protected void addParameterDefinitions(List paramList) + { + super.addParameterDefinitions(paramList); + paramList.add(new ParameterDefinitionImpl(PARAM_CONVERT_COMMAND, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_CONVERT_COMMAND))); + } + + public void setTransformerDebug(TransformerDebug transformerDebug) + { + this.transformerDebug = transformerDebug; + } + + /** * @see org.alfresco.repo.action.executer.TransformActionExecuter#doTransform(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter) - */ - protected void doTransform( Action ruleAction, - NodeRef sourceNodeRef, ContentReader contentReader, + */ + protected void doTransform(Action ruleAction, + NodeRef sourceNodeRef, ContentReader contentReader, NodeRef destinationNodeRef, ContentWriter contentWriter) - { - // Try and transform the content + { + // Try and transform the content String convertCommand = (String) ruleAction.getParameterValue(PARAM_CONVERT_COMMAND); // create some options for the transform ImageTransformationOptions imageOptions = new ImageTransformationOptions(); @@ -81,12 +91,28 @@ public class ImageTransformActionExecuter extends TransformActionExecuter imageOptions.setSourceNodeRef(sourceNodeRef); // check if the transformer is going to work, i.e. is available - if (!this.imageMagickContentTransformer.isTransformable(contentReader.getMimetype(), contentReader.getSize(), contentWriter - .getMimetype(), imageOptions)) + String sourceMimetype = contentReader.getMimetype(); + String targetMimetype = contentWriter.getMimetype(); + long sourceSize = contentReader.getSize(); + try { - throw new NoTransformerException(contentReader.getMimetype(), contentWriter.getMimetype()); - } + transformerDebug.pushAvailable(contentReader.getContentUrl(), sourceMimetype, targetMimetype, imageOptions); + List transformers = new ArrayList(1); + if (imageMagickContentTransformer.isTransformable(sourceMimetype, contentReader.getSize(), targetMimetype, imageOptions)) + { + transformers.add(imageMagickContentTransformer); + } + transformerDebug.availableTransformers(transformers, sourceSize, "ImageTransformActionExecuter.doTransform(...)"); + if (transformers.size() == 0) + { + throw new NoTransformerException(sourceMimetype, targetMimetype); + } - this.imageMagickContentTransformer.transform(contentReader, contentWriter, imageOptions); - } + imageMagickContentTransformer.transform(contentReader, contentWriter, imageOptions); + } + finally + { + transformerDebug.popAvailable(); + } + } } diff --git a/source/java/org/alfresco/repo/action/executer/TransformActionExecuter.java b/source/java/org/alfresco/repo/action/executer/TransformActionExecuter.java index af566c308c..669580f5a8 100644 --- a/source/java/org/alfresco/repo/action/executer/TransformActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/TransformActionExecuter.java @@ -310,13 +310,7 @@ public class TransformActionExecuter extends ActionExecuterAbstractBase TransformationOptions options = new TransformationOptions( sourceNodeRef, ContentModel.PROP_NAME, destinationNodeRef, ContentModel.PROP_NAME); - // try to pre-empt the lack of a transformer - if (this.contentService.isTransformable(contentReader, contentWriter, options) == false) - { - throw new NoTransformerException(contentReader.getMimetype(), contentWriter.getMimetype()); - } - - // transform + // transform - will throw NoTransformerException if there are no transformers this.contentService.transform(contentReader, contentWriter, options); } diff --git a/source/java/org/alfresco/repo/content/ContentServiceImpl.java b/source/java/org/alfresco/repo/content/ContentServiceImpl.java index b537e192a8..fc7bf530c7 100644 --- a/source/java/org/alfresco/repo/content/ContentServiceImpl.java +++ b/source/java/org/alfresco/repo/content/ContentServiceImpl.java @@ -963,9 +963,20 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa throw new AlfrescoRuntimeException("The content writer mimetype must be set: " + writer); } - // look for a transformer - ContentTransformer transformer = transformerRegistry.getTransformer(sourceMimetype, reader.getSize(), targetMimetype, options); - return (transformer != null); + long sourceSize = reader.getSize(); + try + { + // look for a transformer + transformerDebug.pushAvailable(reader.getContentUrl(), sourceMimetype, targetMimetype, options); + List transformers = getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options); + transformerDebug.availableTransformers(transformers, sourceSize, "ContentService.isTransformable(...)"); + + return transformers.size() > 0; + } + finally + { + transformerDebug.popAvailable(); + } } /** diff --git a/source/java/org/alfresco/repo/content/transform/FailoverPdfToImageContentTransformer.java b/source/java/org/alfresco/repo/content/transform/FailoverPdfToImageContentTransformer.java new file mode 100644 index 0000000000..f39fcd10bc --- /dev/null +++ b/source/java/org/alfresco/repo/content/transform/FailoverPdfToImageContentTransformer.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.content.transform; + +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.service.cmr.repository.TransformationOptions; + +/** + * ALF-14303 Only support PDF to PNG rather than all the possible transformations from transformer.worker.ImageMagick + */ +public class FailoverPdfToImageContentTransformer extends FailoverContentTransformer +{ + @Override + public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options) + { + return MimetypeMap.MIMETYPE_PDF.equals(sourceMimetype) && + MimetypeMap.MIMETYPE_IMAGE_PNG.equals(targetMimetype); + } +} diff --git a/source/java/org/alfresco/repo/content/transform/magick/AbstractImageMagickContentTransformerWorker.java b/source/java/org/alfresco/repo/content/transform/magick/AbstractImageMagickContentTransformerWorker.java index 937aee9634..aacc15036e 100644 --- a/source/java/org/alfresco/repo/content/transform/magick/AbstractImageMagickContentTransformerWorker.java +++ b/source/java/org/alfresco/repo/content/transform/magick/AbstractImageMagickContentTransformerWorker.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -180,6 +180,14 @@ public abstract class AbstractImageMagickContentTransformerWorker extends Conten { return false; } + + // Add limited support (so lots of other transforms are not supported) for PDF to PNG. An ALF-14303 workaround. + // Will only be used as part of failover transformer.PdfToImage + if (sourceMimetype.equals(MimetypeMap.MIMETYPE_PDF) && targetMimetype.equals(MimetypeMap.MIMETYPE_IMAGE_PNG)) + { + return true; // ALF-14303 workaround + } + if (!AbstractImageMagickContentTransformerWorker.isSupported(sourceMimetype) || !AbstractImageMagickContentTransformerWorker.isSupported(targetMimetype)) { diff --git a/source/java/org/alfresco/repo/jscript/ScriptNode.java b/source/java/org/alfresco/repo/jscript/ScriptNode.java index b41b2d8b4b..547499354a 100644 --- a/source/java/org/alfresco/repo/jscript/ScriptNode.java +++ b/source/java/org/alfresco/repo/jscript/ScriptNode.java @@ -75,6 +75,7 @@ import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NoTransformerException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.Path; @@ -2472,11 +2473,15 @@ public class ScriptNode implements Scopeable, NamespacePrefixResolverProvider TransformationOptions options = new TransformationOptions(); options.setSourceNodeRef(sourceNodeRef); - if (contentService.isTransformable(reader, writer, options)) + try { contentService.transform(reader, writer, options); transformedNode = newInstance(nodeRef, services, scope); } + catch (NoTransformerException e) + { + // ignore + } return transformedNode; } }; diff --git a/source/java/org/alfresco/repo/template/BaseContentNode.java b/source/java/org/alfresco/repo/template/BaseContentNode.java index 7d714b1228..909d4a55f6 100644 --- a/source/java/org/alfresco/repo/template/BaseContentNode.java +++ b/source/java/org/alfresco/repo/template/BaseContentNode.java @@ -37,6 +37,7 @@ import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.FileTypeImageSize; +import org.alfresco.service.cmr.repository.NoTransformerException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.cmr.repository.TemplateImageResolver; @@ -610,7 +611,7 @@ public abstract class BaseContentNode implements TemplateContent options.setSourceNodeRef(nodeRef); // try and transform the content - if (contentService.isTransformable(reader, writer, options)) + try { contentService.transform(reader, writer, options); @@ -627,6 +628,10 @@ public abstract class BaseContentNode implements TemplateContent } } } + catch (NoTransformerException e) + { + // ignore + } } return result; } diff --git a/source/java/org/alfresco/service/cmr/repository/ContentService.java b/source/java/org/alfresco/service/cmr/repository/ContentService.java index 4dba4f7fca..14063621c9 100644 --- a/source/java/org/alfresco/service/cmr/repository/ContentService.java +++ b/source/java/org/alfresco/service/cmr/repository/ContentService.java @@ -300,22 +300,7 @@ public interface ContentService public ContentTransformer getImageTransformer(); /** - * Returns whether a transformer exists that can read the content from - * the reader and write the content back out to the writer. - *

- * Since no transformation options are specified, only the source and target - * mimetypes will be considered when making this decision. - *

- * The mimetypes used for the transformation must be set both on - * the {@link ContentAccessor#getMimetype() reader} and on the - * {@link ContentAccessor#getMimetype() writer}. - * - * @param reader the source content location and mimetype - * @param writer the target content location and mimetype - * - * @return true if a transformer exists, false otherwise - * - * @see org.alfresco.service.cmr.repository.ContentService.isTransformable(ContentReader, ContentWriter, TransformationOptions) + * @deprecated use {@link #isTransformable(String, String, long, String, TransformationOptions). */ @Auditable(parameters = {"reader", "writer"}) public boolean isTransformable(ContentReader reader, ContentWriter writer); @@ -325,6 +310,10 @@ public interface ContentService * the reader and write the content back out to the writer with the * provided tranformation options. *

+ * If you are about to call {@link #transform(ContentReader, ContentWriter, TransformationOptions)} + * it is best NOT to call this method first as it must perform the same steps and will throw + * NoTransformerException if there are no transformers.

+ * * The mimetypes used for the transformation must be set both on * the {@link ContentAccessor#getMimetype() reader} and on the * {@link ContentAccessor#getMimetype() writer}.