Skip to content

Instantly share code, notes, and snippets.

@yupadhyay
Created April 5, 2017 17:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yupadhyay/2ed7ee10d38c6f10b13e759268948887 to your computer and use it in GitHub Desktop.
Save yupadhyay/2ed7ee10d38c6f10b13e759268948887 to your computer and use it in GitHub Desktop.
AEM custom renderer
package com.wemblog.cq.core.servlet;
import com.day.cq.dam.api.Asset;
import com.day.cq.dam.commons.util.DamUtil;
import com.wemblog.utility.RunModeUtil;
import java.io.IOException;
import java.util.Dictionary;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import org.apache.commons.lang3.StringUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.servlets.OptingServlet;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Servlet to add extra header to PDF file request based on authored property
* @author Yogesh Upadhyay
*
*/
@Component(metatype = true)
@Service
@Properties({ @Property(name = "sling.servlet.resourceTypes", value = "nt:file", propertyPrivate = true), @Property(
name = "sling.servlet.methods", value = { "GET" }, propertyPrivate = true) })
public class CustomPDFRendererServlet extends SlingSafeMethodsServlet implements OptingServlet {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = LoggerFactory.getLogger(CustomPDFRendererServlet.class);
//This is custom RunMode util. You might have write this. Should be simple
//Let me know if you need any help. Here is one example http://wemcode.wemblog.com/check-run-mode
//Or http://programtalk.com/vs/acs-aem-commons/bundle/src/main/java/com/adobe/acs/commons/util/ModeUtil.java/
@Reference
RunModeUtil runModeUtil;
@Property(label = "disable.customPDFRenderor", description = "Disable Custom PDF Renderor", boolValue = false)
private static final String DISABLE_PDF_RENDEROR = "disable.customPDFRenderor";
private boolean _disableCustomPdfRenderor;
private static final String PROPERTY_REL_CANONICAL_URL = "pdf:canonicalUrl";
private static final String PROPERTY_NO_INDEX = "pdf:noIndex";
private static final String HEADER_DISPATCHER_NAME = "Dispatcher";
private static final String HEADER_DISPATCHER_VALUE = "no-cache";
private static final String PDF_CUSTOM_REQUEST_ATTRIBUTE = "PDF_CUSTOM_HEADER_SET";
private static final String HEADER_NO_INDEX_NAME = "X-Robots-Tag";
private static final String HEADER_NO_INDEX_VALUE = "noindex";
private static final String HEADER_REL_CANONICAL = "Link";
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException,
IOException {
final Resource resource = request.getResource();
final RequestDispatcher crd = request.getRequestDispatcher(resource);
//request attribute is required to avoid infinite redirect
request.setAttribute(PDF_CUSTOM_REQUEST_ATTRIBUTE, "true");
if (resource != null) {
LOGGER.debug("Resource Path is {}", resource.getPath());
//Get Asset path based on internal asset path
final Asset asset = DamUtil.resolveToAsset(resource);
if (asset != null) {
LOGGER.debug("This is PDF Asset path is {}", asset.getPath());
boolean isDispatcherCache = true;
if (getNoIndexHeaderString(asset) != null) {
response.setHeader(HEADER_NO_INDEX_NAME, HEADER_NO_INDEX_VALUE);
isDispatcherCache = false;
}
if (getRelCanonicalHeaderString(asset) != null) {
response.setHeader(HEADER_REL_CANONICAL, getRelCanonicalHeaderString(asset));
isDispatcherCache = false;
}
//If custom property is set do not cache this document in dispatcher
if (!isDispatcherCache) {
response.setHeader(HEADER_DISPATCHER_NAME, HEADER_DISPATCHER_VALUE);
crd.include(request, response);
return;
}
}
}
//For all other PDF request just forward to next handler
crd.forward(request, response);
}
/**
* Check if No index is enabled for this document
* @param asset
* @return
*/
private boolean isNoIndexEnabled(Asset asset) {
if (StringUtils.isNotBlank(asset.getMetadataValue(PROPERTY_NO_INDEX))) {
LOGGER.debug("No index is set for document {}", asset.getPath());
return Boolean.parseBoolean(asset.getMetadataValue(PROPERTY_NO_INDEX));
}
return false;
}
/**
* Get rel canonical property from document
* @param asset
* @return
*/
private String getRelCanonicalProperty(Asset asset) {
if (StringUtils.isNotBlank(asset.getMetadataValue(PROPERTY_REL_CANONICAL_URL))) {
LOGGER.debug("Custom rel Canonical set for document {}", asset.getPath());
return asset.getMetadataValue(PROPERTY_REL_CANONICAL_URL);
}
return null;
}
/**
* Get Header String based on property
* Example: https://developers.google.com/webmasters/control-crawl-index/docs/robots_meta_tag
* @param asset
* @return
*/
private String getNoIndexHeaderString(Asset asset) {
if (isNoIndexEnabled(asset)) {
return HEADER_NO_INDEX_VALUE;
}
return null;
}
/**
* Get custom rel canonical string
* Example: http://moz.com/blog/how-to-advanced-relcanonical-http-headers
* @param asset
* @return
*/
private String getRelCanonicalHeaderString(Asset asset) {
if (null != getRelCanonicalProperty(asset)) {
StringBuilder builder = new StringBuilder();
builder.append("<");
builder.append(getRelCanonicalProperty(asset));
builder.append(">; ");
builder.append("rel=\"canonical\"");
return builder.toString();
}
return null;
}
/**
* Check if this is PDF request
* @param request
* @return
*/
private boolean isPDFRequest(SlingHttpServletRequest request) {
return request != null && request.getRequestURI() != null ? request.getRequestURI().endsWith("pdf") : false;
}
/**
* Check if this servlet is already called
* @param request
* @return
*/
private boolean isCustomPDFHeaderSet(SlingHttpServletRequest request) {
return request.getAttribute(PDF_CUSTOM_REQUEST_ATTRIBUTE) != null;
}
/**
* Method to decide whether given request will be handled by this servlet
*/
@Override
public boolean accepts(SlingHttpServletRequest request) {
return runModeUtil.isPublish() && isPDFRequest(request) && !isCustomPDFHeaderSet(request)
&& !this._disableCustomPdfRenderor;
}
@Activate
protected final void activate(final ComponentContext componentContext) {
final Dictionary<?, ?> config = componentContext.getProperties();
this._disableCustomPdfRenderor = PropertiesUtil.toBoolean(config.get(DISABLE_PDF_RENDEROR), false);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment