swf transformer (installed swf tool requied), minor refactor of thumbnail service, thumbnailRegistry created (smallImage and webpreview thumbnail types added), start of thumbnail JS API (extensions to ScriptNode) and POST URL to create thumbnails

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@9259 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2008-05-23 21:19:50 +00:00
parent 6910c48c62
commit bb3c776130
23 changed files with 1598 additions and 336 deletions

View File

@@ -42,6 +42,7 @@
<import resource="classpath:alfresco/projects-context.xml"/>
<import resource="classpath:alfresco/blog-context.xml"/>
<import resource="classpath:alfresco/thumbnail-service-context.xml"/>
<import resource="classpath:alfresco/swf-transform-context.xml"/>
<import resource="classpath:alfresco/site-services-context.xml"/>
<import resource="classpath*:alfresco/patch/*-context.xml" />
<import resource="classpath*:alfresco/domain/*-context.xml" />

View File

@@ -281,11 +281,6 @@
class="org.alfresco.repo.content.transform.MailContentTransformer"
parent="baseContentTransformer" />
<!--
<bean id="transformer.JMagick" class="org.alfresco.repo.content.transform.magick.JMagickContentTransformer" init-method="init" />
</bean>
-->
<bean id="transformer.ImageMagick"
class="org.alfresco.repo.content.transform.magick.ImageMagickContentTransformer"
parent="baseContentTransformer"

View File

@@ -112,5 +112,19 @@
<ref bean="fileFolderService" />
</property>
</bean>
<!-- Repository helper class -->
<bean id="repositoryHelper" class="org.alfresco.repo.model.Repository">
<property name="transactionHelper" ref="retryingTransactionHelper" />
<property name="namespaceService" ref="namespaceService" />
<property name="nodeService" ref="nodeService" />
<property name="personService" ref="personService" />
<property name="fileFolderService" ref="fileFolderService" />
<property name="searchService" ref="searchService" />
<property name="tenantDeployerService" ref="tenantAdminService" />
<property name="avmService" ref="AVMService" />
<property name="companyHomeStore"><value>${spaces.store}</value></property>
<property name="companyHomePath"><value>/${spaces.company_home.childname}</value></property>
</bean>
</beans>

View File

@@ -898,6 +898,16 @@
</properties>
</aspect>
<!-- Aspect containing swf transformation options -->
<aspect name="cm:swfTransformationOptions">
<properties>
<property name="cm:flashVerison">
<title>Flash Version</title>
<type>d:text</type>
</property>
</properties>
</aspect>
</aspects>
</model>

View File

@@ -81,6 +81,9 @@
<property name="serviceRegistry">
<ref bean="ServiceRegistry"/>
</property>
<property name="repositoryHelper">
<ref bean="repositoryHelper"/>
</property>
<property name="storeUrl">
<value>${spaces.store}</value>
</property>

View File

@@ -0,0 +1,34 @@
<?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.Pdf2swf" class="org.alfresco.repo.content.transform.swf.PDFToSWFContentTransformer" parent="baseContentTransformer">
<property name="explicitTransformations">
<list>
<bean class="org.alfresco.repo.content.transform.ExplictTransformationDetails" >
<property name="sourceMimetype"><value>application/pdf</value></property>
<property name="targetMimetype"><value>application/x-shockwave-flash</value></property>
</bean>
</list>
</property>
</bean>
<bean id="transformer.complex.OpenOffice.Pdf2swf"
class="org.alfresco.repo.content.transform.ComplexContentTransformer"
parent="baseContentTransformer" >
<property name="transformers">
<list>
<ref bean="transformer.OpenOffice" />
<ref bean="transformer.Pdf2swf" />
</list>
</property>
<property name="intermediateMimetypes">
<list>
<value>application/pdf</value>
</list>
</property>
</bean>
</beans>

View File

@@ -41,6 +41,45 @@
<property name="nodeService" ref="NodeService"/>
<property name="contentService" ref="ContentService"/>
<property name="mimetypeMap" ref="mimetypeService"/>
</bean>
<property name="thumbnailRegistry" ref="thumbnailRegistry" />
</bean>
<!-- Thumbnail Register -->
<bean id="thumbnailRegistry" class="org.alfresco.repo.thumbnail.ThumbnailRegistry">
<property name="thumbnailDetails">
<list>
<!-- Small image thumbnail options -->
<bean class="org.alfresco.repo.thumbnail.ThumbnailDetails">
<property name="name" value="small" />
<property name="mimetype" value="image/jpeg"/>
<property name="transformationOptions">
<bean class="org.alfresco.repo.content.transform.magick.ImageTransformationOptions">
<property name="resizeOptions">
<bean class="org.alfresco.repo.content.transform.magick.ImageResizeOptions">
<property name="width" value="64"/>
<property name="height" value="64"/>
<property name="maintainAspectRatio" value="true"/>
<property name="resizeToThumbnail" value="true" />
</bean>
</property>
</bean>
</property>
</bean>
<!-- Web Preview thumbnail options -->
<bean class="org.alfresco.repo.thumbnail.ThumbnailDetails">
<property name="name" value="webpreview" />
<property name="mimetype" value="application/x-shockwave-flash"/>
<property name="transformationOptions">
<bean class="org.alfresco.repo.content.transform.swf.SWFTransformationOptions">
<property name="flashVersion" value="9"/>
</bean>
</property>
</bean>
</list>
</property>
</bean>
</beans>

View File

