blob: 6f93f6ba2422446ccd6776027af1352de9ee24d8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 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.internal.deployables;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jem.workbench.utility.JemProjectUtilities;
import org.eclipse.jst.j2ee.application.Application;
import org.eclipse.jst.j2ee.classpathdep.ClasspathDependencyUtil;
import org.eclipse.jst.j2ee.classpathdep.IClasspathDependencyConstants;
import org.eclipse.jst.j2ee.componentcore.J2EEModuleVirtualArchiveComponent;
import org.eclipse.jst.j2ee.componentcore.J2EEModuleVirtualComponent;
import org.eclipse.jst.j2ee.componentcore.util.EARArtifactEdit;
import org.eclipse.jst.j2ee.ejb.EJBJar;
import org.eclipse.jst.j2ee.internal.EjbModuleExtensionHelper;
import org.eclipse.jst.j2ee.internal.IEJBModelExtenderManager;
import org.eclipse.jst.j2ee.internal.J2EEConstants;
import org.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyManifestUtil;
import org.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyVirtualComponent;
import org.eclipse.jst.j2ee.internal.plugin.IJ2EEModuleConstants;
import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin;
import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
import org.eclipse.jst.server.core.IApplicationClientModule;
import org.eclipse.jst.server.core.IConnectorModule;
import org.eclipse.jst.server.core.IEJBModule;
import org.eclipse.jst.server.core.IEnterpriseApplication;
import org.eclipse.jst.server.core.IJ2EEModule;
import org.eclipse.jst.server.core.IWebModule;
import org.eclipse.wst.common.componentcore.ArtifactEdit;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.internal.ComponentResource;
import org.eclipse.wst.common.componentcore.internal.StructureEdit;
import org.eclipse.wst.common.componentcore.internal.WorkbenchComponent;
import org.eclipse.wst.common.componentcore.internal.resources.VirtualArchiveComponent;
import org.eclipse.wst.common.componentcore.internal.util.ComponentUtilities;
import org.eclipse.wst.common.componentcore.internal.util.IModuleConstants;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.ServerUtil;
import org.eclipse.wst.server.core.internal.ModuleFile;
import org.eclipse.wst.server.core.internal.ModuleFolder;
import org.eclipse.wst.server.core.model.IModuleFile;
import org.eclipse.wst.server.core.model.IModuleFolder;
import org.eclipse.wst.server.core.model.IModuleResource;
import org.eclipse.wst.web.internal.deployables.ComponentDeployable;
/**
* J2EE module superclass.
*/
public class J2EEFlexProjDeployable extends ComponentDeployable implements IJ2EEModule, IEnterpriseApplication, IApplicationClientModule, IConnectorModule, IEJBModule, IWebModule {
protected static final IPath WEB_CLASSES_PATH = new Path(J2EEConstants.WEB_INF_CLASSES);
protected static final IPath MANIFEST_PATH = new Path(J2EEConstants.MANIFEST_URI);
protected static IPath WEBLIB = new Path(J2EEConstants.WEB_INF_LIB).makeAbsolute();
protected IPackageFragmentRoot[] cachedSourceContainers;
protected IContainer[] cachedOutputContainers;
protected HashMap cachedOutputMappings;
protected HashMap cachedSourceOutputPairs;
protected List classpathComponentDependencyURIs = new ArrayList();
/**
* Constructor for J2EEFlexProjDeployable.
*
* @param project
* @param aComponent
*/
public J2EEFlexProjDeployable(IProject project, IVirtualComponent aComponent) {
super(project, aComponent);
}
/**
* Constructor for J2EEFlexProjDeployable.
*
* @param project
*/
public J2EEFlexProjDeployable(IProject project) {
super(project);
}
/**
* Returns the root folders for the resources in this module.
*
* @return a possibly-empty array of resource folders
*/
public IContainer[] getResourceFolders() {
List result = new ArrayList();
IVirtualComponent vc = ComponentCore.createComponent(getProject());
if (vc != null) {
IVirtualFolder vFolder = vc.getRootFolder();
if (vFolder != null) {
IContainer[] underlyingFolders = vFolder.getUnderlyingFolders();
result.addAll(Arrays.asList(underlyingFolders));
}
}
return (IContainer[]) result.toArray(new IContainer[result.size()]);
}
/**
* Returns the root folders containing Java output in this module.
*
* @return a possibly-empty array of Java output folders
*/
public IContainer[] getJavaOutputFolders() {
if (cachedOutputContainers == null)
cachedOutputContainers = getJavaOutputFolders(getProject());
return cachedOutputContainers;
}
public IContainer[] getJavaOutputFolders(IProject project) {
if (project == null)
return new IContainer[0];
return J2EEProjectUtilities.getOutputContainers(project);
}
protected boolean shouldIncludeUtilityComponent(IVirtualComponent virtualComp,IVirtualReference[] references, ArtifactEdit edit) {
// If the component module is an EAR we know all archives are filtered out of virtual component members
// and we will return only those archives which are not binary J2EE modules in the EAR DD. These J2EE modules will
// be returned by getChildModules()
if (J2EEProjectUtilities.isEARProject(component.getProject())) {
return virtualComp != null && virtualComp.isBinary() && !isNestedJ2EEModule(virtualComp, references, (EARArtifactEdit)edit);
} else {
return super.shouldIncludeUtilityComponent(virtualComp, references, edit);
}
}
protected void addUtilMember(IVirtualComponent parent, IVirtualReference reference, IPath runtimePath) {
// do not add classpath dependencies whose runtime path (../) maps to the parent component or that represent
// class folders
if (!runtimePath.equals(IClasspathDependencyConstants.RUNTIME_MAPPING_INTO_CONTAINER_PATH)
&& !ClasspathDependencyUtil.isClassFolderReference(reference)) {
super.addUtilMember(parent, reference, runtimePath);
}
}
protected IModuleResource[] getBinaryModuleMembers() {
IPath archivePath = ((J2EEModuleVirtualArchiveComponent)component).getWorkspaceRelativePath();
ModuleFile mf = null;
if (archivePath != null) { //In Workspace
IFile utilFile = ResourcesPlugin.getWorkspace().getRoot().getFile(archivePath);
mf = new ModuleFile(utilFile, utilFile.getName(), ((J2EEModuleVirtualArchiveComponent)component).getRuntimePath().makeRelative());
} else {
File extFile = ((J2EEModuleVirtualArchiveComponent)component).getUnderlyingDiskFile();
mf = new ModuleFile(extFile, extFile.getName(), ((J2EEModuleVirtualArchiveComponent)component).getRuntimePath().makeRelative());
}
return new IModuleResource[] {mf};
}
public IModuleResource[] members() throws CoreException {
members.clear();
classpathComponentDependencyURIs.clear();
// Handle binary components
if (component instanceof J2EEModuleVirtualArchiveComponent)
return getBinaryModuleMembers();
if (J2EEProjectUtilities.isEARProject(component.getProject())) {
// If an EAR, add classpath contributions for all referenced modules
addReferencedComponentClasspathDependencies(component, false);
} else {
if (J2EEProjectUtilities.isDynamicWebProject(component.getProject())) {
// If a web, add classpath contributions for all WEB-INF/lib modules
addReferencedComponentClasspathDependencies(component, true);
}
if (canExportClasspathComponentDependencies(component)){
saveClasspathDependencyURIs(component);
}
// Add all Java output folders that have publish/export attributes
addClassFolderDependencies(component);
}
// If j2ee project structure is a single root structure, just return optimized members
if (isSingleRootStructure()) {
final IModuleResource[] resources = getOptimizedMembers();
if (!classpathComponentDependencyURIs.isEmpty()) {
for (int i = 0; i < resources.length; i++) {
if (resources[i] instanceof IModuleFolder) {
IModuleFolder folder = (IModuleFolder) resources[i];
if (folder.getName().equals(J2EEConstants.META_INF)) {
IModuleResource[] files = folder.members();
for (int j = 0; j < files.length; j++) {
files[j] = replaceManifestFile((IModuleFile) files[j]);
}
}
}
}
}
// add to any potentially mapped Java class folders
for (int i = 0; i < resources.length; i++) {
members.add(resources[i]);
}
return (IModuleResource[]) members.toArray(new IModuleResource[members.size()]);
}
cachedSourceContainers = J2EEProjectUtilities.getSourceContainers(getProject());
try {
IPath javaPath = Path.EMPTY;
if (J2EEProjectUtilities.isDynamicWebProject(component.getProject()))
javaPath = WEB_CLASSES_PATH;
if (component != null) {
IVirtualFolder vFolder = component.getRootFolder();
IModuleResource[] mr = getMembers(vFolder, Path.EMPTY);
int size = mr.length;
for (int j = 0; j < size; j++) {
members.add(mr[j]);
}
}
IContainer[] javaCont = getJavaOutputFolders();
int size = javaCont.length;
for (int i = 0; i < size; i++) {
//If the java output is in the scope of the virtual component, ignore to avoid duplicates
if (ComponentCore.createResources(javaCont[i]).length > 0)
continue;
IModuleResource[] mr = getMembers(javaCont[i], javaPath, javaPath, javaCont);
int size2 = mr.length;
for (int j = 0; j < size2; j++) {
members.add(mr[j]);
}
}
if (component != null) {
addUtilMembers(component);
List consumableMembers = getConsumableReferencedMembers(component);
if (!consumableMembers.isEmpty())
members.addAll(consumableMembers);
}
IModuleResource[] mr = new IModuleResource[members.size()];
members.toArray(mr);
return mr;
} finally {
cachedSourceContainers = null;
cachedOutputContainers = null;
cachedOutputMappings = null;
cachedSourceOutputPairs = null;
}
}
protected IModuleFile createModuleFile(IFile file, IPath path) {
// if this is the MANIFEST.MF file and we have classpath component dependencies,
// update it
return replaceManifestFile(super.createModuleFile(file, path));
}
protected IModuleFile replaceManifestFile(IModuleFile moduleFile) {
final IFile file = (IFile) moduleFile.getAdapter(IFile.class);
final IPath path = moduleFile.getModuleRelativePath();
// if the MANIFEST.MF is being requested and we have classpath component dependencies,
// dynamically generate a customized MANIFEST.MF and return that
if (path.append(file.getName()).equals(MANIFEST_PATH) && !classpathComponentDependencyURIs.isEmpty()) {
final IProject project = file.getProject();
final IPath workingLocation = project.getWorkingLocation(J2EEPlugin.PLUGIN_ID);
// create path to temp MANIFEST.MF
final IPath tempManifestPath = workingLocation.append(MANIFEST_PATH);
final File fsFile = tempManifestPath.toFile();
if (!fsFile.exists()) {
// create parent dirs for temp MANIFEST.MF
final File parent = fsFile.getParentFile();
if (!parent.exists()) {
if (!parent.mkdirs()) {
return moduleFile;
}
}
}
// create temp MANIFEST.MF using util method
try {
ClasspathDependencyManifestUtil.updateManifestClasspath(file, classpathComponentDependencyURIs, new FileOutputStream(fsFile));
// create new ModuleFile that points to temp MANIFEST.MF
return new ModuleFile(fsFile, file.getName(), path);
} catch (IOException ioe) {
return moduleFile;
}
}
return moduleFile;
}
protected IModuleResource[] handleJavaPath(IPath path, IPath javaPath, IPath curPath, IContainer[] javaCont, IModuleResource[] mr, IContainer cc) throws CoreException {
if (curPath.equals(javaPath)) {
int size = javaCont.length;
for (int i = 0; i < size; i++) {
IModuleResource[] mr2 = getMembers(javaCont[i], path.append(cc.getName()), null, null);
IModuleResource[] mr3 = new IModuleResource[mr.length + mr2.length];
System.arraycopy(mr, 0, mr3, 0, mr.length);
System.arraycopy(mr2, 0, mr3, mr.length, mr2.length);
mr = mr3;
}
} else {
boolean containsFolder = false;
String name = javaPath.segment(curPath.segmentCount());
int size = mr.length;
for (int i = 0; i < size && !containsFolder; i++) {
if (mr[i] instanceof IModuleFolder) {
IModuleFolder mf2 = (IModuleFolder) mr[i];
if (name.equals(mf2.getName())) {
containsFolder = true;
}
}
}
if (!containsFolder && javaCont.length > 0) {
ModuleFolder mf2 = new ModuleFolder(javaCont[0], name, curPath);
IModuleResource[] mrf = new IModuleResource[0];
size = javaCont.length;
for (int i = 0; i < size; i++) {
IModuleResource[] mrf2 = getMembers(javaCont[i], javaPath, null, null);
IModuleResource[] mrf3 = new IModuleResource[mrf.length + mrf2.length];
System.arraycopy(mrf, 0, mrf3, 0, mrf.length);
System.arraycopy(mrf2, 0, mrf3, mrf.length, mrf2.length);
mrf = mrf3;
}
mf2.setMembers(mrf);
IModuleResource[] mr3 = new IModuleResource[mr.length + 1];
System.arraycopy(mr, 0, mr3, 0, mr.length);
mr3[mr.length] = mf2;
mr = mr3;
}
}
return mr;
}
/**
* Returns the classpath as a list of absolute IPaths.
*
* @return an array of paths
*/
public IPath[] getClasspath() {
List paths = new ArrayList();
IJavaProject proj = JemProjectUtilities.getJavaProject(getProject());
URL[] urls = JemProjectUtilities.getClasspathAsURLArray(proj);
for (int i = 0; i < urls.length; i++) {
URL url = urls[i];
paths.add(Path.fromOSString(url.getPath()));
}
return (IPath[]) paths.toArray(new IPath[paths.size()]);
}
public String getJNDIName(String ejbName) {
if (!J2EEProjectUtilities.isEJBProject(component.getProject()))
return null;
EjbModuleExtensionHelper modHelper = null;
EJBJar jar = null;
ArtifactEdit ejbEdit = null;
try {
ejbEdit = ComponentUtilities.getArtifactEditForRead(component);
if (ejbEdit != null) {
jar = (EJBJar) ejbEdit.getContentModelRoot();
modHelper = IEJBModelExtenderManager.INSTANCE.getEJBModuleExtension(null);
return modHelper == null ? null : modHelper.getJNDIName(jar, jar.getEnterpriseBeanNamed(ejbName));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ejbEdit != null)
ejbEdit.dispose();
}
return null;
}
/**
* This method will handle a number of J2EE related scenarios. If this is an ear and a child module is passed in,
* the URI for that child module will be returned. If no child module was passed, the URI of the EAR is returned.
* If this is a child component and the module passed in is the EAR, we grab the module uri for this compared to that
* EAR. If no ear module is passed in we look for one and use it and return URI relative to found EAR. If no EAR's
* are found the URI is returned in a default manner.
*
* @return URI string
*/
public String getURI(IModule module) {
// If the component is an ear and the module passed in is a child module
if (component!=null && module!=null && J2EEProjectUtilities.isEARProject(component.getProject()))
return getContainedURI(module);
IVirtualComponent ear = null;
String aURI = null;
// If the component is a child module and the module passed in is the ear
if (module != null && J2EEProjectUtilities.isEARProject(module.getProject()))
ear = ComponentCore.createComponent(module.getProject());
// else if the component is a child module and the module passed in is null, search for first ear
else if (module==null && component != null) {
IProject[] earProjects = J2EEProjectUtilities.getReferencingEARProjects(component.getProject());
if (earProjects.length>0)
ear = ComponentCore.createComponent(earProjects[0]);
}
// We have a valid ear and the component is a valid child
if (ear != null && component != null) {
EARArtifactEdit earEdit = null;
try {
earEdit = EARArtifactEdit.getEARArtifactEditForRead(ear);
if (earEdit != null)
aURI = earEdit.getModuleURI(component);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (earEdit != null)
earEdit.dispose();
}
}
// We have an ear component and no child module
else if (component!=null && J2EEProjectUtilities.isEARProject(component.getProject())) {
aURI = component.getDeployedName()+IJ2EEModuleConstants.EAR_EXT;
}
// We have child components but could not find valid ears
else if (component != null && J2EEProjectUtilities.isDynamicWebProject(component.getProject())) {
if (module != null) {
IVirtualComponent webComp = ComponentCore.createComponent(component.getProject());
IVirtualReference reference = webComp.getReference(module.getProject().getName());
if (J2EEProjectUtilities.isDynamicWebProject(module.getProject())) {
aURI = ComponentUtilities.getDeployUriOfComponent(reference, IJ2EEModuleConstants.WAR_EXT);
}
else if (J2EEProjectUtilities.isJCAProject(module.getProject())) {
aURI = ComponentUtilities.getDeployUriOfComponent(reference, IJ2EEModuleConstants.RAR_EXT);
}
else {
aURI = ComponentUtilities.getDeployUriOfComponent(reference, IJ2EEModuleConstants.JAR_EXT);
}
}
else {
aURI = component.getDeployedName() + IJ2EEModuleConstants.WAR_EXT;
}
}
else if (component!=null && (J2EEProjectUtilities.isEJBProject(component.getProject()) || J2EEProjectUtilities.isApplicationClientProject(component.getProject()))) {
aURI = component.getDeployedName()+IJ2EEModuleConstants.JAR_EXT;
}
else if (component!=null && J2EEProjectUtilities.isJCAProject(component.getProject())) {
aURI = component.getDeployedName()+IJ2EEModuleConstants.RAR_EXT;
}
if (aURI !=null && aURI.length()>1 && aURI.startsWith("/")) //$NON-NLS-1$
aURI = aURI.substring(1);
return aURI;
}
protected boolean isBinaryModuleArchive(IModule module) {
if (module!=null && module.getName().endsWith(IJ2EEModuleConstants.JAR_EXT) || module.getName().endsWith(IJ2EEModuleConstants.WAR_EXT) ||
module.getName().endsWith(IJ2EEModuleConstants.RAR_EXT)) {
if (component!=null && J2EEProjectUtilities.isEARProject(component.getProject()))
return true;
}
return false;
}
private String getContainedURI(IModule module) {
if (component instanceof J2EEModuleVirtualArchiveComponent || isBinaryModuleArchive(module))
return new Path(module.getName()).lastSegment();
IVirtualComponent comp = ComponentCore.createComponent(module.getProject());
String aURI = null;
if (comp!=null && component!=null && J2EEProjectUtilities.isEARProject(component.getProject())) {
EARArtifactEdit earEdit = null;
try {
earEdit = EARArtifactEdit.getEARArtifactEditForRead(component);
if (earEdit != null)
aURI = earEdit.getModuleURI(comp);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (earEdit != null)
earEdit.dispose();
}
}
if (aURI !=null && aURI.length()>1 && aURI.startsWith("/")) //$NON-NLS-1$
aURI = aURI.substring(1);
return aURI;
}
/**
* This method returns the context root property from the deployable project's .component file
*/
public String getContextRoot() {
Properties props = component.getMetaProperties();
if(props.containsKey(J2EEConstants.CONTEXTROOT))
return props.getProperty(J2EEConstants.CONTEXTROOT);
return component.getName();
}
/**
* This method is applicable for a web deployable. The module passed in should either be null or
* the EAR module the web deployable is contained in. It will return the context root from the EAR
* if it has one or return the .component value in the web project if it is standalone.
*
* @param module
* @return contextRoot String
*/
public String getContextRoot(IModule earModule) {
IProject deployProject = component.getProject();
String contextRoot = null;
if (earModule == null)
return getContextRoot();
else if (J2EEProjectUtilities.isEARProject(earModule.getProject()) && J2EEProjectUtilities.isDynamicWebProject(deployProject)) {
EARArtifactEdit edit = null;
try {
edit = EARArtifactEdit.getEARArtifactEditForRead(earModule.getProject());
contextRoot = edit.getWebContextRoot(deployProject);
} finally {
if (edit!=null)
edit.dispose();
}
}
return contextRoot;
}
/**
* Find the source container, if any, for the given file.
*
* @param file
* @return IPackageFragmentRoot sourceContainer for IFile
*/
protected IPackageFragmentRoot getSourceContainer(IFile file) {
if (file == null)
return null;
IPackageFragmentRoot[] srcContainers = getSourceContainers();
for (int i=0; i<srcContainers.length; i++) {
IPath srcPath = srcContainers[i].getPath();
if (srcPath.isPrefixOf(file.getFullPath()))
return srcContainers[i];
}
return null;
}
/**
* Either returns value from cache or stores result as value in cache for the corresponding
* output container for the given source container.
*
* @param sourceContainer
* @return IContainer output container for given source container
*/
protected IContainer getOutputContainer(IPackageFragmentRoot sourceContainer) {
if (sourceContainer == null)
return null;
HashMap pairs = getCachedSourceOutputPairs();
IContainer output = (IContainer) pairs.get(sourceContainer);
if (output == null) {
output = J2EEProjectUtilities.getOutputContainer(getProject(), sourceContainer);
pairs.put(sourceContainer,output);
}
return output;
}
private IPackageFragmentRoot[] getSourceContainers() {
if (cachedSourceContainers != null)
return cachedSourceContainers;
return J2EEProjectUtilities.getSourceContainers(getProject());
}
protected List getConsumableReferencedMembers(IVirtualComponent vc) throws CoreException {
List consumableMembers = new ArrayList();
IVirtualReference[] refComponents = vc.getReferences();
for (int i = 0; i < refComponents.length; i++) {
IVirtualReference reference = refComponents[i];
if (reference != null && reference.getDependencyType()==IVirtualReference.DEPENDENCY_TYPE_CONSUMES) {
IVirtualComponent consumedComponent = reference.getReferencedComponent();
if (consumedComponent!=null && isProjectOfType(consumedComponent.getProject(),IModuleConstants.JST_UTILITY_MODULE)) {
if (consumedComponent != null && consumedComponent.getRootFolder()!=null) {
IVirtualFolder vFolder = consumedComponent.getRootFolder();
IModuleResource[] mr = getMembers(vFolder, reference.getRuntimePath().makeRelative());
int size = mr.length;
for (int j = 0; j < size; j++) {
if (!members.contains(mr[j]))
members.add(mr[j]);
}
addUtilMembers(consumedComponent);
List childConsumableMembers = getConsumableReferencedMembers(consumedComponent);
if (!childConsumableMembers.isEmpty())
members.addAll(childConsumableMembers);
}
IContainer[] javaCont = getJavaOutputFolders(consumedComponent.getProject());
int size = javaCont.length;
for (int j = 0; j < size; j++) {
IModuleResource[] mr = getMembers(javaCont[j], reference.getRuntimePath(), reference.getRuntimePath(), javaCont);
int size2 = mr.length;
for (int k = 0; k < size2; k++) {
if (!members.contains(mr[k]))
members.add(mr[k]);
}
}
}
}
}
return consumableMembers;
}
protected IModule gatherModuleReference(IVirtualComponent component, IVirtualComponent targetComponent ) {
IModule module = super.gatherModuleReference(component, targetComponent);
// Handle binary module components
if (targetComponent instanceof J2EEModuleVirtualArchiveComponent) {
if (J2EEProjectUtilities.isEARProject(component.getProject()) || targetComponent.getProject()!=component.getProject())
module = ServerUtil.getModule(J2EEDeployableFactory.ID+":"+targetComponent.getName()); //$NON-NLS-1$
}
return module;
}
/**
* Determine if the component is nested J2EE module on the application.xml of this EAR
* @param aComponent
* @return boolean is passed in component a nested J2EE module on this EAR
*/
private boolean isNestedJ2EEModule(IVirtualComponent aComponent, IVirtualReference[] references, EARArtifactEdit edit) {
if (edit==null)
return false;
Application app = edit.getApplication();
IVirtualReference reference = getReferenceNamed(references,aComponent.getName());
// Ensure module URI exists on EAR DD for binary archive
return app.getFirstModule(reference.getArchiveName()) != null;
}
protected IVirtualReference getReferenceNamed(IVirtualReference[] references, String name) {
for (int i=0; i<references.length; i++) {
if (references[i].getReferencedComponent().getName().equals(name))
return references[i];
}
return null;
}
protected ArtifactEdit getComponentArtifactEditForRead() {
return EARArtifactEdit.getEARArtifactEditForRead(component.getProject());
}
/**
* The references for J2EE module deployment are only those child modules of EARs or web modules
*/
protected IVirtualReference[] getReferences(IVirtualComponent aComponent) {
if (aComponent == null || aComponent.isBinary()) {
return new IVirtualReference[] {};
} else if (J2EEProjectUtilities.isDynamicWebProject(aComponent.getProject())) {
return getWebLibModules((J2EEModuleVirtualComponent)aComponent);
} else if (J2EEProjectUtilities.isEARProject(aComponent.getProject())) {
return super.getReferences(aComponent);
} else {
return new IVirtualReference[] {};
}
}
/**
* This method will return the list of dependent modules which are utility jars in the web lib
* folder of the deployed path of the module. It will not return null.
*
* @return array of the web library dependent modules
*/
private IVirtualReference[] getWebLibModules(J2EEModuleVirtualComponent comp) {
List result = new ArrayList();
IVirtualReference[] refComponents = comp.getNonManifestReferences();
// Check the deployed path to make sure it has a lib parent folder and matchs the web.xml
// base path
for (int i = 0; i < refComponents.length; i++) {
if (refComponents[i].getRuntimePath().equals(WEBLIB))
result.add(refComponents[i]);
}
return (IVirtualReference[]) result.toArray(new IVirtualReference[result.size()]);
}
/*
* Add any classpath component dependencies from this component
*/
private void addReferencedComponentClasspathDependencies(final IVirtualComponent component, final boolean web) {
final IVirtualReference[] refs = component.getReferences();
final Set absolutePaths = new HashSet();
for (int i = 0; i < refs.length; i++) {
final IVirtualReference reference = refs[i];
final IPath runtimePath = reference.getRuntimePath();
final IVirtualComponent referencedComponent = reference.getReferencedComponent();
// if we are adding to a web project, only process references with the /WEB-INF/lib runtime path
if (web && !runtimePath.equals(WEBLIB)) {
continue;
}
// if the reference cannot export dependencies, skip
if (!canExportClasspathComponentDependencies(referencedComponent)) {
continue;
}
if (!referencedComponent.isBinary() && referencedComponent instanceof J2EEModuleVirtualComponent) {
final IVirtualReference[] cpRefs = ((J2EEModuleVirtualComponent) referencedComponent).getJavaClasspathReferences();
for (int j = 0; j < cpRefs.length; j++) {
final IVirtualReference cpRef = cpRefs[j];
IPath cpRefRuntimePath = cpRef.getRuntimePath();
if (cpRef.getReferencedComponent() instanceof ClasspathDependencyVirtualComponent) {
// want to avoid adding dups
ClasspathDependencyVirtualComponent cpComp = (ClasspathDependencyVirtualComponent) cpRef.getReferencedComponent();
// don't want to process class folder refs here
if (cpComp.isClassFolder()) {
continue;
}
if (cpRefRuntimePath.equals(IClasspathDependencyConstants.RUNTIME_MAPPING_INTO_CONTAINER_PATH)) {
// runtime path within deployed app will be runtime path of parent component
cpRefRuntimePath = runtimePath;
}
final IPath absolutePath = ClasspathDependencyUtil.getClasspathVirtualReferenceLocation(cpRef);
if (absolutePaths.contains(absolutePath)) {
// have already added a member for this archive
continue;
} else {
addUtilMember(component, cpRef, cpRefRuntimePath);
absolutePaths.add(absolutePath);
}
}
}
}
}
}
private boolean canExportClasspathComponentDependencies(IVirtualComponent component) {
final IProject project = component.getProject();
// check for valid project type
if (J2EEProjectUtilities.isEJBProject(project)
|| J2EEProjectUtilities.isDynamicWebProject(project)
|| J2EEProjectUtilities.isJCAProject(project)
|| J2EEProjectUtilities.isUtilityProject(project)) {
return true;
}
return false;
}
private void saveClasspathDependencyURIs(IVirtualComponent component) {
if (!component.isBinary() && component instanceof J2EEModuleVirtualComponent) {
final IVirtualReference[] cpRefs = ((J2EEModuleVirtualComponent) component).getJavaClasspathReferences();
for (int j = 0; j < cpRefs.length; j++) {
final IVirtualReference cpRef = cpRefs[j];
// if we are adding to an EAR project, only process references with the root mapping
if (!cpRef.getRuntimePath().equals(IClasspathDependencyConstants.RUNTIME_MAPPING_INTO_CONTAINER_PATH)) {
// fails the runtime path test
continue;
}
if (cpRef.getReferencedComponent() instanceof VirtualArchiveComponent) {
classpathComponentDependencyURIs.add(cpRef.getArchiveName());
}
}
}
}
private void addClassFolderDependencies(final IVirtualComponent component) throws CoreException {
if (!component.isBinary() && component instanceof J2EEModuleVirtualComponent) {
final IVirtualReference[] cpRefs = ((J2EEModuleVirtualComponent) component).getJavaClasspathReferences();
for (int i = 0; i < cpRefs.length; i++) {
final IVirtualReference cpRef = cpRefs[i];
final IPath runtimePath = cpRef.getRuntimePath();
final IVirtualComponent comp = cpRef.getReferencedComponent();
if (comp instanceof ClasspathDependencyVirtualComponent) {
final ClasspathDependencyVirtualComponent cpComp = (ClasspathDependencyVirtualComponent) comp;
if (cpComp.isClassFolder()) {
IPath targetPath = null;
if (runtimePath.equals(IClasspathDependencyConstants.RUNTIME_MAPPING_INTO_COMPONENT_PATH)) {
targetPath = Path.EMPTY;
} else if (runtimePath.equals(IClasspathDependencyConstants.WEB_INF_CLASSES_PATH)) {
targetPath = WEB_CLASSES_PATH;
} else {
continue;
}
final IContainer container = cpComp.getClassFolder();
final IModuleResource[] mr = getMembers(container, targetPath, targetPath, new IContainer[]{container});
for (int j = 0; j < mr.length; j++) {
members.add(mr[j]);
}
}
}
}
}
}
/**
* Returns <code>true</code> if this module has a simple structure based on a
* single root folder, and <code>false</code> otherwise.
* <p>
* In a single root structure, all files that are contained within the root folder
* are part of the module, and are already in the correct module structure. No
* module resources exist outside of this single folder.
*
* For J2EE, this method will check if the project is already in J2EE spec standard output form.
* The project must follow certain rules, but in general, the project's content roots must be source folders
* and the output folder must also be the the content root folder.
* </p>
*
* @return <code>true</code> if this module has a single root structure, and
* <code>false</code> otherwise
*/
public boolean isSingleRootStructure() {
StructureEdit edit = null;
try {
edit = StructureEdit.getStructureEditForRead(getProject());
if (edit == null || edit.getComponent() == null)
return false;
WorkbenchComponent wbComp = edit.getComponent();
List resourceMaps = wbComp.getResources();
if (J2EEProjectUtilities.isEARProject(getProject())) {
// Always return false for EARs so that members for EAR are always calculated and j2ee modules
// are filtered out
return false;
} else if (J2EEProjectUtilities.isDynamicWebProject(getProject())) {
// If there are any web lib jar references, this is not a standard project
IVirtualReference[] references = ((J2EEModuleVirtualComponent)component).getNonManifestReferences();
for (int i=0; i<references.length; i++) {
if (references[i].getReferencedComponent().isBinary())
return false;
}
// Ensure there are only basic component resource mappings -- one for the content folder
// and any for src folders mapped to WEB-INF/classes
if (hasDefaultWebResourceMappings(resourceMaps)) {
// Verify only one java output folder
if (getJavaOutputFolders().length==1) {
// Verify the java output folder is to <content root>/WEB-INF/classes
IPath javaOutputPath = getJavaOutputFolders()[0].getProjectRelativePath();
IPath compRootPath = component.getRootFolder().getUnderlyingFolder().getProjectRelativePath();
if (compRootPath.append(J2EEConstants.WEB_INF_CLASSES).equals(javaOutputPath))
return true;
}
}
return false;
} else if (J2EEProjectUtilities.isEJBProject(getProject()) || J2EEProjectUtilities.isJCAProject(getProject())
|| J2EEProjectUtilities.isApplicationClientProject(getProject()) || J2EEProjectUtilities.isUtilityProject(getProject())) {
// Ensure there are only source folder component resource mappings to the root content folder
if (isRootResourceMapping(resourceMaps,false)) {
// Verify only one java outputfolder
if (getJavaOutputFolders().length==1) {
// At this point for utility projects, this project is optimized, we can just use the output folder
if (J2EEProjectUtilities.isUtilityProject(getProject()))
return true;
// Verify the java output folder is the same as one of the content roots
IPath javaOutputPath = getJavaOutputFolders()[0].getProjectRelativePath();
IContainer[] rootFolders = component.getRootFolder().getUnderlyingFolders();
for (int i=0; i<rootFolders.length; i++) {
IPath compRootPath = rootFolders[i].getProjectRelativePath();
if (javaOutputPath.equals(compRootPath))
return true;
}
}
}
return false;
}
return true;
} finally {
if (edit !=null)
edit.dispose();
}
}
/**
* Ensure that any component resource mappings are for source folders and
* that they map to the root content folder
*
* @param resourceMaps
* @return boolean
*/
private boolean isRootResourceMapping(List resourceMaps, boolean isForEAR) {
// If the list is empty, return false
if (resourceMaps.size()<1)
return false;
for (int i=0; i<resourceMaps.size(); i++) {
ComponentResource resourceMap = (ComponentResource) resourceMaps.get(i);
// Verify it maps to "/" for the content root
if (!resourceMap.getRuntimePath().equals(Path.ROOT))
return false;
// If this is not for an EAR, verify it is also a src container
if (!isForEAR) {
IPath sourcePath = getProject().getFullPath().append(resourceMap.getSourcePath());
if (!isSourceContainer(sourcePath))
return false;
}
}
return true;
}
/**
* Checks if the path argument is to a source container for the project.
*
* @param a workspace relative full path
* @return is path a source container?
*/
private boolean isSourceContainer(IPath path) {
IPackageFragmentRoot[] srcContainers = getSourceContainers();
for (int i=0; i<srcContainers.length; i++) {
if (srcContainers[i].getPath().equals(path))
return true;
}
return false;
}
/**
* Ensure the default web setup is correct with one resource map and any number of java
* resource maps to WEB-INF/classes
*
* @param resourceMaps
* @return boolean
*/
private boolean hasDefaultWebResourceMappings(List resourceMaps) {
int rootValidMaps = 0;
int javaValidRoots = 0;
// If there aren't at least 2 maps, return false
if (resourceMaps.size()<2)
return false;
IPath webInfClasses = new Path(J2EEConstants.WEB_INF_CLASSES).makeAbsolute();
for (int i=0; i<resourceMaps.size(); i++) {
ComponentResource resourceMap = (ComponentResource) resourceMaps.get(i);
IPath sourcePath = getProject().getFullPath().append(resourceMap.getSourcePath());
// Verify if the map is for the content root
if (resourceMap.getRuntimePath().equals(Path.ROOT)) {
rootValidMaps++;
// Verify if the map is for a java src folder and is mapped to "WEB-INF/classes"
} else if (resourceMap.getRuntimePath().equals(webInfClasses) && isSourceContainer(sourcePath)) {
javaValidRoots++;
// Otherwise we bail because we have a non optimized map
} else {
return false;
}
}
// Make sure only one of the maps is the content root, and that at least one is for the java folder
return rootValidMaps==1 && javaValidRoots>0;
}
/**
* This method is added for performance reasons.
* It assumes the virtual component is not using any flexible features and is in a standard J2EE format
* with one component root folder and an output folder the same as its content folder. This will bypass
* the virtual component API and just return the module resources as they are on disk.
*
* @return array of ModuleResources
* @throws CoreException
*/
private IModuleResource[] getOptimizedMembers() throws CoreException {
if (component != null) {
// For java utility modules, we can just use the output container, at this point we know there is only one
if (J2EEProjectUtilities.isUtilityProject(getProject())) {
return getModuleResources(Path.EMPTY, getJavaOutputFolders()[0]);
}
// For J2EE modules, we use the contents of the content root
else {
IVirtualFolder vFolder = component.getRootFolder();
return getModuleResources(Path.EMPTY, vFolder.getUnderlyingFolder());
}
}
return new IModuleResource[] {};
}
/**
* This method will return from cache or add to cache whether or not an output container
* is mapped in the virtual component.
*
* @param outputContainer
* @return if output container is mapped
*/
private boolean isOutputContainerMapped(IContainer outputContainer) {
if (outputContainer == null)
return false;
HashMap outputMaps = getCachedOutputMappings();
Boolean result = (Boolean) outputMaps.get(outputContainer);
if (result == null) {
// If there are any component resources for the container, we know it is mapped
if (ComponentCore.createResources(outputContainer).length > 0)
result = Boolean.TRUE;
// Otherwise it is not mapped
else
result = Boolean.FALSE;
// Cache the result in the map for this output container
outputMaps.put(outputContainer, result);
}
return result.booleanValue();
}
/**
* Lazy initialize the cached output mappings
* @return HashMap
*/
private HashMap getCachedOutputMappings() {
if (cachedOutputMappings==null)
cachedOutputMappings = new HashMap();
return cachedOutputMappings;
}
/**
* Lazy initialize the cached source - output pairings
* @return HashMap
*/
private HashMap getCachedSourceOutputPairs() {
if (cachedSourceOutputPairs==null)
cachedSourceOutputPairs = new HashMap();
return cachedSourceOutputPairs;
}
/**
* This file should be added to the members list from the virtual component maps only if:
* a) it is not in a source folder
* b) it is in a source folder, and the corresponding output folder is a mapped component resource
*
* @return boolean should file be added to members
*/
protected boolean shouldAddComponentFile(IFile file) {
IPackageFragmentRoot sourceContainer = getSourceContainer(file);
// If the file is not in a source container, return true
if (sourceContainer==null) {
return true;
// Else if it is a source container and the output container is mapped in the component, return true
// Otherwise, return false.
} else {
IContainer outputContainer = getOutputContainer(sourceContainer);
return outputContainer!=null && isOutputContainerMapped(outputContainer);
}
}
}