true
then the rendition will be re-rendered any time any
* property changes occur on the source node. This parameter defaults to
* false
.
*/
public static final String PARAM_UPDATE_RENDITIONS_ON_ANY_PROPERTY_CHANGE = "update-renditions-on-any-property-change";
/**
* This optional {@link String} parameter specifies what user permissions
* are used when creating a rendition. By default the system user is used.
*/
public static final String PARAM_RUN_AS = "runAs";
// mime-type is not a common parameter on all Rendering Actions, but it is
// common to many and is used in some common handling code in this class.
/**
* This optional {@link String} parameter specifies the mime type of the
* rendition content. This defaults to the mime type of the source node
* content.
*/
public static final String PARAM_MIME_TYPE = "mime-type";
/**
* This optional {@link String} paramter specifies the encoding used to
* create the rendition content. The derfault encoding is UTF-8.
*/
public static final String PARAM_ENCODING = "encoding";
/**
* Default {@link NodeLocator} simply returns the source node.
*/
private final static NodeLocator defaultNodeLocator = new SelfNodeLocator();
/*
* Injected beans
*/
private RenditionLocationResolver renditionLocationResolver;
protected NodeService nodeService;
private RenditionService renditionService;
private BehaviourFilter behaviourFilter;
private final NodeLocator temporaryParentNodeLocator;
private final QName temporaryRenditionLinkType;
/**
* Injects the nodeService bean.
*
* @param nodeService
* the nodeService.
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* Injects the renditionService bean.
*
* @param renditionService
*/
public void setRenditionService(RenditionService renditionService)
{
this.renditionService = renditionService;
}
/**
* @param behaviourFilter policy behaviour filter
*/
public void setBehaviourFilter(BehaviourFilter behaviourFilter)
{
this.behaviourFilter = behaviourFilter;
}
public void setRenditionLocationResolver(RenditionLocationResolver renditionLocationResolver)
{
this.renditionLocationResolver = renditionLocationResolver;
}
public AbstractRenderingEngine(NodeLocator temporaryParentNodeLocator, QName temporaryRenditionLinkType)
{
this.publicAction = false;
this.temporaryParentNodeLocator = temporaryParentNodeLocator != null ? temporaryParentNodeLocator
: defaultNodeLocator;
this.temporaryRenditionLinkType = temporaryRenditionLinkType != null ? temporaryRenditionLinkType
: RenditionModel.ASSOC_RENDITION;
}
public AbstractRenderingEngine()
{
this(null, null);
}
/**
* Sets the default rendition-node type.
*
* @param type
*/
public void setDefaultRenditionNodeType(String type)
{
QName qname;
try
{
qname = QName.createQName(type);
}
catch (NamespaceException nx)
{
if (logger.isErrorEnabled())
{
logger.error("Error when setting default rendition node type: ", nx);
}
throw nx;
}
if (logger.isInfoEnabled())
{
logger.info("Using default rendition node type: " + qname);
}
this.defaultRenditionNodeType = qname;
}
/**
* This method returns the type of the default rendition node type.
*
* @return the QName representing the type of the default rendition node
* type.
*/
protected QName getDefaultRenditionNodeType()
{
return defaultRenditionNodeType;
}
protected String getTargetMimeType(RenderingContext context)
{
return context.getParamWithDefault(PARAM_MIME_TYPE, DEFAULT_MIMETYPE);
}
protected String getTargetEncoding(RenderingContext context)
{
return context.getParamWithDefault(PARAM_ENCODING, DEFAULT_ENCODING);
}
/**
* Sets the default rendition content property.
*
* @param prop
*/
public void setDefaultRenditionContentProp(String prop)
{
QName qname;
try
{
qname = QName.createQName(prop);
}
catch (NamespaceException nx)
{
if (logger.isErrorEnabled())
{
logger.error("Error when setting default rendition content property: ", nx);
}
throw nx;
}
if (logger.isInfoEnabled())
{
logger.info("Using default rendition content property: " + qname);
}
this.defaultRenditionContentProp = qname;
}
/**
* This method returns the QName of the property that defines the location
* of the rendition content. An example would be cm:content.
*
* @return the QName the property defining the location of the rendition
* content.
*/
protected QName getDefaultRenditionContentProp()
{
return defaultRenditionContentProp;
}
/**
* Set the content service
*
* @param contentService the content service
*/
public void setContentService(ContentService contentService)
{
this.contentService = contentService;
}
public void setMimetypeMap(MimetypeMap mimetypeMap)
{
this.mimetypeMap = mimetypeMap;
}
public void setActionTrackingService(ActionTrackingService actionTrackingService)
{
this.actionTrackingService = actionTrackingService;
}
@Override
protected ActionDefinition createActionDefinition(String definitionName)
{
return new RenderingEngineDefinitionImpl(definitionName);
}
@Override
protected void executeImpl(final Action action, final NodeRef sourceNode)
{
executeImpl( (RenditionDefinition)action, sourceNode );
}
protected void executeImpl(final RenditionDefinition renditionDef, final NodeRef sourceNode)
{
// Don't render the nodes without content.
// MNT-10178
if (!nodeService.exists(sourceNode))
{
if (logger.isDebugEnabled() == true)
{
logger.debug("Rendition has not been created, because the node no longer exists. (sourceNode=" + sourceNode + ")");
}
notifyCallbackOfException(renditionDef, new RenditionCancelledException("Rendition was cancelled, because the node no longer exists."));
return;
}
else if (nodeService.getProperty(sourceNode, ContentModel.PROP_CONTENT) == null)
{
if (logger.isDebugEnabled() == true)
{
logger.debug("Rendition has not been created, because the node has no content to render. (sourceNode=" + sourceNode + ")");
}
notifyCallbackOfException(renditionDef, new RenditionCancelledException("Rendition was cancelled, because the node has no content to render."));
return;
}
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Rendering node ").append(sourceNode).append(" with rendition definition ").append(
renditionDef.getRenditionName());
msg.append("\n").append(" parameters:").append("\n");
if (renditionDef.getParameterValues().isEmpty() == false)
{
for (String paramKey : renditionDef.getParameterValues().keySet())
{
msg.append(" ").append(paramKey).append("=").append(renditionDef.getParameterValue(paramKey)).append("\n");
}
}
else
{
msg.append(" [None]");
}
logger.debug(msg.toString());
}
Serializable runAsParam = renditionDef.getParameterValue(AbstractRenderingEngine.PARAM_RUN_AS);
String runAsName = runAsParam == null ? DEFAULT_RUN_AS_NAME : (String) runAsParam;
// Renditions should all be created by system by default.
// When renditions are created by a user and are to be created under a
// node
// other than the source node, it is possible that the user will not
// have
// permissions to create content under that node.
// For that reason, we execute all rendition actions as system
// by default.
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWorknull
if the parameter value is null
*
* @param paramName the name of the parameter being checked.
* @param clazz the expected {@link Class} of the parameter value.
* @param definition the {@link RenditionDefinition} containing the
* parameters.
* @return the parameter value or null
.
*/
@SuppressWarnings("unchecked")
public static defaultValue
and throws a
* {@link RenditionServiceException} if it isn't. Returns
* defaultValue
if the parameter value is null
*
* @param rn:rendition
aspects on the rendition node. It applies the
* correct rendition aspect based on the rendition node's location and removes any out-of-date rendition
* aspect.
*/
private void manageRenditionAspects(NodeRef sourceNode, ChildAssociationRef renditionParentAssoc)
{
NodeRef renditionNode = renditionParentAssoc.getChildRef();
NodeRef primaryParent = renditionParentAssoc.getParentRef();
// If the rendition is located directly underneath its own source node
if (primaryParent.equals(sourceNode))
{
// It should be a 'hidden' rendition.
// Ensure we do not update the 'modifier' due to rendition addition
behaviourFilter.disableBehaviour(renditionNode, ContentModel.ASPECT_AUDITABLE);
try
{
nodeService.addAspect(renditionNode, RenditionModel.ASPECT_HIDDEN_RENDITION, null);
nodeService.removeAspect(renditionNode, RenditionModel.ASPECT_VISIBLE_RENDITION);
}
finally
{
behaviourFilter.enableBehaviour(renditionNode, ContentModel.ASPECT_AUDITABLE);
}
// We remove the other aspect to cover the potential case where a
// rendition
// has been updated in a different location.
} else
{
// Renditions stored underneath any node other than their source are
// 'visible'.
behaviourFilter.disableBehaviour(renditionNode, ContentModel.ASPECT_AUDITABLE);
try
{
nodeService.addAspect(renditionNode, RenditionModel.ASPECT_VISIBLE_RENDITION, null);
nodeService.removeAspect(renditionNode, RenditionModel.ASPECT_HIDDEN_RENDITION);
}
finally
{
behaviourFilter.enableBehaviour(renditionNode, ContentModel.ASPECT_AUDITABLE);
}
}
}
/**
* This method calculates the name for a rendition node. The following approaches are attempted in
* the order given below.
* cm:name
value, then that is used.ExecutionSummary
for the given renderingContext
* from the {@link ActionTrackingService}.
*
* Note that multiple summaries of the same action instance are not currently supported.
* @param renderingContext the rendering context
* @return the found summary or null
*/
protected ExecutionSummary getExecutionSummary(RenderingContext renderingContext)
{
List