/*******************************************************************************
 * Copyright (c) 2001, 2004 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.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EObjectContainmentWithInverseEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.jst.j2ee.application.Application;
import org.eclipse.jst.j2ee.application.ApplicationFactory;
import org.eclipse.jst.j2ee.application.ConnectorModule;
import org.eclipse.jst.j2ee.application.EjbModule;
import org.eclipse.jst.j2ee.application.JavaClientModule;
import org.eclipse.jst.j2ee.application.Module;
import org.eclipse.jst.j2ee.application.WebModule;
import org.eclipse.jst.j2ee.client.ApplicationClient;
import org.eclipse.jst.j2ee.common.EjbRef;
import org.eclipse.jst.j2ee.common.SecurityRole;
import org.eclipse.jst.j2ee.commonarchivecore.internal.Archive;
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.EJBJarFile;
import org.eclipse.jst.j2ee.commonarchivecore.internal.File;
import org.eclipse.jst.j2ee.commonarchivecore.internal.ModuleFile;
import org.eclipse.jst.j2ee.commonarchivecore.internal.ModuleRef;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.ArchiveWrappedException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.DeploymentDescriptorLoadException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.DuplicateObjectException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.EmptyResourceException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.ObjectNotFoundException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.OpenFailureException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.ResourceLoadException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveOptions;
import org.eclipse.jst.j2ee.commonarchivecore.internal.looseconfig.LooseArchive;
import org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.LoadStrategy;
import org.eclipse.jst.j2ee.commonarchivecore.internal.util.ArchiveUtil;
import org.eclipse.jst.j2ee.ejb.AssemblyDescriptor;
import org.eclipse.jst.j2ee.ejb.EJBJar;
import org.eclipse.jst.j2ee.ejb.EJBResource;
import org.eclipse.jst.j2ee.ejb.EnterpriseBean;
import org.eclipse.jst.j2ee.internal.J2EEConstants;
import org.eclipse.jst.j2ee.internal.application.ApplicationPackage;
import org.eclipse.jst.j2ee.internal.client.impl.ApplicationClientResourceFactory;
import org.eclipse.jst.j2ee.internal.common.XMLResource;
import org.eclipse.jst.j2ee.internal.common.impl.J2EEResourceFactoryRegistry;
import org.eclipse.jst.j2ee.internal.ejb.EjbPackage;
import org.eclipse.jst.j2ee.internal.ejb.impl.EJBJarResourceFactory;
import org.eclipse.jst.j2ee.internal.jca.impl.ConnectorResourceFactory;
import org.eclipse.jst.j2ee.internal.webapplication.impl.WebAppResourceFactory;
import org.eclipse.jst.j2ee.jca.Connector;
import org.eclipse.jst.j2ee.webapplication.WebApp;
import org.eclipse.wst.common.internal.emf.utilities.EtoolsCopyUtility;


/**
 * @generated
 */
public class EARFileImpl extends ModuleFileImpl implements EARFile {

