001/* 002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * <a href="mailto:tdelprat@nuxeo.com">Tiry</a> 018 */ 019package org.nuxeo.ecm.platform.rendition.lazy; 020 021import java.util.ArrayList; 022import java.util.List; 023 024import org.apache.commons.logging.Log; 025import org.apache.commons.logging.LogFactory; 026import org.nuxeo.ecm.core.api.Blob; 027import org.nuxeo.ecm.core.api.CoreSession; 028import org.nuxeo.ecm.core.api.DocumentModel; 029import org.nuxeo.ecm.core.api.DocumentRef; 030import org.nuxeo.ecm.core.api.NuxeoException; 031import org.nuxeo.ecm.core.api.impl.blob.StringBlob; 032import org.nuxeo.ecm.core.transientstore.api.TransientStore; 033import org.nuxeo.ecm.core.transientstore.api.TransientStoreService; 034import org.nuxeo.ecm.core.transientstore.work.TransientStoreWork; 035import org.nuxeo.ecm.platform.rendition.extension.RenditionProvider; 036import org.nuxeo.ecm.platform.rendition.impl.LazyRendition; 037import org.nuxeo.ecm.platform.rendition.service.RenditionDefinition; 038import org.nuxeo.ecm.platform.rendition.service.RenditionService; 039import org.nuxeo.ecm.platform.rendition.service.RenditionServiceImpl; 040import org.nuxeo.runtime.api.Framework; 041 042/** 043 * @author <a href="mailto:tdelprat@nuxeo.com">Tiry</a> 044 * @since 7.2 045 */ 046public abstract class AbstractRenditionBuilderWork extends TransientStoreWork { 047 048 private static final long serialVersionUID = 1L; 049 050 protected String key; 051 052 protected final DocumentRef docRef; 053 054 protected final String repositoryName; 055 056 protected final String renditionName; 057 058 protected static Log log = LogFactory.getLog(AbstractRenditionBuilderWork.class); 059 060 public static final String CATEGORY = "renditionBuilder"; 061 062 public AbstractRenditionBuilderWork(String key, DocumentModel doc, RenditionDefinition def) { 063 this.key = key; 064 docRef = doc.getRef(); 065 repositoryName = doc.getRepositoryName(); 066 renditionName = def.getName(); 067 setOriginatingUsername(doc.getCoreSession().getPrincipal().getName()); 068 this.id = buildId(doc, def); 069 } 070 071 protected String buildId(DocumentModel doc, RenditionDefinition def) { 072 StringBuffer sb = new StringBuffer("rendition:"); 073 sb.append(doc.getId()); 074 String variant = def.getProvider().getVariant(doc, def); 075 if (variant != null) { 076 sb.append("::"); 077 sb.append(variant); 078 } 079 sb.append("::"); 080 sb.append(def.getName()); 081 return sb.toString(); 082 } 083 084 @Override 085 public String getTitle() { 086 return "Lazy Rendition for " + renditionName + " on " + docRef.toString() 087 + " on behalf of " + originatingUsername; 088 } 089 090 @Override 091 public String getCategory() { 092 return CATEGORY; 093 } 094 095 protected String getTransientStoreName() { 096 return AbstractLazyCachableRenditionProvider.CACHE_NAME; 097 } 098 099 @Override 100 public void work() { 101 openUserSession(); 102 DocumentModel doc = session.getDocument(docRef); 103 104 RenditionService rs = Framework.getService(RenditionService.class); 105 RenditionDefinition def = ((RenditionServiceImpl) rs).getRenditionDefinition(renditionName); 106 107 RenditionProvider renditionProvider = def.getProvider(); 108 if (renditionProvider instanceof AbstractLazyCachableRenditionProvider) { 109 String rendKey = ((AbstractLazyCachableRenditionProvider) renditionProvider).buildRenditionKey(doc, def); 110 if (!rendKey.equals(key)) { 111 refreshStoreEntry(rendKey); 112 this.key = rendKey; 113 } 114 } 115 116 List<Blob> blobs = doComputeRendition(session, doc, def); 117 updateAndCompleteStoreEntry(blobs); 118 } 119 120 @Override 121 public void cleanUp(boolean ok, Exception e) { 122 super.cleanUp(ok, e); 123 if (ok) { 124 return; 125 } 126 List<Blob> blobs = new ArrayList<Blob>(); 127 StringBlob emptyBlob = new StringBlob(""); 128 emptyBlob.setFilename("error"); 129 emptyBlob.setMimeType("text/plain;" + LazyRendition.ERROR_MARKER); 130 blobs.add(emptyBlob); 131 updateAndCompleteStoreEntry(blobs); 132 } 133 134 void refreshStoreEntry(String renditionKey) { 135 TransientStoreService tss = Framework.getService(TransientStoreService.class); 136 TransientStore ts = tss.getStore(getTransientStoreName()); 137 138 // Release old key 139 if (ts.exists(key)) { 140 ts.release(key); 141 } 142 ts.putParameter(renditionKey, AbstractLazyCachableRenditionProvider.WORKERID_KEY, getId()); 143 List<Blob> blobs = new ArrayList<Blob>(); 144 StringBlob emptyBlob = new StringBlob(""); 145 emptyBlob.setFilename("inprogress"); 146 emptyBlob.setMimeType("text/plain;" + LazyRendition.EMPTY_MARKER); 147 blobs.add(emptyBlob); 148 ts.putBlobs(renditionKey, blobs); 149 } 150 151 void updateAndCompleteStoreEntry(List<Blob> blobs) { 152 TransientStoreService tss = Framework.getService(TransientStoreService.class); 153 TransientStore ts = tss.getStore(getTransientStoreName()); 154 155 if (!ts.exists(key)) { 156 throw new NuxeoException("Rendition TransientStore entry can not be null"); 157 } 158 ts.putBlobs(key, blobs); 159 ts.setCompleted(key, true); 160 } 161 162 /** 163 * Does the actual Rendition Computation : this code will be called from inside an Asynchronous Work 164 * 165 * @param session 166 * @param doc 167 * @param def 168 * @return 169 */ 170 protected abstract List<Blob> doComputeRendition(CoreSession session, DocumentModel doc, RenditionDefinition def); 171 172}