001/*
002 *  Copyright 2010 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.cms.transformation.xslt;
017
018import org.apache.avalon.framework.activity.Initializable;
019import org.apache.avalon.framework.context.Context;
020import org.apache.avalon.framework.context.ContextException;
021import org.apache.avalon.framework.context.Contextualizable;
022import org.apache.avalon.framework.logger.AbstractLogEnabled;
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.avalon.framework.service.Serviceable;
026import org.apache.cocoon.components.ContextHelper;
027import org.apache.cocoon.environment.Request;
028
029import org.ametys.cms.transformation.URIResolver;
030import org.ametys.cms.transformation.URIResolverExtensionPoint;
031
032/**
033 * This component resolve links and give a static hack access for xslt calls
034 */
035public class ResolveURIComponent extends AbstractLogEnabled implements Serviceable, Initializable, Contextualizable
036{
037    private static ResolveURIComponent _instance;
038    
039    private static Context _context;
040    
041    private URIResolverExtensionPoint _linkResolverExtensionPoint;
042    
043    @Override
044    public void contextualize(Context context) throws ContextException
045    {
046        _context = context;
047    }
048    
049    @Override
050    public void service(ServiceManager manager) throws ServiceException
051    {
052        _linkResolverExtensionPoint = (URIResolverExtensionPoint) manager.lookup(URIResolverExtensionPoint.ROLE);
053    }
054    
055    @Override
056    public void initialize() throws Exception
057    {
058        _instance = this;
059    }
060    
061    /**
062     * Resolve an uri upon the LinkResolverExtensionPoint
063     * @param type Type name (defined by the extension to use)
064     * @param uri URI depending on the type
065     * @return The uri resolved, or the uri if there is no resolver adapted
066     */
067    public static String resolve(String type, String uri)
068    {
069        return resolve(type, uri, false);
070    }
071
072    /**
073     * Resolve an uri upon the LinkResolverExtensionPoint
074     * @param type Type name (defined by the extension to use)
075     * @param uri URI depending on the type
076     * @param download Is this uri for download purposes.
077     * @return The uri resolved, or the uri if there is no resolver adapted
078     */
079    public static String resolve(String type, String uri, boolean download)
080    {
081        // FIXME CMS-2611 Force absolute 
082        Request request = ContextHelper.getRequest(_context);
083        boolean absolute = request.getAttribute("forceAbsoluteUrl") != null ? (Boolean) request.getAttribute("forceAbsoluteUrl") : false;
084        
085        return resolve(type, uri, download, absolute);
086    }
087    
088    /**
089     * Resolve an uri upon the LinkResolverExtensionPoint
090     * @param type Type name (defined by the extension to use)
091     * @param uri URI depending on the type
092     * @param download Is this uri for download purposes.
093     * @param absolute true to generate absolute url
094     * @return The uri resolved, the empty string if the uri could not be resolved, or the uri itself if there is no resolver adapted
095     */
096    public static String resolve(String type, String uri, boolean download, boolean absolute)
097    {
098        return resolve(type, uri, download, absolute, false);
099    }
100    
101    /**
102     * Resolve an uri upon the LinkResolverExtensionPoint
103     * @param type Type name (defined by the extension to use)
104     * @param uri URI depending on the type
105     * @param download Is this uri for download purposes.
106     * @param absolute true to generate absolute url
107     * @param internal true to get an internal URI.
108     * @return The uri resolved, the empty string if the uri could not be resolved, or the uri itself if there is no resolver adapted
109     */
110    public static String resolve(String type, String uri, boolean download, boolean absolute, boolean internal)
111    {
112        Request request = ContextHelper.getRequest(_context);
113        Object forceRemoteUrl = request.getAttribute("forceRemoteUrl");
114        
115        boolean remote = forceRemoteUrl != null
116                && (forceRemoteUrl instanceof Boolean && (Boolean) forceRemoteUrl 
117                        || Boolean.valueOf((String) forceRemoteUrl));
118        
119        String proxiedUri = remote ? type + ";" + uri : uri;
120        URIResolver uriResolver = _instance._linkResolverExtensionPoint.getResolverForType(remote ? "remote" : type);
121        if (uriResolver != null)
122        {
123            try
124            {
125                request.removeAttribute("forceRemoteUrl");
126                return uriResolver.resolve(proxiedUri, download, absolute, internal);
127            }
128            catch (Exception e)
129            {
130                _instance.getLogger().warn("Error resolving the uri '" + uri + "' with type " + type, e);
131                return "";
132            }
133            finally
134            {
135                request.setAttribute("forceRemoteUrl", forceRemoteUrl);
136            }
137        }
138        else
139        {
140            return uri;
141        }
142    }
143    
144    /**
145     * Resolve an uri upon the LinkResolverExtensionPoint
146     * @param type Type name (defined by the extension to use)
147     * @param uri URI depending on the type
148     * @param height the height
149     * @param width the width
150     * @return The uri resolved, or the uri if there is no resolver adapted
151     */
152    public static String resolveImage(String type, String uri, int height, int width)
153    {
154        return resolveImage (type, uri, height, width, false);
155    }
156    
157    /**
158     * Resolve an uri upon the LinkResolverExtensionPoint
159     * @param type Type name (defined by the extension to use)
160     * @param uri URI depending on the type
161     * @param height the height
162     * @param width the width
163     * @param download Is this uri for download purposes.
164     * @return The uri resolved, or the uri if there is no resolver adapted
165     */
166    public static String resolveImage(String type, String uri, int height, int width, boolean download)
167    {
168        // FIXME CMS-2611 Force absolute 
169        Request request = ContextHelper.getRequest(_context);
170        boolean absolute = request.getAttribute("forceAbsoluteUrl") != null ? (Boolean) request.getAttribute("forceAbsoluteUrl") : false;
171        
172        return resolveImage(type, uri, height, width, download, absolute);
173    }
174    
175    /**
176     * Resolve an uri upon the LinkResolverExtensionPoint
177     * @param type Type name (defined by the extension to use)
178     * @param uri URI depending on the type
179     * @param height the height
180     * @param width the width
181     * @param download Is this uri for download purposes.
182     * @param absolute true to generate absolute url
183     * @return The uri resolved, the empty string if the uri could not be resolved, or the uri itself if there is no resolver adapted
184     */
185    public static String resolveImage(String type, String uri, int height, int width, boolean download, boolean absolute)
186    {
187        return resolveImage(type, uri, height, width, download, absolute, false);
188    }
189    
190    /**
191     * Resolve an uri upon the LinkResolverExtensionPoint
192     * @param type Type name (defined by the extension to use)
193     * @param uri URI depending on the type
194     * @param height the height
195     * @param width the width
196     * @param download Is this uri for download purposes.
197     * @param absolute true to generate absolute url
198     * @param internal true to get an internal URI.
199     * @return The uri resolved, the empty string if the uri could not be resolved, or the uri itself if there is no resolver adapted
200     */
201    public static String resolveImage(String type, String uri, int height, int width, boolean download, boolean absolute, boolean internal)
202    {
203        // FIXME CMS-4059 Force base64 encoding. 
204        Request request = ContextHelper.getRequest(_context);
205        boolean encodeBase64 = request.getAttribute("forceBase64Encoding") != null ? (Boolean) request.getAttribute("forceBase64Encoding") : false;
206        
207        Object forceRemoteUrl = request.getAttribute("forceRemoteUrl");
208        boolean remote = forceRemoteUrl != null
209                        && (forceRemoteUrl instanceof Boolean && (Boolean) forceRemoteUrl
210                                || Boolean.valueOf((String) forceRemoteUrl));
211        
212        String proxiedUri = remote ? type + ";" + uri : uri;
213        URIResolver uriResolver = _instance._linkResolverExtensionPoint.getResolverForType(remote ? "remote" : type);
214        if (uriResolver != null)
215        {
216            try
217            {
218                request.removeAttribute("forceRemoteUrl");
219                if (encodeBase64)
220                {
221                    return uriResolver.resolveImageAsBase64(proxiedUri, height, width);
222                }
223                else
224                {
225                    return uriResolver.resolveImage(proxiedUri, height, width, download, absolute, internal);
226                }
227            }
228            catch (Exception e)
229            {
230                _instance.getLogger().warn("Error resolving the image of uri '" + uri + "' with type " + type, e);
231                return "";
232            }
233            finally
234            {
235                request.setAttribute("forceRemoteUrl", forceRemoteUrl);
236            }
237        }
238        else
239        {
240            return uri;
241        }
242    }
243    
244    /**
245     * Resolve an uri upon the LinkResolverExtensionPoint
246     * @param type Type name (defined by the extension to use)
247     * @param uri URI depending on the type
248     * @param maxHeight the max height
249     * @param maxWidth the max width
250     * @return The uri resolved, or the uri if there is no resolver adapted
251     */
252    public static String resolveBoundedImage(String type, String uri, int maxHeight, int maxWidth)
253    {
254        return resolveBoundedImage (type, uri, maxHeight, maxWidth, false);
255    }
256    
257    /**
258     * Resolve an uri upon the LinkResolverExtensionPoint
259     * @param type Type name (defined by the extension to use)
260     * @param uri URI depending on the type
261     * @param maxHeight the max height
262     * @param maxWidth the max width
263     * @param download Is this uri for download purposes.
264     * @return The uri resolved, or the uri if there is no resolver adapted
265     */
266    public static String resolveBoundedImage(String type, String uri, int maxHeight, int maxWidth, boolean download)
267    {
268        // FIXME CMS-2611 Force absolute 
269        Request request = ContextHelper.getRequest(_context);
270        boolean absolute = request.getAttribute("forceAbsoluteUrl") != null ? (Boolean) request.getAttribute("forceAbsoluteUrl") : false;
271        
272        return resolveBoundedImage(type, uri, maxHeight, maxWidth, download, absolute);
273    }
274    
275    /**
276     * Resolve an uri upon the LinkResolverExtensionPoint
277     * @param type Type name (defined by the extension to use)
278     * @param uri URI depending on the type
279     * @param maxHeight the max height
280     * @param maxWidth the max width
281     * @param download Is this uri for download purposes.
282     * @param absolute true to generate absolute url
283     * @return The uri resolved, the empty string if the uri could not be resolved, or the uri itself if there is no resolver adapted
284     */
285    public static String resolveBoundedImage(String type, String uri, int maxHeight, int maxWidth, boolean download, boolean absolute)
286    {
287        return resolveBoundedImage(type, uri, maxHeight, maxWidth, download, absolute, false);
288    }
289    
290    /**
291     * Resolve an uri upon the LinkResolverExtensionPoint
292     * @param type Type name (defined by the extension to use)
293     * @param uri URI depending on the type
294     * @param maxHeight the max height
295     * @param maxWidth the max width
296     * @param download Is this uri for download purposes.
297     * @param absolute true to generate absolute url
298     * @param internal true to get an internal URI.
299     * @return The uri resolved, the empty string if the uri could not be resolved, or the uri itself if there is no resolver adapted
300     */
301    public static String resolveBoundedImage(String type, String uri, int maxHeight, int maxWidth, boolean download, boolean absolute, boolean internal)
302    {
303        // FIXME CMS-4059 Force base64 encoding. 
304        Request request = ContextHelper.getRequest(_context);
305        boolean encodeBase64 = request.getAttribute("forceBase64Encoding") != null ? (Boolean) request.getAttribute("forceBase64Encoding") : false;
306        
307        Object forceRemoteUrl = request.getAttribute("forceRemoteUrl");
308        boolean remote = forceRemoteUrl != null
309                        && (forceRemoteUrl instanceof Boolean && (Boolean) forceRemoteUrl
310                                || Boolean.valueOf((String) forceRemoteUrl));
311        
312        String proxiedUri = remote ? type + ";" + uri : uri;
313        URIResolver uriResolver = _instance._linkResolverExtensionPoint.getResolverForType(remote ? "remote" : type);
314        if (uriResolver != null)
315        {
316            try
317            {
318                request.removeAttribute("forceRemoteUrl");
319                if (encodeBase64)
320                {
321                    return uriResolver.resolveBoundedImageAsBase64(proxiedUri, maxHeight, maxWidth);
322                }
323                else
324                {
325                    return uriResolver.resolveBoundedImage(proxiedUri, maxHeight, maxWidth, download, absolute, internal);
326                }
327            }
328            catch (Exception e)
329            {
330                _instance.getLogger().warn("Error resolving the image of uri '" + uri + "' with type " + type, e);
331                return "";
332            }
333            finally
334            {
335                request.setAttribute("forceRemoteUrl", forceRemoteUrl);
336            }
337        }
338        else
339        {
340            return uri;
341        }
342    }
343
344    /**
345     * Resolve an uri upon the LinkResolverExtensionPoint
346     * @param type Type name (defined by the extension to use)
347     * @param uri URI depending on the type
348     * @param cropHeight the crop height
349     * @param cropWidth the crop width
350     * @return The uri resolved, or the uri if there is no resolver adapted
351     */
352    public static String resolveCroppedImage(String type, String uri, int cropHeight, int cropWidth)
353    {
354        return resolveCroppedImage (type, uri, cropHeight, cropWidth, false);
355    }
356    
357    /**
358     * Resolve an uri upon the LinkResolverExtensionPoint
359     * @param type Type name (defined by the extension to use)
360     * @param uri URI depending on the type
361     * @param cropHeight the crop height
362     * @param cropWidth the crop width
363     * @param download Is this uri for download purposes.
364     * @return The uri resolved, or the uri if there is no resolver adapted
365     */
366    public static String resolveCroppedImage(String type, String uri, int cropHeight, int cropWidth, boolean download)
367    {
368        // FIXME CMS-2611 Force absolute 
369        Request request = ContextHelper.getRequest(_context);
370        boolean absolute = request.getAttribute("forceAbsoluteUrl") != null ? (Boolean) request.getAttribute("forceAbsoluteUrl") : false;
371        
372        return resolveCroppedImage(type, uri, cropHeight, cropWidth, download, absolute);
373    }
374    
375    /**
376     * Resolve an uri upon the LinkResolverExtensionPoint
377     * @param type Type name (defined by the extension to use)
378     * @param uri URI depending on the type
379     * @param cropHeight the crop height
380     * @param cropWidth the crop width
381     * @param download Is this uri for download purposes.
382     * @param absolute true to generate absolute url
383     * @return The uri resolved, the empty string if the uri could not be resolved, or the uri itself if there is no resolver adapted
384     */
385    public static String resolveCroppedImage(String type, String uri, int cropHeight, int cropWidth, boolean download, boolean absolute)
386    {
387        return resolveCroppedImage(type, uri, cropHeight, cropWidth, download, absolute, false);
388    }
389    
390    /**
391     * Resolve an uri upon the LinkResolverExtensionPoint
392     * @param type Type name (defined by the extension to use)
393     * @param uri URI depending on the type
394     * @param cropHeight the crop height
395     * @param cropWidth the crop width
396     * @param download Is this uri for download purposes.
397     * @param absolute true to generate absolute url
398     * @param internal true to get an internal URI.
399     * @return The uri resolved, the empty string if the uri could not be resolved, or the uri itself if there is no resolver adapted
400     */
401    public static String resolveCroppedImage(String type, String uri, int cropHeight, int cropWidth, boolean download, boolean absolute, boolean internal)
402    {
403        // FIXME CMS-4059 Force base64 encoding. 
404        Request request = ContextHelper.getRequest(_context);
405        boolean encodeBase64 = request.getAttribute("forceBase64Encoding") != null ? (Boolean) request.getAttribute("forceBase64Encoding") : false;
406        
407        URIResolver uriResolver = _instance._linkResolverExtensionPoint.getResolverForType(type);
408        if (uriResolver != null)
409        {
410            try
411            {
412                if (encodeBase64)
413                {
414                    return uriResolver.resolveCroppedImageAsBase64(uri, cropHeight, cropWidth);
415                }
416                else
417                {
418                    return uriResolver.resolveCroppedImage(uri, cropHeight, cropWidth, download, absolute, internal);
419                }
420            }
421            catch (Exception e)
422            {
423                _instance.getLogger().warn("Error resolving the image of uri '" + uri + "' with type " + type, e);
424                return "";
425            }
426        }
427        else
428        {
429            return uri;
430        }
431    }
432}