blob: 71a459dfb18f8f957e126f69672ad2325bee24b2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 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.j2ee.commonarchivecore.internal.impl;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EDataTypeUniqueEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jem.internal.java.adapters.ReadAdaptor;
import org.eclipse.jem.internal.java.adapters.jdk.JavaJDKAdapterFactory;
import org.eclipse.jst.j2ee.commonarchivecore.internal.Archive;
import org.eclipse.jst.j2ee.commonarchivecore.internal.ArchiveTypeDiscriminatorRegistry;
import org.eclipse.jst.j2ee.commonarchivecore.internal.CommonArchiveResourceHandler;
import org.eclipse.jst.j2ee.commonarchivecore.internal.CommonarchivePackage;
import org.eclipse.jst.j2ee.commonarchivecore.internal.Container;
import org.eclipse.jst.j2ee.commonarchivecore.internal.EARFile;
import org.eclipse.jst.j2ee.commonarchivecore.internal.File;
import org.eclipse.jst.j2ee.commonarchivecore.internal.ReadOnlyDirectory;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.DuplicateObjectException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.ManifestException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.OpenFailureException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.ReopenException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.ResourceLoadException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.SaveFailureException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifest;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifestImpl;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveOptions;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.RuntimeClasspathEntry;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.RuntimeClasspathEntryImpl;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.SaveFilter;
import org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.DirectorySaveStrategyImpl;
import org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.LoadStrategy;
import org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.SaveStrategy;
import org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.ZipStreamSaveStrategyImpl;
import org.eclipse.jst.j2ee.commonarchivecore.internal.util.ArchiveFileDynamicClassLoader;
import org.eclipse.jst.j2ee.commonarchivecore.internal.util.ArchiveUtil;
import org.eclipse.jst.j2ee.commonarchivecore.internal.util.ClasspathUtil;
import org.eclipse.jst.j2ee.commonarchivecore.looseconfig.internal.LooseArchive;
import org.eclipse.jst.j2ee.internal.J2EEConstants;
import org.eclipse.wst.common.internal.emf.utilities.EtoolsCopyUtility;
import org.eclipse.wst.common.internal.emf.utilities.ExtendedEcoreUtil;
/**
* @generated
*/
public class ArchiveImpl extends ContainerImpl implements Archive {
/**
* The cached value of the '{@link #getTypes() <em>Types</em>}' attribute list. <!--
* begin-user-doc --> <!-- end-user-doc -->
*
* @see #getTypes()
* @generated
* @ordered
*/
protected EList types = null;
/** Our specialized manifest */
protected ArchiveManifest manifest;
/** Implementer for saving this archive */
protected SaveStrategy saveStrategy;
/**
* Optional filter for saving a subset of files; filter will be applied for all save and extract
* invokations
*/
protected SaveFilter saveFilter;
/** Encoding to be used for all xmi resources and xml dds; defaults to UTF-8 */
protected String xmlEncoding = J2EEConstants.DEFAULT_XML_ENCODING;
/** Custom class loader used to load classes from the archive */
protected ClassLoader archiveClassLoader;
/**
* path of the standard classpath format where the archive may look for classes not found in the
* system classpath or in the archive - used for java reflection
*/
protected String extraClasspath;
protected ArchiveOptions options;
public ArchiveImpl() {
super();
getCommonArchiveFactory().archiveOpened(this);
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
protected EClass eStaticClass() {
return CommonarchivePackage.Literals.ARCHIVE;
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
public EList getTypes() {
if (types == null) {
types = new EDataTypeUniqueEList(String.class, this, CommonarchivePackage.ARCHIVE__TYPES);
}
return types;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case CommonarchivePackage.ARCHIVE__TYPES:
return getTypes();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case CommonarchivePackage.ARCHIVE__TYPES:
getTypes().clear();
getTypes().addAll((Collection)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void eUnset(int featureID) {
switch (featureID) {
case CommonarchivePackage.ARCHIVE__TYPES:
getTypes().clear();
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public boolean eIsSet(int featureID) {
switch (featureID) {
case CommonarchivePackage.ARCHIVE__TYPES:
return types != null && !types.isEmpty();
}
return super.eIsSet(featureID);
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
public String toString() {
if (eIsProxy()) return super.toString();
StringBuffer result = new StringBuffer(super.toString());
result.append(" (types: ");
result.append(types);
result.append(')');
return result.toString();
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public Archive addCopy(Archive anArchive) throws org.eclipse.jst.j2ee.commonarchivecore.internal.exception.DuplicateObjectException {
checkAddValid(anArchive);
Archive copy = getCommonArchiveFactory().copy(anArchive);
getFiles().add(copy);
return copy;
}
/**
* @see com.ibm.etools.commonarchive.Archive Adds a copy of the parameter to this archive
* @throws com.ibm.etools.archive.exception.DuplicateObjectException
* if the archive already contains a file with the specified uri
*/
public File addCopy(File aFile) throws DuplicateObjectException {
if (aFile.isReadOnlyDirectory()) {
addCopy((ReadOnlyDirectory) aFile);
return null;
}
checkAddValid(aFile);
File copy = copy(aFile);
getFiles().add(copy);
return copy;
}
/**
* Get a flattened list from the directory, then addCopy the list
*
* @throws com.ibm.etools.archive.exception.DuplicateObjectException
* if a file with a uri that equals one of the nested files in the directory exists
*
* @return java.util.List the copied files that were added to the archive
*/
public java.util.List addCopy(ReadOnlyDirectory dir) throws org.eclipse.jst.j2ee.commonarchivecore.internal.exception.DuplicateObjectException {
return addCopyFiles(dir.getFilesRecursive());
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public List addCopyFiles(java.util.List list) throws org.eclipse.jst.j2ee.commonarchivecore.internal.exception.DuplicateObjectException {
//Optimization - make sure the fileIndex is already built to speed up
// containsFile
getFiles();
List copyList = new ArrayList();
for (int i = 0; i < list.size(); i++) {
File aFile = (File) list.get(i);
checkAddValid(aFile);
copyList.add(copy(aFile));
}
getFiles().addAll(copyList);
return copyList;
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void addOrReplaceMofResource(org.eclipse.emf.ecore.resource.Resource aResource) {
getLoadStrategy().addOrReplaceMofResource(aResource);
}
/**
* @deprecated Use {@link #getDependentOpenArchives()}
* @see com.ibm.etools.commonarchive.Archive
*/
public boolean canClose() {
return !getCommonArchiveFactory().getOpenArchivesDependingOn(this).isEmpty();
}
protected void checkAddValid(File aFile) throws DuplicateObjectException {
checkAddValid(aFile.getURI());
}
protected void checkAddValid(String aUri) throws DuplicateObjectException {
try {
File f = getFile(aUri);
if (f != null)
throw new DuplicateObjectException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.duplicate_file_EXC_, (new Object[]{getURI(), aUri})), f); // = "The archive named {0} already contains a file named {1}"
} catch (FileNotFoundException ok) {
//Ignore
}
}
protected void cleanupAfterTempSave(String aUri, java.io.File original, java.io.File destinationFile) throws SaveFailureException {
checkWriteable(original);
boolean deleteWorked = false;
if (original.isDirectory() && !isRenameable(original)) {
throw new SaveFailureException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.unable_replace_EXC_, (new Object[]{original.getAbsolutePath()}))); // = "Unable to replace original archive "
}
for (int i = 0; i < 10; i++) {
if (ArchiveUtil.delete(original)) {
deleteWorked = true;
break;
}
try {
// TODO Major hack here; the problem is that a previous call
// to close the source file may not yet have
//been reflected in the os/vm; therefore a subsequent call
// to delete fails. To get around this,
//wait for a bit and retry; if it continues to fail, then
// time out and throw an exception
Thread.sleep(250);
} catch (InterruptedException e) {
//Ignore
}
}
if (deleteWorked) {
for (int i = 0; i < 10; i++) {
if (destinationFile.renameTo(original))
return;
try {
Thread.sleep(250);
} catch (InterruptedException e) {
//Ignore
}
}
}
throw new SaveFailureException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.unable_replace_EXC_, (new Object[]{original.getAbsolutePath()}))); // = "Unable to replace original archive "
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void close() {
getLoadStrategy().close();
releaseClassLoader();
getCommonArchiveFactory().archiveClosed(this);
if (isIndexed()) {
List archives = getArchiveFiles();
for (int i = 0; i < archives.size(); i++) {
((Archive) archives.get(i)).close();
}
}
}
protected File copy(File aFile) {
File copy = null;
if (aFile.isArchive())
copy = getCommonArchiveFactory().copy((Archive) aFile);
else
copy = (File) EtoolsCopyUtility.createCopy(aFile);
return copy;
}
protected LoadStrategy createLoadStrategyForReopen(Archive parent) throws IOException {
LoadStrategy aLoadStrategy = null;
LooseArchive loose = getLoadStrategy().getLooseArchive();
if (loose != null) {
aLoadStrategy = getCommonArchiveFactory().createLoadStrategy(loose.getBinariesPath());
aLoadStrategy.setLooseArchive(loose);
} else if (parent == null)
aLoadStrategy = getCommonArchiveFactory().createLoadStrategy(getURI());
else
aLoadStrategy = getCommonArchiveFactory().createChildLoadStrategy(getURI(), parent.getLoadStrategy());
return aLoadStrategy;
}
protected RuntimeClasspathEntry createRuntimeClasspathEntry(String absolutePath) {
RuntimeClasspathEntry entry = new RuntimeClasspathEntryImpl();
entry.setAbsolutePath(absolutePath);
return entry;
}
/**
* Convert all the classpath entries to absolute paths
*/
protected List createRuntimeClasspathEntries(String[] entries, String parentPath) {
List aList = new ArrayList(entries.length);
for (int i = 0; i < entries.length; i++) {
String entry = entries[i];
/*
* Added for loose module support - if the cananonicalized entry resolves to an archive
* in the containing ear, then add the absolute path of that archive
*/
Archive dependentJar = resolveClasspathEntryInEAR(entry);
if (dependentJar != null) {
try {
RuntimeClasspathEntry runEntry = createRuntimeClasspathEntry(dependentJar.getBinariesPath(), entry);
runEntry.setReferencedArchive(dependentJar);
aList.add(runEntry);
continue;
} catch (FileNotFoundException shouldntHappenInRuntime) {
//Ignore
}
}
//Otherwise, compute the absolute path of the entry relative to
// this jar
java.io.File aFile = new java.io.File(entry);
String absPath = null;
if (aFile.isAbsolute())
absPath = aFile.getAbsolutePath();
else {
absPath = ArchiveUtil.getOSUri(parentPath, entry);
absPath = ClasspathUtil.normalizePath(absPath);
}
aList.add(createRuntimeClasspathEntry(absPath, entry));
}
return aList;
}
protected RuntimeClasspathEntry createRuntimeClasspathEntry(String absolutePath, String manifestValue) {
RuntimeClasspathEntry entry = createRuntimeClasspathEntry(absolutePath);
entry.setManifestValue(manifestValue);
return entry;
}
protected SaveStrategy createSaveStrategyForDirectory(java.io.File dir, int expansionFlags) {
return new DirectorySaveStrategyImpl(dir.getAbsolutePath(), expansionFlags);
}
protected SaveStrategy createSaveStrategyForDirectory(String aUri, int expansionFlags) {
return new DirectorySaveStrategyImpl(aUri, expansionFlags);
}
protected SaveStrategy createSaveStrategyForJar(java.io.File aFile) throws java.io.IOException {
if (aFile.exists() && aFile.isDirectory())
throw new IOException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.file_exist_as_dir_EXC_, (new Object[]{aFile.getAbsolutePath()})));// = "A file named {0} exists and is a directory"
java.io.File parent = aFile.getParentFile();
if (parent != null)
parent.mkdirs();
java.io.OutputStream out = new java.io.FileOutputStream(aFile);
return new ZipStreamSaveStrategyImpl(out);
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void extract(int expansionFlags) throws SaveFailureException, ReopenException {
extractNoReopen(expansionFlags);
reopen();
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void extractNoReopen(int expansionFlags) throws SaveFailureException {
String aUri = getURI();
java.io.File aDir = new java.io.File(aUri);
boolean inUse = getLoadStrategy().isUsing(aDir);
try {
java.io.File destinationDir = inUse ? ArchiveUtil.createTempDirectory(aUri, aDir.getCanonicalFile().getParentFile()) : aDir;
SaveStrategy aSaveStrategy = createSaveStrategyForDirectory(destinationDir, expansionFlags);
save(aSaveStrategy);
aSaveStrategy.close();
close();
if (inUse) {
cleanupAfterTempSave(aUri, aDir, destinationDir);
}
} catch (java.io.IOException ex) {
throw new SaveFailureException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.error_saving_EXC_, (new Object[]{uri})), ex); // = "Error saving "
}
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void extractTo(java.lang.String aUri, int expansionFlags) throws SaveFailureException {
java.io.File aDir = new java.io.File(aUri);
if (getLoadStrategy().isUsing(aDir))
throw new SaveFailureException(CommonArchiveResourceHandler.Extract_destination_is_the_EXC_); // = "Extract destination is the same path as source file"
try {
SaveStrategy aSaveStrategy = createSaveStrategyForDirectory(aDir, expansionFlags);
save(aSaveStrategy);
aSaveStrategy.close();
} catch (java.io.IOException ex) {
throw new SaveFailureException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.error_saving_EXC_, (new Object[]{aUri})), ex); // = "Error saving "
}
}
public java.util.List filterFilesByPrefix(String prefix) {
return filterFiles(prefix, null);
}
public java.util.List filterFiles(String prefix, String[] suffixes) {
List subset = new ArrayList();
List theFiles = getFiles();
for (int i = 0; i < theFiles.size(); i++) {
File aFile = (File) theFiles.get(i);
if (!aFile.isDirectoryEntry() && aFile.getURI().startsWith(prefix))
if (suffixes == null || hasSuffix(aFile.getURI(), suffixes))
subset.add(aFile);
}
return subset;
}
/**
* @param uri
* @param suffixes
* @return
*/
private boolean hasSuffix(String aUri, String[] suffixes) {
for (int i = 0; i < suffixes.length; i++) {
if (aUri.endsWith(suffixes[i]))
return true;
}
return false;
}
public java.util.List filterFilesWithoutPrefix(String[] prefixes) {
List subset = new ArrayList();
List theFiles = getFiles();
for (int i = 0; i < theFiles.size(); i++) {
File aFile = (File) theFiles.get(i);
if (aFile.isDirectoryEntry())
continue;
boolean shouldAdd = true;
for (int j = 0; j < prefixes.length; j++) {
if (aFile.getURI().startsWith(prefixes[j])) {
shouldAdd = false;
break;
}
}
if (shouldAdd)
subset.add(aFile);
}
return subset;
}
/**
* Insert the method's description here. Creation date: (11/29/00 6:35:08 PM)
*
* @return java.lang.ClassLoader
*/
public java.lang.ClassLoader getArchiveClassLoader() {
if (archiveClassLoader == null)
initializeClassLoader();
return archiveClassLoader;
}
/**
* @see com.ibm.etools.commonarchive.EARFile
*/
public java.util.List getArchiveFiles() {
List archives = new ArrayList();
List fileList = getFiles();
for (int i = 0; i < fileList.size(); i++) {
File aFile = (File) fileList.get(i);
if (aFile.isArchive()) {
archives.add(aFile);
}
}
return archives;
}
/**
* Parse the manifest class path and the extra class path, and instantiate a URL classloader,
* with a parent of the archiveClassLoader
*/
protected ClassLoader getClassPathClassLoader(ClassLoader parentCl) {
List classPathComponents = new ArrayList();
if (getManifest() != null)
classPathComponents.addAll(Arrays.asList(getManifest().getClassPathTokenized()));
String extraCp = getExtraClasspath();
if (extraCp != null)
classPathComponents.addAll(Arrays.asList(ArchiveUtil.getTokens(extraCp, ";")));//$NON-NLS-1$
java.net.URL[] urlArray = ArchiveUtil.toLocalURLs(classPathComponents, getRootForRelativeDependentJars());
return new java.net.URLClassLoader(urlArray, parentCl);
}
public ResourceSet getResourceSet() {
return getLoadStrategy().getResourceSet();
}
/**
* Helper method to determine the parent for the custom class loader used by this archive
*/
protected ClassLoader getDefaultClassLoader() {
ClassLoader pluginClassLoader = getClass().getClassLoader();
return pluginClassLoader == null ? ClassLoader.getSystemClassLoader() : pluginClassLoader;
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public java.util.Set getDependentOpenArchives() {
return getCommonArchiveFactory().getOpenArchivesDependingOn(this);
}
/**
* Convert all the classpath entries to absolute paths
*/
protected List getEntriesAsAbsolutePaths(String[] entries, String parentPath) {
List aList = new ArrayList(entries.length);
for (int i = 0; i < entries.length; i++) {
String entry = entries[i];
/*
* Added for loose module support - if the cananonicalized entry resolves to an archive
* in the containing ear, then add the absolute path of that archive
*/
Archive dependentJar = resolveClasspathEntryInEAR(entry);
if (dependentJar != null) {
try {
aList.add(dependentJar.getAbsolutePath());
continue;
} catch (FileNotFoundException shouldntHappenInRuntime) {
//Ignore
}
}
//Otherwise, compute the absolute path of the entry relative to
// this jar
java.io.File aFile = new java.io.File(entry);
if (aFile.isAbsolute())
aList.add(aFile.getAbsolutePath());
else
aList.add(ArchiveUtil.getOSUri(parentPath, entry));
}
return aList;
}
/**
* Insert the method's description here. Creation date: (11/29/00 6:35:08 PM)
*
* @return java.lang.String
*/
public String getExtraClasspath() {
return extraClasspath;
}
/**
* Used internally by the framework, specifically as an optimization when saving/exploding
* archives with nested archives
*/
public org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.FileIterator getFilesForSave() throws IOException {
return getLoadStrategy().getFileIterator();
}
/**
* @see com.ibm.etools.commonarchive.File
*/
public java.io.InputStream getInputStream() throws java.io.FileNotFoundException, java.io.IOException {
if (getLoadingContainer() != null || getLoadStrategy() == null || getLoadStrategy().isDirectory())
return super.getInputStream();
//This archive was copied in; this operation is not supported for
// module files
if (isModuleFile() || !getOptions().isSaveLibrariesAsFiles())
throw new IOException("Undefined state of nested archive"); //$NON-NLS-1$
//We have to find the absolute path of the original archive from which
// this was copied,
//if it is known
List list = getFiles();
String absolutePath = null;
for (int i = 0; i < list.size(); i++) {
File aFile = (File) list.get(i);
if (aFile.isArchive())
continue;
absolutePath = aFile.getLoadingContainer().getAbsolutePath();
}
return new FileInputStream(absolutePath);
}
/**
* @see LoadStrategy#getResourceInputStream(String)
*/
public InputStream getResourceInputStream(String aUri) throws IOException {
return getLoadStrategy().getResourceInputStream(aUri);
}
protected JavaJDKAdapterFactory getJavaAdapterFactory() {
return (JavaJDKAdapterFactory) EcoreUtil.getAdapterFactory(getLoadStrategy().getResourceSet().getAdapterFactories(), ReadAdaptor.TYPE_KEY);
}
/**
* @see com.ibm.etools.commonarchive.Archive returns an immutable collection of the loaded
* resources in the resource set
*/
public Collection getLoadedMofResources() {
return getLoadStrategy().getLoadedMofResources();
}
/**
* Insert the method's description here. Creation date: (11/29/00 6:35:08 PM)
*/
public ArchiveManifest getManifest() {
if (manifest == null) {
InputStream in = null;
try {
in = getInputStream(J2EEConstants.MANIFEST_URI);
makeManifest(in);
} catch (FileNotFoundException ex) {
makeManifest();
} catch (Resource.IOWrappedException ex) {
WrappedException wrapEx = new WrappedException((ex).getWrappedException());
if (ExtendedEcoreUtil.getFileNotFoundDetector().isFileNotFound(wrapEx))
makeManifest();
else
throw new ManifestException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.io_ex_manifest_EXC_, (new Object[]{getURI()})), ex); // = "An IOException occurred reading the manifest: "
} catch (IOException ex) {
throw new ManifestException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.io_ex_manifest_EXC_, (new Object[]{getURI()})), ex); // = "An IOException occurred reading the manifest: "
} finally {
if (in != null)
try {
in.close();
} catch (IOException iox) {
//Ignore
}
}
}
//This is a hack because of the fact that the manifest does not
// serialize correctly if
//The version is not set. In addition to saves, the serialization is
// used for copy
if (manifest.getManifestVersion() == null || manifest.getManifestVersion().equals("")) //$NON-NLS-1$
manifest.setManifestVersion("1.0");//$NON-NLS-1$
return manifest;
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public org.eclipse.emf.ecore.resource.Resource getMofResource(java.lang.String aUri) throws FileNotFoundException, ResourceLoadException {
return getLoadStrategy().getMofResource(aUri);
}
protected Resource getMofResourceMakeIfNecessary(String aUri) {
if (getLoadStrategy() == null)
return null;
Resource resource = null;
try {
resource = getMofResource(aUri);
} catch (java.io.FileNotFoundException ex) {
try {
resource = makeMofResource(aUri);
} catch (DuplicateObjectException dox) {
//We just checked for this; it won't happen
}
}
return resource;
}
public org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveOptions getOptions() {
if (options == null) {
options = new ArchiveOptions();
}
return options;
}
/**
* When looking at the class path of this jar (from the manifest), some of the elements may have
* a relative path, thus we need to determine the install location of this jar. If the absolute
* path from which the archive was loaded, return the parent directory of that path; otherwise,
* see if the containing archive has an absolute path; if neither work, default to the current
* working directory
*/
public String getRootForRelativeDependentJars() {
String path = null;
Container theContainer = this;
while (theContainer != null && path == null) {
try {
path = theContainer.getAbsolutePath();
} catch (FileNotFoundException ex) {
//Ignore
}
theContainer = theContainer.getLoadingContainer();
}
if (path == null) {
path = System.getProperty("user.dir");//$NON-NLS-1$
if (path == null)
//At this point what else can we do?
return "";//$NON-NLS-1$
return new java.io.File(path).getAbsolutePath();
}
return new java.io.File(path).getParentFile().getAbsolutePath();
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public java.lang.String[] getRuntimeClassPath() {
String absolutePath;
try {
absolutePath = getBinariesPath();
} catch (IOException ex) {
return new String[0];
}
List entries = new ArrayList();
entries.add(absolutePath);
String parentPath = new java.io.File(absolutePath).getParentFile().getAbsolutePath();
String[] mfEntries = getManifest().getClassPathTokenized();
entries.addAll(getEntriesAsAbsolutePaths(mfEntries, parentPath));
return (String[]) entries.toArray(new String[entries.size()]);
}
/**
* Optional filter for saving a subset of files; filter will be applied for all save and extract
* invokations
*/
public org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.SaveFilter getSaveFilter() {
return saveFilter;
}
/**
* Insert the method's description here. Creation date: (12/04/00 3:31:32 PM)
*
* @return com.ibm.etools.archive.SaveStrategy
*/
public org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.SaveStrategy getSaveStrategy() {
return saveStrategy;
}
/**
* Insert the method's description here. Creation date: (11/29/00 6:35:08 PM)
*
* @return java.lang.String
*/
public java.lang.String getXmlEncoding() {
return xmlEncoding;
}
/**
* The default is to do nothing; subclasses may override as necessary
*
* @see com.ibm.etools.commonarchive.Archive
*/
public void initializeAfterOpen() {
//Default
}
public void initializeClassLoader() {
//Some load strategies may provide a mof context for which
//an alternate class loader is not necessary
if (!shouldUseJavaReflection())
return;
ClassLoader extraCl = null;
ClassLoader defaultCl = getDefaultClassLoader();
if (getContainer() == null || !getContainer().isEARFile())
extraCl = getClassPathClassLoader(defaultCl);
ClassLoader cl = createDynamicClassLoader(defaultCl, extraCl);
setArchiveClassLoader(cl);
JavaJDKAdapterFactory factory = getJavaAdapterFactory();
factory.setContextClassLoader(cl);
factory.flushAll();
}
public ClassLoader createDynamicClassLoader(ClassLoader parentCl, ClassLoader extraCl) {
return new ArchiveFileDynamicClassLoader(this, parentCl, extraCl);
}
/**
* @see com.ibm.etools.commonarchive.File
*/
public boolean isArchive() {
return true;
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public boolean isDuplicate(java.lang.String aUri) {
return containsFile(aUri) || isMofResourceLoaded(aUri) || J2EEConstants.MANIFEST_URI.equals(aUri);
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public boolean isManifestSet() {
return manifest != null;
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public boolean isMofResourceLoaded(java.lang.String aUri) {
return getLoadStrategy().isMofResourceLoaded(aUri);
}
/**
* By default just test the extension of the uri for one of the known archive types; subclasses
* may which to override.
*
* @see com.ibm.etools.commonarchive.Archive
*/
public boolean isNestedArchive(java.lang.String aUri) {
//110390.3 Error loading alt-bindings
/*
* Don't infer that a folder which ends with .jar is an exploded archive; EAR file will do
* that IF the folder is declared as a module in the EAR
*/
if (getLoadStrategy().isDirectory()) {
try {
String path = ArchiveUtil.getOSUri(getAbsolutePath(), aUri);
java.io.File ioFile = new java.io.File(path);
if (!ioFile.exists() || (ioFile.isDirectory() && aUri.startsWith(J2EEConstants.ALT_INF)))
return false;
} catch (IOException ex) {
return false;
}
}
return ArchiveTypeDiscriminatorRegistry.INSTANCE.isKnownArchiveType(aUri);
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public boolean isOpen() {
return getLoadStrategy() != null && getLoadStrategy().isOpen();
}
public ArchiveManifest makeManifest() {
ArchiveManifest mf = new ArchiveManifestImpl();
setManifest(mf);
return mf;
}
public ArchiveManifest makeManifest(InputStream in) throws IOException {
ArchiveManifest mf = new ArchiveManifestImpl(in);
setManifest(mf);
return mf;
}
public Resource makeMofResource(String aUri) throws DuplicateObjectException {
return makeMofResource(aUri, null);
}
/**
* @see com.ibm.etools.commonarchive.Archive#makeMofResource(String, EList)
*/
public Resource makeMofResource(String aUri, EList extent) throws DuplicateObjectException {
if (isDuplicate(aUri))
throw new DuplicateObjectException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.duplicate_entry_EXC_, (new Object[]{aUri, getURI()}))); // = "A file or resource with uri {0} already exists in the archive named {1}"
return getLoadStrategy().makeMofResource(aUri, extent);
}
/**
* @see Archive
*/
public Archive openNestedArchive(String aUri) throws OpenFailureException {
return getCommonArchiveFactory().openNestedArchive(aUri, this);
}
/**
* @see Archive
*/
public Archive openNestedArchive(LooseArchive loose) throws OpenFailureException {
return getCommonArchiveFactory().openNestedArchive(loose, this);
}
/**
* Set the value of the extra class path with no refresh of the class loader
*/
public void primSetExtraClasspath(java.lang.String newExtraClasspath) {
extraClasspath = newExtraClasspath;
}
/**
* Remove references to the archive class loader to prevent gc problems or problems with temp
* files not getting deleted
*/
public void releaseClassLoader() {
if (archiveClassLoader != null) {
setArchiveClassLoader(null);
getJavaAdapterFactory().setContextClassLoader(null);
}
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void remove(File aFile) {
getFiles().remove(aFile);
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void reopen() throws ReopenException {
reopen(null);
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void reopen(Archive parent) throws ReopenException {
LoadStrategy aLoadStrategy = null;
try {
aLoadStrategy = createLoadStrategyForReopen(parent);
} catch (IOException ex) {
throw new ReopenException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.io_ex_reopen_EXC_, (new Object[]{getURI()})), ex); // = "IOException occurred while reopening "
}
//PQ54572
LoadStrategy current = getLoadStrategy();
if (current != null) {
aLoadStrategy.setResourceSet(current.primGetResourceSet());
/*
* fixing problem with orphaned load strategy listening to the resource set
*/
current.setResourceSet(null);
}
setLoadStrategy(aLoadStrategy);
initializeClassLoader();
if (!isIndexed())
return;
List fileList = getFiles();
for (int i = 0; i < fileList.size(); i++) {
File f = (File) fileList.get(i);
f.setOriginalURI(f.getURI());
f.setLoadingContainer(this);
if (f.isArchive())
((Archive) f).reopen(this);
}
getCommonArchiveFactory().archiveOpened(this);
}
protected void replaceRoot(Resource aResource, EObject root) {
if (aResource == null)
return;
EList extent = aResource.getContents();
EObject existingRoot = null;
if (!extent.isEmpty()) {
existingRoot = (EObject) extent.get(0);
if (existingRoot == root)
return;
extent.remove(0);
}
if (root != null)
extent.add(0, root);
}
protected Archive resolveClasspathEntryInEAR(String entry) {
/*
* Added to support runtime classpath for loose modules
*/
Container parent = getContainer();
if (parent == null || !parent.isEARFile())
return null;
String aUri = ArchiveUtil.deriveEARRelativeURI(entry, this);
if (aUri == null)
return null;
File aFile = null;
try {
aFile = parent.getFile(aUri);
} catch (FileNotFoundException ex) {
return null;
}
return aFile.isArchive() ? (Archive) aFile : null;
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void save() throws SaveFailureException, ReopenException {
saveAs(getURI());
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void save(org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.SaveStrategy aStrategy) throws SaveFailureException {
setSaveStrategy(aStrategy);
SaveFilter existingFilter = aStrategy.getFilter();
boolean oldDelivery = eDeliver();
try {
if (getOptions().isReadOnly())
eSetDeliver(false);
aStrategy.setFilter(getSaveFilter());
aStrategy.save();
try {
aStrategy.finish();
} catch (java.io.IOException iox) {
throw new SaveFailureException(getURI(), iox);
}
} finally {
//We have to leave the file index if we are a directory because we
// might have
//open file handles to archives
if (getOptions().isReadOnly() && !getLoadStrategy().isDirectory()) {
files.clear();
//((BasicEList)files).setListImplementation(new ArrayList(0));
eSetDeliver(oldDelivery);
eAdapters().remove(getFileIndexAdapter());
fileIndexAdapter = null;
fileIndex = null;
}
setSaveStrategy(null);
aStrategy.setFilter(existingFilter);
}
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void saveAs(String aUri) throws SaveFailureException, ReopenException {
saveAsNoReopen(aUri);
reopen();
}
/**
* If we can rename it then we can delete it
*/
protected boolean isRenameable(java.io.File orig) {
java.io.File origCopy1 = null;
java.io.File origCopy2 = null;
try {
origCopy1 = orig.getCanonicalFile();
origCopy2 = orig.getCanonicalFile();
} catch (java.io.IOException ex) {
return false;
}
String name = null;
String baseName = "save.tmp"; //$NON-NLS-1$
try {
if (orig.getParent() != null)
baseName = new java.io.File(orig.getParent(), baseName).getCanonicalPath();
} catch (java.io.IOException ex) {
return false;
}
java.io.File temp = null;
int index = 0;
do {
name = baseName + index;
temp = new java.io.File(name);
index++;
} while (temp.exists());
return origCopy1.renameTo(temp) && temp.renameTo(origCopy2);
}
protected void checkWriteable(java.io.File dest) throws SaveFailureException {
List locked = ArchiveUtil.getWriteProtectedFiles(dest, null);
if (locked.isEmpty())
return;
StringBuffer msg = new StringBuffer();
msg.append("Cannot write to file: "); //$NON-NLS-1$
msg.append(dest.getAbsolutePath());
msg.append('\n');
msg.append("One or more files is write protected or locked:"); //$NON-NLS-1$
msg.append('\n');
for (int i = 0; i < locked.size(); i++) {
java.io.File aFile = (java.io.File) locked.get(i);
msg.append(aFile.getAbsolutePath());
msg.append('\n');
}
throw new SaveFailureException(msg.toString());
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void saveAsNoReopen(String aUri) throws SaveFailureException {
java.io.File aFile = new java.io.File(aUri);
checkWriteable(aFile);
boolean fileExisted = aFile.exists();
//botp 142149
//boolean inUse = getLoadStrategy().isUsing(aFile);
SaveStrategy aSaveStrategy = null;
try {
try {
java.io.File destinationFile = fileExisted ? ArchiveUtil.createTempFile(aUri, aFile.getCanonicalFile().getParentFile()) : aFile;
aSaveStrategy = createSaveStrategyForJar(destinationFile);
save(aSaveStrategy);
aSaveStrategy.close();
this.close();
if (fileExisted) {
cleanupAfterTempSave(aUri, aFile, destinationFile);
}
} catch (java.io.IOException ex) {
throw new SaveFailureException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.error_saving_EXC_, (new Object[]{aUri})), ex); // = "Error saving "
}
} catch (SaveFailureException failure) {
try {
if (aSaveStrategy != null)
aSaveStrategy.close();
} catch (IOException weTried) {
//Ignore
}
if (!fileExisted)
aFile.delete();
throw failure;
}
setURI(aUri);
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void saveNoReopen() throws SaveFailureException {
saveAsNoReopen(getURI());
}
/**
* Insert the method's description here. Creation date: (11/29/00 6:35:08 PM)
*
* @param newArchiveClassLoader
* java.lang.ClassLoader
*/
public void setArchiveClassLoader(java.lang.ClassLoader newArchiveClassLoader) {
archiveClassLoader = newArchiveClassLoader;
}
/**
* Insert the method's description here. Creation date: (11/29/00 6:35:08 PM)
*
* @param newExtraClasspath
* java.lang.String
*/
public void setExtraClasspath(java.lang.String newExtraClasspath) {
primSetExtraClasspath(newExtraClasspath);
//Optimization - only re init if a cl exists; otherwise it will init on
// demand
if (archiveClassLoader != null)
initializeClassLoader();
}
/**
* Insert the method's description here. Creation date: (11/29/00 6:35:08 PM)
*/
public void setManifest(ArchiveManifest newManifest) {
manifest = newManifest;
}
/**
* @see com.ibm.etools.commonarchive.Archive
*/
public void setManifest(java.util.jar.Manifest aManifest) {
setManifest((ArchiveManifest) new org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifestImpl(aManifest));
}
/**
* Sets the Class-path manifest entry, rebuilds the class loader, and refreshes any reflected
* java classes
*/
public void setManifestClassPathAndRefresh(String classpath) {
ArchiveManifest mf = getManifest();
if (manifest == null) {
makeManifest();
}
mf.setClassPath(classpath);
//Optimization - only re init if a cl exists; otherwise it will init on
// demand
if (archiveClassLoader != null)
initializeClassLoader();
}
public void setOptions(org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveOptions newOptions) {
options = newOptions;
}
/**
* Optional filter for saving a subset of files; filter will be applied for all save and extract
* invokations
*/
public void setSaveFilter(org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.SaveFilter newSaveFilter) {
saveFilter = newSaveFilter;
}
/**
* Insert the method's description here. Creation date: (12/04/00 3:31:32 PM)
*
* @param newSaveStrategy
* com.ibm.etools.archive.SaveStrategy
*/
public void setSaveStrategy(org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.SaveStrategy newSaveStrategy) {
saveStrategy = newSaveStrategy;
if (newSaveStrategy != null) {
newSaveStrategy.setArchive(this);
}
}
/**
* Insert the method's description here. Creation date: (11/29/00 6:35:08 PM)
*
* @param newXmlEncoding
* java.lang.String
*/
public void setXmlEncoding(java.lang.String newXmlEncoding) {
xmlEncoding = newXmlEncoding;
}
/**
* Determine whether java reflection should be set up for this archive
*/
public boolean shouldUseJavaReflection() {
return getOptions().useJavaReflection() && getLoadStrategy().isClassLoaderNeeded();
}
protected void throwResourceLoadException(String resourceUri, Exception ex) throws ResourceLoadException {
throw new ResourceLoadException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.load_resource_EXC_, (new Object[]{resourceUri, getURI()})), ex); // = "Could not load resource "{0}" in archive "{1}""
}
public String getResourcesPath() throws FileNotFoundException {
return getLoadStrategy().getResourcesPath();
}
public String getBinariesPath() throws FileNotFoundException {
return getLoadStrategy().getBinariesPath();
}
protected RuntimeClasspathEntry[] emptyClasspath() {
return new RuntimeClasspathEntry[0];
}
protected String internalGetBinariesPath() {
try {
return getBinariesPath();
} catch (FileNotFoundException ex) {
return null;
}
}
/**
* By default return just the contents of this archive
*/
public RuntimeClasspathEntry[] getLocalRuntimeClassPath() {
String absolutePath = internalGetBinariesPath();
if (absolutePath == null)
return emptyClasspath();
return new RuntimeClasspathEntry[]{createRuntimeClasspathEntry(absolutePath)};
}
protected RuntimeClasspathEntry[] getDependencyClassPathAtThisLevel() {
// BZ 170532: Don't use the archive's absolute path when the
// archive is loosely mapped. The current archive's absolute
// path, generally, will not be in a fixed location relative
// to the path of the parent application.
String parentPath = getParentPath();
if ( parentPath == null )
return emptyClasspath();
String[] mfEntries = getManifest().getClassPathTokenized();
if ( mfEntries.length == 0 )
return emptyClasspath();
List entries = new ArrayList();
entries.addAll( createRuntimeClasspathEntries(mfEntries, parentPath) );
return (RuntimeClasspathEntry[]) entries.toArray( new RuntimeClasspathEntry[ entries.size() ] );
}
/**
* <p>Answer a parent path for use by the receiver. Take into
* account wehther the receiver is a loose application or not.
*
* <p>Answer null in case an error is encountered while determining
* the parent path.</p>
*
* <p>Added for BZ 170532.</p>
*
* @return A parent path for use by the receiver. Null in case of an error.
*
* @see getDependencyClassPathAtThisLevel()
*/
protected String getParentPath() {
try {
if ( (getLoadStrategy().getLooseArchive() != null) && getContainer().isEARFile() ) {
return getEARFile().getBinariesPath();
} else {
return new java.io.File(getBinariesPath()).getParentFile().getAbsolutePath();
}
} catch (FileNotFoundException e) {
return null;
}
}
public RuntimeClasspathEntry[] getFullRuntimeClassPath() {
return concat(getLocalRuntimeClassPath(), getDependencyClassPath());
}
protected RuntimeClasspathEntry[] concat(RuntimeClasspathEntry[] array1, RuntimeClasspathEntry[] array2) {
List temp = new ArrayList();
temp.addAll(Arrays.asList(array1));
temp.addAll(Arrays.asList(array2));
return (RuntimeClasspathEntry[]) temp.toArray(new RuntimeClasspathEntry[temp.size()]);
}
public RuntimeClasspathEntry[] getDependencyClassPath() {
List entries = new ArrayList();
Set visited = new HashSet();
Set processedEntries = new HashSet();
visited.add(this);
getDependencyClassPath(visited, entries, processedEntries, this);
return (RuntimeClasspathEntry[]) entries.toArray(new RuntimeClasspathEntry[entries.size()]);
}
protected void getDependencyClassPath(Set visitedArchives, List entries, Set processedEntries, Archive current) {
RuntimeClasspathEntry[] local = ((ArchiveImpl) current).getDependencyClassPathAtThisLevel();
for (int i = 0; i < local.length; i++) {
RuntimeClasspathEntry entry = local[i];
if (!processedEntries.contains(entry)) {
entries.add(entry);
processedEntries.add(entry);
}
Archive resolved = entry.getReferencedArchive();
if (resolved == null)
ClasspathUtil.processManifest(entry.getAbsolutePath(), entries, processedEntries);
else if (!visitedArchives.contains(resolved)) {
visitedArchives.add(resolved);
getDependencyClassPath(visitedArchives, entries, processedEntries, resolved);
}
}
}
protected EARFile getEARFile() {
Container parent = getContainer();
if (parent == null || !(parent instanceof EARFile))
return null;
return (EARFile) parent;
}
protected Archive getResolvedArchive(String mfValue, EARFile ear) {
String aUri = ArchiveUtil.deriveEARRelativeURI(mfValue, this);
if (aUri == null)
return null;
try {
return (Archive) ear.getFile(aUri);
} catch (FileNotFoundException ex) {
return null;
} catch (ClassCastException ex2) {
return null;
}
}
/**
* @see com.ibm.etools.commonarchive.Archive#hasClasspathVisibilityTo(Archive)
*/
public boolean hasClasspathVisibilityTo(Archive other) {
if (other == null)
return false;
EARFile ear = getEARFile();
if (ear == null)
return false;
Set visited = new HashSet();
return hasClasspathVisibilityTo(other, visited, ear);
}
public boolean hasClasspathVisibilityTo(Archive other, Set visited, EARFile ear) {
if (this == other)
return true;
if (visited.contains(this))
return false;
visited.add(this);
String[] mfEntries = getManifest().getClassPathTokenized();
for (int i = 0; i < mfEntries.length; i++) {
Archive anArchive = getResolvedArchive(mfEntries[i], ear);
if (anArchive != null && anArchive.hasClasspathVisibilityTo(other, visited, ear))
return true;
}
return false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jst.j2ee.internal.commonarchivecore.Archive#isType(java.lang.String)
*/
public boolean isType(String type) {
return (types != null && getTypes().contains(type));
}
}