001/*
002 *  Copyright 2012 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.cocoon.source;
017
018import java.io.IOException;
019import java.io.InputStream;
020import java.util.zip.ZipEntry;
021import java.util.zip.ZipFile;
022
023import org.apache.excalibur.source.SourceNotFoundException;
024import org.apache.excalibur.source.impl.AbstractSource;
025
026/**
027 * Implementation of a Source giving access to a zip entry
028 */
029public class ZipSource extends AbstractSource
030{
031    private ZipFile _zipFile;
032
033    private ZipEntry _zipEntry;
034
035    /**
036     * Instanciate a ZipSource
037     * @param location the ZipSource URI, looking like : zip://path/to/file!path/to/entry
038     */
039    public ZipSource(String location)
040    {
041        int index = location.indexOf("://");
042        
043        if (index == -1)
044        {
045            throw new IllegalArgumentException("A ZipSource URI must be like zip://path/to/file!path/to/entry");
046        }
047        
048        setScheme(location.substring(0, index));
049        setSystemId(location.substring(index + 3));
050
051        int fileIndex = location.indexOf('!');
052        
053        if (fileIndex < index)
054        {
055            throw new IllegalArgumentException("A ZipSource URI must be like zip://path/to/file!path/to/entry");
056        }
057        
058        String file = location.substring(index + 1, fileIndex);
059        try
060        {
061            _zipFile = new ZipFile(file);
062        }
063        catch (IOException e)
064        {
065            throw new IllegalArgumentException("Unable to open zip file", e);
066        }
067
068        String entry = location.substring(fileIndex + 1);
069        _zipEntry = _zipFile.getEntry(entry);
070    }
071
072    public boolean exists()
073    {
074        return _zipFile != null && _zipEntry != null;
075    }
076
077    @Override
078    public InputStream getInputStream() throws IOException
079    {
080        if (_zipFile == null || _zipEntry == null)
081        {
082            throw new SourceNotFoundException("ZipSource not available");
083        }
084        
085        return _zipFile.getInputStream(_zipEntry);
086    }
087
088    /**
089     * Releases resources associated with this ZipSource.
090     */
091    public void close()
092    {
093        _zipEntry = null;
094
095        try
096        {
097            _zipFile.close();
098            _zipFile = null;
099        }
100        catch (IOException e)
101        {
102            throw new IllegalArgumentException("Unable to close zip file");
103        }
104    }
105}