/*
* Copyright 2014 cruxframework.org.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.cruxframework.crux.scanner.archiveiterator;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cruxframework.crux.classpath.URLResourceHandler;
import org.cruxframework.crux.classpath.URLResourceHandlersRegistry;
import org.cruxframework.crux.scanner.ScannerRegistration;
import org.cruxframework.crux.scanner.Scanners;
/**
* @author Thiago da Rosa de Bustamante
*
*/
public class ZIPProtocolIterator extends URLIterator
{
protected ZipInputStream zipStream;
protected ZipEntry next;
protected String pathInZip;
protected boolean initial = true;
protected boolean closed = false;
protected URL zip;
private static final Log LOG = LogFactory.getLog(ZIPProtocolIterator.class);
public ZIPProtocolIterator(URL zip, List<ScannerRegistration> scanners, String pathInZip) throws IOException, URISyntaxException
{
super(scanners);
if (zip.toString().startsWith("file:"))
{
this.zip = toZipURL(zip);
this.zipStream = new ZipInputStream(new FileInputStream(new File(zip.toURI())));
}
else
{
this.zip = zip;
this.zipStream = new ZipInputStream(zip.openStream());
}
this.pathInZip = (pathInZip==null?"":pathInZip);
if (this.pathInZip.startsWith("/"))
{
this.pathInZip = this.pathInZip.substring(1);
}
}
protected ZIPProtocolIterator(List<ScannerRegistration> scanners)
{
super(scanners);
}
@Override
public void search()
{
URL url = next();
while (url != null)
{
String fileName = getNextEntryFullName();
if (!Scanners.ignoreScan(zip, fileName))
{
consumeWhenAccepted(zip, url, fileName);
}
url = next();
}
}
private void setNext()
{
initial = true;
try
{
if (next != null) zipStream.closeEntry();
next = null;
do
{
next = zipStream.getNextEntry();
} while (next != null && (next.isDirectory() || !next.getName().startsWith(pathInZip)));
if (next == null)
{
close();
}
}
catch (Exception e)
{
next = null;
LOG.error("failed to browse jar", e);
close();
}
}
/**
* Returns the full name of the next zip entry.
* @return
*/
private String getNextEntryFullName()
{
String prefix = this.zip.toString();
String nextEntry = this.next.getName();
if(prefix.endsWith("/"))
{
prefix = prefix.substring(0, prefix.length() - 1);
}
if(nextEntry.startsWith("/"))
{
nextEntry = nextEntry.substring(1);
}
return prefix + "/" + nextEntry;
}
protected URL next()
{
if (closed || (next == null && !initial)) return null;
setNext();
if (next == null) return null;
URLResourceHandler handler = URLResourceHandlersRegistry.getURLResourceHandler(getProtocol());
return handler.getChildResource(zip, next.getName());
}
protected String getProtocol()
{
return "zip";
}
protected void close()
{
try
{
closed = true;
zipStream.close();
}
catch (IOException ignored)
{
//Do nothing
}
}
private URL toZipURL(URL fileURL) throws MalformedURLException
{
return new URL("zip:"+fileURL.toString().substring(5)+"!/");
}
}