org.exoplatform.services.wcm.utils.WCMCoreUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.exoplatform.services.wcm.utils.WCMCoreUtils.java

Source

/*
 * Copyright (C) 2003-2009 eXo Platform SAS.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License
 * as published by the Free Software Foundation; either version 3
 * 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, see<http://www.gnu.org/licenses/>.
 */
package org.exoplatform.services.wcm.utils;

import org.apache.commons.lang.StringUtils;
import org.exoplatform.commons.utils.ListAccess;
import org.exoplatform.container.ExoContainer;
import org.exoplatform.container.ExoContainerContext;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.container.RootContainer;
import org.exoplatform.container.component.ComponentRequestLifecycle;
import org.exoplatform.container.configuration.ConfigurationManager;
import org.exoplatform.container.definition.PortalContainerConfig;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.container.xml.ObjectParameter;
import org.exoplatform.container.xml.PortalContainerInfo;
import org.exoplatform.portal.config.UserACL;
import org.exoplatform.portal.webui.util.Util;
import org.exoplatform.services.cms.CmsService;
import org.exoplatform.services.cms.link.LinkManager;
import org.exoplatform.services.cms.metadata.MetadataService;
import org.exoplatform.services.cms.templates.TemplateService;
import org.exoplatform.services.deployment.plugins.LinkDeploymentDescriptor;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.ext.app.SessionProviderService;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.listener.ListenerService;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.organization.Membership;
import org.exoplatform.services.organization.OrganizationService;
import org.exoplatform.services.security.ConversationState;
import org.exoplatform.services.wcm.core.NodeLocation;
import org.exoplatform.services.wcm.core.NodetypeConstant;
import org.quartz.JobExecutionContext;
import org.quartz.impl.JobDetailImpl;

import javax.jcr.*;
import javax.jcr.nodetype.NodeType;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * Created by The eXo Platform SAS
 * Author : Tran Nguyen Ngoc
 * ngoc.tran@exoplatform.com
 * Sep 8, 2009
 */
public class WCMCoreUtils {

    private static final Log LOG = ExoLogger.getLogger(WCMCoreUtils.class.getName());

    private static String WEBCONTENT_CSS_QUERY = "select * from exo:cssFile where jcr:path like '{path}/%' "
            + "and exo:active='true' " + "and jcr:mixinTypes <> 'exo:restoreLocation' "
            + "order by exo:priority ASC";

    /**
     * Gets the service.
     *
     * @param clazz the clazz
     *
     * @return the service
     */
    public static <T> T getService(Class<T> clazz) {
        return getService(clazz, null);
    }

    /**
     * Gets the system session provider.
     *
     * @return the system session provider
     */
    public static SessionProvider getSystemSessionProvider() {
        SessionProviderService sessionProviderService = getService(SessionProviderService.class);
        return sessionProviderService.getSystemSessionProvider(null);
    }

    /**
     * Gets the session provider.
     *
     * @return the session provider
     */
    public static SessionProvider getUserSessionProvider() {
        SessionProviderService sessionProviderService = getService(SessionProviderService.class);
        return sessionProviderService.getSessionProvider(null);
    }

    public static boolean isAnonim() {
        String userId = Util.getPortalRequestContext().getRemoteUser();
        if (userId == null)
            return true;
        return false;
    }

    public static SessionProvider createAnonimProvider() {
        return SessionProvider.createAnonimProvider();
    }

    /**
     * Gets the service.
     *
     * @param clazz the class
     * @param containerName the container's name
     *
     * @return the service
     */
    public static <T> T getService(Class<T> clazz, String containerName) {
        ExoContainer container = ExoContainerContext.getCurrentContainer();
        if (containerName != null) {
            container = RootContainer.getInstance().getPortalContainer(containerName);
        }
        if (container.getComponentInstanceOfType(clazz) == null) {
            containerName = PortalContainer.getCurrentPortalContainerName();
            container = RootContainer.getInstance().getPortalContainer(containerName);
        }
        return clazz.cast(container.getComponentInstanceOfType(clazz));
    }

    public static String getContainerNameFromJobContext(JobExecutionContext context) {
        return ((JobDetailImpl) context.getJobDetail()).getGroup().split(":")[0];
    }