@@ -0,0 +1,252 @@
/*
* 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.swf;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.MimetypeMap;
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.alfresco.util.exec.RuntimeExec;
import org.alfresco.util.exec.RuntimeExec.ExecutionResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* PDF to SWF content transformer
*
* @author Roy Wetherall
*/
public class PDFToSWFContentTransformer extends AbstractContentTransformer2
{
/** Logger */
private static final Log logger = LogFactory.getLog(PDFToSWFContentTransformer.class);
/** Used to indicate whether the transformaer in available or not */
private boolean available = false;
/** Check and transform command */
private RuntimeExec checkCommand;
private RuntimeExec transformCommand;
/** Default flash version to convert to */
private static final String DEFAULT_FLASH_VERSION = "9";
/** Check command string */
private static final String PDF2SWF_CHECK = "pdf2swf -V";
/** Transformation command string */
private static final String PDF2SWF_COMMAND = "pdf2swf -t ${flashVersion} \"${source}\" -o \"${target}\"";
private static final String VAR_SOURCE = "source";
private static final String VAR_TARGET = "target";
private static final String VAR_FLASH_VERSION = "flashVersion";
/**
* Get the check command for the PDF2SWF tool
*
* @return RuntimeExec check command
*/
private RuntimeExec getCheckCommand()
{
if (this.checkCommand == null)
{
this.checkCommand = createCommand(PDF2SWF_CHECK);
}
return this.checkCommand;
}
/**
* Get the transform command for the PDF2SWF tool
*
* @return RuntimeExec transform command
*/
private RuntimeExec getTransformCommand()
{
if (this.transformCommand == null)
{
this.transformCommand = createCommand(PDF2SWF_COMMAND);
}
return this.transformCommand;
}
/**
* Helper to create a runtime exec object for a given command string
*
* @param commandString command string
* @return RuntimeExec runtime exec command
*/
private RuntimeExec createCommand(String commandString)
{
// Create command
RuntimeExec result = new RuntimeExec();
// Set the command string
Map<String, String> commandsByOS = new HashMap<String, String>(1);
commandsByOS.put(".*", commandString);
result.setCommandMap(commandsByOS);
// Set the error code
result.setErrorCodes("1");
return result;
}
/**
* @see org.alfresco.repo.content.transform.AbstractContentTransformer2#register()
*/
@Override
public void register()
{
ExecutionResult result = getCheckCommand().execute();
// check the return code
this.available = result.getSuccess();
if (this.available == false)
{
logger.error("Failed to start SWF2PDF transformer: \n" + result);
}
else
{
// no check - just assume it is available
this.available = true;
}
// call the base class to make sure that it gets registered
super.register();
}
/**
* @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
protected void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception
{
// get mimetypes
String sourceMimetype = getMimetype(reader);
String targetMimetype = getMimetype(writer);
// get the extensions to use
String sourceExtension = getMimetypeService().getExtension(sourceMimetype);
String targetExtension = getMimetypeService().getExtension(targetMimetype);
if (sourceExtension == null || targetExtension == null)
{
throw new AlfrescoRuntimeException("Unknown extensions for mimetypes: \n" +
" source mimetype: " + sourceMimetype + "\n" +
" source extension: " + sourceExtension + "\n" +
" target mimetype: " + targetMimetype + "\n" +
" target extension: " + targetExtension);
}
// create required temp files
File sourceFile = TempFileProvider.createTempFile(
getClass().getSimpleName() + "_source_",
"." + sourceExtension);
File targetFile = TempFileProvider.createTempFile(
getClass().getSimpleName() + "_target_",
"." + targetExtension);
String flashVersion = DEFAULT_FLASH_VERSION;
Map<String, String> properties = new HashMap<String, String>(5);
if (options instanceof SWFTransformationOptions)
{
SWFTransformationOptions swfOptions = (SWFTransformationOptions)options;
if (swfOptions.getFlashVersion() != null)
{
flashVersion = swfOptions.getFlashVersion();
}
}
properties.put(VAR_FLASH_VERSION, "-T " + flashVersion);
// add the source and target properties
properties.put(VAR_SOURCE, sourceFile.getAbsolutePath());
properties.put(VAR_TARGET, targetFile.getAbsolutePath());
// pull reader file into source temp file
reader.getContent(sourceFile);
// execute the transformation command
ExecutionResult result = null;
try
{
result = getTransformCommand().execute(properties);
}
catch (Throwable e)
{
throw new ContentIOException("Transformation failed during command execution: \n" + transformCommand, e);
}
// check
if (!result.getSuccess())
{
throw new ContentIOException("Transformation failed - status indicates an error: \n" + result);
}
// check that the file was created
if (!targetFile.exists())
{
throw new ContentIOException("Transformation failed - target file doesn't exist: \n" + result);
}
// copy the target file back into the repo
writer.putContent(targetFile);
// done
if (logger.isDebugEnabled())
{
logger.debug("PDF2SWF transformation completed: \n" +
" source: " + reader + "\n" +
" target: " + writer + "\n" +
" options: " + options + "\n" +
" result: \n" + result);
}
}
/**
* @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)
{
boolean result = false;
if (this.available == true)
{
if (MimetypeMap.MIMETYPE_PDF.equals(sourceMimetype) == true &&
MimetypeMap.MIMETYPE_FLASH.equals(targetMimetype) == true)
{
result = true;
}
}
return result;
}
}

View File

@@ -0,0 +1,85 @@
/*
* 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.swf;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* SFW transformation options
*
* @author Roy Wetherall
*/
public class SWFTransformationOptions extends TransformationOptions
{
private final static QName ASPECT_SWF_TRANSFORMATION_OPTIONS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "swfTransformationOptions");
private final static QName PROP_FLASH_VERSION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "flashVerison");
/** The version of the flash to convert to */
private String flashVersion = "9";
public void setFlashVersion(String flashVersion)
{
this.flashVersion = flashVersion;
}
public String getFlashVersion()
{
return flashVersion;
}
@Override
public void saveToNode(NodeRef nodeRef, NodeService nodeService)
{
super.saveToNode(nodeRef, nodeService);
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(7);
properties.put(PROP_FLASH_VERSION, this.flashVersion);
nodeService.addAspect(nodeRef, ASPECT_SWF_TRANSFORMATION_OPTIONS, properties);
}
@Override
public void populateFromNode(NodeRef nodeRef, NodeService nodeService)
{
super.populateFromNode(nodeRef, nodeService);
// Check whether the node has the image transformation options aspect
if (nodeService.hasAspect(nodeRef, ASPECT_SWF_TRANSFORMATION_OPTIONS) == true)
{
// Get the node's properties
Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);
// Set the properties
this.flashVersion = (String)properties.get(PROP_FLASH_VERSION);
}
}
}

View File

@@ -40,6 +40,9 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.executer.TransformActionExecuter;
import org.alfresco.repo.content.transform.magick.ImageTransformationOptions;
import org.alfresco.repo.search.QueryParameterDefImpl;
import org.alfresco.repo.thumbnail.ThumbnailDetails;
import org.alfresco.repo.thumbnail.ThumbnailRegistry;
import org.alfresco.repo.thumbnail.script.ScriptThumbnail;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
@@ -237,6 +240,22 @@ public class ScriptNode implements Serializable, Scopeable
return this.id;
}
/**
* @return the store type for the node
*/
public String getStoreType()
{
return this.nodeRef.getStoreRef().getProtocol();
}
/**
* @return the store id for the node
*/
public String getStoreId()
{
return this.nodeRef.getStoreRef().getIdentifier();
}
/**
* @return Returns the NodeRef this Node object represents
*/
@@ -1872,6 +1891,58 @@ public class ScriptNode implements Serializable, Scopeable
return this.services.getTemplateService().processTemplateString(null, template, model);
}
// ------------------------------------------------------------------------------
// Thumbnail Methods
/**
* Creates a thumbnail for the content property of the node.
*
* The thumbnail name correspionds to pre-set thumbnail details stored in the
* repository.
*
* @param thumbnailName the name of the thumbnail
* @return ScriptThumbnail the newly create thumbnail node
*/
public ScriptThumbnail createThumbnail(String thumbnailName)
{
// Use the thumbnail registy to get the details of the thumbail
ThumbnailRegistry registry = this.services.getThumbnailService().getThumbnailRegistry();
ThumbnailDetails details = registry.getThumbnailDetails(thumbnailName);
if (details == null)
{
// Throw exception
}
NodeRef thumbnailNodeRef = this.services.getThumbnailService().createThumbnail(
this.nodeRef,
ContentModel.PROP_CONTENT,
details.getMimetype(),
details.getTransformationOptions(),
details.getName());
// Return thumbnail
return new ScriptThumbnail(thumbnailNodeRef, this.services, this.scope);
}
public ScriptThumbnail getThumbnail(String thumbnailName)
{
ScriptThumbnail result = null;
NodeRef thumbnailNodeRef = this.services.getThumbnailService().getThumbnailByName(
this.nodeRef,
ContentModel.PROP_CONTENT,
thumbnailName);
if (thumbnailNodeRef != null)
{
result = new ScriptThumbnail(thumbnailNodeRef, this.services, this.scope);
}
return result;
}
public ScriptableHashMap<String, ScriptThumbnail> getThumbnails()
{
return null;
}
// ------------------------------------------------------------------------------
// Helper methods

