com.day.cq.commons.DownloadResource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
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;
}
}