public void testDependencyManagementOverridesTransitiveDependencyVersion() throws Exception { File localRepo = getLocalRepositoryPath(); File pom0 = new File(localRepo, "p0/pom.xml"); File pom0Basedir = pom0.getParentFile(); File pom1 = new File(pom0Basedir, "p1/pom.xml"); // load the child project, which inherits from p0... MavenProject project0 = getProjectWithDependencies(pom0); MavenProject project1 = getProjectWithDependencies(pom1); assertEquals(pom0Basedir, project1.getParent().getBasedir()); System.out.println("Project " + project1.getId() + " " + project1); Map map = project1.getArtifactMap(); assertNotNull("No artifacts", map); assertTrue("No Artifacts", map.size() > 0); assertTrue("Set size should be 3, is " + map.size(), map.size() == 3); Artifact a = (Artifact) map.get("maven-test:t10-a"); Artifact b = (Artifact) map.get("maven-test:t10-b"); Artifact c = (Artifact) map.get("maven-test:t10-c"); assertNotNull(a); assertNotNull(b); assertNotNull(c); // inherited from depMgmt System.out.println(a.getScope()); assertTrue("Incorrect scope for " + a.getDependencyConflictId(), a.getScope().equals("test")); // transitive dep, overridden b depMgmt assertTrue( "Incorrect scope for " + b.getDependencyConflictId(), b.getScope().equals("runtime")); // direct dep, overrides depMgmt assertTrue( "Incorrect scope for " + c.getDependencyConflictId(), c.getScope().equals("runtime")); }
public void configureClasspath( IProject project, MavenProject mavenProject, IClasspathDescriptor classpath, IProgressMonitor monitor) throws CoreException { // Improve skinny war support by generating the manifest classpath // similar to mvn eclipse:eclipse // http://maven.apache.org/plugins/maven-war-plugin/examples/skinny-wars.html WarPluginConfiguration config = new WarPluginConfiguration(mavenProject, project); WarPackagingOptions opts = new WarPackagingOptions(config); StringBuilder manifestCp = new StringBuilder(); /* * Need to take care of three separate cases * * 1. remove any project dependencies (they are represented as J2EE module dependencies) * 2. add non-dependency attribute for entries originated by artifacts with * runtime, system, test scopes or optional dependencies (not sure about the last one) * 3. make sure all dependency JAR files have unique file names, i.e. artifactId/version collisions */ Set<String> dups = new LinkedHashSet<String>(); Set<String> names = new HashSet<String>(); // first pass removes projects, adds non-dependency attribute and collects colliding filenames Iterator<IClasspathEntryDescriptor> iter = classpath.getEntryDescriptors().iterator(); while (iter.hasNext()) { IClasspathEntryDescriptor descriptor = iter.next(); IClasspathEntry entry = descriptor.getClasspathEntry(); String scope = descriptor.getScope(); String key = ArtifactUtils.versionlessKey(descriptor.getGroupId(), descriptor.getArtifactId()); Artifact artifact = mavenProject.getArtifactMap().get(key); String extension = artifact.getArtifactHandler().getExtension(); if (IClasspathEntry.CPE_PROJECT == entry.getEntryKind() && Artifact.SCOPE_COMPILE.equals(scope)) { // get deployed name for project dependencies // TODO can this be done somehow more elegantly? IProject p = (IProject) ResourcesPlugin.getWorkspace().getRoot().findMember(entry.getPath()); IVirtualComponent component = ComponentCore.createComponent(p); boolean usedInEar = opts.isReferenceFromEar(component, extension); if (opts.isSkinnyWar() && usedInEar) { if (manifestCp.length() > 0) { manifestCp.append(" "); } // MNGECLIPSE-2393 prepend ManifestClasspath prefix if (config.getManifestClasspathPrefix() != null && !JEEPackaging.isJEEPackaging(artifact.getType())) { manifestCp.append(config.getManifestClasspathPrefix()); } manifestCp.append(component.getDeployedName()).append(".").append(extension); } if (!descriptor.isOptionalDependency() || usedInEar) { // remove mandatory project dependency from classpath iter.remove(); continue; } // else : optional dependency not used in ear -> need to trick ClasspathAttribute with // NONDEPENDENCY_ATTRIBUTE } if (opts.isSkinnyWar() && opts.isReferenceFromEar(descriptor)) { if (manifestCp.length() > 0) { manifestCp.append(" "); } if (config.getManifestClasspathPrefix() != null && !JEEPackaging.isJEEPackaging(artifact.getType())) { manifestCp.append(config.getManifestClasspathPrefix()); } manifestCp.append(entry.getPath().lastSegment()); // ear references aren't kept in the Maven Dependencies iter.remove(); continue; } // add non-dependency attribute // Check the scope & set WTP non-dependency as appropriate // Optional artifact shouldn't be deployed if (Artifact.SCOPE_PROVIDED.equals(scope) || Artifact.SCOPE_TEST.equals(scope) || Artifact.SCOPE_SYSTEM.equals(scope) || descriptor.isOptionalDependency()) { descriptor.addClasspathAttribute(NONDEPENDENCY_ATTRIBUTE); } // collect duplicate file names if (!names.add(entry.getPath().lastSegment())) { dups.add(entry.getPath().lastSegment()); } } String targetDir = mavenProject.getBuild().getDirectory(); // second pass disambiguates colliding entry file names iter = classpath.getEntryDescriptors().iterator(); while (iter.hasNext()) { IClasspathEntryDescriptor descriptor = iter.next(); IClasspathEntry entry = descriptor.getClasspathEntry(); if (dups.contains(entry.getPath().lastSegment())) { File src = new File(entry.getPath().toOSString()); String groupId = descriptor.getGroupId(); File dst = new File(targetDir, groupId + "-" + entry.getPath().lastSegment()); try { if (src.canRead()) { if (isDifferent(src, dst)) { // uses lastModified FileUtils.copyFile(src, dst); dst.setLastModified(src.lastModified()); } descriptor.setClasspathEntry( JavaCore.newLibraryEntry( Path.fromOSString(dst.getCanonicalPath()), // entry.getSourceAttachmentPath(), // entry.getSourceAttachmentRootPath(), // entry.getAccessRules(), // entry.getExtraAttributes(), // entry.isExported())); } } catch (IOException ex) { MavenLogger.log("File copy failed", ex); } } } if (opts.isSkinnyWar()) { // writing the manifest only works when the project has been properly created // placing this check on the top of the method broke 2 other tests // thats why its placed here now. if (ComponentCore.createComponent(project) == null) { return; } // write manifest, using internal API - seems ok for 3.4/3.5, though ArchiveManifest mf = J2EEProjectUtilities.readManifest(project); if (mf == null) { mf = new ArchiveManifestImpl(); } mf.addVersionIfNecessary(); mf.setClassPath(manifestCp.toString()); try { J2EEProjectUtilities.writeManifest(project, mf); } catch (Exception ex) { MavenLogger.log("Could not write web module manifest file", ex); } } }
public void setModuleDependencies( IProject project, MavenProject mavenProject, IProgressMonitor monitor) throws CoreException { IVirtualComponent component = ComponentCore.createComponent(project); // if the attempt to create dependencies happens before the project is actually created, abort. // this will be created again when the project exists. if (component == null) { return; } WarPluginConfiguration config = new WarPluginConfiguration(mavenProject, project); WarPackagingOptions opts = new WarPackagingOptions(config); List<AbstractDependencyConfigurator> depConfigurators = ExtensionReader.readDependencyConfiguratorExtensions( projectManager, MavenPlugin.getDefault().getMavenRuntimeManager(), mavenMarkerManager, MavenPlugin.getDefault().getConsole()); Set<IVirtualReference> references = new LinkedHashSet<IVirtualReference>(); List<IMavenProjectFacade> exportedDependencies = getWorkspaceDependencies(project, mavenProject); for (IMavenProjectFacade dependency : exportedDependencies) { String depPackaging = dependency.getPackaging(); if ("pom".equals(depPackaging)) continue; // MNGECLIPSE-744 pom dependencies shouldn't be deployed preConfigureDependencyProject(dependency, monitor); MavenProject depMavenProject = dependency.getMavenProject(monitor); IVirtualComponent depComponent = ComponentCore.createComponent(dependency.getProject()); String artifactKey = ArtifactUtils.versionlessKey(depMavenProject.getArtifact()); Artifact artifact = mavenProject.getArtifactMap().get(artifactKey); // in a skinny war the dependency modules are referenced by manifest classpath // see also <code>configureClasspath</code> the dependeny project is handled in the skinny // case if (opts.isSkinnyWar() && opts.isReferenceFromEar(depComponent, artifact.getArtifactHandler().getExtension())) { continue; } // an artifact in mavenProject.getArtifacts() doesn't have the "optional" value as // depMavenProject.getArtifact(); if (!artifact.isOptional()) { IVirtualReference reference = ComponentCore.createReference(component, depComponent); reference.setRuntimePath(new Path("/WEB-INF/lib")); references.add(reference); } } IVirtualReference[] newRefs = references.toArray(new IVirtualReference[references.size()]); if (hasChanged(component.getReferences(), newRefs)) { // Only write in the .component file if necessary component.setReferences(newRefs); } // TODO why a 2nd loop??? for (IMavenProjectFacade dependency : exportedDependencies) { MavenProject depMavenProject = dependency.getMavenProject(monitor); Iterator<AbstractDependencyConfigurator> configurators = depConfigurators.iterator(); while (configurators.hasNext()) { try { configurators .next() .configureDependency( mavenProject, project, depMavenProject, dependency.getProject(), monitor); } catch (MarkedException ex) { // XXX handle this } } } }