View File

@@ -29,6 +29,7 @@ import java.util.LinkedHashSet;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.search.impl.lucene.LuceneQueryParser;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ContentReader;
@@ -64,6 +65,9 @@ public final class Search extends BaseScopableProcessorExtension
/** Default store reference */
private StoreRef storeRef;
/** Repository helper */
private Repository repository;
/**
* Set the default store reference
@@ -84,6 +88,16 @@ public final class Search extends BaseScopableProcessorExtension
{
this.services = services;
}
/**
* Set the repository helper
*
* @param repository the repository helper
*/
public void setRepositoryHelper(Repository repository)
{
this.repository = repository;
}
/**
* Find a single Node by the Node reference
@@ -118,6 +132,40 @@ public final class Search extends BaseScopableProcessorExtension
}
}
/**
* Helper to convert a Web Script Request URL to a Node Ref
*
* 1) Node - {store_type}/{store_id}/{node_id}
*
* Resolve to node via its Node Reference.
*
* 2) Path - {store_type}/{store_id}/{path}
*
* Resolve to node via its display path.
*
* 3) AVM Path - {store_id}/{path}
*
* Resolve to AVM node via its display path
*
* 4) QName - {store_type}/{store_id}/{child_qname_path}
*
* Resolve to node via its child qname path.
*
* @param referenceType one of node, path, avmpath or qname
* @param reference array of reference segments (as described above for each reference type)
* @return ScriptNode the script node
*/
public ScriptNode findNode(String referenceType, String[] reference)
{
ScriptNode result = null;
NodeRef nodeRef = this.repository.findNodeRef(referenceType, reference);
if (nodeRef != null)
{
result = new ScriptNode(nodeRef, this.services, getScope());
}
return result;
}
/**
* Execute a XPath search
*

View File

@@ -0,0 +1,482 @@
/*
* Copyright (C) 2005-2008 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.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.tenant.TenantDeployer;
import org.alfresco.repo.tenant.TenantDeployerService;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.AbstractLifecycleBean;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
/**
* Provision of Repository Context
*
* @author davidc
*/
public class Repository implements ApplicationContextAware, ApplicationListener, TenantDeployer
{
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
// dependencies
private RetryingTransactionHelper retryingTransactionHelper;
private NamespaceService namespaceService;
private SearchService searchService;
private NodeService nodeService;
private FileFolderService fileFolderService;
private PersonService personService;
private AVMService avmService;
private TenantDeployerService tenantDeployerService;
// company home
private StoreRef companyHomeStore;
private String companyHomePath;
private Map<String, NodeRef> companyHomeRefs;
/**
* Sets the Company Home Store
*
* @param companyHomeStore
*/
public void setCompanyHomeStore(String companyHomeStore)
{
this.companyHomeStore = new StoreRef(companyHomeStore);
}
/**
* Sets the Company Home Path
*
* @param companyHomePath
*/
public void setCompanyHomePath(String companyHomePath)
{
this.companyHomePath = companyHomePath;
}
/**
* Sets helper that provides transaction callbacks
*/
public void setTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
{
this.retryingTransactionHelper = retryingTransactionHelper;
}
/**
* Sets the namespace service
*
* @param namespaceService
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
* Sets the search service
*
* @param searchService
*/
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
/**
* Sets the node service
*
* @param nodeService
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* Sets the file folder service
*
* @param nodeService
*/
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
/**
* Sets the person service
*
* @param personService
*/
public void setPersonService(PersonService personService)
{
this.personService = personService;
}
/**
* Sets the tenant deployer service
*
* @param tenantDeployerService
*/
public void setTenantDeployerService(TenantDeployerService tenantDeployerService)
{
this.tenantDeployerService = tenantDeployerService;
}
/**
* Sets the AVM service
*
* @param avmService
*/
public void setAvmService(AVMService avmService)
{
this.avmService = avmService;
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
lifecycle.setApplicationContext(applicationContext);
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
public void onApplicationEvent(ApplicationEvent event)
{
lifecycle.onApplicationEvent(event);
}
/**
* Hooks into Spring Application Lifecycle
*/
private class ProcessorLifecycle extends AbstractLifecycleBean
{
@Override
protected void onBootstrap(ApplicationEvent event)
{
initContext();
}
@Override
protected void onShutdown(ApplicationEvent event)
{
}
}
/**
* Initialise Repository Context
*/
protected void initContext()
{
tenantDeployerService.register(this);
if (companyHomeRefs == null)
{
companyHomeRefs = new HashMap<String, NodeRef>(1);
}
getCompanyHome();
}
/**
* Gets the root home of the company home store
*
* @return root node ref
*/
public NodeRef getRootHome()
{
return nodeService.getRootNode(companyHomeStore);
}
/**
* Gets the Company Home
*
* @return company home node ref
*/
public NodeRef getCompanyHome()
{
String tenantDomain = tenantDeployerService.getCurrentUserDomain();
NodeRef companyHomeRef = companyHomeRefs.get(tenantDomain);
if (companyHomeRef == null)
{
companyHomeRef = AuthenticationUtil.runAs(new RunAsWork<NodeRef>()
{
public NodeRef doWork() throws Exception
{
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<NodeRef>()
{
public NodeRef execute() throws Exception
{
List<NodeRef> refs = searchService.selectNodes(nodeService.getRootNode(companyHomeStore), companyHomePath, null, namespaceService, false);
if (refs.size() != 1)
{
throw new IllegalStateException("Invalid company home path: " + companyHomePath + " - found: " + refs.size());
}
return refs.get(0);
}
});
}
}, AuthenticationUtil.getSystemUserName());
companyHomeRefs.put(tenantDomain, companyHomeRef);
}
return companyHomeRef;
}
/**
* Gets the currently authenticated person
*
* @return person node ref
*/
public NodeRef getPerson()
{
NodeRef person = null;
String currentUserName = AuthenticationUtil.getCurrentUserName();
if (personService.personExists(currentUserName))
{
person = personService.getPerson(currentUserName);
}
return person;
}
/**
* Gets the user home of the currently authenticated person
*
* @param person person
* @return user home of person
*/
public NodeRef getUserHome(NodeRef person)
{
return (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
}
/**
* Helper to convert a Web Script Request URL to a Node Ref
*
* 1) Node - {store_type}/{store_id}/{node_id}
*
* Resolve to node via its Node Reference.
*
* 2) Path - {store_type}/{store_id}/{path}
*
* Resolve to node via its display path.
*
* 3) AVM Path - {store_id}/{path}
*
* Resolve to AVM node via its display path
*
* 4) QName - {store_type}/{store_id}/{child_qname_path} TODO: Implement
*
* Resolve to node via its child qname path.
*
* @param referenceType one of node, path, avmpath or qname
* @return reference array of reference segments (as described above for each reference type)
*/
public NodeRef findNodeRef(String referenceType, String[] reference)
{
NodeRef nodeRef = null;
if (referenceType.equals("avmpath"))
{
if (reference.length == 0)
{
throw new AlfrescoRuntimeException("Reference " + Arrays.toString(reference) + " is not properly formed");
}
String path = reference[0] + ":/";
if (reference.length > 1)
{
Object[] pathElements = ArrayUtils.subarray(reference, 1, reference.length);
path += StringUtils.join(pathElements, "/");
}
AVMNodeDescriptor nodeDesc = avmService.lookup(-1, path);
if (nodeDesc != null)
{
nodeRef = AVMNodeConverter.ToNodeRef(-1, path);
}
}
else
{
// construct store reference
if (reference.length < 3)
{
throw new AlfrescoRuntimeException("Reference " + Arrays.toString(reference) + " is not properly formed");
}
StoreRef storeRef = new StoreRef(reference[0], reference[1]);
if (nodeService.exists(storeRef))
{
if (referenceType.equals("node"))
{
// find the node the rest of the path is relative to
NodeRef relRef = new NodeRef(storeRef, reference[2]);
if (nodeService.exists(relRef))
{
// are there any relative path elements to process?
if (reference.length == 3 || reference.length == 4)
{
// just the NodeRef can be specified
nodeRef = relRef;
}
else
{
// process optional path elements
List<String> paths = new ArrayList<String>(reference.length - 3);
for (int i=3; i<reference.length; i++)
{
paths.add(reference[i]);
}
try
{
NodeRef parentRef = nodeService.getPrimaryParent(relRef).getParentRef();
FileInfo fileInfo = fileFolderService.resolveNamePath(parentRef, paths);
nodeRef = fileInfo.getNodeRef();
}
catch (FileNotFoundException e)
{
// NOTE: return null node ref
}
}
}
}
else if (referenceType.equals("path"))
{
// NOTE: special case for avm based path
if (reference[0].equals(StoreRef.PROTOCOL_AVM))
{
String path = reference[1] + ":/";
if (reference.length > 2)
{
Object[] pathElements = ArrayUtils.subarray(reference, 2, reference.length);
path += StringUtils.join(pathElements, "/");
}
AVMNodeDescriptor nodeDesc = avmService.lookup(-1, path);
if (nodeDesc != null)
{
nodeRef = AVMNodeConverter.ToNodeRef(-1, path);
}
}
else
{
// TODO: Allow a root path to be specified - for now, hard-code to Company Home
//NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
NodeRef rootNodeRef = getCompanyHome();
if (reference.length == 3)
{
nodeRef = rootNodeRef;
}
else
{
String[] path = new String[reference.length - /*2*/3];
System.arraycopy(reference, /*2*/3, path, 0, path.length);
try
{
FileInfo fileInfo = fileFolderService.resolveNamePath(rootNodeRef, Arrays.asList(path));
nodeRef = fileInfo.getNodeRef();
}
catch (FileNotFoundException e)
{
// NOTE: return null node ref
}
}
}
}
else
{
// TODO: Implement 'qname' style
throw new AlfrescoRuntimeException("Web Script Node URL specified an invalid reference style of '" + referenceType + "'");
}
}
}
return nodeRef;
}
/* (non-Javadoc)
* @see org.alfresco.repo.tenant.TenantDeployer#onEnableTenant()
*/
public void onEnableTenant()
{
init();
}
/* (non-Javadoc)
* @see org.alfresco.repo.tenant.TenantDeployer#onDisableTenant()
*/
public void onDisableTenant()
{
destroy();
}
/* (non-Javadoc)
* @see org.alfresco.repo.tenant.TenantDeployer#init()
*/
public void init()
{
initContext();
}
/* (non-Javadoc)
* @see org.alfresco.repo.tenant.TenantDeployer#destroy()
*/
public void destroy()
{
companyHomeRefs.remove(tenantDeployerService.getCurrentUserDomain());
}
}

View File

@@ -57,6 +57,7 @@ import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.OwnableService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.view.ExporterService;
import org.alfresco.service.cmr.view.ImporterService;
@@ -424,4 +425,12 @@ public class ServiceDescriptorRegistry
{
return (MultilingualContentService) getService(MULTILINGUAL_CONTENT_SERVICE);
}
/**
* @see org.alfresco.service.ServiceRegistry#getThumbnailService()
*/
public ThumbnailService getThumbnailService()
{
return (ThumbnailService)getService(THUMBNAIL_SERVICE);
}
}

