001/* 002 * Copyright 2014 Anyware Services 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 */ 016package org.ametys.plugins.flipbook; 017 018import java.util.Arrays; 019import java.util.Iterator; 020import java.util.List; 021 022import org.apache.avalon.framework.logger.LogEnabled; 023import org.apache.avalon.framework.logger.Logger; 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.cocoon.components.ContextHelper; 027import org.apache.cocoon.environment.Request; 028 029import org.ametys.cms.data.Binary; 030import org.ametys.cms.repository.Content; 031import org.ametys.cms.transformation.URIResolver; 032import org.ametys.core.util.FilenameUtils; 033import org.ametys.core.util.URIUtils; 034import org.ametys.plugins.repository.AmetysObjectResolver; 035import org.ametys.plugins.repository.UnknownAmetysObjectException; 036import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder; 037import org.ametys.plugins.repository.data.holder.group.impl.ModelAwareRepeater; 038import org.ametys.plugins.repository.data.type.ModelItemTypeConstants; 039import org.ametys.plugins.repository.metadata.MetadataAwareAmetysObject; 040import org.ametys.runtime.model.ModelItem; 041import org.ametys.runtime.plugin.component.PluginAware; 042import org.ametys.web.editor.MetadataURIResolver; 043 044/** 045 * {@link URIResolver} for type "metadata-flipbook".<br> 046 * These links point to a document file from the resource explorer converted to flash. 047 */ 048public class Metadata2FlipbookUriResolver extends MetadataURIResolver implements PluginAware, LogEnabled 049{ 050 /** The plugin name. */ 051 protected String _pluginName; 052 053 /** The logger . */ 054 protected Logger _logger; 055 056 /** Metadata to images convertor. */ 057 protected ConvertMetadata2ImagesComponent _metadataComponent; 058 059 @Override 060 public void service(ServiceManager serviceManager) throws ServiceException 061 { 062 super.service(serviceManager); 063 _metadataComponent = (ConvertMetadata2ImagesComponent) serviceManager.lookup(ConvertMetadata2ImagesComponent.ROLE); 064 } 065 066 @Override 067 public void setPluginInfo(String pluginName, String featureName, String id) 068 { 069 _pluginName = pluginName; 070 } 071 072 @Override 073 public void enableLogging(Logger logger) 074 { 075 _logger = logger; 076 } 077 078 @Override 079 public String getType() 080 { 081 return "metadata-flipbook"; 082 } 083 084 @Override 085 public String resolve(String uri, boolean download, boolean absolute, boolean internal) 086 { 087 Request request = ContextHelper.getRequest(_context); 088 089 String metadataPath; 090 String fileName; 091 String siteName = (String) request.getAttribute("site"); 092 MetadataAwareAmetysObject object; 093 try 094 { 095 MetaInfo metaInfo = _getMetaInfo(uri, request); 096 097 metadataPath = metaInfo.getMetadataPath(); 098 object = metaInfo.getAmetysObject(); 099 100 fileName = object.getName(); 101 } 102 catch (UnknownAmetysObjectException e) 103 { 104 return ""; 105 } 106 107 Content content = (Content) object; 108 String resultPath = (absolute ? _prefixHandler.getAbsoluteUriPrefix(siteName) : _prefixHandler.getUriPrefix(siteName)) 109 + "/_plugins/" + _pluginName + "/" + siteName 110 + "/_metadata-flipbook/" 111 + fileName 112 + "/" 113 + metadataPath 114 + "/_contents" 115 + FilenameUtils.encodePath(content.getPath()) 116 + "/book.html"; 117 118 Binary binary = _getBinary(metadataPath, content); 119 120 if (!_metadataComponent.isMimeTypeSupported(binary.getMimeType())) 121 { 122 return super.resolve(uri, download, absolute, internal); 123 } 124 125 new CacheThread(content.getId(), metadataPath, siteName, _resolver, _logger).start(); 126 127 // Encode twice 128 return URIUtils.encodePath(resultPath.toString()); 129 } 130 131 @Override 132 public String resolveImage(String uri, int height, int width, boolean download, boolean absolute, boolean internal) 133 { 134 Request request = ContextHelper.getRequest(_context); 135 136 String metadataPath; 137 String siteName = (String) request.getAttribute("site"); 138 MetadataAwareAmetysObject object; 139 try 140 { 141 MetaInfo metaInfo = _getMetaInfo(uri, request); 142 143 metadataPath = metaInfo.getMetadataPath(); 144 object = metaInfo.getAmetysObject(); 145 } 146 catch (UnknownAmetysObjectException e) 147 { 148 return ""; 149 } 150 151 Content content = (Content) object; 152 Binary binary = _getBinary(metadataPath, content); 153 154 if (!_metadataComponent.isMimeTypeSupported(binary.getMimeType())) 155 { 156 String defaultPath = (absolute ? _prefixHandler.getAbsoluteUriPrefix(siteName) : _prefixHandler.getUriPrefix(siteName)) 157 + "/_plugins/" + _pluginName + "/" + siteName 158 + "/pages" 159 + "/error" 160 + "/thumbnail_" 161 + height + "x" + width 162 + ".png"; 163 164 return URIUtils.encodePath(defaultPath); 165 } 166 167 String result = (absolute ? _prefixHandler.getAbsoluteUriPrefix(siteName) : _prefixHandler.getUriPrefix(siteName)) 168 + "/_plugins/" + _pluginName + "/" + siteName 169 + "/contents/" 170 + content.getName() 171 + "/metadatas/" 172 + metadataPath 173 + "/" 174 + FilenameUtils.encodeName(binary.getFilename()) 175 + "/pages" 176 + "/thumbnail_" 177 + height + "x" + width 178 + ".png"; 179 180 // Encode twice 181 return URIUtils.encodePath(result); 182 } 183 184 @Override 185 public String resolveBoundedImage(String uri, int maxHeight, int maxWidth, boolean download, boolean absolute, boolean internal) 186 { 187 if (maxHeight == 0 && maxWidth == 0) 188 { 189 return resolve(uri, download, absolute, internal); 190 } 191 192 Request request = ContextHelper.getRequest(_context); 193 194 String metadataPath; 195 String siteName = (String) request.getAttribute("site"); 196 MetadataAwareAmetysObject object; 197 try 198 { 199 MetaInfo metaInfo = _getMetaInfo(uri, request); 200 201 metadataPath = metaInfo.getMetadataPath(); 202 object = metaInfo.getAmetysObject(); 203 } 204 catch (UnknownAmetysObjectException e) 205 { 206 return ""; 207 } 208 209 Content content = (Content) object; 210 Binary binary = _getBinary(metadataPath, content); 211 212 if (!_metadataComponent.isMimeTypeSupported(binary.getMimeType())) 213 { 214 String defaultPath = (absolute ? _prefixHandler.getAbsoluteUriPrefix(siteName) : _prefixHandler.getUriPrefix(siteName)) 215 + "/_plugins/" + _pluginName + "/" + siteName 216 + "/pages" 217 + "/error" 218 + "/thumbnail_max" 219 + maxHeight + "x" + maxWidth 220 + ".png"; 221 222 return URIUtils.encodePath(defaultPath); 223 } 224 225 String result = (absolute ? _prefixHandler.getAbsoluteUriPrefix(siteName) : _prefixHandler.getUriPrefix(siteName)) 226 + "/_plugins/" + _pluginName + "/" + siteName 227 + "/contents/" 228 + content.getName() 229 + "/metadatas/" 230 + metadataPath 231 + "/" 232 + FilenameUtils.encodeName(binary.getFilename()) 233 + "/pages" 234 + "/thumbnail_max" 235 + maxHeight + "x" + maxWidth 236 + ".png"; 237 238 // Encode twice 239 return URIUtils.encodePath(result); 240 } 241 242 private Binary _getBinary(String dataPath, Content content) 243 { 244 if (dataPath.contains("[")) 245 { 246 // The path contains a repeater entry with the new syntax ("repeater[1]/myBinaryData"), the getValue method can be used 247 return content.getValue(dataPath); 248 } 249 else 250 { 251 // FILPBOOK-63: The path could contain a repeater with the old syntax ("repeater/1/myBinaryData"), look over each path segment to get the binary data 252 // TODO NEWATTRIBUTEAPI: When all generators have been migrated to the new API, this code is unnecessary 253 List<String> pathSegments = Arrays.asList(dataPath.split(ModelItem.ITEM_PATH_SEPARATOR)); 254 Iterator<String> pathSegmentsIt = pathSegments.iterator(); 255 256 ModelAwareDataHolder dataHolder = content; 257 Binary binary = null; 258 while (pathSegmentsIt.hasNext()) 259 { 260 String pathSegment = pathSegmentsIt.next(); 261 262 if (pathSegmentsIt.hasNext()) 263 { 264 // Not the last segment: it is a repeater or a composite 265 if (dataHolder.getType(pathSegment).getId().equals(ModelItemTypeConstants.REPEATER_TYPE_ID)) 266 { 267 ModelAwareRepeater repeater = dataHolder.getRepeater(pathSegment); 268 int repeaterPosition = Integer.valueOf(pathSegmentsIt.next()); 269 dataHolder = repeater.getEntry(repeaterPosition); 270 } 271 else 272 { 273 dataHolder = dataHolder.getComposite(pathSegment); 274 } 275 } 276 else 277 { 278 binary = dataHolder.getValue(pathSegment); 279 } 280 } 281 282 return binary; 283 } 284 } 285 286 private class CacheThread extends Thread 287 { 288 private String _contentId; 289 private String _metadataPath; 290 private String _siteName; 291 private Logger _cacheLogger; 292 private AmetysObjectResolver _cacheResolver; 293 294 public CacheThread(String contentId, String metadataPath, String siteName, AmetysObjectResolver cacheResolver, Logger cacheLogger) 295 { 296 _contentId = contentId; 297 _metadataPath = metadataPath; 298 _siteName = siteName; 299 _cacheLogger = cacheLogger; 300 _cacheResolver = cacheResolver; 301 setDaemon(true); 302 setName("FlipbookCacheMetadataCreator"); 303 } 304 305 @Override 306 public void run() 307 { 308 try 309 { 310 Content content = _cacheResolver.resolveById(_contentId); 311 _metadataComponent.doCache(content, _metadataPath, _siteName); 312 } 313 catch (Exception e) 314 { 315 _cacheLogger.error("An error occurred during creating cache for content : " + _contentId); 316 } 317 } 318 } 319 320}