001/* 002 * Copyright 2018 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.ByteArrayOutputStream; 019import java.io.IOException; 020import java.io.OutputStream; 021import java.io.Serializable; 022import java.net.URISyntaxException; 023import java.nio.charset.StandardCharsets; 024import java.util.Map; 025 026import org.apache.avalon.framework.parameters.Parameters; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.cocoon.ProcessingException; 030import org.apache.cocoon.environment.ObjectModelHelper; 031import org.apache.cocoon.environment.Request; 032import org.apache.excalibur.source.Source; 033 034import org.ametys.core.DevMode; 035import org.ametys.core.DevMode.DEVMODE; 036import org.ametys.plugins.core.ui.resources.css.CSSFileHelper; 037import org.ametys.plugins.core.ui.resources.css.JSASSResourceURIExtensionPoint; 038 039/** 040 * Resource handler for CSS files 041 */ 042public class CssResourceHandler extends ExpiresResourceHandler 043{ 044 private ProxiedContextPathProvider _proxiedContextPathProvider; 045 private JSASSResourceURIExtensionPoint _jsassResourceURIExtensionPoint; 046 047 @Override 048 public void service(ServiceManager manager) throws ServiceException 049 { 050 super.service(manager); 051 052 _proxiedContextPathProvider = (ProxiedContextPathProvider) manager.lookup(ProxiedContextPathProvider.ROLE); 053 _jsassResourceURIExtensionPoint = (JSASSResourceURIExtensionPoint) manager.lookup(JSASSResourceURIExtensionPoint.ROLE); 054 } 055 056 @Override 057 public Source setup(String location, Map objectModel, Parameters par, Map<String, Object> additionalParameters) throws IOException, ProcessingException 058 { 059 additionalParameters.put("location", location); 060 return super.setup(location, objectModel, par, additionalParameters); 061 } 062 063 @Override 064 public Serializable getKey(Source source, Map objectModel, Parameters parameters, Map<String, Object> additionalParameters) 065 { 066 // files are cached by source and by context path 067 return super.getKey(source, objectModel, parameters, additionalParameters) + "*" + _proxiedContextPathProvider.getContextPath(); 068 } 069 070 @Override 071 public void generateResource(Source source, OutputStream out, Map objectModel, Parameters parameters, Map<String, Object> additionalParameters) throws IOException, ProcessingException 072 { 073 Request request = ObjectModelHelper.getRequest(objectModel); 074 if (DEVMODE.SUPER_DEVELOPPMENT.equals(DevMode.getDeveloperMode(request))) 075 { 076 // Files are not aggregated, thus don't need to be modified 077 super.generateResource(source, out, objectModel, parameters, additionalParameters); 078 return; 079 } 080 081 // Replace relative URIs with absolute values, required before aggregating files served through a new location 082 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 083 super.generateResource(source, baos, objectModel, parameters, additionalParameters); 084 String content = baos.toString(StandardCharsets.UTF_8.toString()); 085 086 String location = (String) additionalParameters.get("location"); 087 try 088 { 089 String locationPath = _jsassResourceURIExtensionPoint.resolve(location); 090 content = CSSFileHelper.replaceRelativeUri(content, locationPath, _jsassResourceURIExtensionPoint, _proxiedContextPathProvider.getContextPath(), _proxiedContextPathProvider.getContextPath()); 091 } 092 catch (URISyntaxException e) 093 { 094 throw new ProcessingException("Unable to replace relative URIs inside of css file '" + location + "'", e); 095 } 096 097 out.write(content.getBytes(StandardCharsets.UTF_8)); 098 } 099}