View File

@@ -138,6 +138,22 @@ public class TemplateNode extends BasePermissionsNode
return this.id;
}
/**
* @return the store type for the node
*/
public String getStoreType()
{
return this.nodeRef.getStoreRef().getProtocol();
}
/**
* @return the store id for the node
*/
public String getStoreId()
{
return this.nodeRef.getStoreRef().getIdentifier();
}
/**
* @return Returns the NodeRef this Node object represents
*/

View File

@@ -0,0 +1,134 @@
/*
* Copyright (C) 2005-2008 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.thumbnail;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* This class provides the thumbnail details to the thumbnail service.
*
* @author Roy Wetherall
*/
public class ThumbnailDetails
{
/** Name of the thumbnail */
private String name;
/** The destination mimetype */
private String mimetype;
/** Transformation options */
private TransformationOptions options;
/**
* Default constructor
*/
public ThumbnailDetails()
{
}
/**
* Constructor
*
* @param destinationMimetype
* @param options
*/
public ThumbnailDetails(String destinationMimetype, TransformationOptions options)
{
this.mimetype = destinationMimetype;
this.options = options;
}
/**
* Constructor. Specify the name of the thumbnail.
*
* @param thumbnailName the name of the thumbnail, can be null
*/
public ThumbnailDetails(String mimetype, TransformationOptions options, String thumbnailName)
{
this(mimetype, options);
this.name= thumbnailName;
}
/**
* Set the destination mimetype
*
* @param mimetype the destination minetype
*/
public void setMimetype(String mimetype)
{
this.mimetype = mimetype;
}
/**
* Get the destination mimetype
*
* @return the destination mimetype
*/
public String getMimetype()
{
return mimetype;
}
/**
* Set the transformation options
*
* @param options the transformation options
*/
public void setTransformationOptions(TransformationOptions options)
{
this.options = options;
}
/**
* Get the transformation options
*
* @return the transformation options
*/
public TransformationOptions getTransformationOptions()
{
return options;
}
/**
* Sets the name of the thumbnail
*
* @param thumbnailName the thumbnail name
*/
public void setName(String thumbnailName)
{
this.name = thumbnailName;
}
/**
* Gets the name of the thumbnail
*
* @return String the name of the thumbnail, null if non specified
*/
public String getName()
{
return name;
}
}

