/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This 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 2.1 of
* the License, or (at your option) any later version.
*
* This software 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 this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.celements.rendering;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.velocity.VelocityContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xwiki.context.Execution;
import org.xwiki.context.ExecutionContext;
import org.xwiki.model.reference.DocumentReference;
import com.celements.pagetype.IPageTypeConfig;
import com.celements.pagetype.PageTypeReference;
import com.celements.pagetype.service.IPageTypeResolverRole;
import com.celements.pagetype.service.IPageTypeRole;
import com.celements.web.service.IWebUtilsService;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.api.Document;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.render.XWikiRenderingEngine;
import com.xpn.xwiki.web.Utils;
public class RenderCommand {
private static Logger LOGGER = LoggerFactory.getLogger(RenderCommand.class);
private PageTypeReference defaultPageTypeRef = null;
private XWikiRenderingEngine renderingEngine;
IPageTypeRole injectedPageTypeService;
IPageTypeResolverRole injectedPageTypeResolver;
private volatile static XWikiRenderingEngine defaultRenderingEngine;
/**
* @Deprecated since 2.18.0 instead use new RenderCommand()
*/
@Deprecated
public RenderCommand(XWikiContext context) {
}
public RenderCommand() {
}
private XWikiContext getContext() {
return (XWikiContext) getExecutionContext().getProperty("xwikicontext");
}
private ExecutionContext getExecutionContext() {
return Utils.getComponent(Execution.class).getContext();
}
/**
* @deprecated since 2.21.0 instead use setDefaultPageTypeReference
*/
@Deprecated
public void setDefaultPageType(String defaultPageType) {
this.defaultPageTypeRef = getPageTypeService().getPageTypeRefByConfigName(defaultPageType);
}
public void setDefaultPageTypeReference(PageTypeReference defaultPageTypeRef) {
this.defaultPageTypeRef = defaultPageTypeRef;
}
public String renderCelementsCell(DocumentReference elemDocRef) throws XWikiException {
XWikiDocument cellDoc = getTemplateDoc(elemDocRef);
return renderCelementsDocument(cellDoc, "view");
}
/**
* renderCelementsCell
*
* @param elementFullName
* @return
* @throws XWikiException
* @Deprecated since 2.17.0 instead use renderCelementsCell(DocumentReference)
*/
@Deprecated
public String renderCelementsCell(String elementFullName) throws XWikiException {
XWikiDocument cellDoc = getTemplateDoc(getWebUtilsService().resolveDocumentReference(
elementFullName));
return renderCelementsDocument(cellDoc, "view");
}
public String renderCelementsDocument(DocumentReference elemDocRef, String renderMode)
throws XWikiException {
return renderCelementsDocument(elemDocRef, getContext().getLanguage(), renderMode);
}
public String renderCelementsDocumentPreserveVelocityContext(DocumentReference elementDocRef,
String lang, String renderMode) throws XWikiException {
VelocityContext preservedVcontext = (VelocityContext) getExecutionContext().getProperty(
"velocityContext");
VelocityContext vContext = (VelocityContext) preservedVcontext.clone();
getContext().put("vcontext", vContext);
getExecutionContext().setProperty("velocityContext", vContext);
try {
return renderCelementsDocument(elementDocRef, lang, renderMode);
} finally {
getContext().put("vcontext", preservedVcontext);
getExecutionContext().setProperty("velocityContext", preservedVcontext);
}
}
public String renderCelementsDocument(DocumentReference elemDocRef, String lang,
String renderMode) throws XWikiException {
XWikiDocument cellDoc = getContext().getWiki().getDocument(elemDocRef, getContext());
return renderCelementsDocument(cellDoc, lang, renderMode);
}
public String renderCelementsDocument(XWikiDocument cellDoc, String renderMode)
throws XWikiException {
return renderCelementsDocument(cellDoc, getContext().getLanguage(), renderMode);
}
public String renderCelementsDocument(XWikiDocument cellDoc, String lang, String renderMode)
throws XWikiException {
LOGGER.debug("renderCelementsDocument: cellDoc [" + cellDoc.getDocumentReference() + "] lang ["
+ lang + "] renderMode [" + renderMode + "].");
String cellDocFN = getWebUtilsService().getRefDefaultSerializer().serialize(
cellDoc.getDocumentReference());
if ((getContext() != null) && (getContext().get("vcontext") != null)
&& getContext().getWiki().getRightService().hasAccessLevel(renderMode,
getContext().getUser(), cellDocFN, getContext())) {
VelocityContext vcontext = (VelocityContext) getContext().get("vcontext");
vcontext.put("celldoc", cellDoc.newDocument(getContext()));
PageTypeReference cellTypeRef = getPageTypeResolver().getPageTypeRefForDocWithDefault(cellDoc,
defaultPageTypeRef);
IPageTypeConfig cellType = null;
if (cellTypeRef != null) {
cellType = getPageTypeService().getPageTypeConfigForPageTypeRef(cellTypeRef);
}
return renderTemplatePath(getRenderTemplatePath(cellType, cellDocFN, renderMode), lang);
} else {
if ((getContext() == null) || (getContext().get("vcontext") == null)) {
LOGGER.error("Failed to renderCelementsDocument '{}', because velocity context "
+ " or context is null.", cellDoc.getDocumentReference());
}
return "";
}
}
public String renderTemplatePath(String renderTemplatePath, String lang) throws XWikiException {
return renderTemplatePath(renderTemplatePath, lang, null);
}
public String renderTemplatePath(String renderTemplatePath, String lang, String defLang)
throws XWikiException {
String templateContent;
XWikiDocument templateDoc = getContext().getDoc();
if (renderTemplatePath.startsWith(":")) {
templateContent = getWebUtilsService().getTranslatedDiscTemplateContent(renderTemplatePath,
lang, defLang);
} else {
DocumentReference renderTemplateDocRef = getWebUtilsService().resolveDocumentReference(
renderTemplatePath);
templateDoc = getTemplateDoc(renderTemplateDocRef);
templateContent = getTranslatedContent(templateDoc, lang);
}
if (!StringUtils.isEmpty(templateContent)) {
if (LOGGER.isDebugEnabled()) {
VelocityContext vcontext = (VelocityContext) getContext().get("vcontext");
Document cellDoc = (Document) vcontext.get("celldoc");
LOGGER.debug("renderTemplatePath: cellDoc before [" + cellDoc + "].");
}
LOGGER.trace("renderTemplatePath: template content for lang [" + lang
+ "] and context.language [" + getContext().getLanguage() + "] is [" + templateContent
+ "]");
String renderedContent = getRenderingEngine().renderText(templateContent, templateDoc,
getContext().getDoc(), getContext());
LOGGER.trace("renderTemplatePath: rendered content for lang [" + lang
+ "] and context.language [" + getContext().getLanguage() + "] is [" + renderedContent
+ "]");
if (LOGGER.isDebugEnabled()) {
VelocityContext vcontext = (VelocityContext) getContext().get("vcontext");
Document cellDoc = (Document) vcontext.get("celldoc");
LOGGER.debug("renderTemplatePath: cellDoc after [" + cellDoc + "].");
}
return renderedContent;
} else {
LOGGER.info("renderTemplatePath: skip rendering, because empty Template ["
+ renderTemplatePath + "].");
}
return "";
}
public String renderDocument(DocumentReference docRef) {
return renderDocument(docRef, getContext().getLanguage());
}
public String renderDocument(DocumentReference docRef, DocumentReference includeDocRef) {
return renderDocument(docRef, includeDocRef, getContext().getLanguage());
}
public String renderDocument(DocumentReference docRef, String lang) {
LOGGER.debug("renderDocument for lang [" + lang + "] and docref [" + docRef + "].");
try {
XWikiDocument xwikidoc = getContext().getWiki().getDocument(docRef, getContext());
return renderDocument(xwikidoc, null, lang);
} catch (XWikiException exp) {
LOGGER.error("Failed to get translated document for [" + docRef + "] in [" + lang + "].",
exp);
}
return "";
}
public String renderDocument(DocumentReference docRef, DocumentReference includeDocRef,
String lang) {
LOGGER.debug("renderDocument for lang [" + lang + "] and docref [" + docRef
+ "] and includeDocRef [" + includeDocRef + "].");
try {
XWikiDocument contentdoc = getContext().getWiki().getDocument(docRef, getContext());
XWikiDocument includeDoc = getContext().getWiki().getDocument(includeDocRef, getContext());
return renderDocument(contentdoc, includeDoc, lang);
} catch (XWikiException exp) {
LOGGER.error("Failed to get translated document for [" + docRef + "] or includeDoc ["
+ includeDocRef + "].", exp);
}
return "";
}
public String renderDocument(XWikiDocument document) throws XWikiException {
return renderDocument(document, null, document.getLanguage());
}
/**
* renderDocument renders the given document content for the requested language. The
* includingdoc will be $doc in the velocity context during rendering.
*/
public String renderDocument(XWikiDocument document, XWikiDocument includingdoc, String lang)
throws XWikiException {
LOGGER.debug("renderDocument for lang [" + lang + "] and doc ["
+ document.getDocumentReference() + "].");
String translatedContent = getTranslatedContent(document, lang);
LOGGER.trace("translated content for lang [" + lang + "] and context.language ["
+ getContext().getLanguage() + "] is [" + translatedContent + "]");
if (includingdoc == null) {
includingdoc = getContext().getDoc();
}
String renderedContent = getRenderingEngine().renderText(translatedContent, document,
includingdoc, getContext());
LOGGER.trace("rendered content for lang [" + lang + "] and context.language ["
+ getContext().getLanguage() + "] is [" + renderedContent + "]");
return renderedContent;
}
XWikiRenderingEngine getRenderingEngine() throws XWikiException {
if (this.renderingEngine == null) {
this.renderingEngine = getDefaultRenderingEngine(getContext());
}
return this.renderingEngine;
}
synchronized static XWikiRenderingEngine getDefaultRenderingEngine(XWikiContext context)
throws XWikiException {
if (defaultRenderingEngine == null) {
defaultRenderingEngine = initRenderingEngine(Arrays.asList("velocity", "groovy"), context);
}
return defaultRenderingEngine;
}
static XWikiRenderingEngine initRenderingEngine(List<String> rendererNames, XWikiContext context)
throws XWikiException {
return new DefaultCelementsRenderingEngine(rendererNames, context);
}
public XWikiRenderingEngine initRenderingEngine(List<String> rendererNames)
throws XWikiException {
return RenderCommand.initRenderingEngine(rendererNames, getContext());
}
public void setRenderingEngine(XWikiRenderingEngine renderingEngine) {
this.renderingEngine = renderingEngine;
}
String getTranslatedContent(XWikiDocument templateDoc, String lang) throws XWikiException {
LOGGER.debug("getTranslatedContent for lang [" + lang + "] and templateDoc ["
+ templateDoc.getDocumentReference() + "].");
String translatedContent = templateDoc.getTranslatedContent(lang, getContext());
if (!getRenderingEngine().getRendererNames().contains("xwiki")) {
return translatedContent.replaceAll("\\{pre\\}|\\{/pre\\}", "");
} else {
return translatedContent;
}
}
XWikiDocument getTemplateDoc(DocumentReference templateDocRef) throws XWikiException {
return getContext().getWiki().getDocument(templateDocRef, getContext());
}
String getTemplatePathOnDisk(String renderTemplatePath) {
return getTemplatePathOnDisk(renderTemplatePath, null);
}
String getTemplatePathOnDisk(String renderTemplatePath, String lang) {
String templateOnDiskPath = getWebUtilsService().getTemplatePathOnDisk(renderTemplatePath,
lang);
if (templateOnDiskPath.startsWith(":")) {
templateOnDiskPath = renderTemplatePath.replaceAll("^:", "/templates/celTemplates/") + ".vm";
}
return templateOnDiskPath;
}
String getRenderTemplatePath(IPageTypeConfig cellType, String cellDocFN, String renderMode)
throws XWikiException {
LOGGER.trace("getRenderTemplatePath: for cellDoc [" + cellDocFN + "] with cellType ["
+ (cellType != null ? cellType.getName() : "null") + "] and renderMode [" + renderMode
+ "].");
if (cellType != null) {
String renderTemplateFullName = cellType.getRenderTemplateForRenderMode(renderMode);
if ((renderTemplateFullName != null) && !"".equals(renderTemplateFullName)) {
LOGGER.debug("getRenderTemplatePath for [" + cellDocFN + "] with cellType ["
+ cellType.getName() + "] and renderTemplate [" + renderTemplateFullName + "].");
return renderTemplateFullName;
}
LOGGER.debug("getRenderTemplatePath for [" + cellDocFN + "] with cellType ["
+ cellType.getName() + "] using content of cellDoc [" + cellDocFN + "].");
}
return cellDocFN;
}
private IWebUtilsService getWebUtilsService() {
return Utils.getComponent(IWebUtilsService.class);
}
IPageTypeResolverRole getPageTypeResolver() {
if (injectedPageTypeResolver != null) {
return injectedPageTypeResolver;
}
return Utils.getComponent(IPageTypeResolverRole.class);
}
IPageTypeRole getPageTypeService() {
if (injectedPageTypeService != null) {
return injectedPageTypeService;
}
return Utils.getComponent(IPageTypeRole.class);
}
}