001/*
002 *  Copyright 2016 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.core.cocoon;
017
018import java.io.IOException;
019import java.io.OutputStream;
020import java.io.Serializable;
021import java.util.Arrays;
022import java.util.Collection;
023import java.util.regex.Matcher;
024import java.util.regex.Pattern;
025
026import org.apache.avalon.framework.component.Component;
027import org.apache.avalon.framework.parameters.Parameters;
028import org.apache.cocoon.ProcessingException;
029import org.apache.cocoon.ResourceNotFoundException;
030import org.apache.commons.lang.StringUtils;
031import org.apache.excalibur.source.Source;
032import org.apache.excalibur.source.SourceException;
033
034import org.ametys.core.util.ImageHelper;
035
036/**
037 * Resource handler for images
038 */
039public class ImageResourceHandler extends AbstractResourceHandler implements Component
040{
041    private static final Pattern _SIZE_PATTERN = Pattern.compile("^(.*)(?:_(max)?([0-9]+)x([0-9]+))(\\.[^./]+)$");
042
043    private static final Collection<String> __ALLOWED_FORMATS = Arrays.asList(new String[]{"png", "gif", "jpg", "jpeg"});
044
045    @Override
046    public Source setup(String location, Parameters par) throws ProcessingException, IOException
047    {
048        Source source = null;
049        try 
050        {
051            source = _resolver.resolveURI(location);
052        } 
053        catch (SourceException e) 
054        {
055            // Nothing
056        }
057        
058        // Compute the locale
059        if (source == null || !source.exists())
060        {
061            Matcher sizeMatcher = _SIZE_PATTERN.matcher(location);
062            if (sizeMatcher.matches())
063            {
064                String computedLocation = sizeMatcher.group(1) + sizeMatcher.group(5);
065                
066                source = _resolver.resolveURI(computedLocation);
067                if (!source.exists())
068                {
069                    throw new ResourceNotFoundException("Resource not found for URI : " + source.getURI());
070                }
071                
072                boolean isMaxSize = sizeMatcher.group(2) != null;
073                String height = sizeMatcher.group(3);
074                String width = sizeMatcher.group(4);
075
076                par.setParameter("height", isMaxSize ? "0" : height);
077                par.setParameter("width", isMaxSize ? "0" : width);
078                par.setParameter("maxHeight", isMaxSize ? height : "0");
079                par.setParameter("maxWidth", isMaxSize ? width : "0");
080            }
081            else
082            {
083                throw new ResourceNotFoundException("Resource not found for URI : " + location);
084            }
085        }
086        
087        return source;
088    }
089
090    @Override
091    public void generateResource(Source source, OutputStream out, Parameters parameters) throws IOException, ProcessingException
092    {
093        String format = StringUtils.substringAfterLast(source.getURI(), ".").toLowerCase();
094        format = __ALLOWED_FORMATS.contains(format) ? format : "png";
095        
096        int width = parameters.getParameterAsInteger("width", 0);
097        int height = parameters.getParameterAsInteger("height", 0);
098        int maxWidth = parameters.getParameterAsInteger("maxWidth", 0);
099        int maxHeight = parameters.getParameterAsInteger("maxHeight", 0);
100        
101        ImageHelper.generateThumbnail(source.getInputStream(), out, format, height, width, maxHeight, maxWidth);
102    }
103
104    @Override
105    public Serializable getKey(Source source, Parameters parameters)
106    {
107        int width = parameters.getParameterAsInteger("width", 0);
108        int height = parameters.getParameterAsInteger("height", 0);
109        int maxWidth = parameters.getParameterAsInteger("maxWidth", 0);
110        int maxHeight = parameters.getParameterAsInteger("maxHeight", 0);
111        
112        return source.getURI() + "###" + width + "x" + height + "x" + maxWidth + "x" + maxHeight;
113    }
114}