View File

@@ -0,0 +1,105 @@
/*
* 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.thumbnail;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.service.cmr.thumbnail.ThumbnailException;
/**
* @author Roy Wetherall
*/
public class ThumbnailRegistry
{
/** Map of thumbnail details */
private Map<String, ThumbnailDetails> thumbnailDetails = new HashMap<String, ThumbnailDetails>(10);
/**
* Add a number of thumbnail details
*
* @param thumbnailDetails list of thumbnail details
*/
public void setThumbnailDetails(List<ThumbnailDetails> thumbnailDetails)
{
for (ThumbnailDetails value : thumbnailDetails)
{
addThumbnailDetails(value);
}
}
/**
* Add a thumnail details
*
* @param thumbnailDetails thumbnail details
*/
public void addThumbnailDetails(ThumbnailDetails thumbnailDetails)
{
String thumbnailName = thumbnailDetails.getName();
if (thumbnailName == null)
{
throw new ThumbnailException("When adding a thumbnail details object make sure the name is set.");
}
this.thumbnailDetails.put(thumbnailName, thumbnailDetails);
}
/**
* Get the details of a named thumbnail
*
* @param thumbnailNam the thumbnail name
* @return ThumbnailDetails the details of the thumbnail
*/
public ThumbnailDetails getThumbnailDetails(String thumbnailName)
{
return this.thumbnailDetails.get(thumbnailName);
}
// /**
// *
// * @param node
// * @param contentProperty
// * @param thumbnailName
// * @return
// */
// public NodeRef createThumbnail(NodeRef node, QName contentProperty, String thumbnailName)
// {
// // Check to see if we have details of the thumbnail in our list
// ThumbnailDetails details = getThumbnailDetails(thumbnailName);
// if (details == null)
// {
// throw new ThumbnailException("The thumbnail name '" + thumbnailName + "' is not recognised");
// }
//
// // Create the thumbnail
// return this.thumbnailService.createThumbnail(
// node,
// contentProperty,
// details.getMimetype(),
// details.getTransformationOptions(),
// thumbnailName);
// }
}

View File

