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.repository.Content;
030import org.ametys.cms.transformation.URIResolver;
031import org.ametys.core.util.URLEncoder;
032import org.ametys.plugins.repository.AmetysObjectResolver;
033import org.ametys.plugins.repository.UnknownAmetysObjectException;
034import org.ametys.plugins.repository.metadata.BinaryMetadata;
035import org.ametys.plugins.repository.metadata.CompositeMetadata;
036import org.ametys.plugins.repository.metadata.CompositeMetadata.MetadataType;
037import org.ametys.plugins.repository.metadata.MetadataAwareAmetysObject;
038import org.ametys.runtime.plugin.component.PluginAware;
039import org.ametys.web.editor.MetadataURIResolver;
040
041/**
042 * {@link URIResolver} for type "resource-pdf2flash".<br> TODO
043 * These links point to a document file from the resource explorer converted to flash. 
044 */
045public class Metadata2FlipbookUriResolver extends MetadataURIResolver implements PluginAware, LogEnabled
046{
047    /** The plugin name. */
048    protected String _pluginName;
049    
050    /** The logger . */
051    protected Logger _logger;
052    
053    /** Metadata to images convertor. */
054    protected ConvertMetadata2ImagesComponent _metadataComponent;
055    
056    @Override
057    public void service(ServiceManager serviceManager) throws ServiceException
058    {
059        super.service(serviceManager);
060        _metadataComponent = (ConvertMetadata2ImagesComponent) serviceManager.lookup(ConvertMetadata2ImagesComponent.ROLE);
061    }
062    
063    @Override
064    public void setPluginInfo(String pluginName, String featureName, String id)
065    {
066        _pluginName = pluginName;
067    }
068    
069    @Override
070    public void enableLogging(Logger logger)
071    {
072        _logger = logger;
073    }
074    
075    @Override
076    public String getType()
077    {
078        return "metadata-flipbook";
079    }
080    
081    @Override
082    public String resolve(String uri, boolean download, boolean absolute, boolean internal)
083    {
084        Request request = ContextHelper.getRequest(_context);
085        
086        String metadataPath;
087        String fileName;
088        String siteName = (String) request.getAttribute("site");
089        MetadataAwareAmetysObject object;
090        try
091        {
092            MetaInfo metaInfo = _getMetaInfo(uri, request);
093            
094            metadataPath = metaInfo.getMetadataPath();
095            object = metaInfo.getAmetysObject();
096
097            fileName = object.getName();
098        }
099        catch (UnknownAmetysObjectException e)
100        {
101            return "";
102        }
103
104        Content content = (Content) object;
105        String resultPath = (absolute ? _prefixHandler.getAbsoluteUriPrefix(siteName) : _prefixHandler.getUriPrefix(siteName))
106                + "/_plugins/" + _pluginName + "/" + siteName
107                + "/_metadata-flipbook/"
108                + fileName
109                + "/" 
110                + metadataPath
111                + "/_contents"
112                + content.getPath()
113                + "/book.html";
114        
115        BinaryMetadata binary = _getBinaryMetadata(metadataPath, ((Content) object).getMetadataHolder());
116        
117        if (!_metadataComponent.isMimeTypeSupported(binary.getMimeType()))
118        {
119            return super.resolve(uri, download, absolute, internal);
120        }
121       
122        new CacheThread(content.getId(), metadataPath, siteName, _resolver, _logger).start();
123        
124        // Encode twice
125        return URLEncoder.encodePath(URLEncoder.encodePath(resultPath.toString()));
126    }
127    
128    @Override
129    public String resolveImage(String uri, int height, int width, boolean download, boolean absolute, boolean internal)
130    {
131        Request request = ContextHelper.getRequest(_context);
132        
133        String metadataPath;
134        String siteName = (String) request.getAttribute("site");
135        MetadataAwareAmetysObject object;
136        try
137        {
138            MetaInfo metaInfo = _getMetaInfo(uri, request);
139            
140            metadataPath = metaInfo.getMetadataPath();
141            object = metaInfo.getAmetysObject();
142        }
143        catch (UnknownAmetysObjectException e)
144        {
145            return "";
146        }
147
148        Content content = (Content) object;
149        BinaryMetadata binary = _getBinaryMetadata(metadataPath, content.getMetadataHolder());
150        
151        if (!_metadataComponent.isMimeTypeSupported(binary.getMimeType()))
152        { 
153            String defaultPath = (absolute ? _prefixHandler.getAbsoluteUriPrefix(siteName) : _prefixHandler.getUriPrefix(siteName))
154                    + "/_plugins/" + _pluginName + "/" + siteName
155                    + "/pages" 
156                    + "/error"
157                    + "/thumbnail_"
158                    + height + "x" + width
159                    + ".png";
160            
161            return URLEncoder.encodePath(defaultPath);
162        }
163
164        String result = (absolute ? _prefixHandler.getAbsoluteUriPrefix(siteName) : _prefixHandler.getUriPrefix(siteName))
165                + "/_plugins/" + _pluginName + "/" + siteName
166                + "/contents/"
167                + content.getName()
168                + "/metadatas/"
169                + metadataPath
170                + "/"
171                + binary.getFilename()
172                + "/pages" 
173                + "/thumbnail_"
174                + height + "x" + width
175                + ".png";
176        
177        // Encode twice
178        return URLEncoder.encodePath(URLEncoder.encodePath(result));
179    }
180    
181    @Override
182    public String resolveBoundedImage(String uri, int maxHeight, int maxWidth, boolean download, boolean absolute, boolean internal)
183    {
184        if (maxHeight == 0 && maxWidth == 0)
185        {
186            return resolve(uri, download, absolute, internal);
187        }
188        
189        Request request = ContextHelper.getRequest(_context);
190        
191        String metadataPath;
192        String siteName = (String) request.getAttribute("site");
193        MetadataAwareAmetysObject object;
194        try
195        {
196            MetaInfo metaInfo = _getMetaInfo(uri, request);
197            
198            metadataPath = metaInfo.getMetadataPath();
199            object = metaInfo.getAmetysObject();
200        }
201        catch (UnknownAmetysObjectException e)
202        {
203            return "";
204        }
205
206        Content content = (Content) object;
207        BinaryMetadata binary = _getBinaryMetadata(metadataPath, content.getMetadataHolder());
208        
209        if (!_metadataComponent.isMimeTypeSupported(binary.getMimeType()))
210        { 
211            String defaultPath = (absolute ? _prefixHandler.getAbsoluteUriPrefix(siteName) : _prefixHandler.getUriPrefix(siteName))
212                    + "/_plugins/" + _pluginName + "/" + siteName
213                    + "/pages" 
214                    + "/error"
215                    + "/thumbnail_max"
216                    + maxHeight + "x" + maxWidth
217                    + ".png";
218            
219            return URLEncoder.encodePath(defaultPath);
220        }
221
222        String result = (absolute ? _prefixHandler.getAbsoluteUriPrefix(siteName) : _prefixHandler.getUriPrefix(siteName))
223                + "/_plugins/" + _pluginName + "/" + siteName
224                + "/contents/"
225                + content.getName()
226                + "/metadatas/"
227                + metadataPath
228                + "/"
229                + binary.getFilename()
230                + "/pages" 
231                + "/thumbnail_max"
232                + maxHeight + "x" + maxWidth
233                + ".png";
234        
235        // Encode twice
236        return URLEncoder.encodePath(URLEncoder.encodePath(result));
237    }
238    
239    private BinaryMetadata _getBinaryMetadata(String metadataPath, CompositeMetadata metadata)
240    {
241        List<String> pathElements = Arrays.asList(metadataPath.split("/"));        
242        Iterator<String> it = pathElements.iterator();
243        
244        CompositeMetadata metadataBis = metadata;
245        BinaryMetadata binary = null;
246        while (it.hasNext())
247        {
248            String pathElement = it.next();
249            
250            if (it.hasNext())
251            {
252                // not the last segment : it is a composite
253                metadataBis = metadataBis.getCompositeMetadata(pathElement);
254            }
255            else
256            {
257                if (metadataBis.getType(pathElement) != MetadataType.BINARY)
258                {
259                    throw new UnsupportedOperationException("Only binary metadata are allowed");
260                }
261                
262                binary = metadataBis.getBinaryMetadata(pathElement);
263            }
264        }
265        
266        return binary;
267    }
268    
269    private class CacheThread extends Thread 
270    {
271        private String _contentId;
272        private String _metadataPath;
273        private String _siteName;
274        private Logger _cacheLogger;
275        private AmetysObjectResolver _cacheResolver;
276        
277        public CacheThread(String contentId, String metadataPath, String siteName, AmetysObjectResolver cacheResolver, Logger cacheLogger) 
278        {
279            _contentId = contentId;
280            _metadataPath = metadataPath;
281            _siteName = siteName;
282            _cacheLogger = cacheLogger;
283            _cacheResolver = cacheResolver;
284            setDaemon(true);
285            setName("FlipbookCacheMetadataCreator");
286        }
287        
288        @Override
289        public void run() 
290        {
291            try
292            {
293                Content content = _cacheResolver.resolveById(_contentId);
294                _metadataComponent.doCache(content, _metadataPath, _siteName);
295            }
296            catch (Exception e)
297            {
298                _cacheLogger.error("An error occurred during creating cache for content : " + _contentId);
299            }
300        }
301    }
302
303}