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