@@ -40,10 +40,9 @@ 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.alfresco.service.cmr.thumbnail.CreateOptions;
import org.alfresco.service.cmr.thumbnail.ThumbnailException;
import org.alfresco.service.cmr.thumbnail.ThumbnailParentAssociationDetails;
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
import org.alfresco.service.cmr.thumbnail.CreateOptions.ParentAssociationDetails;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
@@ -60,7 +59,6 @@ public class ThumbnailServiceImpl implements ThumbnailService
private static final String ERR_DUPLICATE_NAME = "Thumbnail could not be created because of a duplicate name";
private static final String ERR_NO_PARENT = "Thumbnail has no parent so update cannot take place.";
private static final String ERR_TOO_PARENT = "Thumbnail has more than one source content node. This is invalid so update cannot take place.";
private static final String ERR_TRANS_CLASS = "Unable to create transformation options from saved class. Update of thumbnail cannnot take place.";
/** Node service */
private NodeService nodeService;
@@ -71,6 +69,9 @@ public class ThumbnailServiceImpl implements ThumbnailService
/** Mimetype map */
private MimetypeMap mimetypeMap;
/** Thumbnail registry */
private ThumbnailRegistry thumbnailRegistry;
/**
* Set the node service
*
@@ -102,18 +103,46 @@ public class ThumbnailServiceImpl implements ThumbnailService
}
/**
* @see org.alfresco.service.cmr.thumbnail.ThumbnailService#createThumbnail(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, org.alfresco.service.cmr.thumbnail.GenerateOptions)
* Set thumbnail registry
*
* @param thumbnailRegistry thumbnail registry
*/
public NodeRef createThumbnail(NodeRef node, QName contentProperty, CreateOptions createOptions)
public void setThumbnailRegistry(ThumbnailRegistry thumbnailRegistry)
{
this.thumbnailRegistry = thumbnailRegistry;
}
/**
* @see org.alfresco.service.cmr.thumbnail.ThumbnailService#getThumbnailRegistry()
*/
public ThumbnailRegistry getThumbnailRegistry()
{
return this.thumbnailRegistry;
}
/**
* @see org.alfresco.service.cmr.thumbnail.ThumbnailService#createThumbnail(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions, java.lang.String)
*/
public NodeRef createThumbnail(NodeRef node, QName contentProperty, String mimetype, TransformationOptions transformationOptions, String thumbnailName)
{
return createThumbnail(node, contentProperty, mimetype, transformationOptions, thumbnailName, null);
}
/**
* @see org.alfresco.service.cmr.thumbnail.ThumbnailService#createThumbnail(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions, java.lang.String, org.alfresco.service.cmr.thumbnail.ThumbnailParentAssociationDetails)
*/
public NodeRef createThumbnail(NodeRef node, QName contentProperty, String mimetype, TransformationOptions transformationOptions, String thumbnailName, ThumbnailParentAssociationDetails assocDetails)
{
// Parameter check
ParameterCheck.mandatory("node", node);
ParameterCheck.mandatory("contentProperty", contentProperty);
ParameterCheck.mandatoryString( "mimetype", mimetype);
ParameterCheck.mandatory("transformationOptions", transformationOptions);
NodeRef thumbnail = null;
// Check for duplicate names
if (createOptions.getThumbnailName() != null && getThumbnailByName(node, contentProperty, createOptions.getThumbnailName()) != null)
if (thumbnailName != null && getThumbnailByName(node, contentProperty, thumbnailName) != null)
{
// We can't continue because there is already an thumnail with the given name for that content property
throw new ThumbnailException(ERR_DUPLICATE_NAME);
@@ -126,15 +155,14 @@ public class ThumbnailServiceImpl implements ThumbnailService
}
// Get the name of the thumbnail and add to properties map
String thumbnailName = createOptions.getThumbnailName();
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(2);
if (thumbnailName == null)
if (thumbnailName == null || thumbnailName.length() == 0)
{
thumbnailName = GUID.generate();
}
else
{
String thumbnailFileName = generateThumbnailFileName(thumbnailName, createOptions.getDestinationMimetype());
String thumbnailFileName = generateThumbnailFileName(thumbnailName, mimetype);
properties.put(ContentModel.PROP_NAME, thumbnailFileName);
}
@@ -142,13 +170,12 @@ public class ThumbnailServiceImpl implements ThumbnailService
properties.put(ContentModel.PROP_CONTENT_PROPERTY_NAME, contentProperty);
// Add the class name of the transformation options
if (createOptions.getTransformationOptions() != null)
if (transformationOptions != null)
{
properties.put(ContentModel.PROP_TRANSFORMATION_OPTIONS_CLASS, createOptions.getTransformationOptions().getClass().getName());
properties.put(ContentModel.PROP_TRANSFORMATION_OPTIONS_CLASS, transformationOptions.getClass().getName());
}
// See if parent association details have been specified for the thumbnail
ParentAssociationDetails assocDetails = createOptions.getParentAssociationDetails();
if (assocDetails == null)
{
// Create the thumbnail using the thumbnails child association
@@ -180,11 +207,11 @@ public class ThumbnailServiceImpl implements ThumbnailService
// Get the content reader and writer for content nodes
ContentReader reader = this.contentService.getReader(node, contentProperty);
ContentWriter writer = this.contentService.getWriter(thumbnail, ContentModel.PROP_CONTENT, true);
writer.setMimetype(createOptions.getDestinationMimetype());
writer.setMimetype(mimetype);
writer.setEncoding(reader.getEncoding());
// Catch the failure to create the thumbnail
if (this.contentService.isTransformable(reader, writer, createOptions.getTransformationOptions()) == false)
if (this.contentService.isTransformable(reader, writer, transformationOptions) == false)
{
// Throw exception indicating that the thumbnail could not be created
throw new ThumbnailException(ERR_NO_CREATE);
@@ -192,10 +219,10 @@ public class ThumbnailServiceImpl implements ThumbnailService
else
{
// Do the thumnail transformation
this.contentService.transform(reader, writer, createOptions.getTransformationOptions());
this.contentService.transform(reader, writer, transformationOptions);
// Store the transformation options on the thumbnail
createOptions.getTransformationOptions().saveToNode(thumbnail, this.nodeService);
transformationOptions.saveToNode(thumbnail, this.nodeService);
}
// Return the created thumbnail
@@ -215,36 +242,36 @@ public class ThumbnailServiceImpl implements ThumbnailService
}
/**
* @see org.alfresco.service.cmr.thumbnail.ThumbnailService#updateThumbnail(org.alfresco.service.cmr.repository.NodeRef)
* @see org.alfresco.service.cmr.thumbnail.ThumbnailService#updateThumbnail(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.TransformationOptions)
*/
public void updateThumbnail(NodeRef thumbnail)
public void updateThumbnail(NodeRef thumbnail, TransformationOptions transformationOptions)
{
// First check that we are dealing with a thumbnail
if (ContentModel.TYPE_THUMBNAIL.equals(this.nodeService.getType(thumbnail)) == true)
{
// Get the transformation options
TransformationOptions options = null;
String transformationOptionsClassName = (String)this.nodeService.getProperty(thumbnail, ContentModel.PROP_TRANSFORMATION_OPTIONS_CLASS);
if (transformationOptionsClassName == null)
{
options = new TransformationOptions();
}
else
{
// Create an options object of the type specified on the thumbnail
try
{
Class transformationClass = Class.forName(transformationOptionsClassName);
options = (TransformationOptions)transformationClass.newInstance();
}
catch (Exception exception)
{
throw new ThumbnailException(ERR_TRANS_CLASS);
}
// Populate the options from the node
options.populateFromNode(thumbnail, this.nodeService);
}
// TransformationOptions options = null;
// String transformationOptionsClassName = (String)this.nodeService.getProperty(thumbnail, ContentModel.PROP_TRANSFORMATION_OPTIONS_CLASS);
// if (transformationOptionsClassName == null)
// {
// options = new TransformationOptions();
// }
// else
// {
// // Create an options object of the type specified on the thumbnail
// try
// {
// Class transformationClass = Class.forName(transformationOptionsClassName);
// options = (TransformationOptions)transformationClass.newInstance();
// }
// catch (Exception exception)
// {
// throw new ThumbnailException(ERR_TRANS_CLASS);
// }
//
// // Populate the options from the node
// options.populateFromNode(thumbnail, this.nodeService);
// }
// Get the node that is the source of the thumbnail
NodeRef node = null;
@@ -270,13 +297,13 @@ public class ThumbnailServiceImpl implements ThumbnailService
ContentWriter writer = this.contentService.getWriter(node, ContentModel.PROP_CONTENT, true);
// Set the basic detail of the transformation options
options.setSourceNodeRef(node);
options.setSourceContentProperty(contentProperty);
options.setTargetNodeRef(thumbnail);
options.setTargetContentProperty(ContentModel.PROP_CONTENT);
transformationOptions.setSourceNodeRef(node);
transformationOptions.setSourceContentProperty(contentProperty);
transformationOptions.setTargetNodeRef(thumbnail);
transformationOptions.setTargetContentProperty(ContentModel.PROP_CONTENT);
// Catch the failure to create the thumbnail
if (this.contentService.isTransformable(reader, writer, options) == false)
if (this.contentService.isTransformable(reader, writer, transformationOptions) == false)
{
// Throw exception indicating that the thumbnail could not be created
throw new ThumbnailException(ERR_NO_CREATE);
@@ -284,7 +311,7 @@ public class ThumbnailServiceImpl implements ThumbnailService
else
{
// Do the thumnail transformation
this.contentService.transform(reader, writer, options);
this.contentService.transform(reader, writer, transformationOptions);
}
}
// TODO else should we throw an exception?

View File

@@ -41,7 +41,6 @@ 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.TransformationOptions;
import org.alfresco.service.cmr.thumbnail.CreateOptions;
import org.alfresco.service.cmr.thumbnail.ThumbnailException;
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
import org.alfresco.service.namespace.NamespaceService;
@@ -97,12 +96,12 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest
imageResizeOptions.setResizeToThumbnail(true);
ImageTransformationOptions imageTransformationOptions = new ImageTransformationOptions();
imageTransformationOptions.setResizeOptions(imageResizeOptions);
CreateOptions createOptions = new CreateOptions(
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions,
"small");
//ThumbnailDetails createOptions = new ThumbnailDetails();
NodeRef thumbnail1 = this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT, createOptions);
NodeRef thumbnail1 = this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT,
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions,
"small");
assertNotNull(thumbnail1);
checkThumbnailed(jpgOrig, "small");
checkThumbnail(thumbnail1, imageTransformationOptions);
@@ -116,11 +115,11 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest
imageResizeOptions2.setMaintainAspectRatio(false);
ImageTransformationOptions imageTransformationOptions2 = new ImageTransformationOptions();
imageTransformationOptions2.setResizeOptions(imageResizeOptions2);
CreateOptions createOptions2 = new CreateOptions(
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions2,
"small2");
NodeRef thumbnail2 = this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT, createOptions2);
//ThumbnailDetails createOptions2 = new ThumbnailDetails();
NodeRef thumbnail2 = this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT,
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions2,
"small2");
checkThumbnailed(jpgOrig, "small2");
checkThumbnail(thumbnail2, imageTransformationOptions2);
outputThumbnailTempContentLocation(thumbnail2, "jpg", "small2 - 64x64, aspect not maintained");
@@ -133,11 +132,11 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest
imageResizeOptions3.setPercentResize(true);
ImageTransformationOptions imageTransformationOptions3 = new ImageTransformationOptions();
imageTransformationOptions3.setResizeOptions(imageResizeOptions3);
CreateOptions createOptions3 = new CreateOptions(
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions3,
"half");
NodeRef thumbnail3 = this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT, createOptions3);
// ThumbnailDetails createOptions3 = new ThumbnailDetails();
NodeRef thumbnail3 = this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT,
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions3,
"half");
checkThumbnailed(jpgOrig, "half");
checkThumbnail(thumbnail3, imageTransformationOptions3);
outputThumbnailTempContentLocation(thumbnail3, "jpg", "half - 50%x50%");
@@ -151,11 +150,11 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest
imageResizeOptions4.setPercentResize(true);
ImageTransformationOptions imageTransformationOptions4 = new ImageTransformationOptions();
imageTransformationOptions4.setResizeOptions(imageResizeOptions4);
CreateOptions createOptions4 = new CreateOptions(
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions4,
"half2");
NodeRef thumbnail4 = this.thumbnailService.createThumbnail(gifOrig, ContentModel.PROP_CONTENT, createOptions4);
// ThumbnailDetails createOptions4 = new ThumbnailDetails();
NodeRef thumbnail4 = this.thumbnailService.createThumbnail(gifOrig, ContentModel.PROP_CONTENT,
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions4,
"half2");
checkThumbnailed(gifOrig, "half2");
checkThumbnail(thumbnail4, imageTransformationOptions4);
outputThumbnailTempContentLocation(thumbnail4, "jpg", "half2 - 50%x50%, from gif");
@@ -174,18 +173,21 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest
imageResizeOptions.setResizeToThumbnail(true);
ImageTransformationOptions imageTransformationOptions = new ImageTransformationOptions();
imageTransformationOptions.setResizeOptions(imageResizeOptions);
CreateOptions createOptions = new CreateOptions(
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions,
"small");
NodeRef thumbnail1 = this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT, createOptions);
//ThumbnailDetails createOptions = new ThumbnailDetails();
NodeRef thumbnail1 = this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT,
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions,
"small");
assertNotNull(thumbnail1);
checkThumbnailed(jpgOrig, "small");
checkThumbnail(thumbnail1, imageTransformationOptions);
try
{
this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT, createOptions);
this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT,
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions,
"small");
fail("A duplicate exception should have been raised");
}
catch (ThumbnailException exception)
@@ -207,15 +209,14 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest
imageResizeOptions.setHeight(64);
imageResizeOptions.setResizeToThumbnail(true);
ImageTransformationOptions imageTransformationOptions = new ImageTransformationOptions();
imageTransformationOptions.setResizeOptions(imageResizeOptions);
CreateOptions createOptions = new CreateOptions(
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions,
"small");
NodeRef thumbnail1 = this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT, createOptions);
imageTransformationOptions.setResizeOptions(imageResizeOptions);
NodeRef thumbnail1 = this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT,
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions,
"small");
// Update the thumbnail
this.thumbnailService.updateThumbnail(thumbnail1);
this.thumbnailService.updateThumbnail(thumbnail1, imageTransformationOptions);
}
}
@@ -237,12 +238,11 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest
imageResizeOptions.setHeight(64);
imageResizeOptions.setResizeToThumbnail(true);
ImageTransformationOptions imageTransformationOptions = new ImageTransformationOptions();
imageTransformationOptions.setResizeOptions(imageResizeOptions);
CreateOptions createOptions = new CreateOptions(
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions,
"small");
this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT, createOptions);
imageTransformationOptions.setResizeOptions(imageResizeOptions);
this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT,
MimetypeMap.MIMETYPE_IMAGE_JPEG,
imageTransformationOptions,
"small");
// Try and retrieve the thumbnail
NodeRef result2 = this.thumbnailService.getThumbnailByName(jpgOrig, ContentModel.PROP_CONTENT, "small");

