blob: def55bcd499894312cd8cae27057dd9288423204 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.j2ee.commonarchivecore.internal.strategy;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.eclipse.jst.j2ee.commonarchivecore.internal.Archive;
import org.eclipse.jst.j2ee.commonarchivecore.internal.CommonArchiveResourceHandler;
import org.eclipse.jst.j2ee.commonarchivecore.internal.File;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.NestedJarException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.FileIterator;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.NestedArchiveIterator;
/**
* Load strategy used as a last resort to read entries from jars inside of jars. It is a last resort
* because of the poor perfomance involved, as the contents of the zip entries are not cached, and
* sequential scan searches will cause the zip stream to be inflated on each search. Whenever
* possible,
*
* @link {TempFileLoadStrategy} should be used.
*/
public class NestedArchiveLoadStrategyImpl extends LoadStrategyImpl {
/**
* Index to improve lookup performance - not used if in Runtime to reduce footprint
*/
protected Map urisToPositions;
protected LoadStrategy parent;
/**
* NestedArchiveLoadStrategyImpl constructor comment.
*/
public NestedArchiveLoadStrategyImpl(LoadStrategy parentStrategy) {
super();
setParent(parentStrategy);
}
protected void buildIndex() {
Map map = new HashMap();
try {
ZipInputStream zis = getZipInputStream();
ZipEntry entry = null;
long position = 0;
while ((entry = zis.getNextEntry()) != null) {
position++;
map.put(entry.getName(), new Long(position));
}
} catch (IOException iox) {
throwNestedJarException(iox);
}
setUrisToPositions(map);
}
/**
* @see com.ibm.etools.archive.impl.LoadStrategyImpl
*/
protected boolean primContains(String uri) {
if (usingIndex())
return containsUsingIndex(uri);
return containsSequentially(uri);
}
protected boolean containsSequentially(String uri) {
ZipInputStream zis = null;
try {
zis = getZipInputStreamSkippedTo(uri);
return zis != null;
} catch (IOException ex) {
return false;
} finally {
if (zis != null) {
try {
zis.close();
} catch (IOException ioe) {
//Ignore
}
}
}
}
protected boolean containsUsingIndex(String uri) {
return getUrisToPositions().containsKey(uri);
}
/**
* Used internally; clients should not need to call
*/
public FileIterator getFileIterator() throws IOException {
if (((Archive) getContainer()).getOptions().isReadOnly())
return new NestedArchiveIterator(getContainer().getFiles(), getZipInputStream());
return super.getFileIterator();
}
/**
* @see com.ibm.etools.archive.impl.LoadStrategyImpl
*/
public java.util.List getFiles() {
List list = new ArrayList(500);
ZipInputStream zis = null;
try {
zis = getZipInputStream();
ZipEntry entry = zis.getNextEntry();
while (entry != null) {
if (!entry.isDirectory()) {
File aFile = createFile(entry.getName());
aFile.setSize(entry.getSize());
aFile.setLastModified(entry.getTime());
list.add(aFile);
}
entry = zis.getNextEntry();
}
} catch (IOException iox) {
throwNestedJarException(iox);
} finally {
if (zis != null) {
try {
zis.close();
} catch (IOException iox) {
//Ignore
}
}
}
return list;
}
/**
* @see com.ibm.etools.archive.impl.LoadStrategyImpl
*/
public java.io.InputStream getInputStream(String uri) throws IOException, FileNotFoundException {
if (usingIndex())
return getInputStreamUsingIndex(uri);
return getInputStreamSequentially(uri);
}
protected java.io.InputStream getInputStreamSequentially(String uri) throws IOException, FileNotFoundException {
return new java.io.BufferedInputStream(getZipInputStreamSkippedTo(uri));
}
protected java.io.InputStream getInputStreamUsingIndex(String uri) throws IOException, FileNotFoundException {
Long position = (Long) getUrisToPositions().get(uri);
if (position == null)
throw new FileNotFoundException();
ZipInputStream zis = getZipInputStream();
long pos = position.longValue();
for (long i = 0; i < pos; i++) {
zis.getNextEntry();
}
return new java.io.BufferedInputStream(zis);
}
/**
* Insert the method's description here. Creation date: (12/07/00 6:12:36 PM)
*
* @return com.ibm.etools.archive.LoadStrategy
*/
public org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.LoadStrategy getParent() {
return parent;
}
/**
* Insert the method's description here. Creation date: (12/07/00 4:38:21 PM)
*
* @return java.util.Map
*/
public java.util.Map getUrisToPositions() {
if (usingIndex() && urisToPositions == null)
buildIndex();
return urisToPositions;
}
protected ZipInputStream getZipInputStream() throws IOException, FileNotFoundException {
String uri = getContainer().getURI();
InputStream in = getParent().getInputStream(uri);
return new ZipInputStream(in);
}
protected ZipInputStream getZipInputStreamSkippedTo(String uri) throws IOException, FileNotFoundException {
if (uri == null)
throw new NullPointerException(CommonArchiveResourceHandler.Null_uri_EXC_); // = "Null uri"
ZipInputStream zis = null;
ZipEntry entry = null;
try {
zis = getZipInputStream();
entry = zis.getNextEntry();
while (entry != null) {
if (uri.equals(entry.getName()))
return zis;
entry = zis.getNextEntry();
}
} finally {
// entry was not found so close the stream
if (entry == null && zis != null) {
try {
zis.close();
} catch (IOException ioe) {
//Ignore
}
}
}
throw new FileNotFoundException(uri);
}
/**
* Insert the method's description here. Creation date: (12/07/00 6:12:36 PM)
*
* @param newParent
* com.ibm.etools.archive.LoadStrategy
*/
public void setParent(org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.LoadStrategy newParent) {
parent = newParent;
}
/**
* Insert the method's description here. Creation date: (12/07/00 4:38:21 PM)
*
* @param newUrisToPositions
* java.util.Map
*/
public void setUrisToPositions(java.util.Map newUrisToPositions) {
urisToPositions = newUrisToPositions;
}
/**
* An exception was caught reading the nested jar; throws a runtime exception
*/
protected void throwNestedJarException(Exception caughtException) {
throw new NestedJarException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.nested_jar_EXC_, (new Object[]{getContainer().getURI(), getParent().getContainer().getURI()})), caughtException);// = "An error occurred reading {0} from {1}"
}
/**
* Don't use the index in the runtime environment; reduce footprint
*/
public boolean usingIndex() {
return false;
//return !com.ibm.etools.archive.util.ArchiveUtil.isRuntime();
}
}