com.github.maoo.indexer.webscripts.NodeDetailsWebScript.java Source code

Java tutorial

Introduction

Here is the source code for com.github.maoo.indexer.webscripts.NodeDetailsWebScript.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.maoo.indexer.webscripts;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.io.InputStream;

import com.github.maoo.indexer.utils.Utils;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.domain.permissions.Acl;
import org.alfresco.repo.domain.permissions.AclDAO;
import org.alfresco.repo.security.permissions.AccessControlEntry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;

import org.alfresco.repo.admin.SysAdminParams;
import org.alfresco.repo.thumbnail.script.ScriptThumbnailService;
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
import org.alfresco.repo.thumbnail.ThumbnailDefinition;
import org.alfresco.repo.thumbnail.ThumbnailRegistry;
import org.alfresco.service.cmr.repository.ContentReader;
import org.apache.commons.io.IOUtils;
import org.apache.commons.codec.binary.Base64;

import org.alfresco.service.cmr.repository.ContentService;

import com.google.gdata.util.common.base.StringUtil;

/**
 * Given a nodeRef, renders out all data about a node (except binary content): -
 * Node metadata - Node ACLs
 *
 * Please check
 * src/main/amp/config/alfresco/extension/templates/webscripts/com/github/maoo/
 * indexer/webscripts/details.get.desc.xml to know more about the RestFul
 * interface to invoke the WebScript
 *
 * List of pending activities (or TODOs) - Refactor recursive getAllAcls (direct
 * recursion) . Evaluate the possibility to write a SQL statement for that -
 * Move private/static logic into the IndexingService (see notes on
 * NodeChangesWebScript) - Move the following methods (and related SQL
 * statements) into IndexingDaoImpl -- nodeService.getProperties --
 * nodeService.getAspects -- nodeDao.getNodeAclId --
 * solrDao.getNodesByAclChangesetId -- nodeService.getType and
 * dictionaryService.isSubClass (should be merged into one) - Using JSON
 * libraries (or StringBuffer), render out the payload without passing through
 * FreeMarker template
 */
public class NodeDetailsWebScript extends DeclarativeWebScript implements InitializingBean, ResourceLoaderAware {

    protected static final Log logger = LogFactory.getLog(NodeDetailsWebScript.class);
    protected static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    private static final String BASE_READ_PERMISSIONS = "ReadPermissions";