View File

@@ -0,0 +1,49 @@
/*
* 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.thumbnail.script;
import org.alfresco.repo.jscript.ScriptNode;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.mozilla.javascript.Scriptable;
/**
* @author Roy Wetherall
*/
public class ScriptThumbnail extends ScriptNode
{
/**
* Constructor
*
* @param nodeRef
* @param services
* @param scope
*/
public ScriptThumbnail(NodeRef nodeRef, ServiceRegistry services, Scriptable scope)
{
super(nodeRef, services, scope);
}
}

View File

@@ -56,6 +56,7 @@ import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.OwnableService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.view.ExporterService;
import org.alfresco.service.cmr.view.ImporterService;
@@ -119,6 +120,7 @@ public interface ServiceRegistry
static final QName ATTRIBUTE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AttributeService");
static final QName AVM_LOCKING_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AVMLockingService");
static final QName VIRT_SERVER_REGISTRY = QName.createQName(NamespaceService.ALFRESCO_URI, "VirtServerRegistry");
static final QName THUMBNAIL_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ThumbnailService");
/**
* Get the list of services provided by the Repository
@@ -384,4 +386,11 @@ public interface ServiceRegistry
*/
@NotAuditable
EditionService getEditionService();
/**
* Get the Thumbnail Service
* @return
*/
@NotAuditable
ThumbnailService getThumbnailService();
}

View File

