diff --git a/source/java/org/alfresco/repo/rendition/executer/BaseTemplateRenderingEngine.java b/source/java/org/alfresco/repo/rendition/executer/BaseTemplateRenderingEngine.java new file mode 100644 index 0000000000..45124ebaf2 --- /dev/null +++ b/source/java/org/alfresco/repo/rendition/executer/BaseTemplateRenderingEngine.java @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.rendition.executer; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.Collection; + +import org.alfresco.repo.action.ParameterDefinitionImpl; +import org.alfresco.service.cmr.action.ParameterDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.rendition.RenditionServiceException; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.repository.TemplateService; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * This abstract class forms a basis for all rendering engines that are built around + * the Template Service. + * @author Brian Remmington + * @since 3.3 + */ +public abstract class BaseTemplateRenderingEngine extends AbstractRenderingEngine +{ + private static final Log log = LogFactory.getLog(BaseTemplateRenderingEngine.class); + + public static final String NAME = "xsltRenderingEngine"; + public static final String PARAM_MODEL = "model"; + public static final String PARAM_TEMPLATE = "template_string"; + public static final String PARAM_TEMPLATE_NODE = "template_node"; + public static final String PARAM_TEMPLATE_PATH = "template_path"; + + private TemplateService templateService; + private SearchService searchService; + + /* + * @see org.alfresco.repo.rendition.executer.AbstractRenderingEngine#render(org + * .alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.rendition.RenditionDefinition, + * org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ChildAssociationRef) + */ + @Override + protected void render(RenderingContext context) + { + NodeRef templateNode = getTemplateNode(context); + Writer writer = null; + try + { + Object model = buildModel(context); + ContentWriter contentWriter = context.makeContentWriter(); + writer = new OutputStreamWriter(contentWriter.getContentOutputStream()); + processTemplate(context, templateNode, model, writer); + } + catch (RuntimeException ex) + { + throw ex; + } + catch (Exception ex) + { + log.warn("Unexpected error while rendering through XSLT rendering engine.", ex); + } + finally + { + if (writer != null) + { + try + { + writer.flush(); + writer.close(); + } + catch (IOException ex) + { + log.warn("Failed to correctly close content writer.", ex); + } + } + } + } + + private void processTemplate(RenderingContext context, NodeRef templateNode, Object model, Writer out) + { + String templateType = getTemplateType(); + String template = context.getCheckedParam(PARAM_TEMPLATE, String.class); + if (template != null) + { + templateService.processTemplateString(templateType, (String)template, model, out); + } + else if (templateNode != null) + { + templateService.processTemplate(templateType, templateNode.toString(), model, out); + } + else + { + throwTemplateParamsNotFoundException(); + } + } + + + private void throwTemplateParamsNotFoundException() + { + StringBuilder msg = new StringBuilder("This action requires that either the "); + msg.append(PARAM_TEMPLATE); + msg.append(" parameter or the "); + msg.append(PARAM_TEMPLATE_NODE); + msg.append(" parameter be specified. "); + throw new RenditionServiceException(msg.toString()); + } + + protected NodeRef getTemplateNode(RenderingContext context) + { + NodeRef node = context.getCheckedParam(PARAM_TEMPLATE_NODE, NodeRef.class); + if (node == null) + { + String path = context.getCheckedParam(PARAM_TEMPLATE_PATH, String.class); + if (path != null && path.length() > 0) + { + StoreRef storeRef = context.getDestinationNode().getStoreRef(); + ResultSet result = searchService.query(storeRef, SearchService.LANGUAGE_XPATH, path); + if (result.length() != 1) + { + throw new RenditionServiceException("Could not find template node for path: " + path); + } + node = result.getNodeRef(0); + } + } + return node; + } + + /** + * Create the model that will be passed to the template service for rendering + * with the appropriate template. + * @param context The context of the rendering request + * @return The model that is to be passed to the template service + */ + protected abstract Object buildModel(RenderingContext context); + + /** + * Get the type of template that is to be used. This identifies the name of the template + * processor that should be used, such as "freemarker" or "xslt". + * @return + */ + protected abstract String getTemplateType(); + + /* + * @seeorg.alfresco.repo.rendition.executer.AbstractRenderingEngine# getParameterDefinitions() + */ + @Override + protected Collection getParameterDefinitions() + { + Collection paramList = super.getParameterDefinitions(); + ParameterDefinitionImpl modelParamDef = new ParameterDefinitionImpl(PARAM_MODEL, DataTypeDefinition.ANY, false, + getParamDisplayLabel(PARAM_MODEL)); + ParameterDefinitionImpl templateParamDef = new ParameterDefinitionImpl(// + PARAM_TEMPLATE, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_TEMPLATE)); + ParameterDefinitionImpl templateNodeParamDef = new ParameterDefinitionImpl(PARAM_TEMPLATE_NODE, + DataTypeDefinition.NODE_REF, false, getParamDisplayLabel(PARAM_TEMPLATE_NODE)); + ParameterDefinitionImpl templatePathParamDef = new ParameterDefinitionImpl(PARAM_TEMPLATE_PATH, + DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_TEMPLATE_PATH)); + paramList.add(modelParamDef); + paramList.add(templateParamDef); + paramList.add(templateNodeParamDef); + paramList.add(templatePathParamDef); + return paramList; + } + + /** + * @param templateService + * the templateService to set + */ + public void setTemplateService(TemplateService templateService) + { + this.templateService = templateService; + } + + /** + * @param searchService + * the searchService to set + */ + public void setSearchService(SearchService searchService) + { + this.searchService = searchService; + } + + public TemplateService getTemplateService() + { + return templateService; + } + + public SearchService getSearchService() + { + return searchService; + } +}