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;
024
025import org.ametys.cms.transformation.URIResolver;
026import org.ametys.core.util.FilenameUtils;
027import org.ametys.core.util.URIUtils;
028import org.ametys.plugins.explorer.resources.Resource;
029import org.ametys.plugins.repository.AmetysObject;
030import org.ametys.plugins.repository.AmetysObjectResolver;
031import org.ametys.plugins.repository.UnknownAmetysObjectException;
032import org.ametys.runtime.plugin.component.PluginAware;
033import org.ametys.web.editor.ResourceURIResolver;
034import org.ametys.web.explorer.ResourceHelper;
035
036/**
037 * {@link URIResolver} for type "explorer-flipbook".<br>
038 * These links point to a document file from the resource explorer converted to flash. 
039 */
040public class Resource2FlipbookUriResolver extends ResourceURIResolver implements PluginAware, Configurable
041{
042    /** The plugin name. */
043    protected String _pluginName;
044    
045    /** The type. */
046    protected String _type;
047    
048    /** The cache resource component. */
049    protected ConvertResource2ImagesComponent _resourceComponent;
050    
051    @Override
052    public void service(ServiceManager serviceManager) throws ServiceException
053    {
054        super.service(serviceManager);
055        _resourceComponent = (ConvertResource2ImagesComponent) serviceManager.lookup(ConvertResource2ImagesComponent.ROLE);
056    }
057    
058    @Override
059    public void setPluginInfo(String pluginName, String featureName, String id)
060    {
061        _pluginName = pluginName;
062    }
063    
064    public void configure(Configuration configuration) throws ConfigurationException
065    {
066        _type = configuration.getChild("type").getValue("explorer-flipbook");
067    }
068    
069    @Override
070    public String getType()
071    {
072        return _type;
073    }
074    
075    @Override
076    public String resolve(String uri, boolean download, boolean absolute, boolean internal)
077    {
078        String path;
079        Resource resource = null;
080        String siteName = null;
081        try
082        {
083            resource = (Resource) _resolver.resolveById(uri);
084            path = getResourcePath(resource);
085            siteName = _getSiteName(resource);
086        }
087        catch (UnknownAmetysObjectException e)
088        {
089            getLogger().warn("Link to unexisting resource " + uri);
090            return "";
091        }
092        
093        if (!_resourceComponent.isMimeTypeSupported(resource.getMimeType()))
094        {
095            return super.resolve(uri, download, absolute, internal);
096        }
097
098        StringBuilder result = new StringBuilder();
099        
100        // _plugins/flipbook/<site>/_[shared-]resource-flipbook/<path>/<to>/<resource>/<fileName>/book.html
101        result.append(_getUriPrefix(resource, download, internal, absolute, true))
102              .append("/_")
103              .append(getRealPrefix(resource, "resource-flipbook"))
104              .append(FilenameUtils.encodePath(path))
105              .append("/book.html");
106        
107        new CacheThread(resource.getId(), siteName, _resolver, getLogger()).start();
108        
109        return URIUtils.encodePath(result.toString());
110    }
111    
112    @Override
113    public String resolveImage(String uri, int height, int width, boolean download, boolean absolute, boolean internal)
114    {
115        Resource resource = null;
116        String path;
117        try
118        {
119            resource = (Resource) _resolver.resolveById(uri);
120            String fullPath = resource.getPath();
121            
122            if (fullPath.startsWith(ResourceHelper.SHARED_RESOURCE_PATH))
123            {
124                path = fullPath.substring(ResourceHelper.SHARED_RESOURCE_PATH.length());
125            }
126            else
127            {
128                path = resource.getResourcePath();
129            }
130        }
131        catch (UnknownAmetysObjectException e)
132        {
133            getLogger().warn("Link to unexisting resource " + uri);
134            return "";
135        }
136        
137        if (!_resourceComponent.isMimeTypeSupported(resource.getMimeType()))
138        { 
139            String defaultPath = _getUriPrefix(resource, download, absolute, internal, true)
140                    + "/pages" 
141                    + "/error"
142                    + "/thumbnail_"
143                    + height + "x" + width
144                    + ".png";
145            
146            return URIUtils.encodePath(defaultPath);
147        }
148
149        new CacheThread(resource.getId(), _getSiteName(resource), _resolver, getLogger()).start();
150        
151        String result = _getUriPrefix(resource, download, absolute, internal, false)
152                + "/" + getRealPrefix(resource, "resources")
153                + FilenameUtils.encodePath(path)
154                + "/pages" 
155                + "/thumbnail_"
156                + height + "x" + width
157                + ".png";
158        
159        return URIUtils.encodePath(result);
160    }
161    
162    @Override
163    public String resolveBoundedImage(String uri, int maxHeight, int maxWidth, boolean download, boolean absolute, boolean internal)
164    {
165        if (maxHeight == 0 && maxWidth == 0)
166        {
167            return resolve(uri, download, absolute, internal);
168        }
169        
170        Resource resource = null;
171        String path;
172        try
173        {
174            resource = (Resource) _resolver.resolveById(uri);
175            String fullPath = resource.getPath();
176            
177            if (fullPath.startsWith(ResourceHelper.SHARED_RESOURCE_PATH))
178            {
179                path = fullPath.substring(ResourceHelper.SHARED_RESOURCE_PATH.length());
180            }
181            else
182            {
183                path = resource.getResourcePath();
184            }
185        }
186        catch (UnknownAmetysObjectException e)
187        {
188            getLogger().warn("Link to unexisting resource " + uri);
189            return "";
190        }
191        
192        if (!_resourceComponent.isMimeTypeSupported(resource.getMimeType()))
193        { 
194            String defaultPath = _getUriPrefix(resource, download, absolute, internal, true)
195                    + "/pages" 
196                    + "/error"
197                    + "/thumbnail_max"
198                    + maxHeight + "x" + maxWidth
199                    + ".png";
200            
201            return URIUtils.encodePath(defaultPath);
202        }
203        
204        new CacheThread(resource.getId(), _getSiteName(resource), _resolver, getLogger()).start();
205
206        String result = _getUriPrefix(resource, download, absolute, internal, false)
207                + "/" + getRealPrefix(resource, "resources")
208                + FilenameUtils.encodePath(path)
209                + "/pages" 
210                + "/thumbnail_max"
211                + maxHeight + "x" + maxWidth
212                + ".png";
213        
214        return URIUtils.encodePath(result);
215    }
216    
217    private String _getUriPrefix(AmetysObject object, boolean download, boolean absolute, boolean internal, boolean addSiteNameForSharedResources)
218    {
219        Resource resource = (Resource) object;
220        String siteName = _getSiteName(resource);
221        
222        String uriPrefix = super.getUriPrefix(object, download, absolute, internal);
223        
224        uriPrefix +=  "/_plugins/" + _pluginName;
225        
226        if (addSiteNameForSharedResources || !resource.getPath().startsWith(ResourceHelper.SHARED_RESOURCE_PATH))
227        {
228            uriPrefix += "/" + siteName;
229        }
230
231        return uriPrefix;
232    }
233
234    private class CacheThread extends Thread 
235    {
236        private String _resourceId;
237        private String _siteName;
238        private Logger _cacheLogger;
239        private AmetysObjectResolver _cacheResolver;
240        
241        public CacheThread(String resourceId, String siteName, AmetysObjectResolver cacheResolver, Logger cacheLogger) 
242        {
243            _resourceId = resourceId;
244            _siteName = siteName;
245            _cacheLogger = cacheLogger;
246            _cacheResolver = cacheResolver;
247            setDaemon(true);
248            setName("FlipbookCacheResourceCreator");
249        }
250        
251        @Override
252        public void run() 
253        {
254            try
255            {
256                Resource resource = _cacheResolver.resolveById(_resourceId);
257                _resourceComponent.doCache(resource, _siteName);
258            }
259            catch (Exception e)
260            {
261                _cacheLogger.error("An error occurred during creating cache for resource : " + _resourceId);
262            }
263        }
264    }
265}