From 88d2fda16e5a4a7b0f9a9591143669c651841b69 Mon Sep 17 00:00:00 2001 From: Brett Porter Date: Mon, 7 Apr 2008 06:23:47 +0000 Subject: [PATCH] add a consumer (not enabled by default) that can generate a dependency tree as XML git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@645394 13f79535-47bb-0310-9956-ffa450edef68 --- .../archiva-core-consumers/pom.xml | 1 - .../repository/RepositoryPurgeConsumer.java | 2 +- .../archiva-dependency-tree-consumer/pom.xml | 28 ++ .../DependencyTreeGeneratorConsumer.java | 278 ++++++++++++++++++ .../DependencyTreeGeneratorConsumerTest.java | 79 +++++ .../test-data/maven-core-2.0-tree.xml | 200 +++++++++++++ .../maven/maven-core/2.0/maven-core-2.0.pom | 186 ++++++++++++ .../archiva-base/archiva-consumers/pom.xml | 1 + pom.xml | 4 +- 9 files changed, 775 insertions(+), 4 deletions(-) create mode 100644 archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/pom.xml create mode 100644 archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/main/java/org/apache/archiva/consumers/dependencytree/DependencyTreeGeneratorConsumer.java create mode 100644 archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/test/java/org/apache/archiva/consumers/dependencytree/DependencyTreeGeneratorConsumerTest.java create mode 100644 archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/test/resources/test-data/maven-core-2.0-tree.xml create mode 100644 archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/test/resources/test-repo/org/apache/maven/maven-core/2.0/maven-core-2.0.pom diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/pom.xml b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/pom.xml index ad190b22d..165249f01 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/pom.xml +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/pom.xml @@ -26,7 +26,6 @@ archiva-core-consumers Archiva Consumers :: Core Consumers - jar diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumer.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumer.java index 0fd5ac542..0300e022a 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumer.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumer.java @@ -52,7 +52,7 @@ import java.util.Map; * @plexus.component * role="org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer" * role-hint="repository-purge" - * instantiation-strategy="per-lookup + * instantiation-strategy="per-lookup" */ public class RepositoryPurgeConsumer extends AbstractMonitoredConsumer diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/pom.xml b/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/pom.xml new file mode 100644 index 000000000..3caf0ae30 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + org.apache.archiva + archiva-consumers + 1.1-SNAPSHOT + + archiva-dependency-tree-consumer + Archiva Consumers :: Dependency Tree Consumer + + + org.apache.archiva + archiva-consumer-api + + + org.apache.maven.shared + maven-dependency-tree + 1.1 + + + org.apache.maven.wagon + wagon-http-lightweight + 1.0-beta-2 + runtime + + + diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/main/java/org/apache/archiva/consumers/dependencytree/DependencyTreeGeneratorConsumer.java b/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/main/java/org/apache/archiva/consumers/dependencytree/DependencyTreeGeneratorConsumer.java new file mode 100644 index 000000000..2d7537668 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/main/java/org/apache/archiva/consumers/dependencytree/DependencyTreeGeneratorConsumer.java @@ -0,0 +1,278 @@ +package org.apache.archiva.consumers.dependencytree; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; +import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer; +import org.apache.maven.archiva.consumers.ConsumerException; +import org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.repository.ArtifactRepositoryFactory; +import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout; +import org.apache.maven.artifact.resolver.ArtifactCollector; +import org.apache.maven.artifact.resolver.filter.ArtifactFilter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.MavenProjectBuilder; +import org.apache.maven.project.ProjectBuildingException; +import org.apache.maven.shared.dependency.tree.DependencyNode; +import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder; +import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException; +import org.apache.maven.shared.dependency.tree.filter.AncestorOrSelfDependencyNodeFilter; +import org.apache.maven.shared.dependency.tree.filter.DependencyNodeFilter; +import org.apache.maven.shared.dependency.tree.filter.StateDependencyNodeFilter; +import org.apache.maven.shared.dependency.tree.traversal.BuildingDependencyNodeVisitor; +import org.apache.maven.shared.dependency.tree.traversal.CollectingDependencyNodeVisitor; +import org.apache.maven.shared.dependency.tree.traversal.DependencyNodeVisitor; +import org.apache.maven.shared.dependency.tree.traversal.FilteringDependencyNodeVisitor; +import org.dom4j.Document; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; + +/** + * @plexus.component role="org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer" + * role-hint="dependency-tree-generator" instantiation-strategy="per-lookup" + */ +public class DependencyTreeGeneratorConsumer + extends AbstractMonitoredConsumer + implements KnownRepositoryContentConsumer +{ + /** @plexus.configuration */ + private File generatedRepositoryLocation; + + /** @plexus.configuration */ + private File localRepository; + + /** @plexus.requirement */ + private DependencyTreeBuilder dependencyTreeBuilder; + + /** @plexus.requirement */ + private ArtifactFactory artifactFactory; + + /** @plexus.requirement role-hint="maven" */ + private ArtifactMetadataSource artifactMetadataSource; + + /** @plexus.requirement */ + private ArtifactCollector artifactCollector; + + /** @plexus.requirement */ + private MavenProjectBuilder projectBuilder; + + /** @plexus.requirement */ + private ArtifactRepositoryFactory artifactRepositoryFactory; + + private String repositoryLocation; + + public String getDescription() + { + return "Generate dependency tree metadata for tracking changes across algorithms"; + } + + public String getId() + { + return "dependency-tree-generator"; + } + + public boolean isPermanent() + { + return false; + } + + public void setGeneratedRepositoryLocation( File generatedRepositoryLocation ) + { + this.generatedRepositoryLocation = generatedRepositoryLocation; + } + + public void beginScan( ManagedRepositoryConfiguration repository ) + throws ConsumerException + { + repositoryLocation = repository.getLocation(); + + if ( generatedRepositoryLocation == null ) + { + generatedRepositoryLocation = new File( repositoryLocation ); + } + + if ( localRepository == null ) + { + // This is a bit crappy, it would be better to operate entirely within + // the base repository, but would need to adjust maven-artifact + localRepository = new File( System.getProperty( "user.home" ), ".m2/repository" ); + } + } + + public void completeScan() + { + } + + public List getExcludes() + { + return null; + } + + public List getIncludes() + { + return Collections.singletonList( "**/*.pom" ); + } + + public void processFile( String path ) + throws ConsumerException + { + DefaultRepositoryLayout layout = new DefaultRepositoryLayout(); + + ArtifactRepository localRepository; + MavenProject project; + try + { + localRepository = + artifactRepositoryFactory.createArtifactRepository( "local", + this.localRepository.toURL().toExternalForm(), + layout, null, null ); + + project = projectBuilder.build( new File( repositoryLocation, path ), localRepository, null, false ); + } + catch ( ProjectBuildingException e ) + { + throw new ConsumerException( e.getMessage(), e ); + } + catch ( MalformedURLException e ) + { + throw new ConsumerException( e.getMessage(), e ); + } + + DependencyNode rootNode; + try + { + // TODO: do this for different values of new ScopeArtifactFilter( scope ) + ArtifactFilter artifactFilter = null; + + rootNode = + dependencyTreeBuilder.buildDependencyTree( project, localRepository, artifactFactory, + artifactMetadataSource, artifactFilter, artifactCollector ); + } + catch ( DependencyTreeBuilderException e ) + { + throw new ConsumerException( e.getMessage(), e ); + } + + Document document = DocumentHelper.createDocument(); + DependencyNodeVisitor visitor = new XmlSerializingDependencyNodeVisitor( document ); + + // TODO: remove the need for this when the serializer can calculate last nodes from visitor calls only + visitor = new BuildingDependencyNodeVisitor( visitor ); + + CollectingDependencyNodeVisitor collectingVisitor = new CollectingDependencyNodeVisitor(); + DependencyNodeVisitor firstPassVisitor = + new FilteringDependencyNodeVisitor( collectingVisitor, StateDependencyNodeFilter.INCLUDED ); + rootNode.accept( firstPassVisitor ); + + DependencyNodeFilter secondPassFilter = new AncestorOrSelfDependencyNodeFilter( collectingVisitor.getNodes() ); + visitor = new FilteringDependencyNodeVisitor( visitor, secondPassFilter ); + + rootNode.accept( visitor ); + + FileWriter writer = null; + try + { + Artifact artifact = + artifactFactory.createProjectArtifact( project.getGroupId(), project.getArtifactId(), + project.getVersion() ); + + File generatedFile = new File( generatedRepositoryLocation, layout.pathOf( artifact ) + ".xml" ); + generatedFile.getParentFile().mkdirs(); + writer = new FileWriter( generatedFile ); + OutputFormat format = OutputFormat.createPrettyPrint(); + XMLWriter w = new XMLWriter( writer, format ); + w.write( document ); + } + catch ( IOException e ) + { + throw new ConsumerException( e.getMessage(), e ); + } + finally + { + IOUtils.closeQuietly( writer ); + } + } + + private static class XmlSerializingDependencyNodeVisitor + implements DependencyNodeVisitor + { + private Element xmlNode; + + public XmlSerializingDependencyNodeVisitor( Document document ) + { + xmlNode = document.addElement( "tree" ); + } + + // DependencyNodeVisitor methods ------------------------------------------ + + /* + * @see org.apache.maven.shared.dependency.tree.traversal.DependencyNodeVisitor#visit(org.apache.maven.shared.dependency.tree.DependencyNode) + */ + public boolean visit( DependencyNode node ) + { + Element dependency = xmlNode.addElement( "dependency" ); + + Artifact artifact = node.getArtifact(); + dependency.addElement( "groupId" ).setText( artifact.getGroupId() ); + dependency.addElement( "artifactId" ).setText( artifact.getArtifactId() ); + dependency.addElement( "type" ).setText( artifact.getType() ); + dependency.addElement( "version" ).setText( artifact.getVersion() ); + if ( artifact.getScope() != null ) + { + dependency.addElement( "scope" ).setText( artifact.getScope() ); + } + + xmlNode = dependency.addElement( "dependencies" ); + + return true; + } + + /* + * @see org.apache.maven.shared.dependency.tree.traversal.DependencyNodeVisitor#endVisit(org.apache.maven.shared.dependency.tree.DependencyNode) + */ + public boolean endVisit( DependencyNode node ) + { + Element e = xmlNode.getParent(); + + if ( !xmlNode.hasContent() ) + { + e.remove( xmlNode ); + } + + xmlNode = e.getParent(); + + return true; + } + } +} diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/test/java/org/apache/archiva/consumers/dependencytree/DependencyTreeGeneratorConsumerTest.java b/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/test/java/org/apache/archiva/consumers/dependencytree/DependencyTreeGeneratorConsumerTest.java new file mode 100644 index 000000000..9b8bc8a1e --- /dev/null +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/test/java/org/apache/archiva/consumers/dependencytree/DependencyTreeGeneratorConsumerTest.java @@ -0,0 +1,79 @@ +package org.apache.archiva.consumers.dependencytree; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; +import org.apache.maven.archiva.consumers.ConsumerException; +import org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer; +import org.codehaus.plexus.spring.PlexusInSpringTestCase; + +public class DependencyTreeGeneratorConsumerTest + extends PlexusInSpringTestCase +{ + private DependencyTreeGeneratorConsumer consumer; + + private ManagedRepositoryConfiguration repository; + + private File repositoryLocation; + + private File generatedRepositoryLocation; + + public void setUp() + throws Exception + { + super.setUp(); + + consumer = + (DependencyTreeGeneratorConsumer) lookup( KnownRepositoryContentConsumer.class, "dependency-tree-generator" ); + + repositoryLocation = getTestFile( "target/test-" + getName() + "/test-repo" ); + FileUtils.deleteDirectory( repositoryLocation ); + FileUtils.copyDirectory( getTestFile( "target/test-classes/test-repo" ), repositoryLocation ); + + generatedRepositoryLocation = getTestFile( "target/test-" + getName() + "/generated-test-repo" ); + FileUtils.deleteDirectory( generatedRepositoryLocation ); + + consumer.setGeneratedRepositoryLocation( generatedRepositoryLocation ); + + repository = new ManagedRepositoryConfiguration(); + repository.setId( "dependency-tree" ); + repository.setLocation( repositoryLocation.getAbsolutePath() ); + } + + public void testGenerateBasicTree() + throws IOException, ConsumerException + { + consumer.beginScan( repository ); + + String path = "org/apache/maven/maven-core/2.0/maven-core-2.0.pom"; + consumer.processFile( path ); + + File generatedFile = new File( generatedRepositoryLocation, path + ".xml" ); + assertEquals( IOUtils.toString( getClass().getResourceAsStream( "/test-data/maven-core-2.0-tree.xml" ) ), + FileUtils.readFileToString( generatedFile ) ); + + consumer.completeScan(); + } +} diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/test/resources/test-data/maven-core-2.0-tree.xml b/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/test/resources/test-data/maven-core-2.0-tree.xml new file mode 100644 index 000000000..3c55b90d1 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/test/resources/test-data/maven-core-2.0-tree.xml @@ -0,0 +1,200 @@ + + + + + org.apache.maven + maven-core + jar + 2.0 + + + junit + junit + jar + 3.8.1 + test + + + org.apache.maven + maven-settings + jar + 2.0 + compile + + + org.apache.maven.wagon + wagon-file + jar + 1.0-alpha-5 + runtime + + + org.apache.maven + maven-plugin-parameter-documenter + jar + 2.0 + compile + + + org.apache.maven.wagon + wagon-http-lightweight + jar + 1.0-alpha-5 + runtime + + + org.apache.maven.reporting + maven-reporting-api + jar + 2.0 + compile + + + doxia + doxia-sink-api + jar + 1.0-alpha-4 + compile + + + + + org.apache.maven + maven-profile + jar + 2.0 + compile + + + org.apache.maven + maven-model + jar + 2.0 + compile + + + org.apache.maven + maven-artifact + jar + 2.0 + compile + + + org.apache.maven.wagon + wagon-provider-api + jar + 1.0-alpha-5 + compile + + + org.codehaus.plexus + plexus-container-default + jar + 1.0-alpha-8 + compile + + + classworlds + classworlds + jar + 1.1-alpha-2 + compile + + + + + org.apache.maven + maven-repository-metadata + jar + 2.0 + compile + + + org.apache.maven + maven-error-diagnostics + jar + 2.0 + compile + + + org.apache.maven + maven-project + jar + 2.0 + compile + + + org.apache.maven + maven-plugin-registry + jar + 2.0 + compile + + + commons-cli + commons-cli + jar + 1.0 + compile + + + org.apache.maven + maven-plugin-api + jar + 2.0 + compile + + + org.apache.maven + maven-plugin-descriptor + jar + 2.0 + compile + + + org.codehaus.plexus + plexus-interactivity-api + jar + 1.0-alpha-4 + compile + + + org.apache.maven + maven-artifact-manager + jar + 2.0 + compile + + + org.apache.maven + maven-monitor + jar + 2.0 + compile + + + org.apache.maven.wagon + wagon-ssh + jar + 1.0-alpha-5 + runtime + + + com.jcraft + jsch + jar + 0.1.23 + runtime + + + + + org.codehaus.plexus + plexus-utils + jar + 1.0.4 + compile + + + + diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/test/resources/test-repo/org/apache/maven/maven-core/2.0/maven-core-2.0.pom b/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/test/resources/test-repo/org/apache/maven/maven-core/2.0/maven-core-2.0.pom new file mode 100644 index 000000000..a6e158dea --- /dev/null +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-dependency-tree-consumer/src/test/resources/test-repo/org/apache/maven/maven-core/2.0/maven-core-2.0.pom @@ -0,0 +1,186 @@ + + + maven + org.apache.maven + 2.0 + + 4.0.0 + org.apache.maven + maven-core + Maven + 2.0 + + + + maven-assembly-plugin + 2.0-beta-1 + + src/assemble/bin.xml + maven-${version} + + + + + + + org.apache.maven + maven-settings + 2.0 + + + org.apache.maven.wagon + wagon-file + runtime + + + org.apache.maven + maven-plugin-parameter-documenter + 2.0 + + + org.apache.maven.wagon + wagon-http-lightweight + runtime + + + org.apache.maven.reporting + maven-reporting-api + 2.0 + + + org.apache.maven + maven-profile + 2.0 + + + org.apache.maven + maven-model + 2.0 + + + org.apache.maven + maven-artifact + 2.0 + + + org.apache.maven.wagon + wagon-provider-api + + + org.codehaus.plexus + plexus-container-default + + + org.apache.maven + maven-repository-metadata + 2.0 + + + org.apache.maven + maven-error-diagnostics + 2.0 + + + org.apache.maven + maven-project + 2.0 + + + org.apache.maven + maven-plugin-registry + 2.0 + + + commons-cli + commons-cli + 1.0 + + + commons-lang + commons-lang + + + commons-logging + commons-logging + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.apache.maven + maven-plugin-descriptor + 2.0 + + + org.codehaus.plexus + plexus-interactivity-api + 1.0-alpha-4 + + + plexus-utils + plexus + + + plexus-container-default + org.codehaus.plexus + + + + + org.apache.maven + maven-artifact-manager + 2.0 + + + org.apache.maven + maven-monitor + 2.0 + + + org.apache.maven.wagon + wagon-ssh + runtime + + + plexus-utils + plexus + + + plexus-container-default + org.codehaus.plexus + + + + + org.codehaus.plexus + plexus-utils + + + + + + maven-checkstyle-plugin + + + maven-clover-plugin + + + maven-pmd-plugin + + + maven-project-info-reports-plugin + + + + + + website + scp://minotaur.apache.org//www/maven.apache.org/m2 + + deployed + + \ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-consumers/pom.xml b/archiva-modules/archiva-base/archiva-consumers/pom.xml index 2e62ef12e..703dd1b55 100644 --- a/archiva-modules/archiva-base/archiva-consumers/pom.xml +++ b/archiva-modules/archiva-base/archiva-consumers/pom.xml @@ -34,6 +34,7 @@ archiva-database-consumers archiva-lucene-consumers archiva-signature-consumers + archiva-dependency-tree-consumer diff --git a/pom.xml b/pom.xml index f0619b92a..b50255131 100644 --- a/pom.xml +++ b/pom.xml @@ -585,7 +585,7 @@ org.codehaus.plexus plexus-utils - 1.4 + 1.4.5 org.codehaus.plexus @@ -755,7 +755,7 @@ - 2.0.5 + 2.0.8 1.0-rc1-SNAPSHOT 1.1-SNAPSHOT -- 2.39.5