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 */ 016 017package org.ametys.plugins.core.ui.minimize; 018 019import java.io.IOException; 020import java.io.Serializable; 021import java.nio.charset.StandardCharsets; 022import java.util.List; 023 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.cocoon.ProcessingException; 027import org.apache.cocoon.caching.CacheableProcessingComponent; 028import org.apache.cocoon.environment.ObjectModelHelper; 029import org.apache.cocoon.environment.Request; 030import org.apache.cocoon.environment.Response; 031import org.apache.cocoon.reading.ServiceableReader; 032import org.apache.commons.io.IOUtils; 033import org.apache.excalibur.source.SourceValidity; 034import org.apache.excalibur.source.impl.validity.NOPValidity; 035import org.xml.sax.SAXException; 036 037import org.ametys.core.DevMode; 038import org.ametys.core.DevMode.DEVMODE; 039import org.ametys.core.resources.ProxiedContextPathProvider; 040import org.ametys.plugins.core.ui.minimize.HashCache.UriData; 041 042/** 043 * This generator generates a single file to load all ui items files. 044 * Can generates a list of imports of directly intergrates all files. 045 */ 046public abstract class AbstractMinimizeReader extends ServiceableReader implements CacheableProcessingComponent 047{ 048 private HashCache _hashCache; 049 private ProxiedContextPathProvider _proxiedContextPathProvider; 050 051 @Override 052 public void service(ServiceManager smanager) throws ServiceException 053 { 054 super.service(smanager); 055 _hashCache = (HashCache) smanager.lookup(HashCache.ROLE); 056 _proxiedContextPathProvider = (ProxiedContextPathProvider) manager.lookup(ProxiedContextPathProvider.ROLE); 057 } 058 059 @Override 060 public Serializable getKey() 061 { 062 return source + "*" + _proxiedContextPathProvider.getContextPath(); 063 } 064 065 @Override 066 public SourceValidity getValidity() 067 { 068 return new NOPValidity(); 069 } 070 071 @Override 072 public long getLastModified() 073 { 074 return 1000; // the smallest second-precision value 075 } 076 077 @Override 078 public void setup(org.apache.cocoon.environment.SourceResolver res, java.util.Map obj, String src, org.apache.avalon.framework.parameters.Parameters par) throws ProcessingException, SAXException, IOException 079 { 080 super.setup(res, obj, src, par); 081 Response response = ObjectModelHelper.getResponse(objectModel); 082 response.setHeader("Cache-Control", "max-age=31536000, immutable"); // one year from now 083 } 084 085 @Override 086 public void generate() throws IOException, SAXException, ProcessingException 087 { 088 List<UriData> files = _hashCache.getFilesForHash(source, true); 089 if (files == null) 090 { 091 throw new IllegalStateException("There is no list of file to minimize for hashcode '" + source + "'"); 092 } 093 094 Request request = ObjectModelHelper.getRequest(objectModel); 095 boolean generateSourceMap = !DEVMODE.PRODUCTION.equals(DevMode.getDeveloperMode(request)); 096 097 String str = _handleFiles(files, generateSourceMap); 098 099 IOUtils.write(str, out, StandardCharsets.UTF_8); 100 out.flush(); 101 } 102 103 /** 104 * Minimize files 105 * @param files The files 106 * @param generateSourceMap true to generate the source map 107 * @return The minimized string 108 */ 109 protected abstract String _handleFiles(List<UriData> files, boolean generateSourceMap); 110}