org.redpill.alfresco.repo.findwise.SearchIntegrationServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.redpill.alfresco.repo.findwise.SearchIntegrationServiceImpl.java

Source

/*
 * Copyright (C) 2014 Redpill Linpro AB
 *
 * This file is part of Findwise Integration module for Alfresco
 *
 * Findwise Integration module for 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.
 *
 * Findwise Integration module for 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 Findwise Integration module for Alfresco. 
 * If not, see <http://www.gnu.org/licenses/>.
 */

package org.redpill.alfresco.repo.findwise;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.alfresco.model.ContentModel;
import org.alfresco.repo.admin.SysAdminParams;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.UrlUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.redpill.alfresco.repo.findwise.bean.FindwiseFieldBean;
import org.redpill.alfresco.repo.findwise.bean.FindwiseObjectBean;
import org.redpill.alfresco.repo.findwise.model.FindwiseIntegrationModel;
import org.redpill.alfresco.repo.findwise.processor.NodeVerifierProcessor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.extensions.surf.util.URLEncoder;
import org.springframework.util.Assert;

import com.google.gson.Gson;

public class SearchIntegrationServiceImpl implements SearchIntegrationService, InitializingBean {
    private static final Logger LOG = Logger.getLogger(SearchIntegrationServiceImpl.class);
    protected NodeService nodeService;
    protected DictionaryService dictionaryService;
    protected NamespaceService namespaceService;
    protected ContentService contentService;
    protected BehaviourFilter behaviourFilter;
    protected Boolean pushEnabled;
    protected String pushUrl;
    protected NodeVerifierProcessor nodeVerifierProcessor;
    protected SysAdminParams sysAdminParams;
    protected SiteService siteService;
    protected PersonService personService;

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(nodeService);
        Assert.notNull(namespaceService);
        Assert.notNull(dictionaryService);
        Assert.notNull(contentService);
        Assert.notNull(pushEnabled);
        Assert.notNull(pushUrl);
        Assert.notNull(nodeVerifierProcessor);
        Assert.notNull(behaviourFilter);
        Assert.notNull(sysAdminParams);
        Assert.notNull(siteService);
        Assert.notNull(personService);
    }

    public void setPersonService(PersonService personService) {
        this.personService = personService;
    }

    public void setSiteService(SiteService siteService) {
        this.siteService = siteService;
    }

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

    public void setBehaviourFilter(BehaviourFilter behaviourFilter) {
        this.behaviourFilter = behaviourFilter;
    }

    @Override
    public void setNodeVerifierProcessor(NodeVerifierProcessor nodeVerifierProcessor) {
        this.nodeVerifierProcessor = nodeVerifierProcessor;
    }

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

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

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

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

    public void setPushEnabled(Boolean pushEnabled) {
        this.pushEnabled = pushEnabled;
    }

    public void setPushUrl(String pushUrl) {
        this.pushUrl = pushUrl;
    }

    @Override
    public boolean pushUpdateToIndexService(final Set<NodeRef> documentNodeRefs, final String action) {
        boolean result = true;
        Iterator<NodeRef> iterator = documentNodeRefs.iterator();
        while (iterator.hasNext()) {
            boolean thisResult = pushUpdateToIndexService(iterator.next(), action);
            result = result && thisResult;
        }
        return result;
    }

    @Override
    public boolean pushUpdateToIndexService(final NodeRef nodeRef, String action) {
        if (LOG.isTraceEnabled()) {
            LOG.trace("pushUpdateToIndexService begin");
        }
        boolean send = false;
        List<FindwiseObjectBean> fobs = new ArrayList<FindwiseObjectBean>();
        if (!ACTION_CREATE.equals(action) && !ACTION_DELETE.equals(action)) {
            throw new UnsupportedOperationException(action + " is not a supported operation");
        }

        if (ACTION_CREATE.equals(action)) {
            if (nodeRef == null || !nodeService.exists(nodeRef)) {
                LOG.debug(nodeRef + " does not exist");
            } else if (!nodeVerifierProcessor.verifyDocument(nodeRef)) {
                Boolean isInIndex = (Boolean) nodeService.getProperty(nodeRef,
                        FindwiseIntegrationModel.PROP_IN_INDEX);
                if (Boolean.TRUE.equals(isInIndex)) {
                    action = ACTION_DELETE;
                } else {
                    LOG.debug(nodeRef + " did not pass final node verification");
                }
            } else {
                FindwiseObjectBean fob = createFindwiseObjectBean(nodeRef, false);
                fobs.add(fob);
                send = true;
            }
        }

        if (ACTION_DELETE.equals(action)) {
            FindwiseObjectBean fob = createFindwiseObjectBean(nodeRef, true);
            fobs.add(fob);
            send = true;
        }
        boolean pushResult = false;
        if (send && ACTION_CREATE.equals(action)) {
            Gson gson = new Gson();
            String json = gson.toJson(fobs);
            if (LOG.isTraceEnabled()) {
                String jsonString = (json.length() > 2048) ? json.substring(0, 2048) : json;
                LOG.trace("Json: " + jsonString + "...");
            }
            if (Boolean.TRUE.equals(pushEnabled)) {
                pushResult = doPost(json);
            } else {
                LOG.info("Push is disabled");
            }
        } else if (send && ACTION_DELETE.equals(action)) {
            if (Boolean.TRUE.equals(pushEnabled)) {
                pushResult = doDelete(nodeRef);
            } else {
                LOG.info("Push is disabled");
            }
        }

        if (send && nodeService.exists(nodeRef)
                && !nodeService.hasAspect(nodeRef, ContentModel.ASPECT_PENDING_DELETE)) {
            LOG.debug("Setting push result on node " + nodeRef);

            behaviourFilter.disableBehaviour(nodeRef);

            nodeService.setProperty(nodeRef, FindwiseIntegrationModel.PROP_LAST_PUSH_TO_INDEX, new Date());
            if (pushResult == true) {
                // Success
                nodeService.setProperty(nodeRef, FindwiseIntegrationModel.PROP_LAST_PUSH_FAILED, false);
                nodeService.setProperty(nodeRef, FindwiseIntegrationModel.PROP_IN_INDEX,
                        !ACTION_DELETE.equals(action));
            } else {
                // Failed
                nodeService.setProperty(nodeRef, FindwiseIntegrationModel.PROP_LAST_PUSH_FAILED, true);
            }
            behaviourFilter.enableBehaviour(nodeRef);
        }
        if (LOG.isTraceEnabled()) {
            LOG.trace("pushUpdateToIndexService end");
        }
        return pushResult;
    }

    protected boolean isPropertyAllowedToIndex(QName property) {
        if (ContentModel.PROP_AUTO_VERSION.equals(property)) {
            return false;
        } else if (ContentModel.PROP_AUTO_VERSION_PROPS.equals(property)) {
            return false;
        } else if (ContentModel.PROP_INITIAL_VERSION.equals(property)) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * Create bean object from node properties
     * 
     * @param nodeRef
     * @return
     */
    protected FindwiseObjectBean createFindwiseObjectBean(final NodeRef nodeRef, boolean empty) {
        FindwiseObjectBean fob = new FindwiseObjectBean();
        fob.setId(nodeRef.toString());
        if (empty == false) {
            List<FindwiseFieldBean> fields = new ArrayList<FindwiseFieldBean>();

            Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);

            // Get node type
            QName nodeType = nodeService.getType(nodeRef);
            String title = nodeType.toPrefixString(namespaceService);
            fields.add(new FindwiseFieldBean("type", "string", title));

            // Get site info
            SiteInfo site = siteService.getSite(nodeRef);
            String siteName = site.getTitle();
            String siteShortName = site.getShortName();
            fields.add(new FindwiseFieldBean("siteName", "string", siteName));
            fields.add(new FindwiseFieldBean("siteShortName", "string", siteShortName));

            // Get download & details url
            String shareUrl = UrlUtil.getShareUrl(sysAdminParams);
            String downloadPath = "/proxy/alfresco/api/node/content/" + nodeRef.toString().replace("://", "/");
            downloadPath += "/" + URLEncoder.encode((String) properties.get(ContentModel.PROP_NAME));
            downloadPath += "?a=true";
            String downloadUrl = shareUrl + downloadPath;
            String detailsPath = "/page/site/" + siteShortName + "/document-details?nodeRef="
                    + URLEncoder.encode(nodeRef.toString());
            String detailsUrl = shareUrl + detailsPath;
            fields.add(new FindwiseFieldBean("downloadUrl", "string", downloadUrl));
            fields.add(new FindwiseFieldBean("detailsUrl", "string", detailsUrl));

            // Add more user info for creator
            NodeRef creatorNodeRef = personService
                    .getPersonOrNull((String) properties.get(ContentModel.PROP_CREATOR));
            if (creatorNodeRef != null) {
                Map<QName, Serializable> personProperties = nodeService.getProperties(creatorNodeRef);
                String firstName = (String) personProperties.get(ContentModel.PROP_FIRSTNAME);
                if (firstName == null) {
                    firstName = "";
                }
                fields.add(new FindwiseFieldBean("creatorFirstName", "string", firstName));
                String lastName = (String) personProperties.get(ContentModel.PROP_LASTNAME);
                if (lastName == null) {
                    lastName = "";
                }
                fields.add(new FindwiseFieldBean("creatorLastName", "string", lastName));
                fields.add(new FindwiseFieldBean("creatorFullName", "string", firstName + " " + lastName));
                String email = (String) personProperties.get(ContentModel.PROP_EMAIL);
                if (email == null) {
                    email = "";
                }
                fields.add(new FindwiseFieldBean("creatorEmail", "string", email));
            }

            // Add more user info for modifier
            NodeRef modifierNodeRef = personService
                    .getPersonOrNull((String) properties.get(ContentModel.PROP_MODIFIER));
            if (modifierNodeRef != null) {
                Map<QName, Serializable> personProperties = nodeService.getProperties(modifierNodeRef);
                String firstName = (String) personProperties.get(ContentModel.PROP_FIRSTNAME);
                if (firstName == null) {
                    firstName = "";
                }
                fields.add(new FindwiseFieldBean("modifierFirstName", "string", firstName));
                String lastName = (String) personProperties.get(ContentModel.PROP_LASTNAME);
                if (lastName == null) {
                    lastName = "";
                }
                fields.add(new FindwiseFieldBean("modifierLastName", "string", lastName));
                fields.add(new FindwiseFieldBean("modifierFullName", "string", firstName + " " + lastName));
                String email = (String) personProperties.get(ContentModel.PROP_EMAIL);
                if (email == null) {
                    email = "";
                }
                fields.add(new FindwiseFieldBean("modifierEmail", "string", email));
            }

            Iterator<QName> it = properties.keySet().iterator();
            while (it.hasNext()) {
                FindwiseFieldBean ffb = new FindwiseFieldBean();
                QName property = it.next();
                if (LOG.isTraceEnabled()) {
                    LOG.trace("Handling property " + property.toString());
                }
                Serializable value = properties.get(property);
                if (NamespaceService.SYSTEM_MODEL_1_0_URI.equals(property.getNamespaceURI())
                        || FindwiseIntegrationModel.URI.equals(property.getNamespaceURI())
                        || !isPropertyAllowedToIndex(property)) {
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("Skiping property " + property.toString());
                    }
                    continue;
                }
                String javaClassName = "unknown";
                PropertyDefinition propertyDefinition = dictionaryService.getProperty(property);
                // The following condition is needed to properly handle residual
                // properties
                if (propertyDefinition != null) {
                    DataTypeDefinition dataType = propertyDefinition.getDataType();
                    if (dataType != null) {
                        javaClassName = dataType.getJavaClassName();
                    }
                }
                String type;
                if (LOG.isTraceEnabled()) {
                    LOG.trace("Detected " + javaClassName + " java type for property " + property.toString());
                }

                if ("java.util.Date".equals(javaClassName)) {
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("Converting " + property.toString() + " to date");
                    }
                    type = "string";
                    DateTime date = new DateTime((Date) value, DateTimeZone.UTC);
                    ffb.setValue(date.toString());
                } else if ("org.alfresco.service.cmr.repository.ContentData".equals(javaClassName)) {
                    // Create Base64 data
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("Handling content on property " + property.toString());
                    }
                    ContentReader contentReader = contentService.getReader(nodeRef, property);
                    if (contentReader != null) {
                        InputStream contentInputStream = contentReader.getContentInputStream();
                        try {
                            byte[] nodeBytes = IOUtils.toByteArray(contentInputStream);
                            ffb.setValue(new String(Base64.encodeBase64(nodeBytes)));
                        } catch (IOException e) {
                            LOG.warn("Error while reading content", e);
                        } finally {
                            IOUtils.closeQuietly(contentInputStream);
                        }
                    } else {
                        LOG.warn(nodeRef + " had no content");
                    }
                    type = "binary";
                } else {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Unhandled property type, using default conversion");
                    }
                    type = "string";
                    ffb.setValue(value.toString());
                }
                ffb.setType(type);

                String name = property.toPrefixString(namespaceService);
                if (LOG.isTraceEnabled()) {
                    LOG.trace("Short name for property " + property.toString() + ": " + name);
                }

                ffb.setName(name);

                fields.add(ffb);
            }
            fob.setFields(fields);
        }
        return fob;
    }

    protected boolean doPost(final String json) {
        boolean result = false;
        DefaultHttpClient httpclient = new DefaultHttpClient();
        try {
            HttpPost httpPost = new HttpPost(pushUrl);
            StringEntity entity = new StringEntity(json, "UTF-8");
            httpPost.setEntity(entity);
            if (LOG.isDebugEnabled()) {
                LOG.debug("Executing request: " + httpPost.getRequestLine());
            }
            httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
            HttpResponse response = httpclient.execute(httpPost);
            try {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Response" + response.getStatusLine());
                }
                EntityUtils.consume(response.getEntity());
                result = true;
            } finally {
                // response.close();
            }
        } catch (UnsupportedEncodingException e) {
            String jsonString = (json.length() > 2048) ? json.substring(0, 2048) : json;
            LOG.warn("Error transforming json to http entity. Json: " + jsonString + "...", e);
        } catch (Exception e) {
            String jsonString = (json.length() > 2048) ? json.substring(0, 2048) : json;
            LOG.warn("Error executing http post to " + pushUrl + " Json: " + jsonString + "...", e);
        } finally {
            /*
             * try { //httpclient.close(); } catch (IOException e) {
             * LOG.warn("Error making post to " + pushUrl, e); }
             */
        }
        return result;
    }

    // TODO delete
    protected boolean doDelete(final NodeRef nodeRef) {
        boolean result = false;
        DefaultHttpClient httpclient = new DefaultHttpClient();
        try {

            String queryString = "?ids=" + URLEncoder.encode(nodeRef.toString());
            HttpDelete httpDelete = new HttpDelete(pushUrl + queryString);

            if (LOG.isDebugEnabled()) {
                LOG.debug("Executing request: " + httpDelete.getRequestLine());
            }
            httpDelete.addHeader("Content-Type", "application/json;charset=UTF-8");
            HttpResponse response = httpclient.execute(httpDelete);
            try {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Response" + response.getStatusLine());
                }
                EntityUtils.consume(response.getEntity());
                result = true;
            } finally {
                // response.close();
            }
        } catch (Exception e) {
            LOG.warn("Error executing http delete to " + pushUrl + " for " + nodeRef, e);
        } finally {
            /*
             * try { //httpclient.close(); } catch (IOException e) {
             * LOG.warn("Error making post to " + pushUrl, e); }
             */
        }
        return result;
    }

}