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