/* * Copyright (C) 2005-2010 Alfresco Software Limited. * * This file is part of Alfresco * * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Alfresco 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ package org.alfresco.opencmis; import java.io.Serializable; import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.alfresco.model.ContentModel; import org.alfresco.repo.rendition.executer.ImageRenderingEngine; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.rendition.RenditionDefinition; import org.alfresco.service.cmr.rendition.RenditionService; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; import org.apache.chemistry.opencmis.commons.data.RenditionData; import org.apache.chemistry.opencmis.commons.exceptions.CmisFilterNotValidException; import org.apache.chemistry.opencmis.commons.impl.dataobjects.RenditionDataImpl; public class CMISRenditionMapping { private NodeService nodeService; private ContentService contentService; private RenditionService renditionService; private TransactionService transactionService; private Map> kindToRenditionNames; private Map renditionNamesToKind; private Map renditionNameToSize; public CMISRenditionMapping(NodeService nodeService, ContentService contentService, RenditionService renditionService, TransactionService transactionService, Map> renditionKinds) { this.nodeService = nodeService; this.contentService = contentService; this.renditionService = renditionService; this.transactionService = transactionService; if (renditionKinds == null) { this.kindToRenditionNames = new HashMap>(); } else { this.kindToRenditionNames = renditionKinds; } renditionNamesToKind = new HashMap(); for (Entry> entry : renditionKinds.entrySet()) { for (String renditionName : entry.getValue()) { renditionNamesToKind.put(renditionName, entry.getKey()); } } cacheRenditionSizes(); } private void cacheRenditionSizes() { renditionNameToSize = AuthenticationUtil.runAs(new RunAsWork>() { public Map doWork() throws Exception { return transactionService.getRetryingTransactionHelper().doInTransaction( new RetryingTransactionCallback>() { public Map execute() throws Exception { Map rn2s = new HashMap(); List allRenditionDefs = renditionService .loadRenditionDefinitions(); for (RenditionDefinition rd : allRenditionDefs) { QName renditionDefinitionName = rd.getRenditionName(); Number width = (Number) rd .getParameterValue(ImageRenderingEngine.PARAM_RESIZE_WIDTH); Number height = (Number) rd .getParameterValue(ImageRenderingEngine.PARAM_RESIZE_HEIGHT); if ((width != null) || (height != null)) { BigInteger[] size = new BigInteger[2]; size[0] = (width == null ? null : BigInteger.valueOf(width.longValue())); size[1] = (height == null ? null : BigInteger.valueOf(height.longValue())); rn2s.put(renditionDefinitionName.getLocalName(), size); } } return rn2s; }; }, true); } }, AuthenticationUtil.getSystemUserName()); } public List getRenditions(NodeRef nodeRef, String renditionFilter, BigInteger maxItems, BigInteger skipCount) { List result = new ArrayList(); // split the filter Set filterSet = splitRenditionFilter(renditionFilter); if ((filterSet != null) && (filterSet.contains(CMISConnector.RENDITION_NONE))) { // "cmis:none" found -> no renditions return result; } // convert BigIntegers to int int max = (maxItems == null ? Integer.MAX_VALUE : maxItems.intValue()); int skip = (skipCount == null || skipCount.intValue() < 0 ? 0 : skipCount.intValue()); if (max > 0) { // find all renditions and filter them List renditionList = renditionService.getRenditions(nodeRef); int lastIndex = (max + skip > renditionList.size() ? renditionList.size() : max + skip) - 1; for (int i = skip; i <= lastIndex; i++) { ChildAssociationRef rendition = renditionList.get(i); NodeRef rendNodeRef = rendition.getChildRef(); String rendName = rendition.getQName().getLocalName(); // get and check content QName contentProperty = ContentModel.PROP_CONTENT; Serializable contentPropertyName = nodeService.getProperty(rendNodeRef, ContentModel.PROP_CONTENT_PROPERTY_NAME); if (contentPropertyName != null) { contentProperty = (QName) contentPropertyName; } ContentReader reader = contentService.getReader(rendNodeRef, contentProperty); if ((reader == null) || (!reader.exists())) { // no content -> no rendition continue; } // get and clean MIME type String mimeType = reader.getMimetype(); if (mimeType.indexOf(';') > 3) { mimeType = mimeType.substring(0, mimeType.indexOf(';')).trim(); } // if a filter is set, check it if (filterSet != null) { boolean include = false; for (String f : filterSet) { if (f.indexOf('/') == -1) { // found a kind, not a MIME type List renditionNames = kindToRenditionNames.get(f); if (renditionNames != null && renditionNames.contains(rendName)) { include = true; break; } } else if (f.endsWith("*")) { // found MIME type with wildcard if (mimeType.startsWith(f.substring(0, f.length() - 2))) { include = true; break; } } else { // found complete MIME type if (mimeType.equals(f)) { include = true; break; } } } // if no filter matches, skip this rendition if (!include) { continue; } } // gather rendition data String title = rendName; String kind = (renditionNamesToKind.containsKey(rendName) ? renditionNamesToKind.get(rendName) : rendName); BigInteger length = BigInteger.valueOf(reader.getSize()); BigInteger width = null; BigInteger height = null; if (renditionNameToSize.containsKey(rendName)) { BigInteger[] size = renditionNameToSize.get(rendName); width = size[0]; height = size[1]; } // finally add this rendition result.add(createRenditionData(rendNodeRef, mimeType, title, kind, length, width, height)); } } if (filterSet == null || filterSet.contains("cmis:thumbnail")) { } return result; } private Set splitRenditionFilter(String filter) { if (filter == null) { return null; } if (filter.trim().length() == 0) { return null; } Set result = new HashSet(); for (String s : filter.split(",")) { s = s.trim(); if (s.equals("*")) { return null; } else if (s.indexOf('*') > -1) { if (!s.endsWith("*")) { throw new CmisFilterNotValidException("Rendition filter is invalid: " + s); } result.add(s); } else if (s.equalsIgnoreCase(CMISConnector.RENDITION_NONE)) { result.clear(); result.add(CMISConnector.RENDITION_NONE); break; } else if (s.length() > 0) { result.add(s); } } return result; } private RenditionData createRenditionData(NodeRef rendNodeRef, String mimeType, String title, String kind, BigInteger length, BigInteger width, BigInteger height) { RenditionDataImpl result = new RenditionDataImpl(); result.setStreamId(rendNodeRef.getId()); result.setMimeType(mimeType); result.setTitle(title); result.setKind(kind); result.setBigLength(length); result.setBigWidth(width); result.setBigHeight(height); result.setRenditionDocumentId(rendNodeRef.getId()); return result; } }