ThumbnailServiceImpl.java
/*
* Copyright (C) 2003-2007 eXo Platform SAS.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see<http://www.gnu.org/licenses/>.
*/
package org.exoplatform.services.cms.thumbnail.impl;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.List;
import javax.imageio.ImageIO;
import javax.jcr.ItemExistsException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.exoplatform.container.component.ComponentPlugin;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.services.cms.impl.ImageUtils;
import org.exoplatform.services.cms.thumbnail.ThumbnailPlugin;
import org.exoplatform.services.cms.thumbnail.ThumbnailService;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.impl.core.NodeImpl;
import org.exoplatform.services.wcm.utils.WCMCoreUtils;
/**
* Created by The eXo Platform SARL
* Author : Dang Van Minh
* minh.dang@exoplatform.com
* Oct 10, 2008 1:58:10 PM
*/
public class ThumbnailServiceImpl implements ThumbnailService {
final private static String JCR_CONTENT = "jcr:content";
final private static String JCR_MIMETYPE = "jcr:mimeType";
final private static String JCR_DATA = "jcr:data";
final private static String NT_FILE = "nt:file";
private boolean isEnableThumbnail_ = false;
private String smallSize_;
private String mediumSize_;
private String bigSize_;
private String mimeTypes_;
private List<ComponentPlugin> plugins_ = new ArrayList<ComponentPlugin>();
public ThumbnailServiceImpl(InitParams initParams) throws Exception {
smallSize_ = initParams.getValueParam("smallSize").getValue();
mediumSize_ = initParams.getValueParam("mediumSize").getValue();
bigSize_ = initParams.getValueParam("bigSize").getValue();
mimeTypes_ = initParams.getValueParam("mimetypes").getValue();
isEnableThumbnail_ = Boolean.parseBoolean(initParams.getValueParam("enable").getValue());
}
/**
* {@inheritDoc}
*/
public List<Node> getFlowImages(Node node) throws Exception {
NodeIterator nodeIter = node.getNodes();
List<Node> listNodes = new ArrayList<Node>();
Node thumbnailNode = null;
while(nodeIter.hasNext()) {
Node childNode = nodeIter.nextNode();
thumbnailNode = addThumbnailNode(childNode);
if(thumbnailNode != null && thumbnailNode.isNodeType(EXO_THUMBNAIL) && thumbnailNode.hasProperty(BIG_SIZE)) {
listNodes.add(childNode);
}
}
return listNodes;
}
/**
* {@inheritDoc}
*/
public List<Node> getAllFileInNode(Node node) throws RepositoryException {
List<Node> fileListNodes = new ArrayList<Node>();
NodeIterator nodeIter = node.getNodes();
Node childNode = null;
while(nodeIter.hasNext()) {
childNode = nodeIter.nextNode();
if(childNode.isNodeType(NT_FILE)) {
fileListNodes.add(childNode);
}
}
return fileListNodes;
}
/**
* {@inheritDoc}
*/
public List<Node> getFileNodesByType(Node node, String jcrMimeType) throws RepositoryException {
List<Node> fileListNodes = getAllFileInNode(node);
List<Node> listNodes = new ArrayList<Node>();
Node contentNode = null;
for(Node childNode : fileListNodes) {
contentNode = childNode.getNode(JCR_CONTENT);
if(contentNode.getProperty(JCR_MIMETYPE).getString().equals(jcrMimeType)) {
listNodes.add(childNode);
}
}
return listNodes;
}
/**
* {@inheritDoc}
*/
public boolean isEnableThumbnail() {
return isEnableThumbnail_;
}
/**
* {@inheritDoc}
*/
public void setEnableThumbnail(boolean isEnable) {
isEnableThumbnail_ = isEnable;
}
/**
* {@inheritDoc}
*/
public InputStream getThumbnailImage(Node node, String thumbnailType) throws Exception {
Node thumbnailNode = addThumbnailNode(node);
if(thumbnailNode != null && thumbnailNode.hasProperty(thumbnailType)) {
return thumbnailNode.getProperty(thumbnailType).getStream();
}
return null;
}
/**
* {@inheritDoc}
*/
public void addThumbnailImage(Node thumbnailNode, BufferedImage image, String propertyName) throws Exception {
if(propertyName.equals(SMALL_SIZE)) parseImageSize(thumbnailNode, image, smallSize_, SMALL_SIZE);
else if(propertyName.equals(MEDIUM_SIZE)) parseImageSize(thumbnailNode, image, mediumSize_, MEDIUM_SIZE);
else if(propertyName.equals(BIG_SIZE)) parseImageSize(thumbnailNode, image, bigSize_, BIG_SIZE);
else parseImageSize(thumbnailNode, image, propertyName.substring(4), propertyName, false);
}
/**
* {@inheritDoc}
*/
public void createSpecifiedThumbnail(Node node, BufferedImage image, String propertyName) throws Exception {
addThumbnailImage(addThumbnailNode(node), image, propertyName);
}
/**
* {@inheritDoc}
*/
public void createThumbnailImage(Node node, BufferedImage image, String mimeType) throws Exception {
Node thumbnailNode = addThumbnailNode(node);
if(thumbnailNode != null) {
if(mimeType.startsWith("image")) processImage2Image(thumbnailNode, image);
thumbnailNode.setProperty(THUMBNAIL_LAST_MODIFIED, new GregorianCalendar());
thumbnailNode.getSession().save();
}
}
/**
* {@inheritDoc}
*/
public void processThumbnailList(List<Node> listNodes, String type) throws Exception {
for(Node node : listNodes) {
Node thumbnailNode = addThumbnailNode(node);
if(thumbnailNode != null && !thumbnailNode.hasProperty(THUMBNAIL_LAST_MODIFIED) &&
node.isNodeType(NT_FILE)) {
Node contentNode = node.getNode(JCR_CONTENT);
if(contentNode.getProperty(JCR_MIMETYPE).getString().startsWith("image")) {
BufferedImage image = ImageIO.read(contentNode.getProperty(JCR_DATA).getStream());
addThumbnailImage(thumbnailNode, image, type);
}
}
}
}
/**
* {@inheritDoc}
*/
public List<String> getMimeTypes() {
return Arrays.asList(mimeTypes_.split(";"));
}
/**
* {@inheritDoc}
*/
public Node addThumbnailNode(Node node) throws Exception {
Node parentNode = node.getParent();
Node thumbnailFolder = ThumbnailUtils.getThumbnailFolder(parentNode);
String identifier = ((NodeImpl) node).getInternalIdentifier();
Node thumbnailNode = ThumbnailUtils.getThumbnailNode(thumbnailFolder, identifier);
return thumbnailNode;
}
/**
* {@inheritDoc}
*/
public Node getThumbnailNode(Node node) throws Exception {
try {
String nodePath = node.getPath();
String thumPath = nodePath.replace(nodePath.substring(nodePath.lastIndexOf("/") + 1), EXO_THUMBNAILS_FOLDER);
Node thumbnailFolder = (Node)node.getSession().getItem(thumPath);
return thumbnailFolder.getNode(((NodeImpl) node).getInternalIdentifier());
} catch(Exception e) {
return null;
}
}
/**
* {@inheritDoc}
*/
public void processRemoveThumbnail(Node showingNode) throws Exception {
Node parentNode = showingNode.getParent();
if(parentNode.hasNode(EXO_THUMBNAILS_FOLDER)) {
Node thumbnailFolder = parentNode.getNode(EXO_THUMBNAILS_FOLDER);
try {
String workspace = parentNode.getSession().getWorkspace().getName();
RepositoryService repositoryService = WCMCoreUtils.getService(RepositoryService.class);
Session systemSession = WCMCoreUtils.getSystemSessionProvider().getSession(workspace, repositoryService.getCurrentRepository());
thumbnailFolder = (Node) systemSession.getItem(thumbnailFolder.getPath());
thumbnailFolder.getNode(((NodeImpl) showingNode).getInternalIdentifier()).remove();
thumbnailFolder.getSession().save();
} catch(PathNotFoundException path) {
return;
}
}
}
/**
* {@inheritDoc}
*/
public void copyThumbnailNode(Node srcThumbnailNode, Node destNode) throws Exception {
// Validate arguments
if (srcThumbnailNode == null || destNode == null) {
return;
}
// Copy thumbnail to destination node
Node destThumbnailNode = this.addThumbnailNode(destNode);
if (srcThumbnailNode.hasProperty(SMALL_SIZE)) {
destThumbnailNode.setProperty(SMALL_SIZE, srcThumbnailNode.getProperty(SMALL_SIZE).getValue());
}
if (srcThumbnailNode.hasProperty(MEDIUM_SIZE)) {
destThumbnailNode.setProperty(MEDIUM_SIZE, srcThumbnailNode.getProperty(MEDIUM_SIZE).getValue());
}
if (srcThumbnailNode.hasProperty(BIG_SIZE)) {
destThumbnailNode.setProperty(BIG_SIZE, srcThumbnailNode.getProperty(BIG_SIZE).getValue());
}
destThumbnailNode.save();
}
public void addPlugin(ComponentPlugin plugin) {
if(plugin instanceof ThumbnailPlugin) plugins_.add(plugin);
}
public List<ComponentPlugin> getComponentPlugins() {
return plugins_;
}
/**
* Put data from image to 3 property : exo:smallSizes, exo:mediumSizes, exo:bigSizes
* with each property, image is parsed to correlative size
* @param node
* @param image
* @throws Exception
*/
private void processImage2Image(Node node, BufferedImage image) throws Exception {
parseImageSize(node, image, smallSize_, SMALL_SIZE);
parseImageSize(node, image, mediumSize_, MEDIUM_SIZE);
parseImageSize(node, image, bigSize_, BIG_SIZE);
}
/**
* Put image data to property name of node with given height and width
* @param thumbnailNode
* @param image
* @param width
* @param height
* @param propertyName
* @throws Exception
*/
private void createThumbnailImage(Node thumbnailNode, BufferedImage image, int width, int height,
String propertyName, boolean crop) throws Exception {
if (width>1600) width=1600;
if (height>1600) height=1600;
InputStream thumbnailStream = ImageUtils.scaleImage(image, width, height, crop);
try {
thumbnailNode.setProperty(propertyName, thumbnailStream);
thumbnailNode.getSession().save();
thumbnailNode.setProperty(THUMBNAIL_LAST_MODIFIED, new GregorianCalendar());
thumbnailNode.getSession().save();
} catch (ItemExistsException e) {
return;
} finally {
thumbnailStream.close();
}
}
/**
* Analysis size which has format (width x height) and call method createThumbnailImage
* to put data into propertyName of node
* @param node
* @param image
* @param size
* @param propertyName
* @throws Exception
*/
private void parseImageSize(Node node, BufferedImage image, String size, String propertyName) throws Exception {
parseImageSize(node, image, size, propertyName, false);
}
/**
* Analysis size which has format (width x height) and call method createThumbnailImage
* to put data into propertyName of node
* @param node
* @param image
* @param size
* @param propertyName
* @throws Exception
*/
private void parseImageSize(Node node, BufferedImage image, String size, String propertyName, boolean crop) throws Exception {
int width = 0;
int height = 0;
if (size.startsWith("x")) {
height = Integer.parseInt(size.substring(1));
} else if (size.endsWith("x")) {
width = Integer.parseInt(size.substring(0, size.length()-1));
} else if(size.indexOf("x") > -1) {
String[] imageSize = size.split("x");
width = Integer.parseInt(imageSize[0]);
height = Integer.parseInt(imageSize[1]);
}
createThumbnailImage(node, image, width, height, propertyName, crop);
}
}