You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by mc...@apache.org on 2009/09/02 20:57:06 UTC
svn commit: r810669 - in /felix/trunk/bundleplugin: pom.xml
src/main/java/org/apache/maven/shared/dependency/tree/
src/main/java/org/apache/maven/shared/dependency/tree/DependencyTreeResolutionListener.java
Author: mcculls
Date: Wed Sep 2 18:57:05 2009
New Revision: 810669
URL: http://svn.apache.org/viewvc?rev=810669&view=rev
Log:
FELIX-1148: apply local patch for MSHARED-101
Added:
felix/trunk/bundleplugin/src/main/java/org/apache/maven/shared/dependency/tree/
felix/trunk/bundleplugin/src/main/java/org/apache/maven/shared/dependency/tree/DependencyTreeResolutionListener.java (with props)
Modified:
felix/trunk/bundleplugin/pom.xml
Modified: felix/trunk/bundleplugin/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/pom.xml?rev=810669&r1=810668&r2=810669&view=diff
==============================================================================
--- felix/trunk/bundleplugin/pom.xml (original)
+++ felix/trunk/bundleplugin/pom.xml Wed Sep 2 18:57:05 2009
@@ -109,6 +109,11 @@
<version>2.0.7</version>
</dependency>
<dependency>
+ <groupId>org.apache.maven.shared</groupId>
+ <artifactId>maven-dependency-tree</artifactId>
+ <version>1.2</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-provider-api</artifactId>
<version>1.0-beta-2</version>
Added: felix/trunk/bundleplugin/src/main/java/org/apache/maven/shared/dependency/tree/DependencyTreeResolutionListener.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/org/apache/maven/shared/dependency/tree/DependencyTreeResolutionListener.java?rev=810669&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/apache/maven/shared/dependency/tree/DependencyTreeResolutionListener.java (added)
+++ felix/trunk/bundleplugin/src/main/java/org/apache/maven/shared/dependency/tree/DependencyTreeResolutionListener.java Wed Sep 2 18:57:05 2009
@@ -0,0 +1,552 @@
+package org.apache.maven.shared.dependency.tree;
+
+/*
+ * 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.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Stack;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.resolver.ResolutionListener;
+import org.apache.maven.artifact.resolver.ResolutionListenerForDepMgmt;
+import org.apache.maven.artifact.versioning.VersionRange;
+import org.apache.maven.shared.dependency.tree.traversal.CollectingDependencyNodeVisitor;
+import org.codehaus.plexus.logging.Logger;
+
+/**
+ * An artifact resolution listener that constructs a dependency tree.
+ *
+ * @author Edwin Punzalan
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
+ * @version $Id: DependencyTreeResolutionListener.java 661727 2008-05-30 14:21:49Z bentmann $
+ */
+public class DependencyTreeResolutionListener implements ResolutionListener, ResolutionListenerForDepMgmt
+{
+ // fields -----------------------------------------------------------------
+
+ /**
+ * The log to write debug messages to.
+ */
+ private final Logger logger;
+
+ /**
+ * The parent dependency nodes of the current dependency node.
+ */
+ private final Stack parentNodes;
+
+ /**
+ * A map of dependency nodes by their attached artifact.
+ */
+ private final Map nodesByArtifact;
+
+ /**
+ * The root dependency node of the computed dependency tree.
+ */
+ private DependencyNode rootNode;
+
+ /**
+ * The dependency node currently being processed by this listener.
+ */
+ private DependencyNode currentNode;
+
+ /**
+ * Map < String replacementId, String premanaged version >
+ */
+ private Map managedVersions = new HashMap();
+
+ /**
+ * Map < String replacementId, String premanaged scope >
+ */
+ private Map managedScopes = new HashMap();
+
+ // constructors -----------------------------------------------------------
+
+ /**
+ * Creates a new dependency tree resolution listener that writes to the specified log.
+ *
+ * @param logger
+ * the log to write debug messages to
+ */
+ public DependencyTreeResolutionListener( Logger logger )
+ {
+ this.logger = logger;
+
+ parentNodes = new Stack();
+ nodesByArtifact = new IdentityHashMap();
+ rootNode = null;
+ currentNode = null;
+ }
+
+ // ResolutionListener methods ---------------------------------------------
+
+ /**
+ * {@inheritDoc}
+ */
+ public void testArtifact( Artifact artifact )
+ {
+ log( "testArtifact: artifact=" + artifact );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void startProcessChildren( Artifact artifact )
+ {
+ log( "startProcessChildren: artifact=" + artifact );
+
+ if ( !currentNode.getArtifact().equals( artifact ) )
+ {
+ throw new IllegalStateException( "Artifact was expected to be " + currentNode.getArtifact() + " but was "
+ + artifact );
+ }
+
+ parentNodes.push( currentNode );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void endProcessChildren( Artifact artifact )
+ {
+ DependencyNode node = (DependencyNode) parentNodes.pop();
+
+ log( "endProcessChildren: artifact=" + artifact );
+
+ if ( node == null )
+ {
+ throw new IllegalStateException( "Parent dependency node was null" );
+ }
+
+ if ( !node.getArtifact().equals( artifact ) )
+ {
+ throw new IllegalStateException( "Parent dependency node artifact was expected to be " + node.getArtifact()
+ + " but was " + artifact );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void includeArtifact( Artifact artifact )
+ {
+ log( "includeArtifact: artifact=" + artifact );
+
+ DependencyNode existingNode = getNode( artifact );
+
+ /*
+ * Ignore duplicate includeArtifact calls since omitForNearer can be called prior to includeArtifact on the same
+ * artifact, and we don't wish to include it twice.
+ */
+ if ( existingNode == null && isCurrentNodeIncluded() )
+ {
+ DependencyNode node = addNode( artifact );
+
+ /*
+ * Add the dependency management information cached in any prior manageArtifact calls, since includeArtifact
+ * is always called after manageArtifact.
+ */
+ flushDependencyManagement( node );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void omitForNearer( Artifact omitted, Artifact kept )
+ {
+ log( "omitForNearer: omitted=" + omitted + " kept=" + kept );
+
+ if ( !omitted.getDependencyConflictId().equals( kept.getDependencyConflictId() ) )
+ {
+ throw new IllegalArgumentException( "Omitted artifact dependency conflict id "
+ + omitted.getDependencyConflictId() + " differs from kept artifact dependency conflict id "
+ + kept.getDependencyConflictId() );
+ }
+
+ if ( isCurrentNodeIncluded() )
+ {
+ DependencyNode omittedNode = getNode( omitted );
+
+ if ( omittedNode != null )
+ {
+ removeNode( omitted );
+ }
+ else
+ {
+ omittedNode = createNode( omitted );
+
+ currentNode = omittedNode;
+ }
+
+ omittedNode.omitForConflict( kept );
+
+ /*
+ * Add the dependency management information cached in any prior manageArtifact calls, since omitForNearer
+ * is always called after manageArtifact.
+ */
+ flushDependencyManagement( omittedNode );
+
+ DependencyNode keptNode = getNode( kept );
+
+ if ( keptNode == null )
+ {
+ addNode( kept );
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void updateScope( Artifact artifact, String scope )
+ {
+ log( "updateScope: artifact=" + artifact + ", scope=" + scope );
+
+ DependencyNode node = getNode( artifact );
+
+ if ( node == null )
+ {
+ // updateScope events can be received prior to includeArtifact events
+ node = addNode( artifact );
+ }
+
+ node.setOriginalScope( artifact.getScope() );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void manageArtifact( Artifact artifact, Artifact replacement )
+ {
+ // TODO: remove when ResolutionListenerForDepMgmt merged into ResolutionListener
+
+ log( "manageArtifact: artifact=" + artifact + ", replacement=" + replacement );
+
+ if ( replacement.getVersion() != null )
+ {
+ manageArtifactVersion( artifact, replacement );
+ }
+
+ if ( replacement.getScope() != null )
+ {
+ manageArtifactScope( artifact, replacement );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void omitForCycle( Artifact artifact )
+ {
+ log( "omitForCycle: artifact=" + artifact );
+
+ if ( isCurrentNodeIncluded() )
+ {
+ DependencyNode node = createNode( artifact );
+
+ node.omitForCycle();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void updateScopeCurrentPom( Artifact artifact, String scopeIgnored )
+ {
+ log( "updateScopeCurrentPom: artifact=" + artifact + ", scopeIgnored=" + scopeIgnored );
+
+ DependencyNode node = getNode( artifact );
+
+ if ( node == null )
+ {
+ // updateScopeCurrentPom events can be received prior to includeArtifact events
+ node = addNode( artifact );
+ // TODO remove the node that tried to impose its scope and add some info
+ }
+
+ node.setFailedUpdateScope( scopeIgnored );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void selectVersionFromRange( Artifact artifact )
+ {
+ log( "selectVersionFromRange: artifact=" + artifact );
+
+ DependencyNode node = getNode( artifact );
+
+ /*
+ * selectVersionFromRange is called before includeArtifact
+ */
+ if ( node == null && isCurrentNodeIncluded() )
+ {
+ node = addNode( artifact );
+ }
+
+ node.setVersionSelectedFromRange( artifact.getVersionRange() );
+ node.setAvailableVersions( artifact.getAvailableVersions() );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void restrictRange( Artifact artifact, Artifact replacement, VersionRange versionRange )
+ {
+ log( "restrictRange: artifact=" + artifact + ", replacement=" + replacement + ", versionRange=" + versionRange );
+
+ // TODO: track range restriction in node (MNG-3093)
+ }
+
+ // ResolutionListenerForDepMgmt methods -----------------------------------
+
+ /**
+ * {@inheritDoc}
+ */
+ public void manageArtifactVersion( Artifact artifact, Artifact replacement )
+ {
+ log( "manageArtifactVersion: artifact=" + artifact + ", replacement=" + replacement );
+
+ /*
+ * DefaultArtifactCollector calls manageArtifact twice: first with the change; then subsequently with no change.
+ * We ignore the second call when the versions are equal.
+ */
+ if ( isCurrentNodeIncluded() && !replacement.getVersion().equals( artifact.getVersion() ) )
+ {
+ /*
+ * Cache management information and apply in includeArtifact, since DefaultArtifactCollector mutates the
+ * artifact and then calls includeArtifact after manageArtifact.
+ */
+ managedVersions.put( getRangeId( replacement ), artifact.getVersion() );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void manageArtifactScope( Artifact artifact, Artifact replacement )
+ {
+ log( "manageArtifactScope: artifact=" + artifact + ", replacement=" + replacement );
+
+ /*
+ * DefaultArtifactCollector calls manageArtifact twice: first with the change; then subsequently with no change.
+ * We ignore the second call when the scopes are equal.
+ */
+ if ( isCurrentNodeIncluded() && !replacement.getScope().equals( artifact.getScope() ) )
+ {
+ /*
+ * Cache management information and apply in includeArtifact, since DefaultArtifactCollector mutates the
+ * artifact and then calls includeArtifact after manageArtifact.
+ */
+ managedScopes.put( getRangeId( replacement ), artifact.getScope() );
+ }
+ }
+
+ // public methods ---------------------------------------------------------
+
+ /**
+ * Gets a list of all dependency nodes in the computed dependency tree.
+ *
+ * @return a list of dependency nodes
+ * @deprecated As of 1.1, use a {@link CollectingDependencyNodeVisitor} on the root dependency node
+ */
+ public Collection getNodes()
+ {
+ return Collections.unmodifiableCollection( nodesByArtifact.values() );
+ }
+
+ /**
+ * Gets the root dependency node of the computed dependency tree.
+ *
+ * @return the root node
+ */
+ public DependencyNode getRootNode()
+ {
+ return rootNode;
+ }
+
+ // private methods --------------------------------------------------------
+
+ /**
+ * Writes the specified message to the log at debug level with indentation for the current node's depth.
+ *
+ * @param message
+ * the message to write to the log
+ */
+ private void log( String message )
+ {
+ int depth = parentNodes.size();
+
+ StringBuffer buffer = new StringBuffer();
+
+ for ( int i = 0; i < depth; i++ )
+ {
+ buffer.append( " " );
+ }
+
+ buffer.append( message );
+
+ logger.debug( buffer.toString() );
+ }
+
+ /**
+ * Creates a new dependency node for the specified artifact and appends it to the current parent dependency node.
+ *
+ * @param artifact
+ * the attached artifact for the new dependency node
+ * @return the new dependency node
+ */
+ private DependencyNode createNode( Artifact artifact )
+ {
+ DependencyNode node = new DependencyNode( artifact );
+
+ if ( !parentNodes.isEmpty() )
+ {
+ DependencyNode parent = (DependencyNode) parentNodes.peek();
+
+ parent.addChild( node );
+ }
+
+ return node;
+ }
+
+ /**
+ * Creates a new dependency node for the specified artifact, appends it to the current parent dependency node and
+ * puts it into the dependency node cache.
+ *
+ * @param artifact
+ * the attached artifact for the new dependency node
+ * @return the new dependency node
+ */
+ // package protected for unit test
+ DependencyNode addNode( Artifact artifact )
+ {
+ DependencyNode node = createNode( artifact );
+
+ DependencyNode previousNode = (DependencyNode) nodesByArtifact.put( node.getArtifact(), node );
+
+ if ( previousNode != null )
+ {
+ throw new IllegalStateException( "Duplicate node registered for artifact: " + node.getArtifact() );
+ }
+
+ if ( rootNode == null )
+ {
+ rootNode = node;
+ }
+
+ currentNode = node;
+
+ return node;
+ }
+
+ /**
+ * Gets the dependency node for the specified artifact from the dependency node cache.
+ *
+ * @param artifact
+ * the artifact to find the dependency node for
+ * @return the dependency node, or <code>null</code> if the specified artifact has no corresponding dependency
+ * node
+ */
+ private DependencyNode getNode( Artifact artifact )
+ {
+ return (DependencyNode) nodesByArtifact.get( artifact );
+ }
+
+ /**
+ * Removes the dependency node for the specified artifact from the dependency node cache.
+ *
+ * @param artifact
+ * the artifact to remove the dependency node for
+ */
+ private void removeNode( Artifact artifact )
+ {
+ DependencyNode node = (DependencyNode) nodesByArtifact.remove( artifact );
+
+ if ( !artifact.equals( node.getArtifact() ) )
+ {
+ throw new IllegalStateException( "Removed dependency node artifact was expected to be " + artifact
+ + " but was " + node.getArtifact() );
+ }
+ }
+
+ /**
+ * Gets whether the all the ancestors of the dependency node currently being processed by this listener have an
+ * included state.
+ *
+ * @return <code>true</code> if all the ancestors of the current dependency node have a state of
+ * <code>INCLUDED</code>
+ */
+ private boolean isCurrentNodeIncluded()
+ {
+ boolean included = true;
+
+ for ( Iterator iterator = parentNodes.iterator(); included && iterator.hasNext(); )
+ {
+ DependencyNode node = (DependencyNode) iterator.next();
+
+ if ( node.getState() != DependencyNode.INCLUDED )
+ {
+ included = false;
+ }
+ }
+
+ return included;
+ }
+
+ /**
+ * Updates the specified node with any dependency management information cached in prior <code>manageArtifact</code>
+ * calls.
+ *
+ * @param node
+ * the node to update
+ */
+ private void flushDependencyManagement( DependencyNode node )
+ {
+ Artifact artifact = node.getArtifact();
+ String premanagedVersion = (String) managedVersions.get( getRangeId( artifact ) );
+ String premanagedScope = (String) managedScopes.get( getRangeId( artifact ) );
+
+ if ( premanagedVersion != null || premanagedScope != null )
+ {
+ if ( premanagedVersion != null )
+ {
+ node.setPremanagedVersion( premanagedVersion );
+ }
+
+ if ( premanagedScope != null )
+ {
+ node.setPremanagedScope( premanagedScope );
+ }
+
+ premanagedVersion = null;
+ premanagedScope = null;
+ }
+ }
+
+ private static String getRangeId( Artifact artifact )
+ {
+ return artifact.getDependencyConflictId() + ":" + artifact.getVersionRange();
+ }
+}
Propchange: felix/trunk/bundleplugin/src/main/java/org/apache/maven/shared/dependency/tree/DependencyTreeResolutionListener.java
------------------------------------------------------------------------------
svn:eol-style = native