Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.adobe.cq.social.commons.comments.endpoints.UploadOperationUtils Maven / Gradle / Ivy
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2015 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/
package com.adobe.cq.social.commons.comments.endpoints;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.pool.impl.GenericKeyedObjectPool.Config;
import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.adobe.cq.social.commons.comments.api.Comment;
import com.adobe.cq.social.scf.ClientUtilities;
import com.adobe.cq.social.ugcbase.SocialUtils;
import com.day.cq.commons.Externalizer;
import com.day.image.Layer;
import com.day.text.Text;
public class UploadOperationUtils {
private static String UGC_ROOT_DIR = "/content/usergenerated";
private static String TEMP_ROOT_DIR = "tmp";
private static String SOCIAL_DIR = "social";
private static String SKIP_DIRS[] = {"jcr:content"};
private static String IMAGES_DIR = "images";
private static String TEMP_DIR = UGC_ROOT_DIR + "/" + TEMP_ROOT_DIR + "/" + SOCIAL_DIR + "/" + IMAGES_DIR;
private static final Logger LOG = LoggerFactory.getLogger(UploadOperationUtils.class);
private static final Pattern IMG_SRC_PATTERN = Pattern.compile("( ]*?src=\")(.+?)(\"[^<>]*?>)");
private static final Pattern IMG_WIDTH_PATTERN = Pattern.compile("( ]*?width=\")(.+?)(\"[^<>]*?>)");
private static final Pattern IMG_HEIGHT_PATTERN = Pattern.compile("( ]*?height=\")(.+?)(\"[^<>]*?>)");
private static final String THUMBNAIL_PREFIX = "rendition_";
private static final String ACTUAL_IMAGE_PREFIX = "original_";
private static class ThumbnailConfig {
private int width;
private int height;
private boolean doCenter;
public ThumbnailConfig(int width, int height, boolean doCenter) {
super();
this.width = width;
this.height = height;
this.doCenter = doCenter;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public boolean doCenter() {
return doCenter;
}
}
public static Node addAttachment(final Node root, final String name, final InputStream inputStream,
final String mimeType) throws RepositoryException {
/*
* if (!socialUtils.checkPermission(resource.getResourceResolver(), resource.getPath(),
* Session.ACTION_ADD_NODE)) { throw new
* CommentException(String.format("Not allowed to add an attachment to the comment: %s", resource.getPath()));
* }
*/
// Some browsers supply full path
final String fileName = FilenameUtils.getName(name);
Node attachmentNode;
Node contentNode;
if (root.hasNode(fileName)) {
attachmentNode = root.getNode(fileName);
contentNode = attachmentNode.getNode("jcr:content");
} else {
attachmentNode = root.addNode(fileName, "nt:file");
contentNode = attachmentNode.addNode("jcr:content", "nt:resource");
}
contentNode.setProperty("jcr:mimeType", mimeType);
contentNode.setProperty("jcr:data", inputStream);
contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
return attachmentNode;
}
public static Node createOrGetUploadResource(final Session session, final String path)
throws PathNotFoundException, RepositoryException {
final Node ugc = session.getNode(UGC_ROOT_DIR);
if (ugc != null) {
final Node tmp = JcrUtils.getOrAddFolder(ugc, TEMP_ROOT_DIR);
final String folders[] = path.split("/");
Node parent = JcrUtils.getOrAddFolder(tmp, SOCIAL_DIR);
parent = JcrUtils.getOrAddFolder(parent, IMAGES_DIR);
for (int i = path.startsWith("/") ? 0 : 1; i < folders.length; i++) {
if (!skipFolder(folders[i])) {
parent = JcrUtils.getOrAddFolder(parent, folders[i]);
}
}
return parent;
} else {
return null;
}
}
public static void moveImages(final Externalizer externalizer, final boolean author,
final SocialUtils socialUtils, final Comment comment) throws PersistenceException {
moveImages(null, externalizer, author, socialUtils, comment);
}
public static void moveImages(final String contextPath, final Externalizer externalizer, final boolean author,
final SocialUtils socialUtils, final Comment comment) throws PersistenceException {
String message = comment.getMessage();
final Resource resource = comment.getResource();
final com.adobe.cq.social.commons.Comment ocomment =
resource.adaptTo(com.adobe.cq.social.commons.Comment.class);
final ResourceResolver resolver = comment.getResource().getResourceResolver();
boolean updated = false;
Matcher imgMatcher = IMG_SRC_PATTERN.matcher(message);
StringBuffer updatedMessage = new StringBuffer();
while (imgMatcher.find()) {
String startTag = imgMatcher.group(1);
String imgUrl = imgMatcher.group(2);
String endTag = imgMatcher.group(3);
String externalUrl = null;
if (imgUrl.startsWith(TEMP_DIR)) {
final String name = FilenameUtils.getName(imgUrl);
Resource imgResource = resolver.getResource(imgUrl);
if (imgResource != null && imgResource.hasChildren()) {
imgResource = imgResource.getChild("jcr:content");
}
if (imgResource != null) {
final InputStream inputStream = imgResource.adaptTo(InputStream.class);
final ValueMap valueMap = imgResource.adaptTo(ValueMap.class);
final String mimeType = valueMap.get("jcr:mimeType", String.class);
final Resource image = ocomment.addImage(name, inputStream, mimeType);
externalUrl = externalizeLink(contextPath, externalizer, author, resolver, image.getPath());
}
}
if (externalUrl != null) {
imgMatcher.appendReplacement(updatedMessage, Matcher.quoteReplacement(startTag + externalUrl + endTag));
updated = true;
}
}
imgMatcher.appendTail(updatedMessage);
if (updated) {
final ModifiableValueMap mvm = resource.adaptTo(ModifiableValueMap.class);
mvm.put("jcr:description", updatedMessage.toString());
resolver.commit();
}
}
public static void moveImages(final ClientUtilities clientUtils, final Comment comment,
final ResourceResolver serviceUserResolver) throws PersistenceException {
moveImages(clientUtils, comment, serviceUserResolver, null);
}
public static void moveImages(final ClientUtilities clientUtils, final Comment comment,
final ResourceResolver serviceUserResolver, final String contextPath) throws PersistenceException {
String message = comment.getMessage();
final String commentPath = comment.getResource().getPath();
final Resource resource = serviceUserResolver.getResource(commentPath);
final com.adobe.cq.social.commons.Comment ocomment =
resource.adaptTo(com.adobe.cq.social.commons.Comment.class);
int thumbNailSize = comment.getConfiguration().getThumbNailSize();
boolean updated = false;
final Set deletedResources = new HashSet();
Matcher imgMatcher = IMG_SRC_PATTERN.matcher(message);
Matcher heightMatcher = null;
Matcher widthMatcher = null;
StringBuffer updatedMessage = new StringBuffer();
while (imgMatcher.find()) {
heightMatcher = IMG_HEIGHT_PATTERN.matcher(imgMatcher.group());
widthMatcher = IMG_WIDTH_PATTERN.matcher(imgMatcher.group());
String startTag = getStartTag(imgMatcher);
String imgUrl = getImgUrl(imgMatcher);
String endTag = getEndTag(imgMatcher);
ThumbnailConfig config = new ThumbnailConfig(thumbNailSize,thumbNailSize,false);
int imageHeight = getImageAttributeValue(heightMatcher);
int imageWidth = getImageAttributeValue(widthMatcher);
if(imageWidth < config.getWidth() && imageHeight < config.getHeight()) {
config.setHeight(imageHeight);
config.setWidth(imageWidth);
}
imgUrl = Text.unescape(imgUrl);
String externalUrl = null;
String renditionUrl =null;
if (imgUrl.startsWith(contextPath)) {
imgUrl = imgUrl.substring(contextPath.length());
}
String imageName = FilenameUtils.getName(imgUrl);
if (imgUrl.startsWith(TEMP_DIR)) {
Resource imgResource = serviceUserResolver.getResource(imgUrl);
Resource targetResource = imgResource;
if (imgResource != null && imgResource.hasChildren()) {
targetResource = imgResource.getChild("jcr:content");
}
final InputStream inputStream = targetResource.adaptTo(InputStream.class);
final ValueMap valueMap = targetResource.adaptTo(ValueMap.class);
final String mimeType = valueMap.get("jcr:mimeType", String.class);
final Resource imageSource= ocomment.addImage(ACTUAL_IMAGE_PREFIX + imageName, inputStream, mimeType);
if (imageSource != null) {
deletedResources.add(imgResource.getPath());
externalUrl = encode(StringUtils.isBlank(contextPath) ? imageSource.getPath() : contextPath
+ imageSource.getPath(), clientUtils);
}
// Upload rendition Image
InputStream targetInputStream = targetResource.adaptTo(InputStream.class);
InputStream renditionInputStream = generateRenditionImage(targetInputStream, mimeType, config);
if(renditionInputStream!=null) {
final Resource rendImageSource= ocomment.addImage(THUMBNAIL_PREFIX + imageName, renditionInputStream, mimeType);
if (rendImageSource != null) {
renditionUrl = encode(StringUtils.isBlank(contextPath) ? rendImageSource.getPath() : contextPath
+ rendImageSource.getPath(), clientUtils);
}
}
}else{
Resource imgResource = serviceUserResolver.getResource(imgUrl);
if(imgResource!=null){
final ValueMap valueMap = imgResource.adaptTo(ValueMap.class);
final String mimeType = valueMap.get("mimetype", String.class);
InputStream imgResourceInputStream = imgResource.adaptTo(InputStream.class);
InputStream renditionInputStream = generateRenditionImage(imgResourceInputStream, mimeType, config);
final Resource rendImageSource= ocomment.addImage(THUMBNAIL_PREFIX + imageName, renditionInputStream, mimeType);
if (rendImageSource != null) {
externalUrl = encode(StringUtils.isBlank(contextPath) ? imgResource.getPath() : contextPath
+ imgResource.getPath(), clientUtils);
renditionUrl = encode(StringUtils.isBlank(contextPath) ? rendImageSource.getPath() : contextPath
+ rendImageSource.getPath(), clientUtils);
}
}
}
if (externalUrl!=null) {
if(renditionUrl !=null ) {
// Create a thumbnail tag
String resultUrl = createThumbnailURL(imgMatcher, imageWidth, imageHeight, config, externalUrl, renditionUrl);
imgMatcher.appendReplacement(updatedMessage, Matcher.quoteReplacement(resultUrl));
}
else {
imgMatcher.appendReplacement(updatedMessage, Matcher.quoteReplacement(startTag + externalUrl + endTag));
}
updated = true;
}
}
imgMatcher.appendTail(updatedMessage);
if (updated) {
final ModifiableValueMap mvm = resource.adaptTo(ModifiableValueMap.class);
mvm.put("jcr:description", updatedMessage.toString());
for (String deletedResourcePath : deletedResources) {
Resource resourceToDelete = serviceUserResolver.getResource(deletedResourcePath);
serviceUserResolver.delete(resourceToDelete);
}
serviceUserResolver.commit();
}
}
public static InputStream generateAttachmentRenditionImage(final InputStream inputStream, String thumbnailMimeType ,int thumbnailSize){
ThumbnailConfig thumbnailConfig = new ThumbnailConfig(thumbnailSize, thumbnailSize, false);
InputStream thumbnailStream = generateRenditionImage(inputStream, thumbnailMimeType , thumbnailConfig);
return thumbnailStream;
}
private static String getStartTag(Matcher imgMatcher){
String startTag = imgMatcher.group(1);
return startTag;
}
private static String getImgUrl(Matcher imgMatcher){
String endTag = imgMatcher.group(2);
return endTag;
}
private static String getEndTag(Matcher imgMatcher){
String endTag = imgMatcher.group(3);
return endTag;
}
private static String createThumbnailURL(Matcher imgMatcher, int imageWidth, int imageHeight, ThumbnailConfig config, String externalUrl, String renditionUrl) {
String startTag = getStartTag(imgMatcher);
String endTag = getEndTag(imgMatcher);
String aTagOpen = "";
String imgTag = startTag + renditionUrl + endTag;
String aTagClose =" ";
String resultUrl = aTagOpen+imgTag+aTagClose;
resultUrl = resultUrl.replaceAll("height=\""+imageHeight +"\"", "height=\""+config.getHeight() +"\"");
resultUrl = resultUrl.replaceAll("width=\""+imageWidth +"\"", "width=\""+config.getWidth() +"\"");
return resultUrl;
}
private static int getImageAttributeValue(Matcher matcher) {
int result = Integer.MAX_VALUE;
if(matcher.find()){
String attributeValue = matcher.group(2);
if(StringUtils.isNumeric(attributeValue)){
result = Integer.parseInt(attributeValue);
}
}
return result;
}
private static InputStream generateRenditionImage(final InputStream inputStream, String thumbnailMimeType, ThumbnailConfig config) {
BufferedImage image =null;
try {
image = ImageIO.read(inputStream);
} catch (Exception e) {
LOG.error("Error in creating image from inpustream ",e.getStackTrace());
IOUtils.closeQuietly(inputStream);
return null;
}
Layer layer = new Layer(image);
Layer tLayer = createThumb(layer,config);
config.setHeight(layer.getHeight());
config.setWidth(layer.getWidth());
OutputStream out = null;
InputStream in = null;
try {
File tmpFile = File.createTempFile("thumbnail", ".tmp");
out = FileUtils.openOutputStream(tmpFile);
tLayer.write(thumbnailMimeType, 0.8, out);
in = FileUtils.openInputStream(tmpFile);
} catch (Exception e) {
LOG.error("Error in writing thumbnail image",e.getStackTrace());
IOUtils.closeQuietly(in);
} finally {
IOUtils.closeQuietly(out);
}
// if image was centered, create a new layer for further processing
if (tLayer != layer) {
tLayer.dispose();
}
return in;
}
private static Layer createThumb(Layer layer, ThumbnailConfig config) {
Layer finalLayer = null;
final int maxWidth = config.getWidth();
final int maxHeight = config.getHeight();
final boolean doCenter = config.doCenter();
final int width = layer.getWidth();
final int height = layer.getHeight();
final Color bgColor = layer.getBackgroundColor();
if (height > maxHeight || width > maxWidth) {
// resize image
int newWidth, newHeight;
if (height > width) {
newHeight = maxHeight;
newWidth = (width * maxHeight / height);
if (newWidth > maxWidth) {
newWidth = maxWidth;
newHeight = (height * maxWidth / width);
}
} else {
newWidth = maxWidth;
newHeight = (height * maxWidth / width);
if (newHeight > maxHeight) {
newHeight = maxHeight;
newWidth = (width * maxHeight / height);
}
}
layer.resize(newWidth, newHeight, true);
}
// merge and center image so that the "requested" height and width are respected
if ((layer.getHeight() < maxHeight || layer.getWidth() < maxWidth) && doCenter) {
final Color bg = (null != bgColor) ? bgColor : Color.WHITE;
finalLayer = new Layer(maxWidth, maxHeight, bg);
finalLayer.setTransparency(bg);
int y = (maxHeight - layer.getHeight()) / 2;
int x = (maxWidth - layer.getWidth()) / 2;
layer.setX(x);
layer.setY(y);
finalLayer.merge(layer);
layer = finalLayer;
}
return layer;
}
private static String encode(final String str, final ClientUtilities clientUtils) {
final String result = clientUtils.externalLink(str, false);
// TODO: We can't really externalize the link since the clientUtils that the OperationExtension
// doesn't have access to the HttpRequest..
return Text.escapePath(str);
}
private static String replace(final String text, final String replacement, final int startIndex, final int length) {
final int replLength = replacement.length();
int increase = replacement.length() - length;
increase = (increase < 0 ? 0 : increase);
increase *= 16;
StringBuilder buf = new StringBuilder(text.length() + increase);
buf = buf.append(text, 0, startIndex + 1).append(replacement).append(text.substring(startIndex + length));
return buf.toString();
}
private static String externalizeLink(final String contextPath, final Externalizer externalizer,
final boolean author, final ResourceResolver resolver, final String url) {
String externalUrl = (StringUtils.isBlank(contextPath)) ? url : contextPath + "/" + url;
if (externalizer != null) {
if (author) {
externalUrl = externalizer.authorLink(resolver, externalUrl);
} else {
externalUrl = externalizer.publishLink(resolver, externalUrl);
}
}
return getRootBasedURL(url);
}
private static String getRootBasedURL(final String url) {
try {
final URL startURL = new URL(url);
final String HOST_CHECK_HEADER = "origin";
// Only mess with stuff if it's http[s]
if (StringUtils.startsWithIgnoreCase(startURL.getProtocol(), "http")) {
return StringUtils.removeStart(url.toString(), startURL.getProtocol() + "://" + startURL.getHost()
+ ((startURL.getPort() == -1) ? "" : ":" + startURL.getPort()));
}
} catch (final MalformedURLException e) {
// Not sure if we can even get here because that means the externalizer generated a link without http?
}
return url;
}
private static boolean skipFolder(final String name) {
for (int i = 0; i < SKIP_DIRS.length; i++) {
if (name.equals(SKIP_DIRS[i])) {
return true;
}
}
return false;
}
}