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 &lt; String replacementId, String premanaged version >
+     */
+    private Map managedVersions = new HashMap();
+
+    /**
+     * Map &lt; 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