blob: 3f45bc8b24279fb6f7782846d34bbe471fd9ee89 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2007 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.jee.archive.internal;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jst.jee.archive.AbstractArchiveLoadAdapter;
import org.eclipse.jst.jee.archive.ArchiveModelLoadException;
import org.eclipse.jst.jee.archive.ArchiveOptions;
import org.eclipse.jst.jee.archive.IArchive;
import org.eclipse.jst.jee.archive.IArchiveLoadAdapter;
import org.eclipse.jst.jee.archive.IArchiveResource;
public class ArchiveImpl extends ArchiveResourceImpl implements IArchive {
private ArchiveOptions archiveOptions;
private IArchiveLoadAdapter loadAdapter;
private class ArchiveFileIndex {
private Map<IPath, IArchiveResource> index = new HashMap<IPath, IArchiveResource>();
private List<IArchiveResource> fullIndex = null;
private boolean fullyIndexed = false;
public ArchiveFileIndex() {
}
public synchronized boolean containsFile(IPath archiveRelativePath) {
AbstractArchiveLoadAdapter.verifyRelative(archiveRelativePath);
return index.containsKey(archiveRelativePath);
}
public synchronized IArchiveResource getFile(IPath archiveRelativePath) {
AbstractArchiveLoadAdapter.verifyRelative(archiveRelativePath);
IArchiveResource aFile = index.get(archiveRelativePath);
return aFile;
}
public synchronized void noteEmptyFile(IPath archiveRelativePath) {
verifyNotFullyIndexed();
AbstractArchiveLoadAdapter.verifyRelative(archiveRelativePath);
index.put(archiveRelativePath, null);
}
public synchronized void addFile(IArchiveResource aFile) {
verifyNotFullyIndexed();
AbstractArchiveLoadAdapter.verifyRelative(aFile.getPath());
index.put(aFile.getPath(), aFile);
}
public synchronized boolean isFullyIndexed() {
return fullyIndexed;
}
public void fullyIndex(List files) {
synchronized (this) {
if (fullyIndexed) {
verifyNotFullyIndexed();
}
fullyIndexed = true;
}
for (int i = 0; i < files.size(); i++) {
IArchiveResource aFile = (IArchiveResource) files.get(i);
AbstractArchiveLoadAdapter.verifyRelative(aFile.getPath());
synchronized (this) {
if (!index.containsKey(aFile.getPath())) {
index.put(aFile.getPath(), aFile);
}
}
}
}
public synchronized List<IArchiveResource> getFullIndex() {
if (!isFullyIndexed()) {
throw new RuntimeException("File list has not been fully indexed"); //$NON-NLS-1$
}
if (fullIndex == null) {
List<IArchiveResource> list = new ArrayList<IArchiveResource>();
list.addAll(index.values());
fullIndex = Collections.unmodifiableList(list);
}
return fullIndex;
}
private void verifyNotFullyIndexed() {
if (isFullyIndexed()) {
throw new RuntimeException("Attempting to modify a fully indexed file list"); //$NON-NLS-1$
}
}
};
private ArchiveFileIndex archiveFileIndex = new ArchiveFileIndex();
private FailedToCloseException openendBy = null;
public ArchiveImpl(ArchiveOptions archiveOptions) {
setType(IArchiveResource.ARCHIVE_TYPE);
setArchiveOptions(archiveOptions);
loadAdapter = (IArchiveLoadAdapter) getArchiveOptions().getOption(ArchiveOptions.LOAD_ADAPTER);
loadAdapter.setArchive(this);
openendBy = new FailedToCloseException();
}
public boolean isOpen() {
return openendBy != null;
}
public void close() {
openendBy = null;
loadAdapter.close();
}
public IArchiveResource getArchiveResource(IPath archiveRelativePath) throws FileNotFoundException {
AbstractArchiveLoadAdapter.verifyRelative(archiveRelativePath);
IArchiveResource aFile = null;
if (archiveFileIndex.containsFile(archiveRelativePath)) {
aFile = archiveFileIndex.getFile(archiveRelativePath);
} else if (!archiveFileIndex.isFullyIndexed()) {
aFile = loadAdapter.getArchiveResource(archiveRelativePath);
if (aFile == null) {
archiveFileIndex.noteEmptyFile(archiveRelativePath);
} else {
archiveFileIndex.addFile(aFile);
}
}
return aFile;
}
public List<IArchiveResource> getArchiveResources() {
synchronized (this) {
if (!archiveFileIndex.isFullyIndexed()) {
archiveFileIndex.fullyIndex(loadAdapter.getArchiveResources());
}
}
return archiveFileIndex.getFullIndex();
}
public IArchiveLoadAdapter getLoadAdapter() {
return loadAdapter;
}
protected void setArchiveOptions(ArchiveOptions archiveOptions) {
this.archiveOptions = archiveOptions;
}
public ArchiveOptions getArchiveOptions() {
return archiveOptions;
}
public String toString() {
return loadAdapter.toString();
}
protected void finalize() throws Throwable {
super.finalize();
if (isOpen()) {
System.err.println("Archive opener did not close archive: " + this); //$NON-NLS-1$
System.err.println("Archive was opened here:"); //$NON-NLS-1$
openendBy.printStackTrace(System.err);
close();
}
}
public boolean containsModelObject() {
return containsModelObject(IArchive.EMPTY_MODEL_PATH);
}
public boolean containsModelObject(IPath modelObjectPath) {
AbstractArchiveLoadAdapter.verifyRelative(modelObjectPath);
return getLoadAdapter().containsModelObject(modelObjectPath);
}
public Object getModelObject() throws ArchiveModelLoadException {
return getModelObject(IArchive.EMPTY_MODEL_PATH);
}
public Object getModelObject(IPath modelObjectPath) throws ArchiveModelLoadException {
AbstractArchiveLoadAdapter.verifyRelative(modelObjectPath);
return getLoadAdapter().getModelObject(modelObjectPath);
}
public boolean containsArchiveResource(IPath archiveRelativePath) {
AbstractArchiveLoadAdapter.verifyRelative(archiveRelativePath);
if (archiveFileIndex.containsFile(archiveRelativePath)) {
return true;
} else if (!archiveFileIndex.isFullyIndexed()) {
return loadAdapter.containsArchiveResource(archiveRelativePath);
}
return false;
}
}