All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.day.cq.commons.feed.AbstractFeed Maven / Gradle / Ivy

/*
 * Copyright 1997-2008 Day Management AG
 * Barfuesserplatz 6, 4001 Basel, Switzerland
 * All Rights Reserved.
 *
 * This software is the confidential and proprietary information of
 * Day Management AG, ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Day.
 */
package com.day.cq.commons.feed;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ResourceNotFoundException;
import org.apache.sling.api.resource.ValueMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Property;
import javax.servlet.ServletException;
import java.util.Calendar;
import java.util.SimpleTimeZone;
import java.util.Iterator;
import java.util.ArrayList;
import java.io.IOException;
import com.day.cq.commons.SimpleXml;
import com.day.cq.commons.jcr.JcrConstants;
import com.day.text.Text;

/**
 * The AbstractFeed serves as a base for classes printing
 * resources as feeds.
 */
public abstract class AbstractFeed implements Feed {

    /**
     * default logger
     */
    final Logger log = LoggerFactory.getLogger(Feed.class);

    static final String[] textNodes = new String[3]; // todo: make configurable
    static {
        textNodes[0] = "par/text";
        textNodes[1] = "par/textimage";
        textNodes[2] = "blogentry";
    }

    SimpleXml xml;
    SlingHttpServletRequest request;
    SlingHttpServletResponse response;

    String title;
    String description;
    String tags;
    String language;
    String author;
    String publishedDate;
    String nodePath;
    String baseUrl;

    long fileSize;
    String mimeType;

    /**
     * Creates a new feed instance using the specified resource.
     * @param res The resource
     * @param req The servlet request
     * @param resp The servlet response
     * @throws RepositoryException if no node can be found
     */
    public AbstractFeed(Resource res, SlingHttpServletRequest req,
                        SlingHttpServletResponse resp)
            throws RepositoryException {

        request = req;
        response = resp;

        if (res == null) {
            res = request.getResource();
        }
        if (ResourceUtil.isNonExistingResource(res)) {
            throw new ResourceNotFoundException("No data to render.");
        }

        Node node = res.adaptTo(Node.class);
        if (node == null) {
            throw new RepositoryException("No node found for resource: " + res.getPath());
        }
        // if available, make sure we get the properties from jcr:content,
        // but the path from the parent
        Resource propRes = res;
        nodePath = node.getPath();
        if (node.getName().equals(JcrConstants.JCR_CONTENT)) {
            nodePath = node.getParent().getPath();
        } else if (node.hasNode(JcrConstants.JCR_CONTENT)) {
            propRes = res.getChild(JcrConstants.JCR_CONTENT);
        }

        ValueMap props = propRes.adaptTo(ValueMap.class);

        if (node.isNodeType(JcrConstants.NT_FILE)) {
            fileSize = (props.get(JcrConstants.JCR_DATA, Property.class) != null) ? props.get(JcrConstants.JCR_DATA, Property.class).getLength() : 0;
            mimeType = props.get(JcrConstants.JCR_MIMETYPE, "application/octet-stream");
        } else {
            mimeType = "text/html";
        }

        // links & paths
        baseUrl = getUrlPrefix();
        baseUrl += Text.getRelativeParent(nodePath, 1);

        // content
        title = props.get(JcrConstants.JCR_TITLE, node.getName());
        description = props.get(JcrConstants.JCR_DESCRIPTION, "");
        language = props.get(JcrConstants.JCR_LANGUAGE, "");
        author = props.get(JcrConstants.JCR_CREATED_BY, "");
        publishedDate = formatDate(props.get(JcrConstants.JCR_CREATED, props.get("cq:lastModified", Calendar.getInstance())));

        tags = Text.implode(props.get("cq:tags", new String[0]), ",");
    }

    /**
     * {@inheritDoc}
     */
    public String getContentType() {
        return Feed.DEFAULT_CONTENT_TYPE;
    }

    /**
     * {@inheritDoc}
     */
    public String getCharacterEncoding() {
        return Feed.DEFAULT_CHARACTER_ENCODING;
    }

    /**
     * {@inheritDoc}
     */
    public void printEntry(Resource res) throws IOException {
        initXml();
        try {
            // make sure wrapper elements are omitted when including the resource
            request.setAttribute("com.day.cq.wcm.api.components.ComponentContext/bypass", "true");
            StringResponseWrapper wrapper = new StringResponseWrapper(response);
            request.getRequestDispatcher(getFeedEntryPath(res)).include(request, wrapper);
            xml.getWriter().print(wrapper.getString());
        } catch (ServletException se) {
            throw new IOException(se.getMessage());
        }
    }

    /**
     * {@inheritDoc}
     */
    public void printChildEntries() throws IOException {
        printEntries(request.getResourceResolver().listChildren(request.getResource()));
    }

    /**
     * {@inheritDoc}
     */
    public void printChildEntries(int max) throws IOException {
        Iterator iter = request.getResourceResolver().listChildren(request.getResource());
        ArrayList children = new ArrayList();
        while (iter.hasNext()) {
            Resource res = iter.next();
            try {
                if (res.adaptTo(Node.class).getName().equals(JcrConstants.JCR_CONTENT)) {
                    // skip self
                    continue;
                }
            } catch (RepositoryException re) {
                throw new IOException(re.getMessage());
            }
            children.add(res);
        }
        printEntries(children.iterator(), max);
    }

