org.alfresco.repo.web.scripts.solr.NodeContentGet.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.repo.web.scripts.solr.NodeContentGet.java

Source

/*
 * #%L
 * Alfresco Remote API
 * %%
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 * %%
 * This file is part of the Alfresco software. 
 * If the software was purchased under a paid Alfresco license, the terms of 
 * the paid license agreement will prevail.  Otherwise, the software is 
 * provided under the following open source license terms:
 * 
 * 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.
 * 
 * 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */
package org.alfresco.repo.web.scripts.solr;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import javax.servlet.http.HttpServletResponse;

import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.transform.ContentTransformer;
import org.alfresco.repo.content.transform.TransformerDebug;
import org.alfresco.repo.content.transform.UnsupportedTransformationException;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.web.scripts.content.StreamContent;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;

/**
 * A web service to return the text content (transformed if required) of a node's
 * content property.
 * 
 * @since 4.0
 */
public class NodeContentGet extends StreamContent {
    private static final String TRANSFORM_STATUS_HEADER = "X-Alfresco-transformStatus";
    private static final String TRANSFORM_EXCEPTION_HEADER = "X-Alfresco-transformException";
    private static final String TRANSFORM_DURATION_HEADER = "X-Alfresco-transformDuration";

    private static final Log logger = LogFactory.getLog(NodeContentGet.class);

    /**
     * format definied by RFC 822, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 
     */
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z",
            Locale.US);

    private NodeDAO nodeDAO;
    private NodeService nodeService;
    private ContentService contentService;
    private TransformerDebug transformerDebug;

    public void setNodeDAO(NodeDAO nodeDAO) {
        this.nodeDAO = nodeDAO;
    }

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

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

    /**
     * Setter of the transformer debug. 
     * @param transformerDebug TransformerDebug
     */
    public void setTransformerDebug(TransformerDebug transformerDebug) {
        this.transformerDebug = transformerDebug;
    }

    /**
     *
     * @param req WebScriptRequest
     * @param res WebScriptResponse
     * @throws IOException
     */
    public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException {
        ContentReader textReader = null;
        Exception transformException = null;

        String nodeIDString = req.getParameter("nodeId");
        if (nodeIDString == null) {
            throw new WebScriptException("nodeID parameter is required for GetNodeContent");
        }
        long nodeId = Long.valueOf(nodeIDString).longValue();

        String propertyQName = req.getParameter("propertyQName");
        QName propertyName = null;
        if (propertyQName == null) {
            propertyName = ContentModel.PROP_CONTENT;
        } else {
            propertyName = QName.createQName(propertyQName);
        }
        Pair<Long, NodeRef> pair = nodeDAO.getNodePair(nodeId);
        if (pair == null) {
            // If the node does not exists we treat it as if it has no content
            // We could be trying to update the content of a node in the index that has been deleted.
            res.setStatus(HttpStatus.SC_NO_CONTENT);
            return;
        }
        NodeRef nodeRef = pair.getSecond();

        // check If-Modified-Since header and set Last-Modified header as appropriate
        Date modified = (Date) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED);
        // May be null - if so treat as just changed 
        if (modified == null) {
            modified = new Date();
        }
        long modifiedSince = -1;
        String modifiedSinceStr = req.getHeader("If-Modified-Since");
        if (modifiedSinceStr != null) {
            try {
                modifiedSince = dateFormat.parse(modifiedSinceStr).getTime();
            } catch (Throwable e) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Browser sent badly-formatted If-Modified-Since header: " + modifiedSinceStr);
                }
            }

            if (modifiedSince > 0L) {
                // round the date to the ignore millisecond value which is not supplied by header
                long modDate = (modified.getTime() / 1000L) * 1000L;
                if (modDate <= modifiedSince) {
                    res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                    return;
                }
            }
        }

        ContentReader reader = contentService.getReader(nodeRef, propertyName);
        if (reader == null) {
            res.setStatus(HttpStatus.SC_NO_CONTENT);
            return;
        }

        try {
            // get the transformer
            TransformationOptions options = new TransformationOptions();
            options.setUse("index");
            options.setSourceNodeRef(nodeRef);
            transformerDebug.pushAvailable(reader.getContentUrl(), reader.getMimetype(),
                    MimetypeMap.MIMETYPE_TEXT_PLAIN, options);
            long sourceSize = reader.getSize();
            List<ContentTransformer> transformers = contentService.getActiveTransformers(reader.getMimetype(),
                    sourceSize, MimetypeMap.MIMETYPE_TEXT_PLAIN, options);
            transformerDebug.availableTransformers(transformers, sourceSize, options, "SolrIndexer");

            if (transformers.isEmpty()) {
                res.setHeader(TRANSFORM_STATUS_HEADER, "noTransform");
                res.setStatus(HttpStatus.SC_NO_CONTENT);
                return;
            }
            ContentTransformer transformer = transformers.get(0);

            // Perform transformation catering for mimetype AND encoding
            ContentWriter writer = contentService.getTempWriter();
            writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
            writer.setEncoding("UTF-8"); // Expect transformers to produce UTF-8

            try {
                long start = System.currentTimeMillis();
                transformer.transform(reader, writer, options);
                long transformDuration = System.currentTimeMillis() - start;
                res.setHeader(TRANSFORM_DURATION_HEADER, String.valueOf(transformDuration));
            } catch (ContentIOException | UnsupportedTransformationException e) {
                transformException = e;
            }

            if (transformException == null) {
                // point the reader to the new-written content
                textReader = writer.getReader();
                // Check that the reader is a view onto something concrete
                if (textReader == null || !textReader.exists()) {
                    transformException = new ContentIOException(
                            "The transformation did not write any content, yet: \n" + "   transformer:     "
                                    + transformer + "\n" + "   temp writer:     " + writer);
                }
            }

            if (transformException != null) {
                res.setHeader(TRANSFORM_STATUS_HEADER, "transformFailed");
                res.setHeader(TRANSFORM_EXCEPTION_HEADER, transformException.getMessage());
                res.setStatus(HttpStatus.SC_NO_CONTENT);
            } else {
                res.setStatus(HttpStatus.SC_OK);
                streamContentImpl(req, res, textReader, null, null, false, modified,
                        String.valueOf(modified.getTime()), null, null);
            }
        } finally {
            transformerDebug.popAvailable();
        }
    }
}