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 org.apache.avalon.framework.configuration.Configurable;
019import org.apache.avalon.framework.configuration.Configuration;
020import org.apache.avalon.framework.configuration.ConfigurationException;
021import org.apache.avalon.framework.logger.Logger;
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.apache.cocoon.components.ContextHelper;
025import org.apache.cocoon.environment.Request;
026
027import org.ametys.cms.repository.Content;
028import org.ametys.cms.transformation.URIResolver;
029import org.ametys.core.util.FilenameUtils;
030import org.ametys.core.util.URIUtils;
031import org.ametys.plugins.explorer.resources.Resource;
032import org.ametys.plugins.repository.AmetysObject;
033import org.ametys.plugins.repository.AmetysObjectResolver;
034import org.ametys.plugins.repository.UnknownAmetysObjectException;
035import org.ametys.runtime.plugin.component.PluginAware;
036import org.ametys.web.editor.AttachmentURIResolver;
037import org.ametys.web.repository.SiteAwareAmetysObject;
038import org.ametys.web.repository.content.WebContent;
039
040/**
041 * {@link URIResolver} for type "attachment-content-flipbook".<br>
042 * These links point to a document file from the attachments of the current Content converted it to flash. 
043 */
044public class Attachment2FlipbookUriResolver extends AttachmentURIResolver implements PluginAware, Configurable
045{
046    /** The plugin name. */
047    protected String _pluginName;
048    
049    /** The type. */
050    protected String _type;
051    
052    /** The ametys object resolver. */
053    protected ConvertContentAttachment2ImagesComponent _attachmentComponent;
054    
055    @Override
056    public void service(ServiceManager serviceManager) throws ServiceException
057    {
058        super.service(serviceManager);
059        _attachmentComponent = (ConvertContentAttachment2ImagesComponent) serviceManager.lookup(ConvertContentAttachment2ImagesComponent.ROLE);
060    }
061    
062    @Override
063    public void setPluginInfo(String pluginName, String featureName, String id)
064    {
065        _pluginName = pluginName;
066    }
067
068    public void configure(Configuration configuration) throws ConfigurationException
069    {
070        _type = configuration.getChild("type").getValue("attachment-content-flipbook");
071    }
072    
073    @Override
074    public String getType()
075    {
076        return _type;
077    }
078    
079    @Override
080    public String resolve(String uri, boolean download, boolean absolute, boolean internal)
081    {
082        Request request = ContextHelper.getRequest(_context);
083
084        String path;
085        Content content = null;
086        String contentName = null;
087        String siteName = null;
088        Resource resource = null;
089        try
090        {
091            resource = (Resource) _resolver.resolveById(uri);
092            path = resource.getResourcePath();
093
094            AmetysObject ao = resource;
095            do
096            {
097                ao = ao.getParent();
098            }
099            while (ao != null && !(ao instanceof Content));
100            
101            if (ao == null)
102            {
103                throw new IllegalArgumentException("The given attachment URI should be a content attachment.");
104            }
105            
106            content = (Content) ao;
107            contentName = content.getName();
108            
109            if (content instanceof WebContent)
110            {
111                siteName = ((WebContent) content).getSiteName();
112            }
113            else
114            {
115                siteName = (String) request.getAttribute("siteName");
116                if (siteName == null)
117                {
118                    siteName = (String) request.getAttribute("site");
119                }
120            }
121           
122        }
123        catch (UnknownAmetysObjectException e)
124        {
125            getLogger().warn("Link to unexisting resource " + uri);
126            return "";
127        }
128        catch (Exception e)
129        {
130            throw new IllegalStateException(e);
131        }
132        
133        
134        // plugins/flipbook/<siteName>/_attachments-flipbook/<contentName>/<fileName>/book.html
135        String resultPath = getUriPrefix(content, download, absolute, internal)
136                + "/_attachments-flipbook/"
137                + contentName 
138                + FilenameUtils.encodePath(path)
139                + "/_contents"
140                + FilenameUtils.encodePath(resource.getPath())
141                + "/book.html";
142        
143        if (!_attachmentComponent.isMimeTypeSupported(resource.getMimeType()))
144        {
145            return super.resolve(uri, download, absolute, internal);
146        }
147        
148        new CacheThread(resource.getId(), contentName, siteName, _resolver, getLogger()).start();
149        
150        return URIUtils.encodePath(resultPath.toString());
151    }
152    
153    @Override
154    public String resolveImage(String uri, int height, int width, boolean download, boolean absolute, boolean internal)
155    {
156        return _resolveImage(uri, "", height, width, download, absolute, internal);
157    }
158    
159    @Override
160    public String resolveBoundedImage(String uri, int maxHeight, int maxWidth, boolean download, boolean absolute, boolean internal)
161    {
162        return _resolveImage(uri, "max", maxHeight, maxWidth, download, absolute, internal);
163    }
164    
165    private String _resolveImage(String uri, String uriArgument, int height, int width, boolean download, boolean absolute, boolean internal)
166    {
167        if (height == 0 && width == 0)
168        {
169            return resolve(uri, download, absolute, internal);
170        }
171        
172        Content content = null;
173        String contentName = null;
174        String siteName = null;
175        Resource resource = null;
176        try
177        {
178            resource = (Resource) _resolver.resolveById(uri);
179            
180            AmetysObject ao = resource;
181            do
182            {
183                ao = ao.getParent();
184            }
185            while (ao != null && !(ao instanceof Content));
186            
187            if (ao == null)
188            {
189                throw new IllegalArgumentException("The given attachment URI should be a content attachment.");
190            }
191            
192            content = (Content) ao;
193            contentName = content.getName();
194            
195            if (content instanceof WebContent)
196            {
197                siteName = ((WebContent) content).getSiteName();
198            }
199        }
200        catch (UnknownAmetysObjectException e)
201        {
202            getLogger().warn("Link to unexisting resource " + uri);
203            return "";
204        }
205        catch (Exception e)
206        {
207            throw new IllegalStateException(e);
208        }
209        
210        if (!_attachmentComponent.isMimeTypeSupported(resource.getMimeType()))
211        { 
212            String defaultPath = getUriPrefix(content, download, absolute, internal)
213                    + "/pages" 
214                    + "/error"
215                    + "/thumbnail_"
216                    + uriArgument
217                    + height + "x" + width
218                    + ".png";
219            
220            return URIUtils.encodePath(defaultPath);
221        }
222        
223        new CacheThread(resource.getId(), contentName, siteName, _resolver, getLogger()).start();
224
225        String result = getUriPrefix(content, download, absolute, internal)
226                + "/contents/"
227                + contentName
228                + "/attachments"
229                + FilenameUtils.encodePath(resource.getResourcePath())
230                + "/pages" 
231                + "/thumbnail_"
232                + uriArgument
233                + height + "x" + width
234                + ".png";
235        
236        return URIUtils.encodePath(result);
237    }
238    
239    @Override
240    protected String getUriPrefix(AmetysObject object, boolean download, boolean absolute, boolean internal)
241    {
242        Request request = ContextHelper.getRequest(_context);
243        
244        String siteName = null;
245        if (object instanceof SiteAwareAmetysObject)
246        {
247            siteName = ((SiteAwareAmetysObject) object).getSiteName();
248        }
249        else
250        {
251            siteName = (String) request.getAttribute("siteName");
252            
253            if (siteName == null)
254            {
255                siteName = (String) request.getAttribute("site");
256            }
257        }
258        
259        String initialSiteName = (String) ContextHelper.getRequest(_context).getAttribute("initialSiteName");
260        boolean isInitialSite = initialSiteName == null || initialSiteName.equals(siteName);
261        
262        String uriPrefix;
263        if (internal)
264        {
265            uriPrefix = "cocoon://" + siteName;
266        }
267        else if (absolute || !isInitialSite)
268        {
269            uriPrefix = _webPrefixHandler.getAbsoluteUriPrefix(siteName);
270        }
271        else
272        {
273            uriPrefix = _webPrefixHandler.getUriPrefix(siteName);
274        }
275        
276        uriPrefix +=  "/_plugins/" + _pluginName + "/" + siteName;
277        return uriPrefix;
278    }
279    
280    private class CacheThread extends Thread 
281    {
282        private String _resourceId;
283        private String _siteName;
284        private String _contentName;
285        private Logger _cacheLogger;
286        private AmetysObjectResolver _cacheResolver;
287        
288        /**
289         * Constructor
290         * @param resourceId The id of resource
291         * @param contentName The content's name
292         * @param siteName The site name
293         * @param cacheResolver The ametys object resolver
294         * @param cacheLogger The logger
295         */
296        public CacheThread(String resourceId, String contentName, String siteName, AmetysObjectResolver cacheResolver, Logger cacheLogger) 
297        {
298            _resourceId = resourceId;
299            _siteName = siteName;
300            _cacheLogger = cacheLogger;
301            _cacheResolver = cacheResolver;
302            _contentName = contentName;
303            setDaemon(true);
304            setName("FlipbookCacheAttachmentCreator");
305        }
306        
307        @Override
308        public void run() 
309        {
310            try
311            {
312                Resource resource = _cacheResolver.resolveById(_resourceId);
313                _attachmentComponent.doCache(resource, _contentName, _siteName);
314            }
315            catch (Exception e)
316            {
317                _cacheLogger.error("An error occurred during creating cache for resource : " + _resourceId);
318            }
319        }
320    }
321}