
com.day.cq.contentsync.handler.AbstractSlingResourceUpdateHandler Maven / Gradle / Ivy
/*
* Copyright 1997-2011 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.contentsync.handler;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Calendar;
import java.util.Collections;
import org.apache.commons.io.IOUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.engine.SlingRequestProcessor;
import org.apache.sling.jcr.resource.JcrResourceConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.day.cq.commons.jcr.JcrConstants;
import com.day.cq.commons.jcr.JcrUtil;
import com.day.cq.contentsync.handler.util.RequestResponseFactory;
import com.day.cq.contentsync.impl.handler.util.RequestResponseFactoryImpl;
import com.google.common.io.ByteSource;
import com.google.common.io.FileBackedOutputStream;
/**
* The {@code AbstractSlingResourceUpdateHandler} is an abstract base class
* for cache update handlers that would like to use the Sling request processing.
*/
@Component(metatype = false, componentAbstract = true)
public abstract class AbstractSlingResourceUpdateHandler extends AbstractDefaultContentUpdateHandler implements ContentUpdateHandler {
private static final Logger log = LoggerFactory.getLogger(AbstractSlingResourceUpdateHandler.class);
@Reference
protected SlingRequestProcessor slingServlet;
@Reference
protected ResourceResolverFactory resourceResolverFactory;
@Reference
protected RequestResponseFactory requestResponseFactory;
/**
* This method renders the given request URI using the Sling request processing
* and stores the result at the request's location relative to the cache root
* folder. The request is processed in the context of the given user's session.
*
* @param uri The request URI including selectors and extensions
* @param configCacheRoot The cache root folder
* @param admin The admin session used to store the result in the cache
* @param session The user's session
* @return {@code true} if the cache was updated
* @throws IOException if an I/O error occurrs.
* @throws RepositoryException if an error accessing the repository occurrs.
* @throws ServletException if a generic servlet error occurrs.
*/
protected boolean renderResource(String uri, String configCacheRoot, Session admin, Session session) throws RepositoryException, ServletException, IOException {
String cachePath = configCacheRoot + getTargetPath(uri);
FileBackedOutputStream out = new FileBackedOutputStream(1024 * 64);
try {
ResourceResolver resolver = resourceResolverFactory.getResourceResolver(Collections.singletonMap("user.jcr.session", (Object) session));
// render resource
HttpServletRequest request = createRequest(uri);
HttpServletResponse response = ((RequestResponseFactoryImpl) requestResponseFactory).createBufferedResponse(out);
slingServlet.processRequest(request, response, resolver);
response.getWriter().flush();
ByteSource byteSource = out.asByteSource();
String hash = getHashCode(byteSource).toString();
if (!hashMatches(session, cachePath, hash)) {
log.debug("Hash missing or not equal, updating content sync cache: {}", cachePath);
JcrUtil.createPath(cachePath, JcrResourceConstants.NT_SLING_FOLDER, JcrConstants.NT_FILE, admin, false);
Node cacheContentNode = JcrUtil.createPath(cachePath + "/" + JcrConstants.JCR_CONTENT, JcrConstants.NT_RESOURCE, admin);
cacheContentNode.setProperty(JcrConstants.JCR_DATA, admin.getValueFactory().createBinary(byteSource.openStream()));
cacheContentNode.setProperty(JcrConstants.JCR_LASTMODIFIED, Calendar.getInstance());
if (response.getContentType() != null) {
cacheContentNode.setProperty(JcrConstants.JCR_MIMETYPE, response.getContentType());
}
if (response.getCharacterEncoding() != null) {
cacheContentNode.setProperty(JcrConstants.JCR_ENCODING, response.getCharacterEncoding());
}
writeHash(cacheContentNode, hash);
admin.save();
return true;
} else {
log.debug("Skipping update of content sync cache: {}", uri);
return false;
}
} catch (LoginException e) {
log.error("Creating resource resolver for resource rendering failed: ", e);
return false;
} finally {
try {
out.reset();
} catch (IOException e) {
log.warn("Cannot delete temporary file: ", e);
}
if (admin.hasPendingChanges()) {
admin.refresh(false);
}
}
}
/**
* Creates a GET request for the given uri. This method can
* be overridden to provide a customized request object,
* e.g. with added parameters.
*
* @param uri The uri
* @return The request object
* @see com.day.cq.contentsync.handler.util.RequestResponseFactory
*/
protected HttpServletRequest createRequest(String uri) {
return requestResponseFactory.createRequest("GET", uri);
}
/**
* Returns the target path of a rendered resource relative
* to the cache root. This method can be overridden to
* adjust the output path in the zip file. The default
* implementation simply returns the input path.
*
* @param path The initial path
* @return The adjusted path
*/
protected String getTargetPath(String path) {
return path;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy