/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.chemistry.opencmis.inmemory.storedobj.impl; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import org.apache.chemistry.opencmis.commons.data.ContentStream; import org.apache.chemistry.opencmis.commons.data.RenditionData; import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException; import org.apache.chemistry.opencmis.commons.impl.IOUtils; import org.apache.chemistry.opencmis.commons.impl.dataobjects.RenditionDataImpl; import org.apache.chemistry.opencmis.inmemory.storedobj.api.Content; import org.apache.chemistry.opencmis.inmemory.storedobj.api.Folder; import org.apache.chemistry.opencmis.inmemory.storedobj.api.StoredObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RenditionUtil { private static final Logger LOG = LoggerFactory.getLogger(RenditionUtil.class.getName()); private static final int BUFFER_SIZE = 65536; public static final String RENDITION_MIME_TYPE_JPEG = "image/jpeg"; public static final String RENDITION_MIME_TYPE_PNG = "image/png"; public static final String RENDITION_SUFFIX = "-rendition"; public static final int THUMBNAIL_SIZE = 100; public static final int ICON_SIZE = 32; public static boolean hasRendition(StoredObject so, String user) { if (so instanceof Folder) { return true; } else if (so instanceof Content) { ContentStream contentStream = ((Content)so).getContent(); if (null == contentStream) { return false; } String mimeType = contentStream.getMimeType(); return isImage(mimeType) || isAudio(mimeType) || isVideo(mimeType) || isPDF(mimeType) || isPowerpoint(mimeType) || isExcel(mimeType) || isWord(mimeType) || isHtml(mimeType) || isPlainText(mimeType); } else { return false; } } private static boolean isImage(String mimeType) { return mimeType.startsWith("image/"); } private static boolean isWord(String mimeType) { return mimeType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document") || mimeType.equals("application/ms-word"); } private static boolean isExcel(String mimeType) { return mimeType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") || mimeType.equals("application/vnd.ms-excel"); } private static boolean isPowerpoint(String mimeType) { return mimeType.equals("application/vnd.openxmlformats-officedocument.presentationml.slideshow") || mimeType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation") || mimeType.equals("application/vnd.ms-powerpoint"); } private static boolean isPDF(String mimeType) { return mimeType.equals("application/pdf"); } private static boolean isHtml(String mimeType) { return mimeType.equals("text/html"); } private static boolean isAudio(String mimeType) { return mimeType.startsWith("audio/"); } private static boolean isVideo(String mimeType) { return mimeType.startsWith("video/"); } private static boolean isPlainText(String mimeType) { return mimeType.equals("text/plain"); } public static ContentStream getIconFromResourceDir(String name) throws IOException { InputStream imageStream = StoredObjectImpl.class.getResourceAsStream(name); ByteArrayOutputStream ba = new ByteArrayOutputStream(); byte[] buffer = new byte[BUFFER_SIZE]; int noBytesRead = 0; try { while ((noBytesRead = imageStream.read(buffer)) >= 0) { ba.write(buffer, 0, noBytesRead); } } finally { IOUtils.closeQuietly(ba); IOUtils.closeQuietly(imageStream); } ContentStreamDataImpl content = new ContentStreamDataImpl(0); content.setFileName(name); content.setMimeType("image/png"); content.setContent(new ByteArrayInputStream(ba.toByteArray())); return content; } public static boolean testRenditionFilterForImage(String[] formats) { if (formats.length == 1 && null != formats[0] && formats[0].equals("cmis:none")) { return false; } else { return arrayContainsString(formats, "*") || arrayContainsString(formats, "image/*") || arrayContainsString(formats, "image/jpeg"); } } private static boolean arrayContainsString(String[] formats, String val) { for (String s : formats) { if (val.equals(s)) { return true; } } return false; } public static ContentStream getRenditionContent(StoredObject so, String streamId, long offset, long length) { if (so instanceof Folder) { return RenditionUtil.getFolderRenditionContent(streamId, offset, length); } if (!(so instanceof Content)) { throw new CmisInvalidArgumentException("Only objects with content can have a rendition"); } ContentStream contentStream = ((Content)so).getContent(); if (null == contentStream) { return null; } String mimeType = contentStream.getMimeType(); try { if (isImage(mimeType)) { ImageThumbnailGenerator generator = new ImageThumbnailGenerator(contentStream.getStream()); return generator.getRendition(THUMBNAIL_SIZE, 0); } else if (isAudio(mimeType)) { return getIconFromResourceDir("/audio-x-generic.png"); } else if (isVideo(mimeType)) { return getIconFromResourceDir("/video-x-generic.png"); } else if (isPDF(mimeType)) { return getIconFromResourceDir("/application-pdf.png"); } else if (isWord(mimeType)) { return getIconFromResourceDir("/application-msword.png"); } else if (isPowerpoint(mimeType)) { return getIconFromResourceDir("/application-vnd.ms-powerpoint.png"); } else if (isExcel(mimeType)) { return getIconFromResourceDir("/application-vnd.ms-excel.png"); } else if (isHtml(mimeType)) { return getIconFromResourceDir("/text-html.png"); } else if (isPlainText(mimeType)) { return getIconFromResourceDir("/text-x-generic.png"); } else { return null; } } catch (IOException e) { LOG.error("Failed to generate rendition: ", e); throw new CmisRuntimeException("Failed to generate rendition: " + e); } } private static ContentStream getFolderRenditionContent(String streamId, long offset, long length) { try { return getIconFromResourceDir("/folder.png"); } catch (IOException e) { LOG.error("Failed to generate rendition: ", e); throw new CmisRuntimeException("Failed to generate rendition: " + e); } } public static List<RenditionData> getRenditions(StoredObject so, String renditionFilter, long maxItems, long skipCount) { String tokenizer = "[\\s;]"; if (null == renditionFilter) { return null; } String[] formats = renditionFilter.split(tokenizer); boolean isImageRendition = RenditionUtil.testRenditionFilterForImage(formats); if (!(so instanceof Content) && !(so instanceof Folder)) { return null; } if (isImageRendition && hasRendition(so, null)) { String mimeType; if (so instanceof Folder) { mimeType = "image/png"; } else { ContentStream contentStream = ((Content)so).getContent(); mimeType = contentStream.getMimeType(); } List<RenditionData> renditions = new ArrayList<RenditionData>(1); RenditionDataImpl rendition = new RenditionDataImpl(); if (mimeType.equals("image/jpeg")) { rendition.setBigHeight(BigInteger.valueOf(THUMBNAIL_SIZE)); rendition.setBigWidth(BigInteger.valueOf(THUMBNAIL_SIZE)); rendition.setMimeType(RENDITION_MIME_TYPE_JPEG); } else { rendition.setBigHeight(BigInteger.valueOf(ICON_SIZE)); rendition.setBigWidth(BigInteger.valueOf(ICON_SIZE)); rendition.setMimeType(RENDITION_MIME_TYPE_PNG); } rendition.setKind("cmis:thumbnail"); rendition.setRenditionDocumentId(so.getId()); rendition.setStreamId(so.getId() + RENDITION_SUFFIX); rendition.setBigLength(BigInteger.valueOf(-1L)); rendition.setTitle(so.getName()); renditions.add(rendition); return renditions; } else { return null; } } }