| /******************************************************************************* |
| * Copyright (c) 2003, 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jst.j2ee.internal.deployables; |
| |
| import java.io.File; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Properties; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| 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.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.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.Property; |
| import org.eclipse.wst.common.componentcore.internal.StructureEdit; |
| import org.eclipse.wst.common.componentcore.internal.WorkbenchComponent; |
| 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.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 { |
| private static final IPath WEB_CLASSES_PATH = new Path(J2EEConstants.WEB_INF_CLASSES); |
| private static IPath WEBLIB = new Path(J2EEConstants.WEB_INF_LIB).makeAbsolute(); |
| private static String USE_SINGLE_ROOT_PROPERTY = "useSingleRoot"; //$NON-NLS-1$ |
| private IPackageFragmentRoot[] cachedSourceContainers; |
| private IContainer[] cachedOutputContainers; |
| private HashMap cachedOutputMappings; |
| private HashMap cachedSourceOutputPairs; |
| |
| /** |
| * 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 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(); |
| |
| // Handle binary components |
| if (component instanceof J2EEModuleVirtualArchiveComponent) |
| return getBinaryModuleMembers(); |
| |
| // If j2ee project structure is a single root structure, just return optimized members |
| if (isSingleRootStructure()) |
| return getOptimizedMembers(); |
| |
| 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 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; |
| } |
| |
| private 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; |
| } |
| |
| private 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()]); |
| } |
| |
| /* |
| * If the resource to check is a file then this method will return true if the file is linked. If the resource to |
| * check is a folder then this method will return true if it, any of its sub directories, or any file contained |
| * with-in this directory of any of it's sub directories are linked. Otherwise false is returned. |
| */ |
| private boolean hasLinkedContent(final IResource resourceToCheck) throws CoreException { |
| |
| if ((resourceToCheck != null) && resourceToCheck.isAccessible()) { |
| // skip non-accessible files |
| if (resourceToCheck.isLinked()) { |
| return true; |
| } |
| else { |
| switch (resourceToCheck.getType()) { |
| case IResource.FOLDER: |
| // recursively check sub directory contents |
| final IResource[] subDirContents = ((IFolder) resourceToCheck).members(); |
| for (int i = 0; i < subDirContents.length; i++) { |
| if (hasLinkedContent(subDirContents[i])) { |
| return true; |
| } |
| } |
| break; |
| case IResource.FILE: |
| return resourceToCheck.isLinked(); |
| default: |
| // skip as we only care about files and folders |
| break; |
| } |
| } |
| } |
| return false; |
| } |
| |
| /* |
| * This method returns true if the root folders of this component have any linked resources (folder or file); |
| * Otherwise false is returned. |
| */ |
| private boolean rootFoldersHaveLinkedContent() { |
| |
| if (this.component != null) { |
| final IContainer[] rootFolders = this.component.getRootFolder().getUnderlyingFolders(); |
| for (int i = 0; i < rootFolders.length; i++) { |
| try { |
| boolean hasLinkedContent = this.hasLinkedContent(rootFolders[i]); |
| if (hasLinkedContent) { |
| return true; |
| } |
| } |
| catch (CoreException coreEx) { |
| // log any exception that occurs |
| J2EEPlugin.getDefault().log(coreEx.getStatus()); |
| } |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * 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(); |
| |
| // 229650 - check to see if the property 'useSingleRoot' is defined. If it is set and |
| // the value of the property is true then it will override the logic checks below |
| final List componentProperties = wbComp.getProperties(); |
| if (componentProperties != null) { |
| final Iterator componentPropertiesIterator = componentProperties.iterator(); |
| while (componentPropertiesIterator.hasNext()) { |
| Property wbProperty = (Property) componentPropertiesIterator.next(); |
| if (J2EEFlexProjDeployable.USE_SINGLE_ROOT_PROPERTY.equals(wbProperty.getName())) { |
| boolean useSingleRoot = Boolean.valueOf(wbProperty.getValue()).booleanValue(); |
| if (useSingleRoot) { |
| return true; |
| } |
| } |
| } |
| } |
| |
| 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 linked resources then this is not a singleroot module |
| if (this.rootFoldersHaveLinkedContent()) { |
| 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())) { |
| // if there are any linked resources then this is not a singleroot module |
| if (this.rootFoldersHaveLinkedContent()) { |
| return false; |
| } |
| // Ensure there are only source folder component resource mappings to the root content folder |
| if (isRootResourceMapping(resourceMaps,false)) { |
| IContainer[] javaOutputFolders = getJavaOutputFolders(); |
| // Verify only one java outputfolder |
| if (javaOutputFolders.length==1) { |
| // By the time we get here we know: for any folders defined as source in the |
| // .component file that they are also java source folders. |
| if (! isSourceContainer(javaOutputFolders[0].getFullPath())) { |
| // The single output folder is NOT a source folder so this is single-rooted. Since the |
| // output folder (something like classes or bin) is not a source folder, JDT copies all files |
| // (including non Java files) to this folder, so every resource needed at runtime is located |
| // in a single directory. |
| return true; |
| } else { |
| // Don't implement at this time. Currently, we claim single-rooted when ejbModlule is the output folder. However, |
| // we know this is not true because it cannot contain non Java files unless it is the only source folder. But, fixing |
| // at this time would break all current users. |
| // // The single output folder IS a source folder. If there is more than one source folder |
| // // then this cannot be single-rooted because JDT does NOTcopy non Java resources into the |
| // // output folder when it is a source folder. |
| // if (getSourceContainers().length > 1) { |
| // return false; |
| // } else { |
| // // There is only one source folder and since the output folder is a source folder |
| // // this is single-rooted. |
| // return true; |
| // } |
| } |
| // // 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); |
| } |
| } |
| } |