	/**
	 * Internal; clients should use {@link #getModuleRef(Module)}
	 */
	public ModuleFile getModuleFile(Module moduleDescriptor) {
		ModuleRef ref = getModuleRef(moduleDescriptor);
		return (ref == null) ? null : ref.getModuleFile();
	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public ModuleFile addCopy(ModuleFile aModuleFile) throws DuplicateObjectException {
		Object result = primAddCopyRef(aModuleFile);
		if (result instanceof ModuleRef)
			return ((ModuleRef) result).getModuleFile();

		return (ModuleFile) result;
	}

	/**
	 * @generated This field/method will be replaced during code generation.
	 */
	/**
	 * @generated This field/method will be replaced during code generation.
	 */
	protected Application deploymentDescriptor = null;
	/**
	 * @generated This field/method will be replaced during code generation.
	 */
	protected EList moduleRefs = null;

	public EARFileImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	protected EClass eStaticClass() {
		return CommonarchivePackage.eINSTANCE.getEARFile();
	}

	public Archive addCopy(Archive anArchive) throws org.eclipse.jst.j2ee.commonarchivecore.internal.exception.DuplicateObjectException {
		if (anArchive.isModuleFile())
			return addCopy((ModuleFile) anArchive);
		Archive copy = super.addCopy(anArchive);
		copy.initializeClassLoader();
		return copy;
	}

	protected Object primAddCopyRef(ModuleFile aModuleFile) throws DuplicateObjectException {
		//force this list to get initialized before the add
		EList refs = getModuleRefs();

		if (aModuleFile.isEARFile())
			//If it's an ear then just treat it like any other archive
			return (ModuleFile) super.addCopy(aModuleFile);
		checkAddValid(aModuleFile);
		ModuleFile copy = getCommonArchiveFactory().copy(aModuleFile);
		Module newModule = createModuleForCopying(aModuleFile);
		getFiles().add(copy);
		copy.initializeClassLoader();
		if (!copy.getURI().equals(newModule.getUri()))
			copy.setURI(newModule.getUri());

		getDeploymentDescriptor().getModules().add(newModule);
		ModuleRef aRef = createModuleRef(newModule, copy);
		refs.add(aRef);
		return aRef;
	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public ModuleRef addCopyRef(ModuleFile aModuleFile) throws DuplicateObjectException {
		Object result = primAddCopyRef(aModuleFile);
		if (result instanceof ModuleRef)
			return (ModuleRef) result;

		return null;
	}



	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public SecurityRole addCopy(SecurityRole aRole, Module aModule) throws DuplicateObjectException {
		EObject dd = null;
		try {
			dd = getDeploymentDescriptor(aModule);
		} catch (Exception e) {
			throw new DeploymentDescriptorLoadException(CommonArchiveResourceHandler.getString("dd_in_ear_load_EXC_", (new Object[]{aModule.getUri(), getURI()})), e); //$NON-NLS-1$ = "Exception occurred loading deployment descriptor for module "{0}" in ear file "{1}""
		}
		String roleName = aRole.getRoleName();
		SecurityRole copy = (SecurityRole) EtoolsCopyUtility.createCopy(aRole);
		if (aModule.isEjbModule()) {
			EJBJar ejbJar = (EJBJar) dd;
			if (ejbJar.containsSecurityRole(roleName))
				throw new DuplicateObjectException(CommonArchiveResourceHandler.getString("dup_sec_role_module_EXC_", (new Object[]{aModule.getUri(), roleName})), ejbJar.getAssemblyDescriptor().getSecurityRoleNamed(roleName)); //$NON-NLS-1$ = "Deployment descriptor for {0} already contains a security role named {1}"
			getAssemblyDescriptorAddIfNecessary(ejbJar).getSecurityRoles().add(copy);
		} else if (aModule.isWebModule()) {
			WebApp webApp = (WebApp) dd;
			if (webApp.containsSecurityRole(roleName))
				throw new DuplicateObjectException(CommonArchiveResourceHandler.getString("dup_sec_role_module_EXC_", (new Object[]{aModule.getUri(), roleName})), webApp.getSecurityRoleNamed(roleName));//$NON-NLS-1$ = "Deployment descriptor for {0} already contains a security role named {1}"
			webApp.getSecurityRoles().add(copy);
		}
		addCopyIfNotExists(aRole);
		return copy;
	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public SecurityRole addCopyIfNotExists(SecurityRole aRole) {
		Application dd = getDeploymentDescriptor();
		SecurityRole copy = null;
		if (!dd.containsSecurityRole(aRole.getRoleName())) {
			copy = (SecurityRole) EtoolsCopyUtility.createCopy(aRole);
			dd.getSecurityRoles().add(copy);
		}
		return copy;
	}

	protected void checkDuplicate(String aUri) throws DuplicateObjectException {
		if (isDuplicate(aUri))
			throw new DuplicateObjectException(CommonArchiveResourceHandler.getString("dup_resource_EXC_", (new Object[]{aUri, getURI()}))); //$NON-NLS-1$ = "Resource named "{0}" already exists in archive "{1}""
	}


	protected Module createModuleForCopying(ModuleFile aModuleFile) {
		Module aModule = null;
		if (aModuleFile.isWARFile()) {
			aModule = getApplicationFactory().createWebModule();
		} else if (aModuleFile.isEJBJarFile()) {
			aModule = getApplicationFactory().createEjbModule();
		} else if (aModuleFile.isApplicationClientFile()) {
			aModule = getApplicationFactory().createJavaClientModule();
		} else if (aModuleFile.isRARFile()) {
			aModule = getApplicationFactory().createConnectorModule();
		}
		aModule.setUri(aModuleFile.getURI());
		return aModule;
	}

	/**
	 * Retrieves the deployment descriptor root element for the specified module. Takes into account
	 * altDD indirection.
	 * 
	 * @return Only return null if an altDD is not defined.
	 */
	public EObject getAltDeploymentDescriptor(Module aModule) throws FileNotFoundException, ResourceLoadException, EmptyResourceException {
		// Look for altDD
		String altDD = aModule.getAltDD();
		if (ArchiveUtil.isNullOrEmpty(altDD))
			return null;
		if (!isMofResourceLoaded(altDD.trim()))
			registerResourceFactory(aModule, altDD);
		XMLResource ddRes = (XMLResource) getMofResource(altDD.trim());
		if (!ddRes.isAlt()) {
			ddRes.setIsAlt(true);
			ddRes.setApplication(getDeploymentDescriptor());
		}
		return ArchiveUtil.getRoot(ddRes);

	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public java.util.List getApplicationClientFiles() {
		List clientFiles = new ArrayList();
		List fileList = getFiles();
		for (int i = 0; i < fileList.size(); i++) {
			File aFile = (File) fileList.get(i);
			if (aFile.isApplicationClientFile()) {
				clientFiles.add(aFile);
			}
		}
		return clientFiles;
	}

	protected ApplicationFactory getApplicationFactory() {
		return ((ApplicationPackage) EPackage.Registry.INSTANCE.getEPackage(ApplicationPackage.eNS_URI)).getApplicationFactory();
	}

	protected AssemblyDescriptor getAssemblyDescriptorAddIfNecessary(EJBJar ejbJar) {
		AssemblyDescriptor ad = ejbJar.getAssemblyDescriptor();
		if (ad == null) {
			ad = ((EjbPackage) EPackage.Registry.INSTANCE.getEPackage(EjbPackage.eNS_URI)).getEjbFactory().createAssemblyDescriptor();
			ejbJar.setAssemblyDescriptor(ad);
		}
		return ad;
	}


	/**
	 * @throws DeploymentDescriptorLoadException -
	 *             is a runtime exception, because we can't override the signature of the generated
	 *             methods
	 */
	public Application getDeploymentDescriptor() throws DeploymentDescriptorLoadException {
		Application dd = this.getDeploymentDescriptorGen();
		if (dd == null && canLazyInitialize()) {
			try {
				getImportStrategy().importMetaData();
			} catch (Exception e) {
				throw new DeploymentDescriptorLoadException(getDeploymentDescriptorUri(), e);
			}
		}
		return this.getDeploymentDescriptorGen();
	}

	/**
	 * Retrieves the deployment descriptor root element for the specified module. Takes into account
	 * altDD indirection.
	 */
	public Connector getDeploymentDescriptor(ConnectorModule aModule) throws FileNotFoundException, ResourceLoadException, EmptyResourceException {
		return (Connector) getDeploymentDescriptor((Module) aModule);
	}

	/**
	 * Retrieves the deployment descriptor root element for the specified module. Takes into account
	 * altDD indirection.
	 */
	public EJBJar getDeploymentDescriptor(EjbModule aModule) throws FileNotFoundException, ResourceLoadException, EmptyResourceException {
		return (EJBJar) getDeploymentDescriptor((Module) aModule);
	}

	/**
	 * Retrieves the deployment descriptor root element for the specified module. Takes into account
	 * altDD indirection.
	 */
	public ApplicationClient getDeploymentDescriptor(JavaClientModule aModule) throws FileNotFoundException, ResourceLoadException, EmptyResourceException {
		return (ApplicationClient) getDeploymentDescriptor((Module) aModule);
	}

	/**
	 * Retrieves the deployment descriptor root element for the specified module. Takes into account
	 * altDD indirection.
	 */
	public EObject getDeploymentDescriptor(Module aModule) throws FileNotFoundException, ResourceLoadException, EmptyResourceException {
		EObject dd = getAltDeploymentDescriptor(aModule);
		if (dd == null)
			dd = getModuleFile(aModule).getStandardDeploymentDescriptor();
		return dd;
	}

	/**
	 * Retrieves the deployment descriptor root element for the specified module. Takes into account
	 * altDD indirection.
	 */
	public WebApp getDeploymentDescriptor(WebModule aModule) throws FileNotFoundException, ResourceLoadException, EmptyResourceException {
		return (WebApp) getDeploymentDescriptor((Module) aModule);
	}

	/**
	 * @see com.ibm.etools.commonarchive.ModuleFile
	 */
	public java.lang.String getDeploymentDescriptorUri() {
		return J2EEConstants.APPLICATION_DD_URI;
	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public java.util.List getEJBJarFiles() {
		List ejbJarFiles = new ArrayList();
		List fileList = getFiles();
		for (int i = 0; i < fileList.size(); i++) {
			File aFile = (File) fileList.get(i);
			if (aFile.isEJBJarFile()) {
				ejbJarFiles.add(aFile);
			}
		}
		return ejbJarFiles;
	}

	/**
	 * Return an enterprise bean referenced by the EjbRef, if one exists. The ejb-link value of the
	 * ref must equate to a named enterprise bean contained in the jar; otherwise return null.
	 * Returns the first hit found; assumption that the ejb names are unique within the scope of the
	 * ear file. This will likely be replaced with a better way for dereferencing ejb refs.
	 * 
	 * Can be used with ejb 1.1 references only.
	 * 
	 * @deprecated {@link#getEnterpiseBeanFromRef(EjbRef ref, String moduleUri )
	 * @param EjbRef
	 *            ref - An ejb reference
	 * @return EnterpriseBean
	 */
	public EnterpriseBean getEnterpiseBeanFromRef(EjbRef ref) {
		String link = ref.getLink();
		if (link == null) {
			return null;
		}
		List jarFiles = getEJBJarFiles();
		for (int i = 0; i < jarFiles.size(); i++) {
			EnterpriseBean bean = ((EJBJarFile) jarFiles.get(i)).getDeploymentDescriptor().getEnterpriseBeanNamed(link);
			if (bean != null) {
				return bean;
			}
		}
		return null;
	}

	/**
	 * Return an enterprise bean referenced by the EjbRef, if one exists. The ejb-link value of the
	 * ref must equate to a named enterprise bean contained in the jar; otherwise return null.
	 * Returns the first hit found; assumption that the ejb names are unique within the scope of the
	 * ear file. This will likely be replaced with a better way for dereferencing ejb refs
	 * 
	 * Can be used with ejb 1.1 & ejb 2.0 references.
	 * 
	 * @param EjbRef
	 *            ref - An ejb reference
	 * @param String
	 *            moduleUri - The module uri
	 * @return EnterpriseBean
	 */
	public EnterpriseBean getEnterpiseBeanFromRef(EjbRef ref, String moduleUri) {
		String link = ref.getLink();
		if (link == null) {
			return null;
		}// if

		if (link.indexOf('#') == -1) {
			EnterpriseBean linkedEJB = null;
			XMLResource res = (XMLResource) ref.eResource();
			if (res instanceof EJBResource) {
				//Must be in an EJB JAR to be here
				EJBJar jar = ((EJBResource) res).getEJBJar();
				if (jar != null)
					linkedEJB = jar.getEnterpiseBeanFromRef(ref);
			}
			if (linkedEJB == null) {
				List jarFiles = getEJBJarFiles();
				for (int i = 0; i < jarFiles.size(); i++) {
					linkedEJB = ((EJBJarFile) jarFiles.get(i)).getDeploymentDescriptor().getEnterpriseBeanNamed(link);
					if (linkedEJB != null) {
						return linkedEJB;
					}// if
				}// for
			} else
				return linkedEJB;
		} else {
			//Grab the ejb name and ejb jar name from the link
			String ejbBeanName = link.substring(link.indexOf("#") + 1, link.length()); //$NON-NLS-1$
			String ejbJarName = link.substring(0, link.indexOf("#")); //$NON-NLS-1$

			if (ejbBeanName != null && ejbJarName != null) {
				//Get the uri of the jar name.
				String ejbJarUri = ArchiveUtil.deriveEARRelativeURI(ejbJarName, moduleUri);
				if (ejbJarUri != null) {
					try {
						//Get the actual jar file
						File aFile = getFile(ejbJarUri);
						if (aFile == null || !aFile.isEJBJarFile())
							return null;

						EJBJarFile jarFile = (EJBJarFile) getFile(ejbJarUri);
						List ejbs = jarFile.getDeploymentDescriptor().getEnterpriseBeans();
						//Check if any of the beans in the list match the given ejb bean name give
						// in
						//the link
						if (ejbs != null && !ejbs.isEmpty()) {
							Iterator it = ejbs.iterator();
							while (it.hasNext()) {
								EnterpriseBean ejbBean = (EnterpriseBean) it.next();
								if (ejbBean != null && ejbBean.getName().equals(ejbBeanName)) {
									return ejbBean;
								}// if
							}// while
						}// if
					} catch (FileNotFoundException fe) {
						return null;
					}// try
				}// if
			}// if
		}// if
		return null;
	}// getEnterpiseBeanFromRef

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public Module getModule(String aUri, String altDD) {
		return getDeploymentDescriptor().getModule(aUri, altDD);
	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public ModuleRef getModuleRef(Module moduleDescriptor) {
		List refs = getModuleRefs();
		for (int i = 0; i < refs.size(); i++) {
			ModuleRef ref = (ModuleRef) refs.get(i);
			if (ref.getModule() == moduleDescriptor)
				return ref;
		}
		return null;
	}

	/**
	 * Return a filtered list of the archives
	 */
	public List getModuleFiles() {
		List moduleFiles = new ArrayList();
		List fileList = getFiles();
		for (int i = 0; i < fileList.size(); i++) {
			File aFile = (File) fileList.get(i);
			if (aFile.isModuleFile()) {
				moduleFiles.add(aFile);
			}
		}
		return moduleFiles;
	}

	protected ArchiveOptions getOptionsForOpening(String aUri) throws IOException {

		LoadStrategy strategy = getCommonArchiveFactory().createChildLoadStrategy(aUri, getLoadStrategy());
		return getOptions().cloneWith(strategy, aUri);
	}

	protected ArchiveOptions getOptionsForOpening(LooseArchive loose) throws IOException {
		LoadStrategy strategy = getCommonArchiveFactory().createLoadStrategy(loose.getBinariesPath());
		strategy.setLooseArchive(loose);
		return getOptions().cloneWith(strategy, loose.getUri());
	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public java.util.List getRARFiles() {
		List rarFiles = new ArrayList();
		List fileList = getFiles();
		for (int i = 0; i < fileList.size(); i++) {
			File aFile = (File) fileList.get(i);
			if (aFile.isRARFile()) {
				rarFiles.add(aFile);
			}
		}
		return rarFiles;
	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public EList getRolesFromAllModules() {
		EList roleList = new org.eclipse.emf.common.util.BasicEList();
		List modules = getDeploymentDescriptor().getModules();
		for (int i = 0, n = modules.size(); i < n; i++) {
			Module aModule = (Module) modules.get(i);
			EList roles = getRolesFromModule(aModule);
			for (int j = 0, m = roles.size(); j < m; j++) {
				roleList.add(roles.get(j));
			}
		}
		return roleList;
	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public EList getRolesFromModule(Module aModule) {
		EList roleList = new org.eclipse.emf.common.util.BasicEList();
		try {
			if (aModule.isWebModule())
				roleList = getDeploymentDescriptor((WebModule) aModule).getSecurityRoles();
			else if (aModule.isEjbModule())
				roleList = getAssemblyDescriptorAddIfNecessary(getDeploymentDescriptor((EjbModule) aModule)).getSecurityRoles();
		} catch (Exception e) {
			throw new DeploymentDescriptorLoadException(CommonArchiveResourceHandler.getString("dd_in_ear_load_EXC_", (new Object[]{aModule.getUri(), getURI()})), e); //$NON-NLS-1$ = "Exception occurred loading deployment descriptor for module "{0}" in ear file "{1}""
		}
		return roleList;
	}

	/**
	 * Return the DeployementDescriptor.
	 */
	public EObject getStandardDeploymentDescriptor() throws DeploymentDescriptorLoadException {
		return getDeploymentDescriptor();
	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public java.util.List getWARFiles() {
		List warFiles = new ArrayList();
		List fileList = getFiles();
		for (int i = 0; i < fileList.size(); i++) {
			File aFile = (File) fileList.get(i);
			if (aFile.isWARFile()) {
				warFiles.add(aFile);
			}
		}
		return warFiles;
	}

	public void initializeAfterOpen() {
		super.initializeAfterOpen();
	}

	public boolean isDeploymentDescriptorSet() {
		return deploymentDescriptor != null;
	}

	/**
	 * @see com.ibm.etools.commonarchive.File
	 */
	public boolean isEARFile() {
		return true;
	}

	/**
	 * Return true if super returns true, or return whether the app dd contains a module having the
	 * uri
	 */
	public boolean isNestedArchive(String aUri) {
		if (super.isNestedArchive(aUri))
			return true;
		return getDeploymentDescriptor().getFirstModule(aUri) != null;
	}

	/**
	 * @see com.ibm.etools.commonarchive.impl.ModuleFileImpl
	 */
	public org.eclipse.emf.ecore.EObject makeDeploymentDescriptor(XMLResource resource) {
		Application appl = ((ApplicationPackage) EPackage.Registry.INSTANCE.getEPackage(ApplicationPackage.eNS_URI)).getApplicationFactory().createApplication();
		resource.setID(appl, J2EEConstants.APPL_ID);
		setDeploymentDescriptorGen(appl);
		resource.getContents().add(appl);
		return appl;
	}

	/**
	 * @see com.ibm.etools.commonarchive.Archive
	 */
	public Archive openNestedArchive(LooseArchive loose) throws OpenFailureException {

		Module m = getDeploymentDescriptor().getFirstModule(loose.getUri());
		if (m == null)
			return super.openNestedArchive(loose);

		try {
			ArchiveOptions archiveOptions = getOptionsForOpening(loose);
			return openNestedArchive(m, archiveOptions);
		} catch (java.io.IOException ex) {
			//Probably the file did not exist; silently fail, per request from WS runtime
			//More than likely a failure is going to occur down the road when a ModuleFile for a
			// Module
			//in the dd is requested
		}
		return null;
	}

	/**
	 * @see com.ibm.etools.commonarchive.Archive
	 */
	public Archive openNestedArchive(String aUri) throws OpenFailureException {

		Module m = getDeploymentDescriptor().getFirstModule(aUri);
		if (m == null)
			return super.openNestedArchive(aUri);

		try {
			ArchiveOptions archiveOptions = getOptionsForOpening(aUri);
			return openNestedArchive(m, archiveOptions);
		} catch (java.io.IOException ex) {
			//Probably the file did not exist; silently fail, per request from WS runtime
			//More than likely a failure is going to occur down the road when a ModuleFile for a
			// Module
			//in the dd is requested
		}
		return null;
	}

	protected Archive openNestedArchive(Module m, ArchiveOptions archiveOptions) throws OpenFailureException {
		String aUri = m.getUri();

		try {
			/*
			 * Since we have a clue about the type of archive to open Use the appropriate open
			 * method, so if a failure occurrs, we can get a more specific message
			 */
			if (m.isWebModule())
				return getCommonArchiveFactory().openWARFile(archiveOptions, aUri);
			else if (m.isEjbModule())
				return getCommonArchiveFactory().openEJBJarFile(archiveOptions, aUri);
			else if (m.isJavaModule())
				return getCommonArchiveFactory().openApplicationClientFile(archiveOptions, aUri);
			else if (m.isConnectorModule())
				return getCommonArchiveFactory().openRARFile(archiveOptions, aUri);

		} catch (OpenFailureException ex) {
			throw new OpenFailureException(CommonArchiveResourceHandler.getString("nested_open_fail_EXC_", (new Object[]{aUri, getURI()})), ex); //$NON-NLS-1$ = "Unable to open module file "{0}" in EAR file "{1}""
		}
		//Should never reach the code below
		return null;
	}

	/**
	 * @see EARFile
	 */
	public void pushDownRole(SecurityRole role) {
		if (role == null)
			throw new IllegalArgumentException(CommonArchiveResourceHandler.getString("Parameter_should_not_be_nu_EXC_")); //$NON-NLS-1$ = "Parameter should not be null"

		List modules = getDeploymentDescriptor().getModules();
		for (int i = 0; i < modules.size(); i++) {
			Module m = (Module) modules.get(i);
			pushDownRole(role, m);
		}
	}

	/**
	 * @see EARFile
	 */
	public void pushDownRole(SecurityRole role, Module aModule) {
		try {
			if (aModule.isWebModule()) {
				WebApp dd = getDeploymentDescriptor((WebModule) aModule);
				if (dd.getSecurityRoleNamed(role.getRoleName()) == null)
					dd.getSecurityRoles().add(EtoolsCopyUtility.createCopy(role));
			} else if (aModule.isEjbModule()) {
				AssemblyDescriptor assembly = getAssemblyDescriptorAddIfNecessary(getDeploymentDescriptor((EjbModule) aModule));
				if (assembly.getSecurityRoleNamed(role.getRoleName()) == null)
					assembly.getSecurityRoles().add(EtoolsCopyUtility.createCopy(role));
			}
		} catch (Exception e) {
			throw new DeploymentDescriptorLoadException(CommonArchiveResourceHandler.getString("dd_in_ear_load_EXC_", (new Object[]{aModule.getUri(), getURI()})), e); //$NON-NLS-1$ = "Exception occurred loading deployment descriptor for module "{0}" in ear file "{1}""
		}
	}

	/**
	 * An alt-dd is about to be loaded; register the appropriate resource factory for the uri so it
	 * will get loaded correctly.
	 */
	protected void registerResourceFactory(Module aModule, String aUri) {
		org.eclipse.emf.ecore.resource.Resource.Factory factory = null;
		if (aModule.isEjbModule())
			factory = EJBJarResourceFactory.getRegisteredFactory();
		else if (aModule.isWebModule())
			factory = WebAppResourceFactory.getRegisteredFactory();
		else if (aModule.isJavaModule())
			factory = ApplicationClientResourceFactory.getRegisteredFactory();
		else if (aModule.isConnectorModule())
			factory = ConnectorResourceFactory.getRegisteredFactory();

		if (factory != null) {
			ResourceSet set = getResourceSet();
			((J2EEResourceFactoryRegistry) set.getResourceFactoryRegistry()).registerLastFileSegment(aUri, factory);
		}
	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public void remove(ModuleRef aModuleRef) {
		if (aModuleRef == null)
			return;
		Module aModule = aModuleRef.getModule();

		if (aModule != null)
			getDeploymentDescriptor().getModules().remove(aModule);

		getModuleRefs().remove(aModuleRef);
		if (getModuleRefs(aModuleRef.getModuleFile()).isEmpty())
			getFiles().remove(aModuleRef.getModuleFile());
	}

	/**
	 * @see EARFile
	 */
	public List getModuleRefs(ModuleFile aModuleFile) {
		List refs = getModuleRefs();
		List result = new ArrayList(1);
		for (int i = 0; i < refs.size(); i++) {
			ModuleRef ref = (ModuleRef) refs.get(i);
			if (ref.getModuleFile() == aModuleFile)
				result.add(ref);
		}
		return result;
	}

	protected void renameRolesInModuleDDs(String existingRoleName, String newRoleName) {
		List modules = getDeploymentDescriptor().getModules();
		for (int i = 0; i < modules.size(); i++) {
			Module m = (Module) modules.get(i);
			try {
				if (m.isEjbModule())
					getDeploymentDescriptor((EjbModule) m).renameSecurityRole(existingRoleName, newRoleName);
				else if (m.isWebModule())
					getDeploymentDescriptor((WebModule) m).renameSecurityRole(existingRoleName, newRoleName);
			} catch (Exception e) {
				throw new DeploymentDescriptorLoadException(CommonArchiveResourceHandler.getString("dd_in_ear_load_EXC_", (new Object[]{m.getUri(), getURI()})), e); //$NON-NLS-1$ = "Exception occurred loading deployment descriptor for module "{0}" in ear file "{1}""
			}
		}
	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public void renameSecurityRole(String existingRoleName, String newRoleName) throws ObjectNotFoundException, DuplicateObjectException {
		Application app = getDeploymentDescriptor();
		SecurityRole aRole = app.getSecurityRoleNamed(existingRoleName);
		if (aRole == null)
			throw new ObjectNotFoundException(CommonArchiveResourceHandler.getString("no_sec_role_EXC_", (new Object[]{getURI(), existingRoleName}))); //$NON-NLS-1$ = ": EAR File deployment descriptor does not contain a security role named "
		if (app.getSecurityRoleNamed(newRoleName) != null)
			throw new DuplicateObjectException(CommonArchiveResourceHandler.getString("dup_sec_role_EXC_", (new Object[]{getURI(), newRoleName})), app.getSecurityRoleNamed(newRoleName)); //$NON-NLS-1$ = ": EAR File deployment descriptor already contains a security role named "

		aRole.setRoleName(newRoleName);

		renameRolesInModuleDDs(existingRoleName, newRoleName);
	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public void rollUpRoles() {
		List modules = getDeploymentDescriptor().getModules();
		for (int i = 0; i < modules.size(); i++) {
			Module aModule = (Module) modules.get(i);
			rollUpRoles(aModule);
		}
	}

	/**
	 * @see com.ibm.etools.commonarchive.EARFile
	 */
	public void rollUpRoles(Module aModule) {
		List securityRoles = null;
		try {
			if (aModule.isWebModule())
				securityRoles = getDeploymentDescriptor((WebModule) aModule).getSecurityRoles();
			else if (aModule.isEjbModule())
				securityRoles = getAssemblyDescriptorAddIfNecessary(getDeploymentDescriptor((EjbModule) aModule)).getSecurityRoles();
		} catch (Exception e) {
			throw new DeploymentDescriptorLoadException(CommonArchiveResourceHandler.getString("dd_in_ear_load_EXC_", (new Object[]{aModule.getUri(), getURI()})), e); //$NON-NLS-1$ = "Exception occurred loading deployment descriptor for module "{0}" in ear file "{1}""
		}

		if (securityRoles == null)
			return;
		for (int i = 0; i < securityRoles.size(); i++) {
			addCopyIfNotExists((SecurityRole) securityRoles.get(i));
		}
	}

	public void setDeploymentDescriptor(Application l) {
		this.setDeploymentDescriptorGen(l);
		replaceRoot(getMofResourceMakeIfNecessary(getDeploymentDescriptorUri()), l);
	}

	/**
	 * @generated This field/method will be replaced during code generation.
	 */
	public boolean eIsSet(EStructuralFeature eFeature) {
		switch (eDerivedStructuralFeatureID(eFeature)) {
			case CommonarchivePackage.EAR_FILE__URI :
				return URI_EDEFAULT == null ? uri != null : !URI_EDEFAULT.equals(uri);
			case CommonarchivePackage.EAR_FILE__LAST_MODIFIED :
				return isSetLastModified();
			case CommonarchivePackage.EAR_FILE__SIZE :
				return isSetSize();
			case CommonarchivePackage.EAR_FILE__DIRECTORY_ENTRY :
				return isSetDirectoryEntry();
			case CommonarchivePackage.EAR_FILE__ORIGINAL_URI :
				return ORIGINAL_URI_EDEFAULT == null ? originalURI != null : !ORIGINAL_URI_EDEFAULT.equals(originalURI);
			case CommonarchivePackage.EAR_FILE__LOADING_CONTAINER :
				return loadingContainer != null;
			case CommonarchivePackage.EAR_FILE__CONTAINER :
				return getContainer() != null;
			case CommonarchivePackage.EAR_FILE__FILES :
				return files != null && !files.isEmpty();
			case CommonarchivePackage.EAR_FILE__TYPES :
				return types != null && !types.isEmpty();
			case CommonarchivePackage.EAR_FILE__MODULE_REFS :
				return moduleRefs != null && !moduleRefs.isEmpty();
			case CommonarchivePackage.EAR_FILE__DEPLOYMENT_DESCRIPTOR :
				return deploymentDescriptor != null;
		}
		return eDynamicIsSet(eFeature);
	}

	/**
	 * @generated This field/method will be replaced during code generation.
	 */
	public void eSet(EStructuralFeature eFeature, Object newValue) {
		switch (eDerivedStructuralFeatureID(eFeature)) {
			case CommonarchivePackage.EAR_FILE__URI :
				setURI((String) newValue);
				return;
			case CommonarchivePackage.EAR_FILE__LAST_MODIFIED :
				setLastModified(((Long) newValue).longValue());
				return;
			case CommonarchivePackage.EAR_FILE__SIZE :
				setSize(((Long) newValue).longValue());
				return;
			case CommonarchivePackage.EAR_FILE__DIRECTORY_ENTRY :
				setDirectoryEntry(((Boolean) newValue).booleanValue());
				return;
			case CommonarchivePackage.EAR_FILE__ORIGINAL_URI :
				setOriginalURI((String) newValue);
				return;
			case CommonarchivePackage.EAR_FILE__LOADING_CONTAINER :
				setLoadingContainer((Container) newValue);
				return;
			case CommonarchivePackage.EAR_FILE__CONTAINER :
				setContainer((Container) newValue);
				return;
			case CommonarchivePackage.EAR_FILE__FILES :
				getFiles().clear();
				getFiles().addAll((Collection) newValue);
				return;
			case CommonarchivePackage.EAR_FILE__TYPES :
				getTypes().clear();
				getTypes().addAll((Collection) newValue);
				return;
			case CommonarchivePackage.EAR_FILE__MODULE_REFS :
				getModuleRefs().clear();
				getModuleRefs().addAll((Collection) newValue);
				return;
			case CommonarchivePackage.EAR_FILE__DEPLOYMENT_DESCRIPTOR :
				setDeploymentDescriptor((Application) newValue);
				return;
		}
		eDynamicSet(eFeature, newValue);
	}

	/**
	 * @generated This field/method will be replaced during code generation.
	 */
	public void eUnset(EStructuralFeature eFeature) {
		switch (eDerivedStructuralFeatureID(eFeature)) {
			case CommonarchivePackage.EAR_FILE__URI :
				setURI(URI_EDEFAULT);
				return;
			case CommonarchivePackage.EAR_FILE__LAST_MODIFIED :
				unsetLastModified();
				return;
			case CommonarchivePackage.EAR_FILE__SIZE :
				unsetSize();
				return;
			case CommonarchivePackage.EAR_FILE__DIRECTORY_ENTRY :
				unsetDirectoryEntry();
				return;
			case CommonarchivePackage.EAR_FILE__ORIGINAL_URI :
				setOriginalURI(ORIGINAL_URI_EDEFAULT);
				return;
			case CommonarchivePackage.EAR_FILE__LOADING_CONTAINER :
				setLoadingContainer((Container) null);
				return;
			case CommonarchivePackage.EAR_FILE__CONTAINER :
				setContainer((Container) null);
				return;
			case CommonarchivePackage.EAR_FILE__FILES :
				getFiles().clear();
				return;
			case CommonarchivePackage.EAR_FILE__TYPES :
				getTypes().clear();
				return;
			case CommonarchivePackage.EAR_FILE__MODULE_REFS :
				getModuleRefs().clear();
				return;
			case CommonarchivePackage.EAR_FILE__DEPLOYMENT_DESCRIPTOR :
				setDeploymentDescriptor((Application) null);
				return;
		}
		eDynamicUnset(eFeature);
	}

	/**
	 * @generated This field/method will be replaced during code generation
	 */
	public Application getDeploymentDescriptorGen() {
		if (deploymentDescriptor != null && deploymentDescriptor.eIsProxy()) {
			Application oldDeploymentDescriptor = deploymentDescriptor;
			deploymentDescriptor = (Application) EcoreUtil.resolve(deploymentDescriptor, this);
			if (deploymentDescriptor != oldDeploymentDescriptor) {
				if (eNotificationRequired())
					eNotify(new ENotificationImpl(this, Notification.RESOLVE, CommonarchivePackage.EAR_FILE__DEPLOYMENT_DESCRIPTOR, oldDeploymentDescriptor, deploymentDescriptor));
			}
		}
		return deploymentDescriptor;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public Application basicGetDeploymentDescriptor() {
		return deploymentDescriptor;
	}

	/**
	 * @generated This field/method will be replaced during code generation.
	 */
	public void setDeploymentDescriptorGen(Application newDeploymentDescriptor) {
		Application oldDeploymentDescriptor = deploymentDescriptor;
		deploymentDescriptor = newDeploymentDescriptor;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, CommonarchivePackage.EAR_FILE__DEPLOYMENT_DESCRIPTOR, oldDeploymentDescriptor, deploymentDescriptor));
	}

	/**
	 * @generated This field/method will be replaced during code generation
	 */
	public EList getModuleRefsGen() {
		if (moduleRefs == null) {
			moduleRefs = new EObjectContainmentWithInverseEList(ModuleRef.class, this, CommonarchivePackage.EAR_FILE__MODULE_REFS, CommonarchivePackage.MODULE_REF__EAR_FILE);
		}
		return moduleRefs;
	}

	public EList getModuleRefs() {
		EList refs = getModuleRefsGen();

		if (refs.isEmpty())
			initRefs(refs);

		return refs;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, Class baseClass, NotificationChain msgs) {
		if (featureID >= 0) {
			switch (eDerivedStructuralFeatureID(featureID, baseClass)) {
				case CommonarchivePackage.EAR_FILE__CONTAINER :
					if (eContainer != null)
						msgs = eBasicRemoveFromContainer(msgs);
					return eBasicSetContainer(otherEnd, CommonarchivePackage.EAR_FILE__CONTAINER, msgs);
				case CommonarchivePackage.EAR_FILE__FILES :
					return ((InternalEList) getFiles()).basicAdd(otherEnd, msgs);
				case CommonarchivePackage.EAR_FILE__MODULE_REFS :
					return ((InternalEList) getModuleRefs()).basicAdd(otherEnd, msgs);
				default :
					return eDynamicInverseAdd(otherEnd, featureID, baseClass, msgs);
			}
		}
		if (eContainer != null)
			msgs = eBasicRemoveFromContainer(msgs);
		return eBasicSetContainer(otherEnd, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, Class baseClass, NotificationChain msgs) {
		if (featureID >= 0) {
			switch (eDerivedStructuralFeatureID(featureID, baseClass)) {
				case CommonarchivePackage.EAR_FILE__CONTAINER :
					return eBasicSetContainer(null, CommonarchivePackage.EAR_FILE__CONTAINER, msgs);
				case CommonarchivePackage.EAR_FILE__FILES :
					return ((InternalEList) getFiles()).basicRemove(otherEnd, msgs);
				case CommonarchivePackage.EAR_FILE__MODULE_REFS :
					return ((InternalEList) getModuleRefs()).basicRemove(otherEnd, msgs);
				default :
					return eDynamicInverseRemove(otherEnd, featureID, baseClass, msgs);
			}
		}
		return eBasicSetContainer(null, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public NotificationChain eBasicRemoveFromContainer(NotificationChain msgs) {
		if (eContainerFeatureID >= 0) {
			switch (eContainerFeatureID) {
				case CommonarchivePackage.EAR_FILE__CONTAINER :
					return eContainer.eInverseRemove(this, CommonarchivePackage.CONTAINER__FILES, Container.class, msgs);
				default :
					return eDynamicBasicRemoveFromContainer(msgs);
			}
		}
		return eContainer.eInverseRemove(this, EOPPOSITE_FEATURE_BASE - eContainerFeatureID, null, msgs);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public Object eGet(EStructuralFeature eFeature, boolean resolve) {
		switch (eDerivedStructuralFeatureID(eFeature)) {
			case CommonarchivePackage.EAR_FILE__URI :
				return getURI();
			case CommonarchivePackage.EAR_FILE__LAST_MODIFIED :
				return new Long(getLastModified());
			case CommonarchivePackage.EAR_FILE__SIZE :
				return new Long(getSize());
			case CommonarchivePackage.EAR_FILE__DIRECTORY_ENTRY :
				return isDirectoryEntry() ? Boolean.TRUE : Boolean.FALSE;
			case CommonarchivePackage.EAR_FILE__ORIGINAL_URI :
				return getOriginalURI();
			case CommonarchivePackage.EAR_FILE__LOADING_CONTAINER :
				if (resolve)
					return getLoadingContainer();
				return basicGetLoadingContainer();
			case CommonarchivePackage.EAR_FILE__CONTAINER :
				return getContainer();
			case CommonarchivePackage.EAR_FILE__FILES :
				return getFiles();
			case CommonarchivePackage.EAR_FILE__TYPES :
				return getTypes();
			case CommonarchivePackage.EAR_FILE__MODULE_REFS :
				return getModuleRefs();
			case CommonarchivePackage.EAR_FILE__DEPLOYMENT_DESCRIPTOR :
				if (resolve)
					return getDeploymentDescriptor();
				return basicGetDeploymentDescriptor();
		}
		return eDynamicGet(eFeature, resolve);
	}

	public void initRefs(EList refs) {
		List modules = getDeploymentDescriptor().getModules();
		for (int i = 0; i < modules.size(); i++) {
			Module module = (Module) modules.get(i);
			refs.add(createModuleRef(module, null));
		}
	}

	protected ModuleRef createModuleRef(Module aModule, ModuleFile aFile) {
		ModuleRef newRef = null;

		if (aModule.isEjbModule())
			newRef = getCommonArchiveFactory().createEJBModuleRef();
		else if (aModule.isWebModule())
			newRef = getCommonArchiveFactory().createWebModuleRef();
		else if (aModule.isConnectorModule())
			newRef = getCommonArchiveFactory().createConnectorModuleRef();
		else if (aModule.isJavaModule())
			newRef = getCommonArchiveFactory().createClientModuleRef();

		newRef.setModule(aModule);
		newRef.setModuleFile(aFile);

		return newRef;
	}

	/*
	 * @see EARFile#getClientModuleRefs()
	 */
	public List getClientModuleRefs() {
		List result = new ArrayList();
		List refs = getModuleRefs();
		for (int i = 0; i < refs.size(); i++) {
			ModuleRef ref = (ModuleRef) refs.get(i);
			if (ref.isClient())
				result.add(ref);
		}
		return result;
	}

	/*
	 * @see EARFile#getConnectorModuleRefs()
	 */
	public List getConnectorModuleRefs() {
		List result = new ArrayList();
		List refs = getModuleRefs();
		for (int i = 0; i < refs.size(); i++) {
			ModuleRef ref = (ModuleRef) refs.get(i);
			if (ref.isConnector())
				result.add(ref);
		}
		return result;
	}

	/*
	 * @see EARFile#getEJBModuleRefs()
	 */
	public List getEJBModuleRefs() {
		List result = new ArrayList();
		List refs = getModuleRefs();
		for (int i = 0; i < refs.size(); i++) {
			ModuleRef ref = (ModuleRef) refs.get(i);
			if (ref.isEJB())
				result.add(ref);
		}
		return result;
	}

	/*
	 * @see EARFile#getWebModuleRefs()
	 */
	public List getWebModuleRefs() {
		List result = new ArrayList();
		List refs = getModuleRefs();
		for (int i = 0; i < refs.size(); i++) {
			ModuleRef ref = (ModuleRef) refs.get(i);
			if (ref.isWeb())
				result.add(ref);
		}
		return result;
	}

	/*
	 * @see EARFile#getFARFiles()
	 */
	public List getFARFiles() {
		List farFiles = new ArrayList();
		List fileList = getFiles();
		for (int i = 0; i < fileList.size(); i++) {
			File aFile = (File) fileList.get(i);
			if (aFile.isFARFile()) {
				farFiles.add(aFile);
			}
		}
		return farFiles;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.etools.commonarchive.EARFile#getArchivesOfType(java.lang.String)
	 */
	public List getArchivesOfType(String type) {
		return Collections.EMPTY_LIST;
	}

	public Map getEJBReferences(boolean filterLinkedReferences, boolean filterNonLinkedReferences) throws ArchiveWrappedException {
		if (!filterLinkedReferences || !filterNonLinkedReferences) {
			Application app = getDeploymentDescriptor();
			if (app != null) {
				List modules = app.getModules();
				Module module;
				Map references = null;
				for (int i = 0; i < modules.size(); i++) {
					module = (Module) modules.get(i);
					try {
						references = collectEJBReferences(module, filterLinkedReferences, filterNonLinkedReferences, references);
					} catch (ResourceLoadException e) {
						throw new ArchiveWrappedException(e);
					} catch (FileNotFoundException e) {
						throw new ArchiveWrappedException(e);
					} catch (EmptyResourceException e) {
						throw new ArchiveWrappedException(e);
					}
				}
				return references;
			}
		}
		return Collections.EMPTY_MAP;
	}

	/**
	 * @param module
	 * @param filterLinkedReferences
	 * @param filterNonLinkedReferences
	 * @param references
	 * @return
	 */
	private Map collectEJBReferences(Module module, boolean filterLinkedReferences, boolean filterNonLinkedReferences, Map references) throws ResourceLoadException, FileNotFoundException, EmptyResourceException {
		Map myReferences = references;
		List moduleReferences = getEJBReferneces(module);
		if (moduleReferences != null && !moduleReferences.isEmpty()) {
			EjbRef ref = null;
			List filteredRefs = null;
			String link = null;
			for (int i = 0; i < moduleReferences.size(); i++) {
				ref = (EjbRef) moduleReferences.get(i);
				link = ref.getLink();
				if ((link != null && link.length() > 0 && !filterLinkedReferences) || (link == null || link.length() == 0 && !filterNonLinkedReferences)) {
					if (filteredRefs == null)
						filteredRefs = new ArrayList(moduleReferences.size());
					filteredRefs.add(ref);
				}
			}
			if (filteredRefs != null) {
				if (myReferences == null)
					myReferences = new HashMap();
				myReferences.put(module, filteredRefs);
			}
		}
		return myReferences;
	}

	/**
	 * @param module
	 * @return
	 */
	private List getEJBReferneces(Module module) throws ResourceLoadException, FileNotFoundException, EmptyResourceException {
		if (module != null) {
			if (module.isEjbModule()) {
				EJBJar ejbJar = getDeploymentDescriptor((EjbModule) module);
				return getEJBReferences(ejbJar);
			} else if (module.isWebModule()) {
				WebApp webApp = getDeploymentDescriptor((WebModule) module);
				if (webApp != null)
					return webApp.getEjbRefs();
			} else if (module.isJavaModule()) {
				ApplicationClient appClient = getDeploymentDescriptor((JavaClientModule) module);
				if (appClient != null)
					return appClient.getEjbReferences();
			}
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * @param ejbJar
	 * @return
	 */
	private List getEJBReferences(EJBJar ejbJar) {
		if (ejbJar != null) {
			List ejbs = ejbJar.getEnterpriseBeans();
			List refs = null;
			EnterpriseBean ejb = null;
			for (int i = 0; i < ejbs.size(); i++) {
				ejb = (EnterpriseBean) ejbs.get(i);
				if (refs == null)
					refs = new ArrayList();
				refs.addAll(ejb.getEjbRefs());
			}
			if (refs != null)
				return refs;
		}
		return Collections.EMPTY_LIST;
	}

}
