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

com.day.cq.commons.DownloadResource Maven / Gradle / Ivy

The newest version!
/*
 * 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;

import com.day.cq.commons.jcr.JcrConstants;
import com.day.text.Text;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ResourceWrapper;
import org.apache.sling.api.resource.ValueMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

/**
 * Provides convenience methods for rendering download paragraphs.
 */
public class DownloadResource extends ResourceWrapper {

    /**
     * internal logger
     */
    private static final Logger log = LoggerFactory.getLogger(DownloadResource.class);

    /**
     * name of the file reference property. this can hold a path to a
     * file or resource node, to a binary property or a uuid to a resource node.
     */
    public static final String PN_REFERENCE = "fileReference";

    /**
     * name of the file node.
     */
    public static final String NN_FILE = "file";

    /**
     * name of the 'file name' property.
     */
    public static final String PN_FILE_NAME = "fileName";

    /**
     * name of the title property.
     */
    public static final String PN_TITLE = JcrConstants.JCR_TITLE;

    /**
     * name of the description property
     */
    public static final String PN_DESCRIPTION = JcrConstants.JCR_DESCRIPTION;

    /**
     * internal properties
     */
    protected final ValueMap properties;

    /**
     * internal node
     */
    protected final Node node;

    /**
     * map of overlaid properties.
      */
    private final Map overlaid = new HashMap();

    /**
     * path to the file node.
     */
    private String fileNodePath = null;

    /**
     * href/src attribute
     */
    private String source = null;

    /**
     * extension for the source attribute
     */
    private String extension = ".res";

    /**
     * selector for the src attribute.
     */
    private String selector = "";

    /**
     * suffix for the src attribute
     */
    private String suffix = null;

    /**
     * query attribute
     */
    private String query = null;

    /**
     * map of tag attributes
     */
    protected Map attrs;

    /**
     * the inner html object for drawing the link.
     */
    private Object innerHtml;

    /**
     * cached file data property
     * @see #getData()
     */
    private Property data;

    /**
     * internal mapping for item names.
     */
    private Map itemNames = new HashMap();

    /**
     * label of diff version
     */
    private String diffVersionLabel;

    /**
     * is in UI Touch mode
     */
    private boolean isTouchAuthoringUIMode = false;

    /**
     * Creates a new download based on the given resource. the file properties
     * are considered to be 'on' the given resource.
     *
     * @param resource resource of the image
     * @throws IllegalArgumentException if the given resource is not adaptable to node.
     */
    public DownloadResource(Resource resource) {
        super(resource);
        this.node = resource.adaptTo(Node.class);
        ValueMap props = null;
        try {
            props = ResourceUtil.getValueMap(resource);
        } catch (Exception e) {
            // ignore exceptions. see SLING-988
        }
        // ensure that we never have 'null' properties
        this.properties = props == null ? ValueMap.EMPTY : props;

        // check for diff info
        DiffInfo info = resource.adaptTo(DiffInfo.class);
        if (info != null) {
            Resource dr = info.getContent();
            if (dr != null) {
                // find version name
                String path = dr.getPath();
                int idx = path.indexOf("/" + JcrConstants.JCR_FROZENNODE + "/");
                if (idx > 0) {
                    diffVersionLabel = Text.getName(path.substring(0, idx), '/');
                    addQueryParam(DiffService.REQUEST_PARAM_DIFF_TO, diffVersionLabel);
                }
            }
            if (info.getType() != DiffInfo.TYPE.SAME) {
                addQueryParam(DiffService.REQUEST_PARAM_DIFF_TYPE, info.getType().name());
            }
        }
    }

    /**
     * Returns if page is in UI Touch mode?
     * @return if page is in UI Touch mode
     */
    public boolean isTouchAuthoringUIMode() {
        return isTouchAuthoringUIMode;
    }

    /**
     * Page is in UI Touch mode?
     * @param inUITouchMode value to set
     */
    public void setIsInUITouchMode(boolean inUITouchMode) {
        isTouchAuthoringUIMode = inUITouchMode;
    }

    /**
     * Get a property either from the overlaid map or the underlying properties.
     *
     * @param name name of the property
     * @return string value of the property or an empty string
     */
    public String get(String name) {
        String value = overlaid.get(name);
        if (value == null) {
            value = properties.get(name, "");
        }
        return value;
    }