@@ -1,231 +0,0 @@
/*
* Copyright (C) 2005-2008 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.service.cmr.thumbnail;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck;
/**
* This class provides the thumbnail create options to the thumbnail service.
*
* @author Roy Wetherall
*/
public class CreateOptions
{
/** Parent association details */
private ParentAssociationDetails assocDetails;
/** Name of the thumbnail */
private String thumbnailName;
/** The destination mimetype */
private String destinationMimetype;
/** Transformation options */
private TransformationOptions options;
/**
* Default constructor.
*/
public CreateOptions(String destinationMimetype, TransformationOptions options)
{
this.destinationMimetype = destinationMimetype;
this.options = options;
}
/**
* Constructor. Specify the name of the thumbnail.
*
* @param thumbnailName the name of the thumbnail, can be null
*/
public CreateOptions(String destinationMimetype, TransformationOptions options, String thumbnailName)
{
this(destinationMimetype, options);
this.thumbnailName= thumbnailName;
}
/**
* Constructor. Specify the parent association details of the thumbnail.
*
* @param thumnailName the name of the thumbnail, can be null
* @param parent the parent node reference
* @param assocType the child association type
* @param asscoName the child association name
*/
public CreateOptions(String destinationMimetype, TransformationOptions options, String thumbnailName,
NodeRef parent, QName assocType, QName assocName)
{
this(destinationMimetype, options, thumbnailName);
this.assocDetails = new ParentAssociationDetails(parent, assocType, assocName);
}
/**
* Set the destination mimetype
*
* @param destinationMimetype the destination minetype
*/
public void setDestinationMimetype(String destinationMimetype)
{
this.destinationMimetype = destinationMimetype;
}
/**
* Get the destination mimetype
*
* @return the destination mimetype
*/
public String getDestinationMimetype()
{
return destinationMimetype;
}
/**
* Set the transformation options
*
* @param options the transformation options
*/
public void setTransformationOptions(TransformationOptions options)
{
this.options = options;
}
/**
* Get the transformation options
*
* @return the transformation options
*/
public TransformationOptions getTransformationOptions()
{
return options;
}
/**
* Sets the name of the thumbnail
*
* @param thumbnailName the thumbnail name
*/
public void setThumbnailName(String thumbnailName)
{
this.thumbnailName = thumbnailName;
}
/**
* Gets the name of the thumbnail
*
* @return String the name of the thumbnail, null if non specified
*/
public String getThumbnailName()
{
return thumbnailName;
}
/**
* Sets the details of the thumnails parent association
*
* @param assocDetails the parent association details
*/
public void setParentAssociationDetails(ParentAssociationDetails assocDetails)
{
this.assocDetails = assocDetails;
}
/**
* Get the parent association details
*
* @return ParentAssociationDetails the parent association details
*/
public ParentAssociationDetails getParentAssociationDetails()
{
return this.assocDetails;
}
/**
* Encapsulates the details of a thumbnails parent association
*/
public class ParentAssociationDetails
{
/** The parent node reference */
private NodeRef parent;
/** The child association type */
private QName assocType;
/** The child association name */
private QName assocName;
/**
* Constructor. All parameters must be specified.
*
* @param parent the parent node reference
* @param assocType the child association type
* @param assocName the child association name
*/
public ParentAssociationDetails(NodeRef parent, QName assocType, QName assocName)
{
// Make sure all the details of the parent are provided
ParameterCheck.mandatory("parent", parent);
ParameterCheck.mandatory("assocType", assocType);
ParameterCheck.mandatory("assocName", assocName);
// Set the values
this.parent = parent;
this.assocType = assocType;
this.assocName = assocName;
}
/**
* Get the parent node reference
*
* @return NodeRef the parent node reference
*/
public NodeRef getParent()
{
return parent;
}
/**
* Get the child association type
*
* @return QName the child association type
*/
public QName getAssociationType()
{
return assocType;
}
/**
* Get the child association name
*
* @return QName the child association name
*/
public QName getAssociationName()
{
return assocName;
}
}
}

View File

@@ -0,0 +1,97 @@
/*
* 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.service.cmr.thumbnail;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck;
/**
* Encapsulates the details of a thumbnails parent association
*
* @author Roy Wetherall
*/
public class ThumbnailParentAssociationDetails
{
/** The parent node reference */
private NodeRef parent;
/** The child association type */
private QName assocType;
/** The child association name */
private QName assocName;
/**
* Constructor. All parameters must be specified.
*
* @param parent the parent node reference
* @param assocType the child association type
* @param assocName the child association name
*/
public ThumbnailParentAssociationDetails(NodeRef parent, QName assocType, QName assocName)
{
// Make sure all the details of the parent are provided
ParameterCheck.mandatory("parent", parent);
ParameterCheck.mandatory("assocType", assocType);
ParameterCheck.mandatory("assocName", assocName);
// Set the values
this.parent = parent;
this.assocType = assocType;
this.assocName = assocName;
}
/**
* Get the parent node reference
*
* @return NodeRef the parent node reference
*/
public NodeRef getParent()
{
return parent;
}
/**
* Get the child association type
*
* @return QName the child association type
*/
public QName getAssociationType()
{
return assocType;
}
/**
* Get the child association name
*
* @return QName the child association name
*/
public QName getAssociationName()
{
return assocName;
}
}

View File

@@ -26,6 +26,7 @@ package org.alfresco.service.cmr.thumbnail;
import java.util.List;
import org.alfresco.repo.thumbnail.ThumbnailRegistry;
import org.alfresco.service.Auditable;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.TransformationOptions;
@@ -38,11 +39,16 @@ import org.alfresco.service.namespace.QName;
*/
public interface ThumbnailService
{
ThumbnailRegistry getThumbnailRegistry();
/**
* Creates a new thumbnail for the given node and content property.
*
* The passed create options specify the details of the thumbnail, including the
* mimetpye, size and location of the thumbnail.
* The mimetype and transformation options are used to determine the content transformer that
* will be best suited to create the thumbnail.
*
* The thumbnail name is optional, but is usally set to provide an easy way to identify a perticular
* 'type' of thumbnail.
*
* Once created the source node will have the 'tn:thumbnailed' aspect applied and an
* association to the thumbnail node (or type 'tn:thumbnail') will be created.
@@ -50,28 +56,35 @@ public interface ThumbnailService
* The returned node reference is to the 'tn:thumbnail' content node that contains
* the thumnail content in the standard 'cm:content' property.
*
* @see org.alfresco.service.cmr.thumnail.GenerateOptions
* @see org.alfresco.service.cmr.thumnail.ThumbnailDetails
*
* @param node the source content node
* @param contentProperty the content property
* @param createOptions the create options
* @return NodeRef node reference to the newly created thumbnail
* @param node the source content node
* @param contentProperty the content property
* @param mimetype the thumbnail mimetype
* @param transformationOptions the thumbnail transformation options
* @param name the name of the thumbnail (optional, pass null for unnamed thumbnail)
* @return NodeRef node reference to the newly created thumbnail
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"node", "contentProperty", "createOptions"})
NodeRef createThumbnail(NodeRef node, QName contentProperty, CreateOptions createOptions);
@Auditable(key = Auditable.Key.ARG_0, parameters = {"node", "contentProperty", "mimetype", "transformationOptions", "name"})
NodeRef createThumbnail(NodeRef node, QName contentProperty, String mimetype, TransformationOptions transformationOptions, String name);
NodeRef createThumbnail(NodeRef node, QName contentProperty, String mimetype, TransformationOptions transformationOptions, String name, ThumbnailParentAssociationDetails assocDetails);
/**
* Updates the content of a thumbnail.
*
* The original creation options are used when updating the thumbnail. The content of
* the associated thumbnailed node is used to update.
* The origional thumbnail content is updated from the source content using the transformation
* options provided. The mimetype and name of the thumbnail remain unchanged.
*
* To change the name or mimertpe of an updated thumbnail it should be deleted and recreated.
*
* An error is raised if the original content no longer exisits.
*
* @param thumbnail the thumbnail node
* @param transformationOptions the transformation options used when updating the thumbnail
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"thumbnail"})
void updateThumbnail(NodeRef thumbnail);
@Auditable(key = Auditable.Key.ARG_0, parameters = {"thumbnail", "transformationOptions"})
void updateThumbnail(NodeRef thumbnail, TransformationOptions transformationOptions);
/**
* Get's the thumbnail for a given content property with a given name.