    /**
     * {@inheritDoc}
     */
    public void printEntries(Iterator iter) throws IOException {
        printEntries(iter, 0);
    }

    /**
     * {@inheritDoc}
     */
    public void printEntries(Iterator iter, int max) throws IOException {
        int i = 0;
        while (iter.hasNext()) {
            printEntry(iter.next());
            if (max > 0 && ++i > max) {
                break;
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public void printFooter() throws IOException {
        initXml();
        xml.closeDocument();
    }

    /**
     * Initializes the XML writer.
     * @throws IOException If output fails
     */
    void initXml() throws IOException {
        if (xml == null) {
            xml = new SimpleXml(response.getWriter());
        }
    }

    /**
     * Returns the path to the feed entry for the specified resource.
     * @param res The resource
     * @return The path
     */
    String getFeedEntryPath(Resource res) {
        return res.getPath() + Feed.SUFFIX_FEEDENTRY;
    }

    /**
     * Formats the date according to the sepification of the feed.
     * Default is UTC.
     * @param calendar The calendar
     * @return The formatted date
     */
    String formatDate(Calendar calendar) {
        // UTC
        try {
            calendar.setTimeZone(new SimpleTimeZone(0, "UTC"));
            return String.format("%1$tFT%1$tTZ", calendar);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * States whether the feed is a file
     * @return true if feed is binary, false otherwise
     */
    boolean isFile() {
        return fileSize > 0;
    }

    /**
     * Returns the file size of the feed.
     * @return The size
     */
    String getFileSize() {
        return fileSize + "";
    }

    /**
     * Returns the mime type of the feed.
     * @return The type
     */
    String getMimeType() {
        return mimeType;
    }

    /**
     * Returns the title of the feed.
     * @return The title
     */
    String getTitle() {
        return title;
    }

    /**
     * Returns the summary of the feed.
     * @return The summary
     */
    String getSummary() {
        return description;
    }

    /**
     * Returns the description of the feed.
     * @return The description
     */
    @SuppressWarnings({"ConstantConditions"})
    String getDescription() {
        return description;
    }

    /**
     * Returns the comma-separated tags (or categories) of the feed.
     * @return The tags
     */
    String getTags() {
        return tags;
    }

    /**
     * Returns the language of the feed.
     * @return The language
     */
    String getLanguage() {
        return language;
    }

    /**
     * Returns the author's name.
     * @return The name
     */
    String getAuthorName() {
        return author;
    }

    /**
     * Returns the author's e-mail address.
     * @return The e-mail address
     */
    String getAuthorEmail() {
        return !"".equals(author) ? author + "@" + request.getServerName() : "";
    }

    /**
     * Returns the formatted date the feed was published.
     * @return The date
     */
    String getPublishedDate() {
        return publishedDate;
    }

    /**
     * Returns the path of the content node of the feed.
     * @return The path
     */
    String getNodePath() {
        return nodePath;
    }

    /**
     * Returns the prefix for links including scheme, server name,
     * server port (if applicable) and context path.
     * @return The URL prefix
     */
    String getUrlPrefix() {
        StringBuffer url = new StringBuffer();
        int port = request.getServerPort();
        int defaultPort = "http".equals(request.getScheme()) ? 80 : "https".equals(request.getScheme()) ? 443 : -1;

        url.append(request.getScheme());
        url.append("://");
        url.append(request.getServerName());

        if (port > 0 && port != defaultPort) {
            url.append(":");
            url.append(port);
        }

        url.append(request.getContextPath());

        return url.toString();
    }

    /**
     * Returns the HTML link of the feed.
     * @return The link
     */
    String getHtmlLink() {
        return getUrlPrefix() + getNodePath() + Feed.SUFFIX_HTML;
    }

    /**
     * Returns the XML link of the feed.
     * @return The link
     */
    String getFeedLink() {
        return getUrlPrefix() + getNodePath() + Feed.SUFFIX_FEED;
    }

    /**
     * Returns the XML link of the feed entry.
     * @return The link
     */
    String getFeedEntryLink() {
        return getUrlPrefix() + getNodePath() + Feed.SUFFIX_FEEDENTRY;
    }

    /**
     * Returns the comments link of the feed.
     * @return The link
     */
    String getCommentsLink() {
        return getUrlPrefix() + getNodePath() + Feed.SUFFIX_COMMENTS;
    }

    /**
     * Returns the file link of the feed.
     * @return The link
     */
    String getFileLink() {
        return getUrlPrefix() + getNodePath();
    }

    /**
     * Returns the base URL of the feed.
     * @return The base URL
     */
    String getBaseUrl() {
        return baseUrl;
    }

    /**
     * Returns the name of the feed generator.
     * @return The generator name
     * todo: retrieve from system
     */
    String getGeneratorName() {
        return "CQ5";
    }

    /**
     * Returns the version of the feed generator.
     * @return The generator version
     * todo: retrieve from system
     */
    String getGeneratorVersion() {
        return "5.2";
    }

    /**
     * Returns the link to the feed generator.
     * @return The generator link
     * todo: retrieve from system
     */
    String getGeneratorLink() {
        return "http://www.day.com/communique";
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy