001/* 002 * (C) Copyright 2010 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * Contributors: 014 * Nuxeo - initial API and implementation 015 */ 016package org.nuxeo.ecm.platform.rendition.service; 017 018import static org.nuxeo.ecm.platform.rendition.Constants.FILES_FILES_PROPERTY; 019import static org.nuxeo.ecm.platform.rendition.Constants.FILES_SCHEMA; 020import static org.nuxeo.ecm.platform.rendition.Constants.RENDITION_FACET; 021import static org.nuxeo.ecm.platform.rendition.Constants.RENDITION_NAME_PROPERTY; 022import static org.nuxeo.ecm.platform.rendition.Constants.RENDITION_SOURCE_ID_PROPERTY; 023import static org.nuxeo.ecm.platform.rendition.Constants.RENDITION_SOURCE_VERSIONABLE_ID_PROPERTY; 024 025import java.io.Serializable; 026import java.util.ArrayList; 027import java.util.Map; 028 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031import org.nuxeo.ecm.core.api.Blob; 032import org.nuxeo.ecm.core.api.CoreSession; 033import org.nuxeo.ecm.core.api.DocumentModel; 034import org.nuxeo.ecm.core.api.DocumentModelList; 035import org.nuxeo.ecm.core.api.DocumentRef; 036import org.nuxeo.ecm.core.api.IdRef; 037import org.nuxeo.ecm.core.api.LifeCycleConstants; 038import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner; 039import org.nuxeo.ecm.core.api.VersioningOption; 040import org.nuxeo.ecm.core.api.blobholder.BlobHolder; 041import org.nuxeo.ecm.core.api.blobholder.DocumentStringBlobHolder; 042import org.nuxeo.ecm.core.api.security.ACE; 043import org.nuxeo.ecm.core.api.security.ACL; 044import org.nuxeo.ecm.core.api.security.ACP; 045import org.nuxeo.ecm.core.api.security.SecurityConstants; 046import org.nuxeo.ecm.core.api.security.impl.ACLImpl; 047import org.nuxeo.ecm.core.api.security.impl.ACPImpl; 048import org.nuxeo.ecm.core.versioning.VersioningService; 049import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeEntry; 050import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeRegistry; 051import org.nuxeo.runtime.api.Framework; 052 053/** 054 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a> 055 */ 056public class RenditionCreator extends UnrestrictedSessionRunner { 057 058 private static final Log log = LogFactory.getLog(RenditionCreator.class); 059 060 public static final String FILE = "File"; 061 062 protected DocumentRef renditionRef; 063 064 protected DocumentModel detachedDendition; 065 066 protected String liveDocumentId; 067 068 protected DocumentRef versionDocumentRef; 069 070 protected Blob renditionBlob; 071 072 protected String renditionName; 073 074 public RenditionCreator(CoreSession session, DocumentModel liveDocument, DocumentModel versionDocument, 075 Blob renditionBlob, String renditionName) { 076 super(session); 077 liveDocumentId = liveDocument.getId(); 078 versionDocumentRef = versionDocument.getRef(); 079 this.renditionBlob = renditionBlob; 080 this.renditionName = renditionName; 081 } 082 083 public DocumentRef getRenditionDocumentRef() { 084 return renditionRef; 085 } 086 087 public DocumentModel getDetachedDendition() { 088 return detachedDendition; 089 } 090 091 @Override 092 public void run() { 093 DocumentModel versionDocument = session.getDocument(versionDocumentRef); 094 DocumentModel rendition = createRenditionDocument(versionDocument); 095 removeBlobs(rendition); 096 updateMainBlob(rendition); 097 updateIconAndSizeFields(rendition); 098 099 // create a copy of the doc 100 if(rendition.getId()==null) { 101 rendition = session.createDocument(rendition); 102 } 103 // be sure to have the same version info 104 setCorrectVersion(rendition, versionDocument); 105 // set ACL 106 // giveReadRightToUser(rendition); 107 // do not apply default versioning to rendition 108 rendition.putContextData(VersioningService.VERSIONING_OPTION, VersioningOption.NONE); 109 rendition = session.saveDocument(rendition); 110 111 // rendition is checkout : make it checkin 112 renditionRef = rendition.checkIn(VersioningOption.NONE, null); 113 rendition = session.getDocument(renditionRef); 114 session.save(); 115 116 rendition.detach(true); 117 detachedDendition = rendition; 118 } 119 120 protected DocumentModel createRenditionDocument(DocumentModel versionDocument) { 121 String doctype = versionDocument.getType(); 122 String renditionMimeType = renditionBlob.getMimeType(); 123 if (versionDocument.getAdapter(BlobHolder.class) instanceof DocumentStringBlobHolder 124 && !(renditionMimeType.startsWith("text/") || renditionMimeType.startsWith("application/xhtml"))) { 125 // We have a Note or other blob holder that can only hold strings, but the rendition is not a string-related 126 // MIME type. We'll have to create a File instead to hold it. 127 doctype = FILE; 128 } 129 130 DocumentModel rendition=null; 131 DocumentModelList existingRenditions = session.query("select * from " + doctype + " where ecm:isProxy = 0 AND ecm:mixinType ='" 132 + RENDITION_FACET + "' AND " + RENDITION_SOURCE_VERSIONABLE_ID_PROPERTY + "='" + liveDocumentId 133 + "' and " + RENDITION_NAME_PROPERTY + "='" + renditionName + "'"); 134 if (existingRenditions.size() > 0) { 135 rendition = existingRenditions.get(0); 136 if (rendition.isVersion()) { 137 String sid = rendition.getVersionSeriesId(); 138 rendition = session.getDocument(new IdRef(sid)); 139 } 140 } else { 141 rendition = session.createDocumentModel(null, versionDocument.getName(), doctype); 142 } 143 144 rendition.copyContent(versionDocument); 145 rendition.getContextData().putScopedValue(LifeCycleConstants.INITIAL_LIFECYCLE_STATE_OPTION_NAME, 146 versionDocument.getCurrentLifeCycleState()); 147 148 rendition.addFacet(RENDITION_FACET); 149 rendition.setPropertyValue(RENDITION_SOURCE_ID_PROPERTY, versionDocument.getId()); 150 rendition.setPropertyValue(RENDITION_SOURCE_VERSIONABLE_ID_PROPERTY, liveDocumentId); 151 rendition.setPropertyValue(RENDITION_NAME_PROPERTY, renditionName); 152 153 return rendition; 154 } 155 156 protected void removeBlobs(DocumentModel rendition) { 157 if (rendition.hasSchema(FILES_SCHEMA)) { 158 rendition.setPropertyValue(FILES_FILES_PROPERTY, new ArrayList<Map<String, Serializable>>()); 159 } 160 } 161 162 protected void updateMainBlob(DocumentModel rendition) { 163 BlobHolder bh = rendition.getAdapter(BlobHolder.class); 164 bh.setBlob(renditionBlob); 165 } 166 167 private void updateIconAndSizeFields(DocumentModel rendition) { 168 if (!rendition.hasSchema("common")) { 169 return; 170 } 171 MimetypeRegistry mimetypeService; 172 try { 173 mimetypeService = Framework.getService(MimetypeRegistry.class); 174 } catch (Exception e) { 175 log.error("Cannot fetch Mimetype service when updating icon and file size rendition", e); 176 return; 177 } 178 MimetypeEntry mimetypeEntry = mimetypeService.getMimetypeEntryByMimeType(renditionBlob.getMimeType()); 179 if (mimetypeEntry != null && mimetypeEntry.getIconPath() != null) { 180 rendition.setPropertyValue("common:icon", "/icons/" + mimetypeEntry.getIconPath()); 181 } 182 rendition.setPropertyValue("common:size", renditionBlob.getLength()); 183 } 184 185 protected void giveReadRightToUser(DocumentModel rendition) { 186 ACP acp = new ACPImpl(); 187 ACL acl = new ACLImpl(); 188 acp.addACL(acl); 189 ACE ace = new ACE(getOriginatingUsername(), SecurityConstants.READ, true); 190 acl.add(ace); 191 rendition.setACP(acp, true); 192 } 193 194 protected void setCorrectVersion(DocumentModel rendition, DocumentModel versionDocument) { 195 Long minorVersion = (Long) versionDocument.getPropertyValue("uid:minor_version"); // - 196 // 1L; 197 rendition.setPropertyValue("uid:minor_version", minorVersion); 198 rendition.setPropertyValue("uid:major_version", versionDocument.getPropertyValue("uid:major_version")); 199 } 200 201}