/******************************************************************************* * Copyright (c) 2008-2010 Sonatype, Inc. * 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: * Sonatype, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.m2e.core.embedder; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.InputStream; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.artifact.ArtifactTypeRegistry; import org.eclipse.aether.collection.CollectRequest; import org.eclipse.aether.collection.DependencyCollectionException; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.util.filter.ScopeDependencyFilter; import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; import org.eclipse.aether.util.graph.transformer.ConflictResolver; import org.eclipse.aether.util.graph.transformer.JavaScopeDeriver; import org.eclipse.aether.util.graph.transformer.JavaScopeSelector; import org.eclipse.aether.util.graph.transformer.NearestVersionSelector; import org.eclipse.aether.util.graph.transformer.SimpleOptionalitySelector; import org.eclipse.aether.util.graph.visitor.CloningDependencyVisitor; import org.eclipse.aether.util.graph.visitor.FilteringDependencyVisitor; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.osgi.util.NLS; import org.apache.maven.RepositoryUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.model.DependencyManagement; import org.apache.maven.project.MavenProject; import org.eclipse.m2e.core.internal.IMavenConstants; import org.eclipse.m2e.core.internal.MavenPluginActivator; import org.eclipse.m2e.core.internal.Messages; import org.eclipse.m2e.core.project.IMavenProjectFacade; import org.eclipse.m2e.core.project.IMavenProjectRegistry; /** * Model manager used to read and and modify Maven models * * @author Eugene Kuleshov XXX fix circular dependency */ public class MavenModelManager { private static final Logger log = LoggerFactory.getLogger(MavenModelManager.class); private final IMavenProjectRegistry projectManager; private final IMaven maven; public MavenModelManager(IMaven maven, IMavenProjectRegistry projectManager) { this.maven = maven; this.projectManager = projectManager; } public org.apache.maven.model.Model readMavenModel(InputStream reader) throws CoreException { return maven.readModel(reader); } public org.apache.maven.model.Model readMavenModel(File pomFile) throws CoreException { return maven.readModel(pomFile); } public org.apache.maven.model.Model readMavenModel(IFile pomFile) throws CoreException { return maven.readModel(pomFile.getLocation().toFile()); } public void createMavenModel(IFile pomFile, org.apache.maven.model.Model model) throws CoreException { String pomFileName = pomFile.getLocation().toString(); if(pomFile.exists()) { String msg = NLS.bind(Messages.MavenModelManager_error_pom_exists, pomFileName); throw new CoreException(new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1, msg, null)); } try { ByteArrayOutputStream buf = new ByteArrayOutputStream(); maven.writeModel(model, buf); // XXX MNGECLIPSE-495 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setNamespaceAware(false); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document document = documentBuilder.parse(new ByteArrayInputStream(buf.toByteArray())); Element documentElement = document.getDocumentElement(); NamedNodeMap attributes = documentElement.getAttributes(); if(attributes == null || attributes.getNamedItem("xmlns") == null) { //$NON-NLS-1$ Attr attr = document.createAttribute("xmlns"); //$NON-NLS-1$ attr.setTextContent("http://maven.apache.org/POM/4.0.0"); //$NON-NLS-1$ documentElement.setAttributeNode(attr); } if(attributes == null || attributes.getNamedItem("xmlns:xsi") == null) { //$NON-NLS-1$ Attr attr = document.createAttribute("xmlns:xsi"); //$NON-NLS-1$ attr.setTextContent("http://www.w3.org/2001/XMLSchema-instance"); //$NON-NLS-1$ documentElement.setAttributeNode(attr); } if(attributes == null || attributes.getNamedItem("xsi:schemaLocation") == null) { //$NON-NLS-1$ Attr attr = document.createAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation"); //$NON-NLS-1$ //$NON-NLS-2$ attr.setTextContent("http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"); //$NON-NLS-1$ documentElement.setAttributeNode(attr); } TransformerFactory transfac = TransformerFactory.newInstance(); Transformer trans = transfac.newTransformer(); trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$ buf.reset(); trans.transform(new DOMSource(document), new StreamResult(buf)); pomFile.create(new ByteArrayInputStream(buf.toByteArray()), true, new NullProgressMonitor()); } catch(RuntimeException ex) { String msg = NLS.bind(Messages.MavenModelManager_error_create, pomFileName, ex.toString()); throw new CoreException(new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1, msg, ex)); } catch(Exception ex) { String msg = NLS.bind(Messages.MavenModelManager_error_create, pomFileName, ex.toString()); throw new CoreException(new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1, msg, ex)); } } /** * @deprecated use {@link #readDependencyTree(IMavenProjectFacade, MavenProject, String, IProgressMonitor)}, which * supports workspace dependency resolution */ public synchronized DependencyNode readDependencyTree(IFile file, String classpath, IProgressMonitor monitor) throws CoreException { monitor.setTaskName(Messages.MavenModelManager_monitor_reading); MavenProject mavenProject = readMavenProject(file, monitor); return readDependencyTree(mavenProject, classpath, monitor); } /** * @deprecated use {@link #readDependencyTree(IMavenProjectFacade, MavenProject, String, IProgressMonitor)}, which * supports workspace dependency resolution */ public DependencyNode readDependencyTree(MavenProject mavenProject, String classpath, IProgressMonitor monitor) throws CoreException { return readDependencyTree(null, mavenProject, classpath, monitor); } public synchronized DependencyNode readDependencyTree(IMavenProjectFacade context, final MavenProject mavenProject, final String scope, IProgressMonitor monitor) throws CoreException { monitor.setTaskName(Messages.MavenModelManager_monitor_building); ICallable<DependencyNode> callable = new ICallable<DependencyNode>() { public DependencyNode call(IMavenExecutionContext context, IProgressMonitor monitor) throws CoreException { return readDependencyTree(context.getRepositorySession(), mavenProject, scope); } }; return (context != null) ? projectManager.execute(context, callable, monitor) : maven.execute(callable, monitor); } DependencyNode readDependencyTree(RepositorySystemSession repositorySession, MavenProject mavenProject, String scope) throws CoreException { DefaultRepositorySystemSession session = new DefaultRepositorySystemSession(repositorySession); // // Taken from MavenRepositorySystemSession.newSession() // ConflictResolver transformer = new ConflictResolver(new NearestVersionSelector(), new JavaScopeSelector(), new SimpleOptionalitySelector(), new JavaScopeDeriver()); session.setDependencyGraphTransformer(transformer); session.setConfigProperty(ConflictResolver.CONFIG_PROP_VERBOSE, Boolean.toString(true)); session.setConfigProperty(DependencyManagerUtils.CONFIG_PROP_VERBOSE, true); ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(maven.getProjectRealm(mavenProject)); ArtifactTypeRegistry stereotypes = session.getArtifactTypeRegistry(); CollectRequest request = new CollectRequest(); request.setRequestContext("project"); //$NON-NLS-1$ request.setRepositories(mavenProject.getRemoteProjectRepositories()); for(org.apache.maven.model.Dependency dependency : mavenProject.getDependencies()) { request.addDependency(RepositoryUtils.toDependency(dependency, stereotypes)); } DependencyManagement depMngt = mavenProject.getDependencyManagement(); if(depMngt != null) { for(org.apache.maven.model.Dependency dependency : depMngt.getDependencies()) { request.addManagedDependency(RepositoryUtils.toDependency(dependency, stereotypes)); } } DependencyNode node; try { node = MavenPluginActivator.getDefault().getRepositorySystem().collectDependencies(session, request).getRoot(); } catch(DependencyCollectionException ex) { String msg = Messages.MavenModelManager_error_read; log.error(msg, ex); throw new CoreException(new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1, msg, ex)); } Collection<String> scopes = new HashSet<String>(); Collections.addAll(scopes, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_COMPILE, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_TEST); if(Artifact.SCOPE_COMPILE.equals(scope)) { scopes.remove(Artifact.SCOPE_COMPILE); scopes.remove(Artifact.SCOPE_SYSTEM); scopes.remove(Artifact.SCOPE_PROVIDED); } else if(Artifact.SCOPE_RUNTIME.equals(scope)) { scopes.remove(Artifact.SCOPE_COMPILE); scopes.remove(Artifact.SCOPE_RUNTIME); } else if(Artifact.SCOPE_COMPILE_PLUS_RUNTIME.equals(scope)) { scopes.remove(Artifact.SCOPE_COMPILE); scopes.remove(Artifact.SCOPE_SYSTEM); scopes.remove(Artifact.SCOPE_PROVIDED); scopes.remove(Artifact.SCOPE_RUNTIME); } else { scopes.clear(); } CloningDependencyVisitor cloner = new CloningDependencyVisitor(); node.accept(new FilteringDependencyVisitor(cloner, new ScopeDependencyFilter(null, scopes))); node = cloner.getRootNode(); return node; } finally { Thread.currentThread().setContextClassLoader(oldClassLoader); } } public MavenProject readMavenProject(IFile file, IProgressMonitor monitor) throws CoreException { IMavenProjectFacade projectFacade = projectManager.create(file, true, monitor); MavenProject mavenProject = projectFacade.getMavenProject(monitor); return mavenProject; } }