Package org.jahia.services.render

Source Code of org.jahia.services.render.RenderService$RenderServiceBeanPostProcessor

/**
* This file is part of Jahia, next-generation open source CMS:
* Jahia's next-generation, open source CMS stems from a widely acknowledged vision
* of enterprise application convergence - web, search, document, social and portal -
* unified by the simplicity of web content management.
*
* For more information, please visit http://www.jahia.com.
*
* Copyright (C) 2002-2011 Jahia Solutions Group SA. All rights reserved.
*
* 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 (or any later version), you may redistribute this Program in connection
* with Free/Libre and Open Source Software ("FLOSS") applications as described
* in Jahia's FLOSS exception. You should have received a copy of the text
* describing the FLOSS exception, and it is also available here:
* http://www.jahia.com/license
*
* Commercial and Supported Versions of the program (dual licensing):
* alternatively, commercial and supported versions of the program may be used
* in accordance with the terms and conditions contained in a separate
* written agreement between you and Jahia Solutions Group SA.
*
* If you are unsure which license is appropriate for your use,
* please contact the sales department at sales@jahia.com.
*/

package org.jahia.services.render;

import org.apache.commons.lang.StringUtils;
import org.jahia.exceptions.JahiaException;
import org.jahia.exceptions.JahiaInitializationException;
import org.jahia.services.cache.CacheImplementation;
import org.jahia.services.cache.CacheProvider;
import org.jahia.services.content.*;
import org.jahia.services.content.decorator.JCRSiteNode;
import org.jahia.services.content.nodetypes.ExtendedNodeType;
import org.jahia.services.render.filter.RenderChain;
import org.jahia.services.render.filter.RenderFilter;
import org.jahia.services.render.filter.RenderServiceAware;
import org.jahia.services.render.filter.cache.DefaultCacheKeyGenerator;
import org.jahia.services.render.scripting.Script;
import org.jahia.services.render.scripting.ScriptResolver;
import org.jahia.services.templates.JahiaTemplateManagerService;
import org.jahia.services.usermanager.JahiaGroupManagerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import javax.jcr.*;
import javax.jcr.query.Query;
import javax.jcr.query.QueryResult;

import java.io.IOException;
import java.util.*;

/**
* Service to render node
*
* @author toto
*/
public class RenderService {

    public static final String RENDER_SERVICE_TEMPLATES_CACHE = "RenderService.TemplatesCache";

    public void setCacheKeyGenerator(DefaultCacheKeyGenerator cacheKeyGenerator) {
        this.cacheKeyGenerator = cacheKeyGenerator;
    }

    public void setCacheProvider(CacheProvider cacheProvider) {
        this.cacheProvider = cacheProvider;
        templatesCache = (CacheImplementation<String, Template>) cacheProvider.newCacheImplementation(RENDER_SERVICE_TEMPLATES_CACHE);
    }

