Index: D:/EWA_02/m2e/src/org/maven/ide/eclipse/embedder/BuildPathManager.java =================================================================== --- D:/EWA_02/m2e/src/org/maven/ide/eclipse/embedder/BuildPathManager.java (revision 305) +++ D:/EWA_02/m2e/src/org/maven/ide/eclipse/embedder/BuildPathManager.java (working copy) @@ -59,15 +59,19 @@ import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IProjectNature; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IBundleGroup; +import org.eclipse.core.runtime.IBundleGroupProvider; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jdt.core.IAccessRule; import org.eclipse.jdt.core.IClasspathAttribute; @@ -91,6 +95,13 @@ public class BuildPathManager { + + public static final String CLASSPATH_COMPONENT_NON_DEPENDENCY = "org.eclipse.jst.component.nondependency"; + public static final String CLASSPATH_COMPONENT_DEPENDENCY = "org.eclipse.jst.component.dependency"; + public static final String JST_IDENTIFER = "org.eclipse.jst"; + public static final String PACKAGING_EAR = "ear"; + public static final String PACKAGING_WAR = "war"; + private final MavenEmbedderManager embedderManager; private final Maven2Console console; @@ -198,6 +209,11 @@ JavaCore.setClasspathContainer(container.getPath(), new IJavaProject[] {javaProject}, new IClasspathContainer[] {container}, monitor); + + String runtimePath = getRuntimePath(pomFile); + if (runtimePath != null) { + setWTPDependencyAttribute(javaProject, container, runtimePath); + } } Set dependentProjects = mavenModelManager.getDependentProjects(pomFile); @@ -228,6 +244,8 @@ boolean downloadSources = !offline & preferenceStore.getBoolean(Maven2PreferenceConstants.P_DOWNLOAD_SOURCES); boolean downloadJavadoc = !offline & preferenceStore.getBoolean(Maven2PreferenceConstants.P_DOWNLOAD_JAVADOC); boolean debug = preferenceStore.getBoolean(Maven2PreferenceConstants.P_DEBUG_OUTPUT); + // TODO: Should be done only once and when bundles are reinstalled + boolean wtpAvailable = isWTPAvailable(); MavenExecutionResult result = mavenModelManager.readMavenProject(pomFile, monitor, offline, debug, resolverConfiguration); @@ -265,10 +283,19 @@ } moduleArtifacts.put(artifactKey, a); + + List attributes = new ArrayList(); mavenModelManager.addProjectArtifact(pomFile, a); // this is needed to projects with have modules (either inner or external) mavenModelManager.addProjectArtifact(rootPomFile, a); + // Check the scope & set WTP non-dependency as appropriate + String scope = a.getScope(); + if (Artifact.SCOPE_PROVIDED.equals(scope) + || Artifact.SCOPE_TEST.equals(scope) + || Artifact.SCOPE_SYSTEM.equals(scope)) { + attributes.add(JavaCore.newClasspathAttribute(CLASSPATH_COMPONENT_NON_DEPENDENCY, "")); + } IFile artifactPomFile = mavenModelManager.getArtifactFile(a); if(artifactPomFile != null) { @@ -278,6 +305,13 @@ // add our own project to ourself continue; } + + if (wtpAvailable + && PACKAGING_WAR.equals(mavenProject.getPackaging()) + && hasDynamicWebProjectNature(currentProject)) { + // Leave it out so that the user can handle it the WTP way + continue; + } } if(resolverConfiguration.shouldResolveWorkspaceProjects()) { @@ -297,7 +331,6 @@ String artifactLocation = a.getFile().getAbsolutePath(); - ArrayList attributes = new ArrayList(); attributes.add(JavaCore.newClasspathAttribute(Maven2Plugin.GROUP_ID_ATTRIBUTE, a.getGroupId())); attributes.add(JavaCore.newClasspathAttribute(Maven2Plugin.ARTIFACT_ID_ATTRIBUTE, a.getArtifactId())); attributes.add(JavaCore.newClasspathAttribute(Maven2Plugin.VERSION_ATTRIBUTE, a.getVersion())); @@ -1024,5 +1057,130 @@ return project; } - + + // TODO work out how to listen for changes in the installed bundles and only run this then + private boolean isWTPAvailable() { + IBundleGroupProvider[] bundleGroupProviders = Platform.getBundleGroupProviders(); + for(int i = 0; i < bundleGroupProviders.length; i++ ) { + IBundleGroupProvider bundleGroupProvider = bundleGroupProviders[i]; + IBundleGroup[] bundleGroups = bundleGroupProvider.getBundleGroups(); + for(int j = 0; j < bundleGroups.length; j++ ) { + IBundleGroup bundleGroup = bundleGroups[j]; + if (JST_IDENTIFER.equals(bundleGroup.getIdentifier())) { + String version = bundleGroup.getVersion(); + int majorVersion = Integer.parseInt(version.substring(0, version.indexOf('.'))); + if (majorVersion >= 2) { + return true; + } + } + } + } + return false; + } + + private boolean hasDynamicWebProjectNature(IProject project) { + try { + IProjectNature nature1 = project.getNature("org.eclipse.wst.common.modulecore.ModuleCoreNature"); + IProjectNature nature2 = project.getNature("org.eclipse.wst.common.project.facet.core.nature"); + if (nature1 != null && nature2 != null) { + return true; + } + } catch (Exception e) { + console.logError("Unable to inspect nature: " + e); + } + return false; + } + + /** + * Returns the path where this container dependencies will be located at runtime + * (like /WEB-INF/lib for war packaging). + * If the project packaging does not know about deployment, it will be null. + * @param pomFile + * @return the path to the runtime folder, or null. + */ + private String getRuntimePath(IFile pomFile) { + Model model = mavenModelManager.getMavenModel(pomFile); + String packaging = model.getPackaging(); + String runtimePath = null; + if (PACKAGING_WAR.equalsIgnoreCase(packaging)) { + runtimePath = "/WEB-INF/lib"; + } + return runtimePath; + } + + /** + * Updates the specified Java project so that the Maven Classpath Container has + * the WTP component dependency attribute. + * @param javaProject Target Java project. + * @param entries Classpath entries that should have the component dependency attribute. Map from IClasspathEntry + * to the IClasspathAttribute for the WTP classpath component dependency. + * @throws CoreException Thrown if an error is encountered. + */ + private void setWTPDependencyAttribute(final IJavaProject javaProject, IClasspathContainer container, String runtimePath) throws CoreException { + if (javaProject == null || !javaProject.getProject().isAccessible()) { + return; + } + final List updatedClasspath = new ArrayList(); + final IClasspathEntry[] rawClasspath = javaProject.getRawClasspath(); + boolean found = false; + for (int i = 0; i < rawClasspath.length; i++) { + IClasspathEntry entry = rawClasspath[i]; + if (found == false && entry.getPath().equals(container.getPath())) { + found = true; + if (hasComponentDependencyAttribute(entry)) { + // No work to do + return; + } + // should have the attribute and currently missing it + IClasspathAttribute attrib = JavaCore.newClasspathAttribute(CLASSPATH_COMPONENT_DEPENDENCY, runtimePath); + IClasspathAttribute[] updatedAttributes = updateAttributes(entry.getExtraAttributes(), attrib, true); + entry = JavaCore.newContainerEntry(entry.getPath(), entry.getAccessRules(), updatedAttributes, entry.isExported()); + } + + updatedClasspath.add(entry); + } + final IClasspathEntry[] updatedCPArray = (IClasspathEntry[]) updatedClasspath.toArray(new IClasspathEntry[updatedClasspath.size()]); + javaProject.setRawClasspath(updatedCPArray, null); + } + + private IClasspathAttribute[] updateAttributes(final IClasspathAttribute[] currentAttribs, final IClasspathAttribute targetAttrib, final boolean add) { + final List updatedAttribs = new ArrayList(); + boolean hasAttrib = false; + for (int i = 0; i < currentAttribs.length; i++) { + if (currentAttribs[i].getName().equals(targetAttrib.getName())) { + hasAttrib = true; + if (!add) { + continue; + } + } + updatedAttribs.add(currentAttribs[i]); + } + if (add && !hasAttrib) { + updatedAttribs.add(targetAttrib); + } + return (IClasspathAttribute[]) updatedAttribs.toArray(new IClasspathAttribute[updatedAttribs.size()]); + } + + /** + * Checks if the specified IClasspathEntry has one of the special WTP component dependency + * attribute (org.eclipse.jst.component.dependency) that indicates it should be mapped into the virtual component for the associated project. + * + * @param entry The IClasspathEntry. + * @return true if the classpath entry will be mapped, false if it lacks the attribute. + */ + private static boolean hasComponentDependencyAttribute(final IClasspathEntry entry) { + if (entry == null) { + throw new IllegalArgumentException("Parameter 'entry' can't be null"); + } + final IClasspathAttribute[] attributes = entry.getExtraAttributes(); + for (int i = 0; i < attributes.length; i++) { + final IClasspathAttribute attribute = attributes[i]; + if (CLASSPATH_COMPONENT_DEPENDENCY.equals(attribute.getName())) { + // Attribute found + return true; + } + } + // Attribute not found + return false; + } }