mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
JavaScript API enhancements - Document and Image transformation services
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3465 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -66,6 +66,9 @@
|
|||||||
<property name="policyComponent">
|
<property name="policyComponent">
|
||||||
<ref bean="policyComponent" />
|
<ref bean="policyComponent" />
|
||||||
</property>
|
</property>
|
||||||
|
<property name="imageMagickContentTransformer">
|
||||||
|
<ref bean="transformer.ImageMagick" />
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="mimetypeConfigService" class="org.alfresco.config.xml.XMLConfigService" init-method="init">
|
<bean id="mimetypeConfigService" class="org.alfresco.config.xml.XMLConfigService" init-method="init">
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<mime-type>application/pdf</mime-type>
|
<mime-type>application/pdf</mime-type>
|
||||||
<file-extension>pdf</file-extension>
|
<file-extension>pdf</file-extension>
|
||||||
<export-filters>
|
<export-filters>
|
||||||
<entry><family>Presentation</family><string>impress_pdf_Export</string></entry>
|
<entry><family>Presentation</family><string>impress_pdf_Export</string></entry>
|
||||||
<entry><family>Spreadsheet</family><string>calc_pdf_Export</string></entry>
|
<entry><family>Spreadsheet</family><string>calc_pdf_Export</string></entry>
|
||||||
<entry><family>Text</family><string>writer_pdf_Export</string></entry>
|
<entry><family>Text</family><string>writer_pdf_Export</string></entry>
|
||||||
</export-filters>
|
</export-filters>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<mime-type>text/html</mime-type>
|
<mime-type>text/html</mime-type>
|
||||||
<file-extension>html</file-extension>
|
<file-extension>html</file-extension>
|
||||||
<export-filters>
|
<export-filters>
|
||||||
<entry><family>Presentation</family><string>impress_html_Export</string></entry>
|
<entry><family>Presentation</family><string>impress_html_Export</string></entry>
|
||||||
<entry><family>Spreadsheet</family><string>HTML (StarCalc)</string></entry>
|
<entry><family>Spreadsheet</family><string>HTML (StarCalc)</string></entry>
|
||||||
<entry><family>Text</family><string>HTML (StarWriter)</string></entry>
|
<entry><family>Text</family><string>HTML (StarWriter)</string></entry>
|
||||||
</export-filters>
|
</export-filters>
|
||||||
|
@@ -405,6 +405,7 @@
|
|||||||
org.alfresco.service.cmr.repository.ContentService.getWriter=ACL_NODE.0.sys:base.WriteContent
|
org.alfresco.service.cmr.repository.ContentService.getWriter=ACL_NODE.0.sys:base.WriteContent
|
||||||
org.alfresco.service.cmr.repository.ContentService.isTransformable=ACL_ALLOW
|
org.alfresco.service.cmr.repository.ContentService.isTransformable=ACL_ALLOW
|
||||||
org.alfresco.service.cmr.repository.ContentService.getTransformer=ACL_ALLOW
|
org.alfresco.service.cmr.repository.ContentService.getTransformer=ACL_ALLOW
|
||||||
|
org.alfresco.service.cmr.repository.ContentService.getImageTransformer=ACL_ALLOW
|
||||||
org.alfresco.service.cmr.repository.ContentService.transform=ACL_ALLOW
|
org.alfresco.service.cmr.repository.ContentService.transform=ACL_ALLOW
|
||||||
org.alfresco.service.cmr.repository.ContentService.getTempWriter=ACL_ALLOW
|
org.alfresco.service.cmr.repository.ContentService.getTempWriter=ACL_ALLOW
|
||||||
</value>
|
</value>
|
||||||
|
@@ -169,7 +169,7 @@ public class TransformActionExecuter extends ActionExecuterAbstractBase
|
|||||||
|
|
||||||
// Calculate the destination name
|
// Calculate the destination name
|
||||||
String originalName = (String)nodeService.getProperty(actionedUponNodeRef, ContentModel.PROP_NAME);
|
String originalName = (String)nodeService.getProperty(actionedUponNodeRef, ContentModel.PROP_NAME);
|
||||||
String newName = transformName(originalName, mimeType);
|
String newName = transformName(this.mimetypeService, originalName, mimeType);
|
||||||
|
|
||||||
// Since we are overwriting we need to figure out whether the destination node exists
|
// Since we are overwriting we need to figure out whether the destination node exists
|
||||||
NodeRef copyNodeRef = null;
|
NodeRef copyNodeRef = null;
|
||||||
@@ -225,7 +225,7 @@ public class TransformActionExecuter extends ActionExecuterAbstractBase
|
|||||||
String originalTitle = (String)nodeService.getProperty(actionedUponNodeRef, ContentModel.PROP_TITLE);
|
String originalTitle = (String)nodeService.getProperty(actionedUponNodeRef, ContentModel.PROP_TITLE);
|
||||||
if (originalTitle != null && originalTitle.length() > 0)
|
if (originalTitle != null && originalTitle.length() > 0)
|
||||||
{
|
{
|
||||||
String newTitle = transformName(originalTitle, mimeType);
|
String newTitle = transformName(this.mimetypeService, originalTitle, mimeType);
|
||||||
nodeService.setProperty(copyNodeRef, ContentModel.PROP_TITLE, newTitle);
|
nodeService.setProperty(copyNodeRef, ContentModel.PROP_TITLE, newTitle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,11 +267,11 @@ public class TransformActionExecuter extends ActionExecuterAbstractBase
|
|||||||
* Transform name from original extension to new extension
|
* Transform name from original extension to new extension
|
||||||
*
|
*
|
||||||
* @param original
|
* @param original
|
||||||
* @param originalMimetype
|
|
||||||
* @param newMimetype
|
* @param newMimetype
|
||||||
* @return
|
*
|
||||||
|
* @return name with new extension as appropriate for the mimetype
|
||||||
*/
|
*/
|
||||||
private String transformName(String original, String newMimetype)
|
public static String transformName(MimetypeService mimetypeService, String original, String newMimetype)
|
||||||
{
|
{
|
||||||
// get the current extension
|
// get the current extension
|
||||||
int dotIndex = original.lastIndexOf('.');
|
int dotIndex = original.lastIndexOf('.');
|
||||||
|
@@ -28,6 +28,7 @@ import org.alfresco.repo.content.ContentServicePolicies.OnContentUpdatePolicy;
|
|||||||
import org.alfresco.repo.content.filestore.FileContentStore;
|
import org.alfresco.repo.content.filestore.FileContentStore;
|
||||||
import org.alfresco.repo.content.transform.ContentTransformer;
|
import org.alfresco.repo.content.transform.ContentTransformer;
|
||||||
import org.alfresco.repo.content.transform.ContentTransformerRegistry;
|
import org.alfresco.repo.content.transform.ContentTransformerRegistry;
|
||||||
|
import org.alfresco.repo.content.transform.magick.ImageMagickContentTransformer;
|
||||||
import org.alfresco.repo.policy.ClassPolicyDelegate;
|
import org.alfresco.repo.policy.ClassPolicyDelegate;
|
||||||
import org.alfresco.repo.policy.JavaBehaviour;
|
import org.alfresco.repo.policy.JavaBehaviour;
|
||||||
import org.alfresco.repo.policy.PolicyComponent;
|
import org.alfresco.repo.policy.PolicyComponent;
|
||||||
@@ -72,6 +73,7 @@ public class RoutingContentService implements ContentService
|
|||||||
private ContentStore store;
|
private ContentStore store;
|
||||||
/** the store for all temporarily created content */
|
/** the store for all temporarily created content */
|
||||||
private ContentStore tempStore;
|
private ContentStore tempStore;
|
||||||
|
private ImageMagickContentTransformer imageMagickContentTransformer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The policy component
|
* The policy component
|
||||||
@@ -122,6 +124,11 @@ public class RoutingContentService implements ContentService
|
|||||||
this.policyComponent = policyComponent;
|
this.policyComponent = policyComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setImageMagickContentTransformer(ImageMagickContentTransformer imageMagickContentTransformer)
|
||||||
|
{
|
||||||
|
this.imageMagickContentTransformer = imageMagickContentTransformer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service initialise
|
* Service initialise
|
||||||
*/
|
*/
|
||||||
@@ -385,6 +392,14 @@ public class RoutingContentService implements ContentService
|
|||||||
return transformer;
|
return transformer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.service.cmr.repository.ContentService#getImageTransformer()
|
||||||
|
*/
|
||||||
|
public ContentTransformer getImageTransformer()
|
||||||
|
{
|
||||||
|
return imageMagickContentTransformer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.alfresco.repo.content.transform.ContentTransformerRegistry
|
* @see org.alfresco.repo.content.transform.ContentTransformerRegistry
|
||||||
* @see org.alfresco.repo.content.transform.ContentTransformer
|
* @see org.alfresco.repo.content.transform.ContentTransformer
|
||||||
|
@@ -30,6 +30,8 @@ import java.util.StringTokenizer;
|
|||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.action.executer.TransformActionExecuter;
|
||||||
|
import org.alfresco.repo.content.transform.magick.ImageMagickContentTransformer;
|
||||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||||
import org.alfresco.repo.version.VersionModel;
|
import org.alfresco.repo.version.VersionModel;
|
||||||
import org.alfresco.service.ServiceRegistry;
|
import org.alfresco.service.ServiceRegistry;
|
||||||
@@ -45,6 +47,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
|
|||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||||
|
import org.alfresco.service.cmr.repository.NoTransformerException;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
import org.alfresco.service.cmr.repository.TemplateImageResolver;
|
import org.alfresco.service.cmr.repository.TemplateImageResolver;
|
||||||
@@ -1420,6 +1423,196 @@ public final class Node implements Serializable, Scopeable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// Transformation and Rendering API
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform a document to a new document mimetype format. A copy of the document is made and
|
||||||
|
* the extension changed to match the new mimetype, then the transformation is applied.
|
||||||
|
*
|
||||||
|
* @param mimetype Mimetype destination for the transformation
|
||||||
|
*
|
||||||
|
* @return Node representing the newly transformed document.
|
||||||
|
*/
|
||||||
|
public Node transformDocument(String mimetype)
|
||||||
|
{
|
||||||
|
return transformDocument(mimetype, getPrimaryParentAssoc().getParentRef());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform a document to a new document mimetype format. A copy of the document is made in the
|
||||||
|
* specified destination folder and the extension changed to match the new mimetype, then then
|
||||||
|
* transformation is applied.
|
||||||
|
*
|
||||||
|
* @param mimetype Mimetype destination for the transformation
|
||||||
|
* @param destination Destination folder location
|
||||||
|
*
|
||||||
|
* @return Node representing the newly transformed document.
|
||||||
|
*/
|
||||||
|
public Node transformDocument(String mimetype, Node destination)
|
||||||
|
{
|
||||||
|
return transformDocument(mimetype, destination.getNodeRef());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node transformDocument(String mimetype, NodeRef destination)
|
||||||
|
{
|
||||||
|
// the delegate definition for transforming a document
|
||||||
|
Transformer transformer = new Transformer()
|
||||||
|
{
|
||||||
|
public Node transform(ContentService contentService, NodeRef nodeRef, ContentReader reader, ContentWriter writer)
|
||||||
|
{
|
||||||
|
Node transformedNode = null;
|
||||||
|
if (contentService.isTransformable(reader, writer))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
contentService.transform(reader, writer);
|
||||||
|
transformedNode = new Node(nodeRef, services, imageResolver, scope);
|
||||||
|
}
|
||||||
|
catch (NoTransformerException err)
|
||||||
|
{
|
||||||
|
// failed to find a useful transformer - do not return a node instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return transformedNode;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return transformNode(transformer, mimetype, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic method to transform Node content from one mimetype to another.
|
||||||
|
*
|
||||||
|
* @param transformer The Transformer delegate supplying the transformation logic
|
||||||
|
* @param mimetype Mimetype of the destination content
|
||||||
|
* @param destination Destination folder location for the resulting document
|
||||||
|
*
|
||||||
|
* @return Node representing the transformed content - or null if the transform failed
|
||||||
|
*/
|
||||||
|
private Node transformNode(Transformer transformer, String mimetype, NodeRef destination)
|
||||||
|
{
|
||||||
|
Node transformedNode = null;
|
||||||
|
|
||||||
|
// get the content reader
|
||||||
|
ContentService contentService = this.services.getContentService();
|
||||||
|
ContentReader reader = contentService.getReader(this.nodeRef, ContentModel.PROP_CONTENT);
|
||||||
|
|
||||||
|
// only perform the transformation if some content is available
|
||||||
|
if (reader != null)
|
||||||
|
{
|
||||||
|
// Copy the content node to a new node
|
||||||
|
NodeRef copyNodeRef = this.services.getCopyService().copy(
|
||||||
|
this.nodeRef,
|
||||||
|
destination,
|
||||||
|
ContentModel.ASSOC_CONTAINS,
|
||||||
|
getPrimaryParentAssoc().getQName(),
|
||||||
|
false);
|
||||||
|
|
||||||
|
// modify the name of the copy to reflect the new mimetype
|
||||||
|
this.nodeService.setProperty(
|
||||||
|
copyNodeRef,
|
||||||
|
ContentModel.PROP_NAME,
|
||||||
|
TransformActionExecuter.transformName(
|
||||||
|
this.services.getMimetypeService(), getName(), mimetype));
|
||||||
|
|
||||||
|
// get the writer and set it up
|
||||||
|
ContentWriter writer = contentService.getWriter(copyNodeRef, ContentModel.PROP_CONTENT, true);
|
||||||
|
writer.setMimetype(mimetype); // new mimetype
|
||||||
|
writer.setEncoding(reader.getEncoding()); // original encoding
|
||||||
|
|
||||||
|
// Try and transform the content using the supplied delegate
|
||||||
|
transformedNode = transformer.transform(contentService, copyNodeRef, reader, writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return transformedNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform an image to a new image format. A copy of the image document is made and
|
||||||
|
* the extension changed to match the new mimetype, then the transformation is applied.
|
||||||
|
*
|
||||||
|
* @param mimetype Mimetype destination for the transformation
|
||||||
|
*
|
||||||
|
* @return Node representing the newly transformed image.
|
||||||
|
*/
|
||||||
|
public Node transformImage(String mimetype)
|
||||||
|
{
|
||||||
|
return transformImage(mimetype, null, getPrimaryParentAssoc().getParentRef());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform an image to a new image format. A copy of the image document is made and
|
||||||
|
* the extension changed to match the new mimetype, then the transformation is applied.
|
||||||
|
*
|
||||||
|
* @param mimetype Mimetype destination for the transformation
|
||||||
|
* @param options Image convert command options
|
||||||
|
*
|
||||||
|
* @return Node representing the newly transformed image.
|
||||||
|
*/
|
||||||
|
public Node transformImage(String mimetype, String options)
|
||||||
|
{
|
||||||
|
return transformImage(mimetype, options, getPrimaryParentAssoc().getParentRef());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform an image to a new image mimetype format. A copy of the image document is made in the
|
||||||
|
* specified destination folder and the extension changed to match the new mimetype, then then
|
||||||
|
* transformation is applied.
|
||||||
|
*
|
||||||
|
* @param mimetype Mimetype destination for the transformation
|
||||||
|
* @param destination Destination folder location
|
||||||
|
*
|
||||||
|
* @return Node representing the newly transformed image.
|
||||||
|
*/
|
||||||
|
public Node transformImage(String mimetype, Node destination)
|
||||||
|
{
|
||||||
|
return transformImage(mimetype, null, destination.getNodeRef());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform an image to a new image mimetype format. A copy of the image document is made in the
|
||||||
|
* specified destination folder and the extension changed to match the new mimetype, then then
|
||||||
|
* transformation is applied.
|
||||||
|
*
|
||||||
|
* @param mimetype Mimetype destination for the transformation
|
||||||
|
* @param options Image convert command options
|
||||||
|
* @param destination Destination folder location
|
||||||
|
*
|
||||||
|
* @return Node representing the newly transformed image.
|
||||||
|
*/
|
||||||
|
public Node transformImage(String mimetype, String options, Node destination)
|
||||||
|
{
|
||||||
|
return transformImage(mimetype, options, destination.getNodeRef());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node transformImage(String mimetype, final String options, NodeRef destination)
|
||||||
|
{
|
||||||
|
// the delegate definition for transforming an image
|
||||||
|
Transformer transformer = new Transformer()
|
||||||
|
{
|
||||||
|
public Node transform(ContentService contentService, NodeRef nodeRef, ContentReader reader, ContentWriter writer)
|
||||||
|
{
|
||||||
|
Node transformedNode = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Map<String, Object> opts = new HashMap<String, Object>(1);
|
||||||
|
opts.put(ImageMagickContentTransformer.KEY_OPTIONS, options != null ? options : "");
|
||||||
|
contentService.getImageTransformer().transform(reader, writer, opts);
|
||||||
|
transformedNode = new Node(nodeRef, services, imageResolver, scope);
|
||||||
|
}
|
||||||
|
catch (NoTransformerException err)
|
||||||
|
{
|
||||||
|
// failed to find a useful transformer - do not return a node instance
|
||||||
|
}
|
||||||
|
return transformedNode;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return transformNode(transformer, mimetype, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
// Helper methods
|
// Helper methods
|
||||||
|
|
||||||
@@ -1647,4 +1840,23 @@ public final class Node implements Serializable, Scopeable
|
|||||||
private ContentData contentData;
|
private ContentData contentData;
|
||||||
private QName property;
|
private QName property;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface contract for simple anonymous classes that implement document transformations
|
||||||
|
*/
|
||||||
|
private interface Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the reader to the specified writer
|
||||||
|
*
|
||||||
|
* @param contentService ContentService
|
||||||
|
* @param noderef NodeRef of the destination for the transform
|
||||||
|
* @param reader Source reader
|
||||||
|
* @param writer Destination writer
|
||||||
|
*
|
||||||
|
* @return Node representing the transformed entity
|
||||||
|
*/
|
||||||
|
Node transform(ContentService contentService, NodeRef noderef, ContentReader reader, ContentWriter writer);
|
||||||
|
}
|
||||||
}
|
}
|
@@ -126,6 +126,14 @@ public interface ContentService
|
|||||||
@Auditable(parameters = {"sourceMimetype", "targetMimetype"})
|
@Auditable(parameters = {"sourceMimetype", "targetMimetype"})
|
||||||
public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype);
|
public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the transformer that is capable of transforming image content.
|
||||||
|
*
|
||||||
|
* @return Returns a transformer that can be used, or null if one was not available
|
||||||
|
*/
|
||||||
|
@Auditable
|
||||||
|
public ContentTransformer getImageTransformer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether a transformer exists that can read the content from
|
* Returns whether a transformer exists that can read the content from
|
||||||
* the reader and write the content back out to the writer.
|
* the reader and write the content back out to the writer.
|
||||||
|
Reference in New Issue
Block a user