001/*
002 *  Copyright 2011 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.web.skin.generators;
017
018import java.io.IOException;
019import java.nio.file.Files;
020import java.nio.file.Path;
021import java.util.stream.Stream;
022
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.cocoon.ProcessingException;
026import org.apache.cocoon.generation.ServiceableGenerator;
027import org.apache.cocoon.serialization.ZipArchiveSerializer;
028import org.apache.cocoon.xml.AttributesImpl;
029import org.apache.cocoon.xml.XMLUtils;
030import org.xml.sax.SAXException;
031
032import org.ametys.core.util.LambdaUtils;
033import org.ametys.core.util.LambdaUtils.LambdaException;
034import org.ametys.web.skin.Skin;
035import org.ametys.web.skin.SkinsManager;
036
037/**
038 * Generates a ZIP archive for the given skin
039 *
040 */
041public class ZipArchiveGenerator extends ServiceableGenerator
042{
043    private SkinsManager _skinsManager;
044    
045    @Override
046    public void service(ServiceManager smanager) throws ServiceException
047    {
048        _skinsManager = (SkinsManager) smanager.lookup(SkinsManager.ROLE);
049    }
050
051    @Override
052    public void generate() throws IOException, SAXException, ProcessingException
053    {
054        String id = parameters.getParameter("id", null);
055        
056        Skin skin = _skinsManager.getSkin(id);
057        
058        Path file = skin.getRawPath();
059        
060        contentHandler.startDocument();
061        contentHandler.startPrefixMapping("zip", ZipArchiveSerializer.ZIP_NAMESPACE);
062        XMLUtils.startElement(contentHandler, ZipArchiveSerializer.ZIP_NAMESPACE, "archive");
063
064        _saxEntries("skin:", id, file, file);
065        
066        XMLUtils.endElement(contentHandler, ZipArchiveSerializer.ZIP_NAMESPACE, "archive");
067        contentHandler.endPrefixMapping("zip");
068        contentHandler.endDocument();
069    }
070    
071    /**
072     * SAX ZIP entries
073     * @param protocol Such as skin: or model:
074     * @param id The identifier to use in protocol and as first directory name
075     * @param file the file
076     * @param prefixPath the path's prefix
077     * @throws SAXException if an error occurred while saxing ZIP entries
078     */
079    protected void _saxEntries(String protocol, String id, Path file, Path prefixPath) throws SAXException
080    {
081        try (Stream<Path> children = Files.list(file))
082        {
083            children
084                .forEach(LambdaUtils.wrapConsumer(child -> 
085                {
086                    if (Files.isRegularFile(child))
087                    {
088                        String relativePath = prefixPath.relativize(child).toString();
089                        
090                        AttributesImpl attr = new AttributesImpl();
091                        attr.addCDATAAttribute("name", id + "/" + relativePath);
092                        attr.addCDATAAttribute("src", protocol + id + "://" + relativePath);
093                        XMLUtils.startElement(contentHandler, ZipArchiveSerializer.ZIP_NAMESPACE, "entry", attr);
094                        XMLUtils.endElement(contentHandler, ZipArchiveSerializer.ZIP_NAMESPACE, "entry");
095                    }
096                    else
097                    {
098                        _saxEntries(protocol, id, child, prefixPath);
099                    }
100                }));
101        }
102        catch (LambdaException e)
103        {
104            throw (SAXException) e.getCause();
105        }
106        catch (IOException e)
107        {
108            throw new SAXException(e);
109        }
110    }
111
112}