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}