    @Override
    protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache) {

        final String serviceContextPath = req.getServerPath() + req.getServiceContextPath();

        final List<String> readableAuthorities = new ArrayList<String>();

        // Parsing parameters passed from the WebScript invocation
        Map<String, String> templateArgs = req.getServiceMatch().getTemplateVars();
        String storeId = templateArgs.get("storeId");
        String storeProtocol = templateArgs.get("storeProtocol");
        String uuid = templateArgs.get("uuid");
        NodeRef nodeRef = new NodeRef(storeProtocol, storeId, uuid);
        logger.debug(
                String.format("Invoking ACLs Webscript, using the following params\n" + "nodeRef: %s\n", nodeRef));

        // Processing properties
        Map<QName, Serializable> propertyMap = nodeService.getProperties(nodeRef);
        Map<String, Pair<String, String>> properties = toStringMap(propertyMap);

        // Processing aspects
        Set<QName> aspectsSet = nodeService.getAspects(nodeRef);
        Set<String> aspects = toStringSet(aspectsSet);

        // Processing content data
        ContentData contentData = (ContentData) propertyMap.get(ContentModel.PROP_CONTENT);

        // Get the node ACL Id
        Long dbId = (Long) propertyMap.get(ContentModel.PROP_NODE_DBID);
        Long nodeAclId = nodeDao.getNodeAclId(dbId);

        // Get also the inherited ones
        List<Acl> acls = getAllAcls(nodeAclId);
        // @TODO - avoid reverse by implementing direct recursion
        Collections.reverse(acls);

        // Getting path and siteName
        Path pathObj = nodeService.getPath(nodeRef);
        String path = pathObj.toPrefixString(namespaceService);
        String siteName = Utils.getSiteName(pathObj);

        // Walk through ACLs and related ACEs, rendering out authority names
        // having a granted permission on the node
        for (Acl acl : acls) {
            List<AccessControlEntry> aces = aclDao.getAccessControlList(acl.getId()).getEntries();
            for (AccessControlEntry ace : aces) {
                if ((!ace.getPermission().getName().equals(BASE_READ_PERMISSIONS))
                        && ace.getAccessStatus().equals(AccessStatus.ALLOWED)) {
                    if (!readableAuthorities.contains(ace.getAuthority())) {
                        readableAuthorities.add(ace.getAuthority());
                    }
                }
            }
        }

        Map<String, Object> model = new HashMap<String, Object>(1, 1.0f);
        if (contentData != null) {
            model.put("mimetype", contentData.getMimetype());
            model.put("size", contentData.getSize());
        }

        model.put("nsResolver", namespaceService);
        model.put("readableAuthorities", readableAuthorities);
        model.put("properties", properties);
        model.put("aspects", aspects);
        model.put("path", path);
        model.put("serviceContextPath", serviceContextPath);
        model.put("documentUrlPrefix", documentUrlPrefix);
        model.put("shareUrl", shareUrl);
        model.put("shareUrlPrefix", shareUrlPrefix);
        model.put("thumbnailUrlPrefix", thumbnailUrlPrefix);
        model.put("previewUrlPrefix", previewUrlPrefix);

        String documentUrlPath = String.format("/%s/%s/%s", storeProtocol, storeId, uuid);
        model.put("documentUrlPath", documentUrlPath);

        // Calculating the contentUrlPath and adding it only if the contentType
        // is child of cm:content
        boolean isContentAware = isContentAware(nodeRef);
        if (isContentAware) {
            String contentUrlPath = String.format("/api/node/%s/%s/%s/content", storeProtocol, storeId, uuid);
            model.put("contentUrlPath", contentUrlPath);

            // Rendering out the (relative) URL path to Alfresco Share
            String shareUrlPath = null;

            if (!StringUtil.isEmpty(siteName)) {
                shareUrlPath = String.format("/page/site/%s/document-details?nodeRef=%s", siteName,
                        nodeRef.toString());

            } else {
                shareUrlPath = String.format("/page/document-details?nodeRef=%s", nodeRef.toString());
            }

            if (shareUrlPath != null) {
                model.put("shareUrlPath", shareUrlPath);
            }
        }

        String previewUrlPath = String.format("/api/node/%s/%s/%s/content/thumbnails/webpreview", storeProtocol,
                storeId, uuid);
        model.put("previewUrlPath", previewUrlPath);

        String thumbnailUrlPath = String.format(
                "/api/node/%s/%s/%s/content/thumbnails/doclib?c=queue&ph=true&lastModified=1", storeProtocol,
                storeId, uuid);
        model.put("thumbnailUrlPath", thumbnailUrlPath);

        ThumbnailRegistry registry = thumbnailService.getThumbnailRegistry();
        ThumbnailDefinition details = registry.getThumbnailDefinition("doclib");
        try {
            NodeRef thumbRef = thumbnailService.getThumbnailByName(nodeRef, ContentModel.PROP_CONTENT, "doclib");
            if (thumbRef == null) {
                thumbRef = thumbnailService.createThumbnail(nodeRef, ContentModel.PROP_CONTENT,
                        details.getMimetype(), details.getTransformationOptions(), details.getName());
            }

            ContentReader thumbReader = contentService.getReader(thumbRef, ContentModel.PROP_CONTENT);
            InputStream thumbsIs = thumbReader.getContentInputStream();
            String thumbBase64 = Base64.encodeBase64String(IOUtils.toByteArray(thumbsIs));
            model.put("thumbnailBase64", thumbBase64);
            IOUtils.closeQuietly(thumbsIs);
        } catch (Exception e) {
            if (logger.isDebugEnabled()) {
                logger.debug("It was not possible to get/build thumbnail doclib for nodeRef: " + nodeRef
                        + ". Message: " + e.getMessage());
            }

            // thumbnail placeholder
            String phPath = scriptThumbnailService.getMimeAwarePlaceHolderResourcePath("doclib",
                    details.getMimetype());

            StringBuilder sb = new StringBuilder("classpath:").append(phPath);
            final String classpathResource = sb.toString();

            InputStream is = null;
            try {
                is = resourceLoader.getResource(classpathResource).getInputStream();
                String thumbBase64 = Base64.encodeBase64String(IOUtils.toByteArray(is));
                model.put("thumbnailBase64", thumbBase64);
            } catch (Exception e2) {
                if (logger.isWarnEnabled()) {
                    logger.warn("It was not possible to get/build placeholder thumbnail doclib for nodeRef: "
                            + nodeRef + ". Message: " + e2.getMessage());
                }
            } finally {
                IOUtils.closeQuietly(is);
            }

        }

        model.put("contentUrlPrefix", contentUrlPrefix);

        return model;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        boolean alfrescoWithPort = true;
        if ((sysAdminParams.getAlfrescoProtocol() == "https" && sysAdminParams.getAlfrescoPort() == 443)
                || (sysAdminParams.getAlfrescoProtocol() == "http" && sysAdminParams.getAlfrescoPort() == 80)) {
            alfrescoWithPort = false;
        }
        String alfrescoPrefix = sysAdminParams.getAlfrescoProtocol() + "://" + sysAdminParams.getAlfrescoHost()
                + (alfrescoWithPort ? ":" + sysAdminParams.getAlfrescoPort() : "") + "/"
                + sysAdminParams.getAlfrescoContext();
        contentUrlPrefix = alfrescoPrefix + "/service";
        previewUrlPrefix = alfrescoPrefix + "/service";
        thumbnailUrlPrefix = alfrescoPrefix + "/service";

        boolean shareWithPort = true;
        if ((sysAdminParams.getShareProtocol() == "https" && sysAdminParams.getSharePort() == 443)
                || (sysAdminParams.getShareProtocol() == "http" && sysAdminParams.getSharePort() == 80)) {
            shareWithPort = false;
        }
        shareUrlPrefix = sysAdminParams.getShareProtocol() + "://" + sysAdminParams.getShareHost()
                + (shareWithPort ? ":" + sysAdminParams.getSharePort() : "") + "/"
                + sysAdminParams.getShareContext();

    }

    private boolean isContentAware(NodeRef nodeRef) {
        QName contentType = nodeService.getType(nodeRef);
        return dictionaryService.isSubClass(contentType, ContentModel.TYPE_CONTENT);
    }

    private Set<String> toStringSet(Set<QName> aspectsSet) {
        Set<String> ret = new HashSet<String>();
        for (QName aspect : aspectsSet) {
            ret.add(aspect.toPrefixString(namespaceService));
        }
        return ret;
    }

    private Map<String, Pair<String, String>> toStringMap(Map<QName, Serializable> propertyMap) {
        Map<String, Pair<String, String>> ret = new HashMap<String, Pair<String, String>>(1, 1.0f);
        for (QName propertyName : propertyMap.keySet()) {
            Serializable propertyValue = propertyMap.get(propertyName);
            if (propertyValue != null) {
                String propertyType = propertyValue.getClass().getName();
                String stringValue = propertyValue.toString();
                if (propertyType.equals("java.util.Date")) {
                    stringValue = sdf.format(propertyValue);
                }
                ret.put(propertyName.toPrefixString(namespaceService),
                        new Pair<String, String>(propertyType, stringValue));
            }
        }
        return ret;
    }

    private List<Acl> getAllAcls(Long nodeAclId) {
        logger.debug("getAllAcls from " + nodeAclId);
        Acl acl = aclDao.getAcl(nodeAclId);
        Long parentNodeAclId = acl.getInheritsFrom();
        logger.debug("parent acl is  " + parentNodeAclId);
        if (parentNodeAclId == null || !acl.getInherits()) {
            List<Acl> ret = new ArrayList<Acl>();
            ret.add(acl);
            return ret;
        } else {
            List<Acl> inheritedAcls = getAllAcls(parentNodeAclId);
            logger.debug("Current acl with id " + nodeAclId + " is " + acl);
            inheritedAcls.add(acl);
            return inheritedAcls;
        }
    }

    public List<String> getThumbnailDefinitions(NodeRef nodeRef) {
        List<String> result = new ArrayList<String>(7);

        ContentReader contentReader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
        if (contentReader != null) {
            String mimetype = contentReader.getMimetype();
            List<ThumbnailDefinition> thumbnailDefinitions = thumbnailService.getThumbnailRegistry()
                    .getThumbnailDefinitions(mimetype, contentReader.getSize());
            for (ThumbnailDefinition thumbnailDefinition : thumbnailDefinitions) {
                result.add(thumbnailDefinition.getName());
            }
        }

        return result;
    }

    private DictionaryService dictionaryService;
    private NamespaceService namespaceService;
    private NodeService nodeService;
    private NodeDAO nodeDao;
    private AclDAO aclDao;
    private String documentUrlPrefix;
    private String shareUrl;
    private String shareUrlPrefix;
    private String thumbnailUrlPrefix;
    private String previewUrlPrefix;
    private SysAdminParams sysAdminParams;
    private ResourceLoader resourceLoader;
    private ScriptThumbnailService scriptThumbnailService;
    private ThumbnailService thumbnailService;
    private ContentService contentService;
    private String contentUrlPrefix;

    public void setDictionaryService(DictionaryService dictionaryService) {
        this.dictionaryService = dictionaryService;
    }

    public void setNamespaceService(NamespaceService namespaceService) {
        this.namespaceService = namespaceService;
    }

    public void setNodeService(NodeService nodeService) {
        this.nodeService = nodeService;
    }

    public void setNodeDao(NodeDAO nodeDao) {
        this.nodeDao = nodeDao;
    }

    public void setAclDao(AclDAO aclDao) {
        this.aclDao = aclDao;
    }

    public void setDocumentUrlPrefix(String documentUrlPrefix) {
        this.documentUrlPrefix = documentUrlPrefix;
    }

    public void setShareUrl(String shareUrl) {
        this.shareUrl = shareUrl;
    }

    public void setThumbnailUrlPrefix(String thumbnailUrlPrefix) {
        this.thumbnailUrlPrefix = thumbnailUrlPrefix;
    }

    public void setPreviewUrlPrefix(String previewUrlPrefix) {
        this.previewUrlPrefix = previewUrlPrefix;
    }

    public void setShareUrlPrefix(String shareUrlPrefix) {
        this.shareUrlPrefix = shareUrlPrefix;
    }

    public void setSysAdminParams(SysAdminParams sysAdminParams) {
        this.sysAdminParams = sysAdminParams;
    }

    public void setThumbnailService(ThumbnailService thumbnailService) {
        this.thumbnailService = thumbnailService;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    public void setScriptThumbnailService(ScriptThumbnailService scriptThumbnailService) {
        this.scriptThumbnailService = scriptThumbnailService;
    }

    public void setContentService(ContentService contentService) {
        this.contentService = contentService;
    }

    public void setContentUrlPrefix(String contentUrlPrefix) {
        this.contentUrlPrefix = contentUrlPrefix;
    }

}