    /**
     * Check current user has permission to access a node or not
     * -    For each permission, compare with user's permissions
     * -      If permission has membership type is "*", just check the user's group id only
     * -      If permission has other membership types, then check the user's membership type and user's group id
     *
     * @param userId the current user's name
     * @param permissions the current node
     * @param isNeedFullAccess if true, count full access (4) then return true, if false, return true if match first permission
     *
     * @return true is user has permissions, otherwise return false
     */
    public static boolean hasPermission(String userId, List<String> permissions, boolean isNeedFullAccess) {
        try {
            OrganizationService organizationService = WCMCoreUtils.getService(OrganizationService.class);
            startRequest(organizationService);
            Collection<?> memberships = organizationService.getMembershipHandler().findMembershipsByUser(userId);
            String userMembershipTmp;
            Membership userMembership;
            int count = 0;
            String permissionTmp = "";
            for (String permission : permissions) {
                if (!permissionTmp.equals(permission))
                    count = 0;
                for (Object userMembershipObj : memberships) {
                    userMembership = (Membership) userMembershipObj;
                    if (permission.equals(userMembership.getUserName())) {
                        return true;
                    } else if ("any".equals(permission)) {
                        if (isNeedFullAccess) {
                            count++;
                            if (count == 4)
                                return true;
                        } else
                            return true;
                    } else if (permission.startsWith("*") && permission.contains(userMembership.getGroupId())) {
                        if (isNeedFullAccess) {
                            count++;
                            if (count == 4)
                                return true;
                        } else
                            return true;
                    } else {
                        userMembershipTmp = userMembership.getMembershipType() + ":" + userMembership.getGroupId();
                        if (permission.equals(userMembershipTmp)) {
                            if (isNeedFullAccess) {
                                count++;
                                if (count == 4)
                                    return true;
                            } else
                                return true;
                        }
                    }
                }
                permissionTmp = permission;
            }
            endRequest(organizationService);
        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("hasPermission() failed because of ", e);
            }
        }
        return false;
    }

    public static <T> List<T> getAllElementsOfListAccess(ListAccess<T> listAccess) {
        try {
            return Arrays.asList(listAccess.load(0, listAccess.getSize()));
        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("getAllElementsOfListAccess() failed because of ", e);
            }
        }
        return null;
    }

    /**
     * Get the current repository
     *
     * @return the current manageable repository
     */
    public static ManageableRepository getRepository() {
        try {
            RepositoryService repositoryService = getService(RepositoryService.class);
            return repositoryService.getCurrentRepository();
        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("getRepository() failed because of ", e);
            }
        }
        return null;
    }

    public static void startRequest(OrganizationService orgService) throws Exception {
        if (orgService instanceof ComponentRequestLifecycle) {
            ((ComponentRequestLifecycle) orgService).startRequest(ExoContainerContext.getCurrentContainer());
        }
    }

    public static void endRequest(OrganizationService orgService) throws Exception {
        if (orgService instanceof ComponentRequestLifecycle) {
            ((ComponentRequestLifecycle) orgService).endRequest(ExoContainerContext.getCurrentContainer());
        }
    }

    public static String getProjectVersion() throws Exception {
        String filePath = "jar:/conf/projectInfo.properties";
        Properties productInformationProperties = new Properties();
        try {
            ConfigurationManager configManager = WCMCoreUtils.getService(ConfigurationManager.class);
            if (LOG.isInfoEnabled()) {
                LOG.info("Read products versions from " + filePath);
            }
            InputStream inputStream = configManager.getInputStream(filePath);

            productInformationProperties.load(inputStream);
        } catch (IOException exception) {
            throw new RuntimeException("Couldn't parse the file " + filePath, exception);
        } catch (Exception exception) {
            throw new RuntimeException("Error occured while reading the file " + filePath, exception);
        }

        if (!productInformationProperties.containsKey("project.current.version")) {
            throw new RuntimeException("Missing product information.");
        }
        return productInformationProperties.getProperty("project.current.version");
    }

    public static String getActiveStylesheet(Node webcontent) throws Exception {
        StringBuilder buffer = new StringBuilder();
        String cssQuery = StringUtils.replaceOnce(WEBCONTENT_CSS_QUERY, "{path}", webcontent.getPath());
        // Need re-login to get session because this node is get from template and the session is not live anymore.
        // If node is version (which is stored in system workspace) we have to login to system workspace to get data
        NodeLocation webcontentLocation = NodeLocation.getNodeLocationByNode(webcontent);
        ManageableRepository repository = (ManageableRepository) webcontent.getSession().getRepository();
        Session session;
        try {
            if (webcontentLocation.getPath().startsWith("/jcr:system"))
                session = WCMCoreUtils.getSystemSessionProvider()
                        .getSession(repository.getConfiguration().getSystemWorkspaceName(), repository);
            else {
                session = WCMCoreUtils.getSystemSessionProvider().getSession(webcontentLocation.getWorkspace(),
                        repository);
            }

            QueryManager queryManager = session.getWorkspace().getQueryManager();
            Query query = queryManager.createQuery(cssQuery, Query.SQL);
            QueryResult queryResult = query.execute();
            NodeIterator iterator = queryResult.getNodes();
            while (iterator.hasNext()) {
                Node registeredCSSFile = iterator.nextNode();
                buffer.append(registeredCSSFile.getNode(NodetypeConstant.JCR_CONTENT)
                        .getProperty(NodetypeConstant.JCR_DATA).getString());
            }
        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("Unexpected problem happen when active stylesheet", e);
            }
        }
        return buffer.toString();
    }

    /**
     * gets the global css of given site node. For example, if the site is acme<br/>
     * we then return all css code only inside acme/css
     * @param siteNode the root node of the site
     * @return global css code inside this site
     * @throws Exception
     */
    public static String getSiteGlobalActiveStylesheet(Node siteNode) throws Exception {
        StringBuilder buffer = new StringBuilder();
        try {
            List<Node> cssNodeList = new ArrayList<Node>();
            NodeIterator iterator = siteNode.getNodes();
            //get all cssFolder child nodes of siteNode
            while (iterator.hasNext()) {
                Node cssFolder = iterator.nextNode();
                if (cssFolder.isNodeType(NodetypeConstant.EXO_CSS_FOLDER)) {
                    NodeIterator iter = cssFolder.getNodes();
                    //get all cssFile child nodes of cssFolder node
                    while (iter.hasNext()) {
                        Node registeredCSSFile = iter.nextNode();
                        if (registeredCSSFile.isNodeType(NodetypeConstant.EXO_CSS_FILE)
                                && registeredCSSFile.getProperty(NodetypeConstant.EXO_ACTIVE).getBoolean()) {
                            cssNodeList.add(registeredCSSFile);
                        }
                    }
                }
            }
            //sort cssFile by priority and merge them
            Collections.sort(cssNodeList, new FileCSSComparatorByPriority());
            for (Node registeredCSSFile : cssNodeList) {
                try {
                    buffer.append(registeredCSSFile.getNode(NodetypeConstant.JCR_CONTENT)
                            .getProperty(NodetypeConstant.JCR_DATA).getString());
                } catch (Exception e) {
                    continue;
                }
            }
        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("Unexpected problem happen when active stylesheet", e);
            }
        }
        return buffer.toString();
    }

    /**
     * gets the global javascript of given site node. For example, if the site is acme<br/>
     * we then return all javascript code only inside acme/js
     * @param siteNode the root node of the site
     * @return global javascript code inside this site
     * @throws Exception
     */
    public static String getSiteGlobalActiveJs(Node siteNode) throws Exception {
        StringBuilder buffer = new StringBuilder();
        try {
            List<Node> jsNodeList = new ArrayList<Node>();
            NodeIterator iterator = siteNode.getNodes();
            //get all jsFolder child nodes of siteNode
            while (iterator.hasNext()) {
                Node jsFolder = iterator.nextNode();
                if (jsFolder.isNodeType(NodetypeConstant.EXO_JS_FOLDER)) {
                    NodeIterator iter = jsFolder.getNodes();
                    //get all jsFile child nodes of jsFolder node
                    while (iter.hasNext()) {
                        Node registeredJSFile = iter.nextNode();
                        if (registeredJSFile.isNodeType(NodetypeConstant.EXO_JS_FILE)
                                && registeredJSFile.getProperty(NodetypeConstant.EXO_ACTIVE).getBoolean()) {
                            jsNodeList.add(registeredJSFile);
                        }
                    }
                }
            }
            //sort jsFile by priority and merge them
            Collections.sort(jsNodeList, new FileComparatorByPriority());
            for (Node registeredJSFile : jsNodeList) {
                try {
                    buffer.append(registeredJSFile.getNode(NodetypeConstant.JCR_CONTENT)
                            .getProperty(NodetypeConstant.JCR_DATA).getString());
                } catch (Exception e) {
                    continue;
                }
            }
        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("Unexpected problem happen when active javascript", e);
            }
        }
        return buffer.toString();
    }

    public static Hashtable<String, String> getMetadataTemplates(Node node) throws Exception {
        MetadataService metadataService = WCMCoreUtils.getService(MetadataService.class);
        Hashtable<String, String> templates = new Hashtable<String, String>();
        List<String> metaDataList = metadataService.getMetadataList();

        NodeType[] nodeTypes = node.getMixinNodeTypes();
        for (NodeType nt : nodeTypes) {
            if (metaDataList.contains(nt.getName())) {
                templates.put(nt.getName(), metadataService.getMetadataPath(nt.getName(), false));
            }
        }
        Item primaryItem;
        try {
            primaryItem = node.getPrimaryItem();
        } catch (ItemNotFoundException e) {
            primaryItem = null;
        }
        if (primaryItem != null && primaryItem.isNode()) {
            Node primaryNode = (Node) node.getPrimaryItem();
            NodeType[] primaryTypes = primaryNode.getMixinNodeTypes();
            for (NodeType nt : primaryTypes) {
                if (metaDataList.contains(nt.getName())) {
                    templates.put(nt.getName(), metadataService.getMetadataPath(nt.getName(), false));
                }
            }
        }
        return templates;
    }

    public static String getRestContextName() {
        ExoContainer container = ExoContainerContext.getCurrentContainer();
        PortalContainerConfig portalContainerConfig = (PortalContainerConfig) container
                .getComponentInstance(PortalContainerConfig.class);
        PortalContainerInfo containerInfo = (PortalContainerInfo) container
                .getComponentInstanceOfType(PortalContainerInfo.class);
        return portalContainerConfig.getRestContextName(containerInfo.getContainerName());
    }

    public static void deployLinkToPortal(InitParams initParams, RepositoryService repositoryService,
            LinkManager linkManager, SessionProvider sessionProvider, String portalName) throws Exception {
        Iterator iterator = initParams.getObjectParamIterator();
        LinkDeploymentDescriptor deploymentDescriptor = null;
        try {
            while (iterator.hasNext()) {
                ObjectParameter objectParameter = (ObjectParameter) iterator.next();
                deploymentDescriptor = (LinkDeploymentDescriptor) objectParameter.getObject();
                String sourcePath = deploymentDescriptor.getSourcePath();
                String targetPath = deploymentDescriptor.getTargetPath();

                //in case: create portal from template
                if (portalName != null && portalName.length() > 0) {
                    sourcePath = StringUtils.replace(sourcePath, "{portalName}", portalName);
                    targetPath = StringUtils.replace(targetPath, "{portalName}", portalName);
                }

                // sourcePath should looks like : repository:collaboration:/sites
                // content/live/acme
                String[] src = sourcePath.split(":");
                String[] tgt = targetPath.split(":");

                if (src.length == 3 && tgt.length == 3) {
                    ManageableRepository repository = repositoryService.getCurrentRepository();
                    Session session = sessionProvider.getSession(src[1], repository);
                    ManageableRepository repository2 = repositoryService.getCurrentRepository();
                    Session session2 = sessionProvider.getSession(tgt[1], repository2);
                    Node nodeSrc = session.getRootNode().getNode(src[2].substring(1));
                    Node nodeTgt = session2.getRootNode().getNode(tgt[2].substring(1));
                    linkManager.createLink(nodeTgt, "exo:taxonomyLink", nodeSrc);
                    ExoContainer container = ExoContainerContext.getCurrentContainer();
                    PortalContainerInfo containerInfo = (PortalContainerInfo) container
                            .getComponentInstanceOfType(PortalContainerInfo.class);
                    String containerName = containerInfo.getContainerName();
                    ListenerService listenerService = WCMCoreUtils.getService(ListenerService.class, containerName);
                    CmsService cmsService = WCMCoreUtils.getService(CmsService.class, containerName);
                    listenerService.broadcast("WCMPublicationService.event.updateState", cmsService, nodeSrc);
                }
                if (LOG.isInfoEnabled()) {
                    LOG.info(sourcePath + " has a link into " + targetPath);
                }
            }
        } catch (Exception ex) {
            if (LOG.isErrorEnabled()) {
                LOG.error("create link from " + deploymentDescriptor.getSourcePath() + " to "
                        + deploymentDescriptor.getTargetPath() + " is FAILURE at " + new Date().toString() + "\n",
                        ex);
            }
            throw ex;
        }
    }

    /**
     * compares two JsFile node by exo:priority value, tending to sort in DESC order
     * because Js file with higher priority is loaded first
     * @author vu_nguyen
     *
     */
    private static class FileComparatorByPriority implements Comparator<Node> {
        @Override
        public int compare(Node o1, Node o2) {
            try {
                if (!o1.hasProperty(NodetypeConstant.EXO_PRIORITY)) {
                    return 1;
                } else if (!o2.hasProperty(NodetypeConstant.EXO_PRIORITY)) {
                    return -1;
                } else {
                    return (int) (o2.getProperty(NodetypeConstant.EXO_PRIORITY).getLong()
                            - o1.getProperty(NodetypeConstant.EXO_PRIORITY).getLong());
                }
            } catch (Exception e) {
                return 0;
            }
        }
    }

    /**
     * compares two CSSFile node by exo:priority value, tending to sort in ASC order
     * because CSSFile file with higher priority is loaded last
     * @author vinh_nguyen
     */
    private static class FileCSSComparatorByPriority implements Comparator<Node> {
        @Override
        public int compare(Node o1, Node o2) {
            try {
                if (!o1.hasProperty(NodetypeConstant.EXO_PRIORITY)) {
                    return -1;
                } else if (!o2.hasProperty(NodetypeConstant.EXO_PRIORITY)) {
                    return 1;
                } else {
                    return (int) (o1.getProperty(NodetypeConstant.EXO_PRIORITY).getLong()
                            - o2.getProperty(NodetypeConstant.EXO_PRIORITY).getLong());
                }
            } catch (Exception e) {
                return 0;
            }
        }
    }

    /**
     * Generate uri.
     *
     * @param file the node
     * @param propertyName the image property name, null if file is an image node
     *
     * @return the string
     *
     * @throws Exception the exception
     */
    public static String generateImageURI(Node file, String propertyName) throws Exception {
        StringBuilder builder = new StringBuilder();
        NodeLocation fileLocation = NodeLocation.getNodeLocationByNode(file);
        String repository = fileLocation.getRepository();
        String workspaceName = fileLocation.getWorkspace();
        String nodeIdentifiler = file.isNodeType("mix:referenceable") ? file.getUUID()
                : file.getPath().replaceFirst("/", "");
        String portalName = PortalContainer.getCurrentPortalContainerName();
        String restContextName = PortalContainer.getCurrentRestContextName();

        if (propertyName == null) {
            if (!file.isNodeType("nt:file"))
                return null;
            InputStream stream = file.getNode("jcr:content").getProperty("jcr:data").getStream();
            if (stream.available() == 0)
                return null;
            stream.close();
            builder.append("/").append(portalName).append("/").append(restContextName).append("/").append("images/")
                    .append(repository).append("/").append(workspaceName).append("/").append(nodeIdentifiler)
                    .append("?param=file");
            return builder.toString();
        }
        builder.append("/").append(portalName).append("/").append(restContextName).append("/").append("images/")
                .append(repository).append("/").append(workspaceName).append("/").append(nodeIdentifiler)
                .append("?param=").append(propertyName);
        return builder.toString();
    }

    public static String getPortalName() {
        PortalContainerInfo containerInfo = WCMCoreUtils.getService(PortalContainerInfo.class);
        return containerInfo.getContainerName();
    }

    public static String getRemoteUser() {
        try {
            return ConversationState.getCurrent().getIdentity().getUserId();
        } catch (NullPointerException npe) {
            return null;
        }
    }

    public static String getSuperUser() {
        return getService(UserACL.class).getSuperUser();
    }

    public static boolean isDocumentNodeType(Node node) throws Exception {
        boolean isDocument = true;
        TemplateService templateService = WCMCoreUtils.getService(TemplateService.class);
        isDocument = templateService.getAllDocumentNodeTypes().contains(node.getPrimaryNodeType().getName());
        return isDocument;
    }
}