    public static class RenderServiceBeanPostProcessor implements BeanPostProcessor {
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }

        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof RenderServiceAware) {
                ((RenderServiceAware) bean).setRenderService(getInstance());
            }
            if(bean instanceof RenderFilter) {
        logger.info("Registering render filter {}", bean.getClass().getName());
        getInstance().addFilter((RenderFilter) bean);
            }
            return bean;
        }
    }
   
    private static final Logger logger = LoggerFactory.getLogger(RenderService.class);

    private void addFilter(RenderFilter renderFilter) {
        filters.add(renderFilter);
    }

    private static volatile RenderService instance;

    public static RenderService getInstance() {
        if (instance == null) {
            synchronized (RenderService.class) {
                if (instance == null) {
                    instance = new RenderService();
                }
            }
        }
        return instance;
    }

    private JahiaTemplateManagerService templateManagerService;

    private Collection<ScriptResolver> scriptResolvers;

    private List<RenderFilter> filters = new LinkedList<RenderFilter>();

    public void setTemplateManagerService(JahiaTemplateManagerService templateManagerService) {
        this.templateManagerService = templateManagerService;
    }

    public void setScriptResolvers(Collection<ScriptResolver> scriptResolvers) {
        this.scriptResolvers = scriptResolvers;
    }

    public void start() throws JahiaInitializationException {

    }

    public void stop() throws JahiaException {

    }

    /**
     * Render a specific resource and returns it as a StringBuffer.
     *
     * @param resource Resource to display
     * @param context  The render context
     * @return The rendered result
     * @throws RenderException in case of rendering issues
     */
    public String render(Resource resource, RenderContext context) throws RenderException {
        if (context.getResourcesStack().contains(resource)) {
            return "loop";
        }

        RenderChain renderChain = new RenderChain();
        renderChain.addFilters(filters);
        renderChain.addFilters(templateManagerService.getRenderFilters());
        String output = renderChain.doFilter(context, resource);

        return output;
    }

    /**
     * This resolves the executable script from the resource object. This should be able to find the proper script
     * depending of the template / template type. Currently resolves only simple JSPScript.
     * <p/>
     * If template cannot be resolved, fall back on default template
     *
     * @param resource The resource to display
     * @param context
     * @return An executable script
     * @throws RepositoryException
     * @throws IOException
     */
    public Script resolveScript(Resource resource, RenderContext context) throws RepositoryException, TemplateNotFoundException {
        for (ScriptResolver scriptResolver : scriptResolvers) {
            Script s = scriptResolver.resolveScript(resource, context);
            if (s != null) {
                return s;
            }
        }
        return null;
    }


    public boolean hasView(JCRNodeWrapper node, String key) {
        try {
            if (hasView(node.getPrimaryNodeType(), key)) {
                return true;
            }
            for (ExtendedNodeType type : node.getMixinNodeTypes()) {
                if (hasView(type, key)) {
                    return true;
                }
            }
        } catch (RepositoryException e) {

        }
        return false;
    }
    public boolean hasView(ExtendedNodeType nt, String key) {
        for (ScriptResolver scriptResolver : scriptResolvers) {
            if (scriptResolver.hasView(nt, key)) {
                return true;
            }
        }
        return false;
    }

    public SortedSet<View> getAllViewsSet() {
        SortedSet<View> set = new TreeSet<View>();
        for (ScriptResolver scriptResolver : scriptResolvers) {
            set.addAll(scriptResolver.getAllViewsSet());
        }
        return set;
    }

    public SortedSet<View> getViewsSet(ExtendedNodeType nt) {
        SortedSet<View> set = new TreeSet<View>();
        for (ScriptResolver scriptResolver : scriptResolvers) {
            set.addAll(scriptResolver.getViewsSet(nt));
        }
        return set;
    }
   
    public org.jahia.services.render.Template resolveTemplate(Resource resource, RenderContext renderContext) throws AccessDeniedException {
        final JCRNodeWrapper node = resource.getNode();
        String templateName = resource.getTemplate();
        if ("default".equals(templateName)) {
            templateName = null;
        }
        JCRNodeWrapper current = node;


        org.jahia.services.render.Template template = null;
        try {
            JCRNodeWrapper site;
            String jsite = null;
            if (renderContext.getRequest() != null) {
                jsite = renderContext.getRequest().getParameter("jsite");
            }
            if (jsite == null && renderContext.getMainResource() != null) {
                jsite = (String) renderContext.getMainResource().getModuleParams().get("jsite");
            }
            if(jsite!=null) {
                site = node.getSession().getNodeByIdentifier(jsite);
                renderContext.setSite((JCRSiteNode) site);
            } else {
                site = node.getResolveSite();
            }
            JCRNodeWrapper templatesNode = null;
            if (site != null) {
                try {
                    templatesNode = site.getNode("templates");
                } catch (PathNotFoundException e) {
                }
            }

            if (current.isNodeType("jnt:template")) {
                // Display a template node in studio
                if (!current.hasProperty("j:view") || "default".equals(current.getProperty("j:view").getString())) {
                    JCRNodeWrapper parent = current.getParent();
                    while (!(parent.isNodeType("jnt:templatesFolder"))) {
                        template = new org.jahia.services.render.Template(parent.hasProperty("j:view") ? parent.getProperty("j:view").getString() :
                                templateName, parent.getIdentifier(), template);
                        parent = parent.getParent();
                    }
                    template = addContextualTemplates(node, templateName, template, parent);
                }
            } else {
                if (resource.getTemplate().equals("default") && current.hasProperty("j:templateNode")) {
                    // A template node is specified on the current node
                    JCRNodeWrapper templateNode = (JCRNodeWrapper) current.getProperty("j:templateNode").getNode();
                    if (!checkTemplatePermission(resource, renderContext, templateNode)) {
                        throw new AccessDeniedException(resource.getTemplate());
                    }
                    template = new org.jahia.services.render.Template(templateNode.hasProperty("j:view") ? templateNode.getProperty("j:view").getString() :
                            templateName, templateNode.getIdentifier(), template);
                } else if (templatesNode != null) {
                    template = addTemplates(resource, renderContext, templatesNode);
                }

                if (template == null) {
                    template = addTemplates(resource, renderContext,
                            node.getSession().getNode(JCRContentUtils.getSystemSitePath() + "/templates"));
                }

                if (template != null) {
                    // Add cascade of parent templates
                    JCRNodeWrapper templateNode = resource.getNode().getSession().getNodeByIdentifier(template.getNode()).getParent();
                    while (!(templateNode.isNodeType("jnt:templatesFolder"))) {
                        template = new org.jahia.services.render.Template(templateNode.hasProperty("j:view") ? templateNode.getProperty("j:view").getString() :
                                null, templateNode.getIdentifier(), template);
                        templateNode = templateNode.getParent();
                    }
                } else {
                    return null;
                }
            }
            if (template != null) {
                Template currentTemplate = template;
                // Be sure to take the first template which has a defined view
                do {
                    if (!currentTemplate.getView().equals("default")) {
                        template = currentTemplate;
                    }
                    currentTemplate = currentTemplate.getNext();
                } while (currentTemplate != null);

                if ("default".equals(template.getView())) {
                    JCRNodeWrapper parent = node.getSession().getNodeByUUID(template.getNode()).getParent();
                    template = addContextualTemplates(node, templateName, template, parent);
                }
            } else {
                template = new Template(null,null,null);
            }

        } catch (AccessDeniedException e) {
            throw e;
        } catch (RepositoryException e) {
            logger.error("Cannot find template", e);
        }
        return template;
    }

    private Template addContextualTemplates(JCRNodeWrapper node, String templateName, Template template, JCRNodeWrapper parent) throws RepositoryException {
        if (parent.isNodeType("jnt:templatesFolder") && parent.hasProperty("j:rootTemplatePath")) {
            String rootTemplatePath = parent.getProperty("j:rootTemplatePath").getString();
            JCRNodeWrapper systemSite = node.getSession().getNode(JCRContentUtils.getSystemSitePath());
            parent = systemSite.getNode("templates"+ rootTemplatePath);
            while (!(parent.isNodeType("jnt:templatesFolder"))) {
                template = new Template(parent.hasProperty("j:view") ? parent.getProperty("j:view").getString() :
                        templateName, parent.getIdentifier(), template);
                parent = parent.getParent();
            }
        }
        return template;
    }

    private CacheImplementation<String,Template> templatesCache;

    private CacheProvider cacheProvider;

    private DefaultCacheKeyGenerator cacheKeyGenerator;

    private org.jahia.services.render.Template addTemplates(Resource resource, RenderContext renderContext,
                                                            JCRNodeWrapper templateNode) throws RepositoryException {
        String type = "contentTemplate";
        if (resource.getNode().isNodeType("jnt:page")) {
            type = "pageTemplate";
        }
        boolean isNotDefaultTemplate = resource.getTemplate() != null && !resource.getTemplate().equals("default");

        String key = new StringBuffer(templateNode.getPath()).append(type).append(
                isNotDefaultTemplate ? resource.getTemplate() : "default").toString() +
                     resource.getNode().getPrimaryNodeTypeName()+cacheKeyGenerator.appendAcls(resource, renderContext, false);

        Template template = templatesCache.get(key);

        if (template == null) {
            String query =
                    "select * from [jnt:" + type + "] as w where isdescendantnode(w, ['" + templateNode.getPath() +
                    "'])";
            if (isNotDefaultTemplate) {
                query += " and name(w)='" + resource.getTemplate() + "'";
            } else {
                query += " and [j:defaultTemplate]=true";
            }
            query += " order by [j:priority] desc";
            Query q = templateNode.getSession().getWorkspace().getQueryManager().createQuery(query, Query.JCR_SQL2);
            QueryResult result = q.execute();
            NodeIterator ni = result.getNodes();

            List<Template> templates = new ArrayList<Template>();
            while (ni.hasNext()) {
                final JCRNodeWrapper contentTemplateNode = (JCRNodeWrapper) ni.nextNode();
                addTemplate(resource, renderContext, contentTemplateNode, templates);
            }
            if (templates.isEmpty()) {
                templatesCache.put(key, null, new EmptyTemplate(null,null,null));
                return null;
            } else {
                templatesCache.put(key,null, templates.get(0));
                return templates.get(0);
            }
        } else {
            return template.getClass().getName().equals(EmptyTemplate.class.getName()) ? null : template;
        }
    }

    private void addTemplate(Resource resource, RenderContext renderContext, JCRNodeWrapper templateNode, List<Template> templates)
            throws RepositoryException {
        boolean ok = true;
        if (templateNode.hasProperty("j:applyOn")) {
            ok = false;
            Value[] values = templateNode.getProperty("j:applyOn").getValues();
            for (Value value : values) {
                if (resource.getNode().isNodeType(value.getString())) {
                    ok = true;
                    break;
                }
            }
            if (values.length == 0) {
                ok = true;
            }
        }
        if (!checkTemplatePermission(resource, renderContext, templateNode)) return;

        if (ok) {
            templates.add(new Template(
                    templateNode.hasProperty("j:view") ? templateNode.getProperty("j:view").getString() :
                            null, templateNode.getIdentifier(), null));
        }
    }

    private boolean checkTemplatePermission(Resource resource, RenderContext renderContext, JCRNodeWrapper templateNode) throws RepositoryException {
        if (templateNode.hasProperty("j:requiredMode")) {
            String req = templateNode.getProperty("j:requiredMode").getString();
            if (renderContext.isContributionMode() && !req.equals("contribute")) {
                return false;
            } else if (!renderContext.isContributionMode() && !req.equals("live")) {
                return false;
            }

        }
        if (templateNode.hasProperty("j:requiredPermissions")) {
            final Value[] values = templateNode.getProperty("j:requiredPermissions").getValues();
            List<String> perms = JCRTemplate.getInstance().doExecuteWithSystemSession(null, new JCRCallback<List<String>>() {
                public List<String> doInJCR(JCRSessionWrapper session) throws RepositoryException {
                    List<String> permissionNames = new ArrayList<String>();
                    for (Value value : values) {
                        permissionNames.add(session.getNodeByUUID(value.getString()).getName());
                    }
                    return permissionNames;
                }
            });
            JCRNodeWrapper contextNode = resource.getNode();
            if (templateNode.hasProperty("j:contextNodePath")) {
                String contextPath = templateNode.getProperty("j:contextNodePath").getString();
                if (!StringUtils.isEmpty(contextPath)) {
                    if (contextPath.startsWith("/")) {
                        contextNode = contextNode.getSession().getNode(contextPath);
                    } else {
                        contextNode = contextNode.getNode(contextPath);
                    }
                }
            }
            for (String perm : perms) {
                if (!contextNode.hasPermission(perm)) {
                    return false;
                }
            }
        }
        if (templateNode.hasProperty("j:requireLoggedUser") && templateNode.getProperty("j:requireLoggedUser").getBoolean()) {
            if (!renderContext.isLoggedIn()) {
                return false;
            }
        }
        if (templateNode.hasProperty("j:requirePrivilegedUser") && templateNode.getProperty("j:requirePrivilegedUser").getBoolean()) {
            if (!renderContext.getUser().isMemberOfGroup(0,JahiaGroupManagerService.PRIVILEGED_GROUPNAME)) {
                return false;
            }
        }
        return true;
    }
   
    public void flushCache() {
        templatesCache.flushAll(true);
    }

}
TOP

Related Classes of org.jahia.services.render.RenderService$RenderServiceBeanPostProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.