    /**
     * Get a property and convert it to an integer. If any exception
     * occurs, return the default value.
     *
     * @param name name of the property
     * @param defaultValue default value
     * @return integer value
     */
    public int get(String name, int defaultValue) {
        try {
            return Integer.parseInt(get(name));
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * Set a property to the overlaid map.
     *
     * @param name  name of the property
     * @param value value of the property
     */
    public void set(String name, String value) {
        overlaid.put(name, value);
    }

    /**
     * Adds a tag attribute to this download. The attributes are included when
     * {@link #draw(Writer) drawing} the tag.
     *
     * @param name  name of the attribute
     * @param value value of the attribute
     */
    public void addAttribute(String name, String value) {
        if (attrs == null) {
            attrs = new HashMap();
        }
        attrs.put(name, value);
    }

    /**
     * Adds a CSS class name to the respective attribute. If the class name
     * is already present, nothing is added.
     * @param name the class name
     */
    public void addCssClass(String name) {
        if (attrs == null || !attrs.containsKey("class")) {
            addAttribute("class", name);
        } else {
            String prev = attrs.get("class");
            if (prev.length() == 0) {
                prev = name;
            } else if (!prev.equals(name)
                    && !prev.contains(" " + name)
                    && !prev.contains(name + " ")) {
                prev += " " + name;
            }
            attrs.put("class", prev);
        }
    }

    /**
     * Calculates all default values if 'source' is null
     */
    public void init() {
        if (source == null) {
            // calculate default file node path
            if (fileNodePath == null) {
                fileNodePath = getItemName(NN_FILE);
            }
            if (fileNodePath.length() > 0 && fileNodePath.charAt(0) != '/') {
                try {
                    if (node != null && node.hasNode(fileNodePath)) {
                        fileNodePath = node.getNode(fileNodePath).getPath();
                    } else {
                        fileNodePath = "";
                    }
                } catch (RepositoryException e) {
                    fileNodePath = "";
                    log.warn("Error while accessing the repository.", e);
                }
            }

            // calculate file name
            String fileName = get(getItemName(PN_FILE_NAME));
            if (fileName.length() == 0) {
                String fileRef = getFileReference();
                if (fileRef != null && fileRef.length() > 0) {
                    fileName = Text.getName(fileRef);
                } else {
                    fileName = "";
                }
                set(getItemName(PN_FILE_NAME), fileName);
            }
            // override suffix if not defined
            if (suffix == null) {
                setSuffix(fileName);
            }

            // calculate source
            if (selector.length() > 0 && !ResourceUtil.isNonExistingResource(this)) {
                source = getPath() + getSelector() + getExtension() + getSuffix();
            } else if (fileNodePath.length() > 0) {
                source = fileNodePath + getExtension() + getSuffix();
            } else if (getFileReference().length() > 0) {
                source = getFileReference();
            }
        }
    }

    /**
     * Returns the name of the given item which is either the default or
     * can be redefined by {@link #setItemName(String, String)}. If the name
     * is not defined, the given name is returned.
     *
     * Example: Download.getItemName(Download.PN_FILE_NAME)
     * @param name item name
     * @return defined item name
     */
    public String getItemName(String name) {
        return itemNames.containsKey(name) ? itemNames.get(name) : name;
    }

    /**
     * Defines the name of an item.
     * @param key key. eg {@link #PN_FILE_NAME}.
     * @param name redefined name
     */
    public void setItemName(String key, String name) {
        itemNames.put(key, name);
    }

    /**
     * Returns the file reference.
     * @return the file reference.
     */
    public String getFileReference() {
        return get(getItemName(PN_REFERENCE));
    }

    /**
     * Sets the file reference.
     *
     * @param fileReference the file reference.
     */
    public void setFileReference(String fileReference) {
        set(getItemName(PN_REFERENCE), fileReference);
    }

    /**
     * Returns the inner html object for the download link.
     * @return the inner html or null if not defined.
     */
    public Object getInnerHtml() {
        return innerHtml;
    }

    /**
     * Sets the inner html object for the download. If not inner html is defined
     * the file name is used when drawing the download link.
     *
     * @param innerHtml the inner html object
     */
    public void setInnerHtml(Object innerHtml) {
        this.innerHtml = innerHtml;
    }

    /**
     * Returns the file path. This defaults to the path of the node addressed
     * by 'getItemName(NN_FILE)' or an empty string if that node does
     * not exist.
     *
     * @return path of the file node.
     */
    public String getFileNodePath() {
        init();
        return fileNodePath != null ? fileNodePath : "";
    }

    /**
     * Sets the path to the file node. Set this to an empty string to disable
     * fetching data from the respective node. the path can be relative to
     * address a node relative to the image node.
     *
     * @param fileNodePath path of the file node.
     */
    public void setFileNodePath(String fileNodePath) {
        this.fileNodePath = fileNodePath;
    }

    /**
     * Returns the file name of this download as defined by the property with
     * the name from 'getItemName(PN_FILE_NAME). this is an informative property
     * and is not used for any logic. the file name is added per default as
     * suffix to the link path.
     *
     * @return file name.
     */
    public String getFileName() {
        init();
        return get(getItemName(PN_FILE_NAME));
    }

    /**
     * Sets the file name.
     * @param fileName the file name
     */
    public void setFileName(String fileName) {
        set(getItemName(PN_FILE_NAME), fileName);
    }

    /**
     * Returns the image title as defined by 'getItemName(PN_TITLE)'
     * or overridden by {@link #setTitle(String)}.
     *
     * @return the title
     */
    public String getTitle() {
        return getTitle(false);
    }

    /**
     * Returns the image title as defined by 'getItemName(PN_TITLE)'
     * or overridden by {@link #setTitle(String)}.
     *
     * @param escape if true the string is HTML escaped
     * @return the title
     */
    public String getTitle(boolean escape) {
        return escape
                ? StringEscapeUtils.escapeHtml4(get(getItemName(PN_TITLE)))
                : get(getItemName(PN_TITLE));
    }

    /**
     * Sets the title.
     *
     * @param title the title.
     */
    public void setTitle(String title) {
        set(getItemName(PN_TITLE), title);
    }

    /**
     * Returns the image description as defined by getItemName(PN_DESCRIPTION)
     * or overridden by {@link #setDescription(String)}.
     *
     * @return the description
     */
    public String getDescription() {
        return getDescription(false);
    }

    /**
     * Returns the image description as defined by 'getItemName(PN_DESCRIPTION)'
     * or overridden by {@link #setDescription(String)}.
     *
     * @param escape if true the string is HTML escaped
     * @return the description
     */
    public String getDescription(boolean escape) {
        return escape
                ? StringEscapeUtils.escapeHtml4(get(getItemName(PN_DESCRIPTION)))
                : get(getItemName(PN_DESCRIPTION));
    }

    /**
     * Sets the description.
     * @param description the description.
     */
    public void setDescription(String description) {
        set(getItemName(PN_DESCRIPTION), description);
    }

    /**
     * Returns the href attribute of this download. the source is computed as
     * follows:
     * 
    *
  • if a selector is defined the path of the current resource concatenated * with the selector, extension, and suffix is used. *
  • if a file node path is defined it is concatenated with the extension and suffix. *
  • if a file reference is defined it is concatenated with the suffix. *
* * @return the href attribute */ public String getHref() { init(); return source; } /** * Sets the href attribute * @param href the href attribute */ public void setHref(String href) { this.source = href; } /** * Gets the query attribute * @return the query */ public String getQuery() { return query; } /** * Sets the query attribute, overwrites any previously generated queries. * @param query the query */ public void setQuery(String query) { this.query = query; } /** * Adds a query param to the 'query' attribute * @param name name of the param * @param value value of the param */ public void addQueryParam(String name, String value) { if (query == null || query.length() == 0) { query = "?"; } else { query += "&"; } query += Text.escape(name) + "=" + Text.escape(value); } /** * Returns the extension. defaults to .res * @return the extension. */ public String getExtension() { return extension; } /** * Sets the extension. * @param extension the extension. */ public void setExtension(String extension) { if (extension == null) { this.extension = ""; } else if (!extension.startsWith(".")) { this.extension = "." + extension; } else { this.extension = extension; } } /** * Returns the icon type of this file. * * Note: currently the mime type of the file is not respected but only the * extension of the file name is used. * * @return the icon type. */ public String getIconType() { String fileName = getFileName(); if (fileName.lastIndexOf('.') > 0) { return fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase(); } return "dat"; } /** * Returns a path to an icon representing the file. * * @return a path to an icon or null. * * @deprecated since 5.4 please use css classes for the icon, like "icon_xls.gif" */ @Deprecated public String getIconPath() { return null; } /** * Returns the suffix. defaults to "" * @return the suffix. */ public String getSuffix() { return suffix; } /** * Sets the suffix. * @param suffix the suffix. */ public void setSuffix(String suffix) { if (source != null) { log.warn("Illegal call to setSuffix() after source already calculated."); } if (suffix == null || suffix.length() == 0) { this.suffix = ""; } else if (!suffix.startsWith("/")) { this.suffix = "/" + suffix; } else { this.suffix = suffix; } } /** * Returns the selector string. defaults to an empty string. * * Note: in order to use a spool script, you need to defined the selector, * otherwise the file will be addressed directly. * * @return the selector string. */ public String getSelector() { return selector; } /** * Sets the selector string. * @param selector the selector string. */ public void setSelector(String selector) { if (source != null) { log.warn("Illegal call to setSelector() after source already calculated."); } if (selector == null) { this.selector = ""; } else if (!selector.startsWith(".")) { this.selector = "." + selector; } else { this.selector = selector; } } /** * Checks if this download has content. i.e. if there either an file or an * file reference defined and they have binary data. * * @return true if this download has content. */ public boolean hasContent() { try { return getData() != null; } catch (RepositoryException e) { // ignore return false; } } /** * Writes this download as link tag to the given writer * @param w the writer * @throws IOException if an I/O error occurs */ public void draw(Writer w) throws IOException { if (!hasContent()) { return; } PrintWriter out = new PrintWriter(w); out.printf(""); out.print(innerHtml == null ? getFileName() : innerHtml); out.print(""); } /** * Returns a string representation as HTML tag of this image. * @return the HTML tag. */ public String getString() { StringWriter w = new StringWriter(); try { draw(w); } catch (IOException e) { // should never occur } return w.getBuffer().toString(); } /** * Returns the mime type of this image. This is a convenience method that * gets the {@value JcrConstants#JCR_MIMETYPE} sibling property of the * data property returned by {@link #getData()}. * * @return the mime type of the image or null if the image * has no content. * @throws RepositoryException if an error accessing the repository occurs. */ public String getMimeType() throws RepositoryException { Property data = getData(); if (data == null || data.getParent() == null) { return null; } Property mimeTypeProp = data.getParent().getProperty(JcrConstants.JCR_MIMETYPE); return (mimeTypeProp != null)? mimeTypeProp.getString() : null; } /** * Returns the last modified of this image. This is a convenience method that * gets the {@value JcrConstants#JCR_LASTMODIFIED} sibling property of the * data property returned by {@link #getData()}. * * @return the last modified of the image or null if the image * has no content. * @throws RepositoryException if an error accessing the repository occurs. */ public Calendar getLastModified() throws RepositoryException { Property data = getData(); if (data == null || data.getParent() == null) { return null; } Property lastModifiedProp = data.getParent().getProperty(JcrConstants.JCR_LASTMODIFIED); return (lastModifiedProp != null)? lastModifiedProp.getDate() : null; } /** * Returns the property that contains the binary data of this download. This * can either by a property addressed by the internal file resource or a * property addressed by an external file reference. * * @return binary property or null * @throws RepositoryException if an error accessing the repository occurs. */ public Property getData() throws RepositoryException { if (data != null) { return data; } String ref = getFileReference(); Node fileNode; if (ref.length() > 0) { if (ref.charAt(0) != '/') { // assume uuid //noinspection deprecation Session s = node == null ? getResourceResolver().adaptTo(Session.class) : node.getSession(); fileNode = s.getNodeByUUID(ref); } else { Resource res = getReferencedResource(ref); if (res != null) { data = res.adaptTo(Property.class); if (data != null) { return data; } fileNode = res.adaptTo(Node.class); if (fileNode == null) { return null; } } else { return null; } } } else if (node != null) { if (node.hasNode(getItemName(NN_FILE))) { fileNode = node.getNode(getItemName(NN_FILE)); } else { return null; } } else { Resource fileResource = getResource().getChild(getItemName(NN_FILE)); if (fileResource != null) { fileNode = fileResource.adaptTo(Node.class); if (fileNode == null) { return null; } } else { return null; } } if (fileNode.hasNode(JcrConstants.JCR_CONTENT)) { fileNode = fileNode.getNode(JcrConstants.JCR_CONTENT); } if (fileNode.hasProperty(JcrConstants.JCR_DATA)) { return data = fileNode.getProperty(JcrConstants.JCR_DATA); } return null; } /** * Returns the resource that is referenced by path. Subclasses can provide * further semantics. * @param path path to the resource * @return the resource or null. */ protected Resource getReferencedResource(String path) { return getResourceResolver().getResource(path); } /** * Returns a map of attributes. * @return the attributes map. */ public Map getAttributes() { return attrs; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy