You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by jd...@apache.org on 2011/08/25 22:03:57 UTC
svn commit: r1161723 [2/3] - in /maven/sandbox/trunk/mae: ./
mae-boms/mae-library-bom/ mae-booter/
mae-booter/src/main/java/org/apache/maven/mae/boot/embed/
mae-booter/src/test/java/org/apache/maven/mae/internal/container/
mae-booter/src/test/java/org/...
Added: maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/DependencyGraphResolver.java
URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/DependencyGraphResolver.java?rev=1161723&view=auto
==============================================================================
--- maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/DependencyGraphResolver.java (added)
+++ maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/DependencyGraphResolver.java Thu Aug 25 20:03:54 2011
@@ -0,0 +1,763 @@
+/*
+ * 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.
+ */
+
+package org.apache.maven.mae.depgraph.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.log4j.Logger;
+import org.apache.maven.RepositoryUtils;
+import org.apache.maven.mae.depgraph.DepGraphNode;
+import org.apache.maven.mae.depgraph.DepGraphRootNode;
+import org.apache.maven.mae.depgraph.DependencyGraph;
+import org.apache.maven.mae.project.session.ProjectToolsSession;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.DependencyManagement;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.sonatype.aether.RepositorySystem;
+import org.sonatype.aether.RepositorySystemSession;
+import org.sonatype.aether.artifact.Artifact;
+import org.sonatype.aether.artifact.ArtifactTypeRegistry;
+import org.sonatype.aether.collection.CollectRequest;
+import org.sonatype.aether.collection.CollectResult;
+import org.sonatype.aether.collection.DependencyCollectionException;
+import org.sonatype.aether.graph.DependencyFilter;
+import org.sonatype.aether.graph.DependencyNode;
+import org.sonatype.aether.graph.DependencyVisitor;
+import org.sonatype.aether.graph.Exclusion;
+import org.sonatype.aether.repository.RemoteRepository;
+import org.sonatype.aether.resolution.ArtifactRequest;
+import org.sonatype.aether.resolution.ArtifactResolutionException;
+import org.sonatype.aether.resolution.ArtifactResult;
+import org.sonatype.aether.util.DefaultRepositorySystemSession;
+import org.sonatype.aether.util.artifact.JavaScopes;
+
+@Component( role = DependencyGraphResolver.class )
+public class DependencyGraphResolver
+{
+
+ private static final Logger LOGGER = Logger.getLogger( DependencyGraphResolver.class );
+
+ @Requirement
+ private RepositorySystem repositorySystem;
+
+ public DependencyGraph accumulateGraph( final Collection<MavenProject> rootProjects,
+ RepositorySystemSession rss,
+ final ProjectToolsSession session )
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Preparing for dependency-graph accumulation..." );
+ }
+ }
+ rss = prepareForGraphResolution( rss, session );
+
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Accumulating dependency graph..." );
+ }
+ }
+
+ return accumulate( session, rss, rootProjects, session.getRemoteRepositoriesArray() );
+ }
+
+ public DependencyGraph resolveGraph( final DependencyGraph depGraph,
+ final Collection<MavenProject> rootProjects,
+ final RepositorySystemSession rss,
+ final ProjectToolsSession session )
+ {
+
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Resolving dependencies in graph..." );
+ }
+ }
+ resolve( rss, rootProjects, depGraph, session );
+
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Graph state contains: " + depGraph.size() + " nodes." );
+ }
+ }
+
+ return depGraph;
+ }
+
+ // TODO: Allow fine-tuning of scopes resolved...
+ private RepositorySystemSession prepareForGraphResolution( final RepositorySystemSession s,
+ final ProjectToolsSession session )
+ {
+ final DefaultRepositorySystemSession result = new DefaultRepositorySystemSession( s );
+ result.setDependencySelector( session.getDependencySelector() );
+
+ return result;
+ }
+
+ private void resolve( final RepositorySystemSession session,
+ final Collection<MavenProject> rootProjects,
+ final DependencyGraph depGraph, final ProjectToolsSession toolsSession )
+ {
+ final Set<DependencyResolveWorker> workers = new HashSet<DependencyResolveWorker>();
+ for ( final DepGraphNode node : depGraph )
+ {
+ if ( node == null || node.hasErrors() || node.isPreResolved() )
+ {
+ continue;
+ }
+
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Resolving: " + node.getLatestArtifact() );
+ }
+ }
+ workers.add( new DependencyResolveWorker( node, session, repositorySystem ) );
+ }
+
+ runResolve( workers, toolsSession );
+ // for ( final DependencyResolveWorker worker : workers )
+ // {
+ // worker.run();
+ // }
+
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Dependency-graph resolution complete." );
+ }
+ }
+ }
+
+ private void runResolve( final Set<DependencyResolveWorker> workers,
+ final ProjectToolsSession session )
+ {
+ final ExecutorService executorService =
+ Executors.newFixedThreadPool( session.getResolveThreads() );
+
+ final CountDownLatch latch = new CountDownLatch( workers.size() );
+ for ( final DependencyResolveWorker worker : workers )
+ {
+ worker.setLatch( latch );
+ executorService.execute( worker );
+ }
+
+ synchronized ( latch )
+ {
+ long count = 0;
+ while ( ( count = latch.getCount() ) > 0 )
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( count + " resolution workers remaining. Waiting 3s..." );
+ }
+ }
+ try
+ {
+ latch.await( 3, TimeUnit.SECONDS );
+ }
+ catch ( final InterruptedException e )
+ {
+ break;
+ }
+ }
+ }
+
+ boolean terminated = false;
+ int count = 1;
+ while ( !terminated )
+ {
+ try
+ {
+ executorService.shutdown();
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Attempt " + count
+ + " to shutdown graph-resolver. Waiting 3s..." );
+ }
+ }
+
+ count++;
+ terminated = executorService.awaitTermination( 3, TimeUnit.SECONDS );
+ }
+ catch ( final InterruptedException e )
+ {
+ break;
+ }
+ }
+ }
+
+ private DependencyGraph accumulate( final ProjectToolsSession session,
+ final RepositorySystemSession rss,
+ final Collection<MavenProject> projects,
+ final RemoteRepository... remoteRepositories )
+ {
+ final ArtifactTypeRegistry stereotypes = rss.getArtifactTypeRegistry();
+
+ DependencyGraph depGraph;
+ synchronized ( session )
+ {
+ depGraph = session.getState( DependencyGraph.class );
+ if ( depGraph == null )
+ {
+ depGraph = new DependencyGraph();
+ }
+ }
+
+ final GraphAccumulator accumulator =
+ new GraphAccumulator( depGraph, session.getDependencyFilter() );
+
+ for ( final MavenProject project : projects )
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Collecting dependencies for: " + project );
+ }
+ }
+ final CollectRequest request = new CollectRequest();
+ request.setRequestContext( "project" );
+ request.setRepositories( Arrays.asList( remoteRepositories ) );
+
+ if ( project.getDependencyArtifacts() == null )
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Adding dependencies to collection request..." );
+ }
+ }
+ for ( final Dependency dependency : project.getDependencies() )
+ {
+ request.addDependency( RepositoryUtils.toDependency( dependency, stereotypes ) );
+ }
+ }
+ else
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Mapping project dependencies by management key..." );
+ }
+ }
+ final Map<String, Dependency> dependencies = new HashMap<String, Dependency>();
+ for ( final Dependency dependency : project.getDependencies() )
+ {
+ final String key = dependency.getManagementKey();
+ dependencies.put( key, dependency );
+ }
+
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Adding dependencies to collection request..." );
+ }
+ }
+ for ( final org.apache.maven.artifact.Artifact artifact : project.getDependencyArtifacts() )
+ {
+ final String key = artifact.getDependencyConflictId();
+ final Dependency dependency = dependencies.get( key );
+ final Collection<org.apache.maven.model.Exclusion> exclusions =
+ dependency != null ? dependency.getExclusions() : null;
+
+ org.sonatype.aether.graph.Dependency dep =
+ RepositoryUtils.toDependency( artifact, exclusions );
+ if ( !JavaScopes.SYSTEM.equals( dep.getScope() )
+ && dep.getArtifact().getFile() != null )
+ {
+ // enable re-resolution
+ org.sonatype.aether.artifact.Artifact art = dep.getArtifact();
+ art = art.setFile( null ).setVersion( art.getBaseVersion() );
+ dep = dep.setArtifact( art );
+ }
+ request.addDependency( dep );
+ }
+ }
+
+ final DependencyManagement depMngt = project.getDependencyManagement();
+ if ( depMngt != null )
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Adding managed dependencies to collection request..." );
+ }
+ }
+ for ( final Dependency dependency : depMngt.getDependencies() )
+ {
+ request.addManagedDependency( RepositoryUtils.toDependency( dependency,
+ stereotypes ) );
+ }
+ }
+
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Collecting dependencies..." );
+ }
+ }
+ CollectResult result;
+ final Object old = rss.getData().get( ProjectToolsSession.SESSION_KEY );
+ try
+ {
+ rss.getData().set( ProjectToolsSession.SESSION_KEY, session );
+ result = repositorySystem.collectDependencies( rss, request );
+ }
+ catch ( final DependencyCollectionException e )
+ {
+ // TODO: Handle problem resolving POMs...
+ result = e.getResult();
+
+ // result.setDependencyGraph( e.getResult().getRoot() );
+ // result.setCollectionErrors( e.getResult().getExceptions() );
+ //
+ // throw new DependencyResolutionException( result, "Could not resolve dependencies for project "
+ // + project.getId() + ": " + e.getMessage(), e );
+ }
+ finally
+ {
+ rss.getData().set( ProjectToolsSession.SESSION_KEY, old );
+ }
+
+ final DependencyNode root = result.getRoot();
+ final DepGraphRootNode rootNode = depGraph.addRoot( root, project );
+
+ accumulator.resetForNextRun( root, rootNode );
+
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Adding collected dependencies to consolidated dependency graph..." );
+ }
+ }
+ result.getRoot().accept( accumulator );
+
+ }
+
+ return depGraph;
+ }
+
+ private static final class GraphAccumulator
+ implements DependencyVisitor
+ {
+ private final LinkedList<DependencyNode> parents = new LinkedList<DependencyNode>();
+
+ private final Set<Exclusion> exclusions = new HashSet<Exclusion>();
+
+ private final Set<Exclusion> lastExclusions = new HashSet<Exclusion>();
+
+ private final DependencyGraph depGraph;
+
+ private DependencyNode root;
+
+ private DepGraphRootNode rootNode;
+
+ private final DependencyFilter filter;
+
+ GraphAccumulator( final DependencyGraph depGraph, final DependencyFilter filter )
+ {
+ this.depGraph = depGraph;
+ this.filter = filter;
+ }
+
+ void resetForNextRun( final DependencyNode root, final DepGraphRootNode rootNode )
+ {
+ parents.clear();
+ this.root = root;
+ this.rootNode = rootNode;
+ exclusions.clear();
+ lastExclusions.clear();
+ }
+
+ @Override
+ public boolean visitEnter( final DependencyNode node )
+ {
+ if ( filter != null && !filter.accept( node, parents ) )
+ {
+ return false;
+ }
+
+ if ( node == root )
+ {
+ parents.addFirst( root );
+ return true;
+ }
+ else if ( node == null || node.getDependency() == null
+ || node.getDependency().getArtifact() == null )
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Invalid node: " + node );
+ }
+ }
+ return true;
+ }
+
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "START: dependency-processing for: " + node );
+ }
+ }
+
+ boolean result = false;
+ final Artifact artifact = node.getDependency().getArtifact();
+ if ( !excluded( artifact ) )
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Enabling resolution for: " + node );
+ }
+ }
+
+ final DependencyNode parent = parents.getFirst();
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Adding dependency from: " + parent + " to: " + node );
+ }
+ }
+
+ // TODO: don't traverse beyond this node if it's already been considered...though we still need to
+ // connect it
+ // to the parent node (see below).
+ result = !depGraph.contains( node );
+
+ // result = true;
+
+ if ( parent == root )
+ {
+ depGraph.addDependency( rootNode, node );
+ }
+ else
+ {
+ depGraph.addDependency( parent, node );
+ }
+
+ if ( node.getDependency().getExclusions() != null )
+ {
+ for ( final Exclusion exclusion : node.getDependency().getExclusions() )
+ {
+ if ( exclusions.add( exclusion ) )
+ {
+ lastExclusions.add( exclusion );
+ }
+ }
+ }
+
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Pushing node: " + node + " onto parents stack." );
+ }
+ }
+ parents.addFirst( node );
+
+ final StringBuilder builder = new StringBuilder();
+ for ( int i = 0; i < parents.size(); i++ )
+ {
+ builder.append( " " );
+ }
+ builder.append( ">>>" );
+ builder.append( node );
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( builder.toString() );
+ }
+ }
+ }
+ else
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "DISABLING resolution for: " + node );
+ }
+ }
+ }
+
+ if ( node != null && !node.getRelocations().isEmpty() )
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "The artifact " + node.getRelocations().get( 0 )
+ + " has been relocated to " + node.getDependency().getArtifact() );
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private boolean excluded( final Artifact artifact )
+ {
+ for ( final Exclusion exclusion : exclusions )
+ {
+ if ( match( exclusion.getGroupId(), artifact.getGroupId() )
+ && match( exclusion.getArtifactId(), artifact.getArtifactId() )
+ && match( exclusion.getExtension(), artifact.getExtension() )
+ && match( exclusion.getClassifier(), artifact.getClassifier() ) )
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "EXCLUDED: " + artifact );
+ }
+ }
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean match( final String excluded, final String check )
+ {
+ return "*".equals( excluded ) || excluded.equals( check );
+ }
+
+ @Override
+ public boolean visitLeave( final DependencyNode node )
+ {
+ if ( node == null || parents.isEmpty() )
+ {
+ return true;
+ }
+
+ if ( node == parents.getFirst() )
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "Removing exclusions from last node: " + node );
+ }
+ }
+
+ for ( final Exclusion exclusion : lastExclusions )
+ {
+ exclusions.remove( exclusion );
+ }
+
+ lastExclusions.clear();
+
+ final StringBuilder builder = new StringBuilder();
+ for ( int i = 0; i < parents.size(); i++ )
+ {
+ builder.append( " " );
+ }
+ builder.append( "<<<" );
+ builder.append( node );
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( builder.toString() );
+ }
+ }
+
+ parents.removeFirst();
+ }
+ else
+ {
+ final int idx = parents.indexOf( node );
+ if ( idx > -1 )
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "TRAVERSAL LEAK. Removing " + ( idx + 1 )
+ + " unaccounted-for parents that have finished traversal." );
+ }
+ }
+
+ for ( int i = 0; i <= idx; i++ )
+ {
+ parents.removeFirst();
+ }
+ }
+ }
+
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "END: dependency-processing for: " + node );
+ }
+ }
+
+ return true;
+ }
+
+ }
+
+ private static final class DependencyResolveWorker
+ implements Runnable
+ {
+
+ private final DepGraphNode depState;
+
+ private final RepositorySystemSession session;
+
+ private final RepositorySystem repositorySystem;
+
+ private ArtifactResult result;
+
+ private CountDownLatch latch;
+
+ DependencyResolveWorker( final DepGraphNode depState,
+ final RepositorySystemSession session,
+ final RepositorySystem repositorySystem )
+ {
+ this.depState = depState;
+ this.session = session;
+ this.repositorySystem = repositorySystem;
+ }
+
+ void setLatch( final CountDownLatch latch )
+ {
+ this.latch = latch;
+ }
+
+ @Override
+ public void run()
+ {
+ final Artifact artifact = depState.getLatestArtifact();
+
+ try
+ {
+ final ArtifactRequest request =
+ new ArtifactRequest(
+ artifact,
+ new ArrayList<RemoteRepository>(
+ depState.getRemoteRepositories() ),
+ "project" );
+
+ result = new ArtifactResult( request );
+ if ( validateForResolution() )
+ {
+ try
+ {
+ // if ( LOGGER.isDebugEnabled() )
+ {
+ if ( LOGGER.isDebugEnabled() )
+ {
+ LOGGER.debug( "RESOLVE: " + artifact );
+ }
+ }
+
+ result = repositorySystem.resolveArtifact( session, request );
+ }
+ catch ( final ArtifactResolutionException e )
+ {
+ result.addException( e );
+ }
+ }
+ }
+ finally
+ {
+ // final Runtime r = Runtime.getRuntime();
+ //
+ // final long MB = 1024 * 1024;
+ //
+ // System.out.println( "Memory status: " + ( r.totalMemory() - r.freeMemory() ) / MB + "M/"
+ // + r.totalMemory() / MB + "M" );
+
+ // FIXME: Do we need to detect whether resolution already happened for this artifact before we try to
+ // resolve it
+ // again??
+ depState.merge( result );
+ if ( latch != null )
+ {
+ latch.countDown();
+ }
+ }
+ }
+
+ private boolean validateForResolution()
+ {
+ boolean valid = true;
+ if ( session == null )
+ {
+ result.addException( new IllegalArgumentException( "Cannot resolve dependency: "
+ + depState.getLatestArtifact() + ", RepositorySystemSession has not been set!" ) );
+
+ valid = false;
+ }
+
+ if ( repositorySystem == null )
+ {
+ result.addException( new IllegalArgumentException( "Cannot resolve dependency: "
+ + depState.getLatestArtifact() + ", RepositorySystem has not been set!" ) );
+
+ valid = false;
+ }
+
+ return valid;
+ }
+ }
+
+}
Propchange: maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/DependencyGraphResolver.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/DisconnectedDepNode.java
URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/DisconnectedDepNode.java?rev=1161723&view=auto
==============================================================================
--- maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/DisconnectedDepNode.java (added)
+++ maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/DisconnectedDepNode.java Thu Aug 25 20:03:54 2011
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+package org.apache.maven.mae.depgraph.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.sonatype.aether.artifact.Artifact;
+import org.sonatype.aether.graph.Dependency;
+import org.sonatype.aether.graph.DependencyNode;
+import org.sonatype.aether.graph.DependencyVisitor;
+import org.sonatype.aether.repository.RemoteRepository;
+import org.sonatype.aether.version.Version;
+import org.sonatype.aether.version.VersionConstraint;
+
+final class DisconnectedDepNode
+ implements DependencyNode
+{
+
+ private final DependencyNode delegate;
+
+ DisconnectedDepNode( final DependencyNode delegate )
+ {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public List<DependencyNode> getChildren()
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean accept( final DependencyVisitor visitor )
+ {
+ return false;
+ }
+
+ @Override
+ public Dependency getDependency()
+ {
+ return delegate.getDependency();
+ }
+
+ @Override
+ public void setArtifact( final Artifact artifact )
+ {
+ delegate.setArtifact( artifact );
+ }
+
+ @Override
+ public List<Artifact> getRelocations()
+ {
+ return delegate.getRelocations();
+ }
+
+ @Override
+ public Collection<Artifact> getAliases()
+ {
+ return delegate.getAliases();
+ }
+
+ @Override
+ public VersionConstraint getVersionConstraint()
+ {
+ return delegate.getVersionConstraint();
+ }
+
+ @Override
+ public Version getVersion()
+ {
+ return delegate.getVersion();
+ }
+
+ @Override
+ public void setScope( final String scope )
+ {
+ delegate.setScope( scope );
+ }
+
+ @Override
+ public String getPremanagedVersion()
+ {
+ return delegate.getPremanagedVersion();
+ }
+
+ @Override
+ public String getPremanagedScope()
+ {
+ return delegate.getPremanagedScope();
+ }
+
+ @Override
+ public List<RemoteRepository> getRepositories()
+ {
+ return delegate.getRepositories();
+ }
+
+ @Override
+ public String getRequestContext()
+ {
+ return delegate.getRequestContext();
+ }
+
+ @Override
+ public void setRequestContext( final String context )
+ {
+ delegate.setRequestContext( context );
+ }
+
+ @Override
+ public Map<Object, Object> getData()
+ {
+ return delegate.getData();
+ }
+
+ @Override
+ public void setData( final Object key, final Object value )
+ {
+ delegate.setData( key, value );
+ }
+
+}
Propchange: maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/DisconnectedDepNode.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/FlexibleScopeDependencySelector.java
URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/FlexibleScopeDependencySelector.java?rev=1161723&view=auto
==============================================================================
--- maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/FlexibleScopeDependencySelector.java (added)
+++ maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/FlexibleScopeDependencySelector.java Thu Aug 25 20:03:54 2011
@@ -0,0 +1,166 @@
+package org.apache.maven.mae.depgraph.impl;
+
+/*******************************************************************************
+ * Copyright (c) 2010-2011 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Apache License v2.0 which accompanies this distribution.
+ * The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * The Apache License v2.0 is available at
+ * http://www.apache.org/licenses/LICENSE-2.0.html
+ * You may elect to redistribute this code under either of these licenses.
+ *******************************************************************************/
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.sonatype.aether.collection.DependencyCollectionContext;
+import org.sonatype.aether.collection.DependencySelector;
+import org.sonatype.aether.graph.Dependency;
+
+/**
+ * A dependency selector that filters transitive dependencies based on their scope. Direct dependencies are always
+ * included regardless of their scope. <em>Note:</em> This filter does not assume any relationships between the scopes.
+ * In particular, the filter is not aware of scopes that logically include other scopes.
+ *
+ * @author Benjamin Bentmann
+ * @see Dependency#getScope()
+ */
+public class FlexibleScopeDependencySelector
+ implements DependencySelector
+{
+
+ private boolean transitive;
+
+ private final Set<String> included;
+
+ private final Set<String> excluded;
+
+ public FlexibleScopeDependencySelector()
+ {
+ included = new HashSet<String>();
+ excluded = new HashSet<String>();
+ }
+
+ /**
+ * Creates a new selector using the specified includes and excludes.
+ *
+ * @param included The set of scopes to include, may be {@code null} or empty to include any scope.
+ * @param excluded The set of scopes to exclude, may be {@code null} or empty to exclude no scope.
+ */
+ public FlexibleScopeDependencySelector( final Collection<String> included,
+ final Collection<String> excluded )
+ {
+ transitive = false;
+ if ( included != null )
+ {
+ this.included = new HashSet<String>();
+ this.included.addAll( included );
+ }
+ else
+ {
+ this.included = Collections.emptySet();
+ }
+ if ( excluded != null )
+ {
+ this.excluded = new HashSet<String>();
+ this.excluded.addAll( excluded );
+ }
+ else
+ {
+ this.excluded = Collections.emptySet();
+ }
+ }
+
+ /**
+ * Creates a new selector using the specified excludes.
+ *
+ * @param excluded The set of scopes to exclude, may be {@code null} or empty to exclude no scope.
+ */
+ public FlexibleScopeDependencySelector( final String... excluded )
+ {
+ this( null, Arrays.asList( excluded ) );
+ }
+
+ private FlexibleScopeDependencySelector( final boolean transitive,
+ final Collection<String> included,
+ final Collection<String> excluded )
+ {
+ this.transitive = transitive;
+ this.included = included == null ? null : new HashSet<String>( included );
+ this.excluded = excluded == null ? null : new HashSet<String>( excluded );
+ }
+
+ @Override
+ public boolean selectDependency( final Dependency dependency )
+ {
+ if ( !transitive )
+ {
+ return true;
+ }
+
+ String scope = dependency.getScope();
+ return ( included.isEmpty() || included.contains( scope ) )
+ && ( excluded.isEmpty() || !excluded.contains( scope ) );
+ }
+
+ @Override
+ public DependencySelector deriveChildSelector( final DependencyCollectionContext context )
+ {
+ if ( this.transitive || context.getDependency() == null )
+ {
+ return this;
+ }
+
+ return new FlexibleScopeDependencySelector( true, included, excluded );
+ }
+
+ @Override
+ public boolean equals( final Object obj )
+ {
+ if ( this == obj )
+ {
+ return true;
+ }
+ else if ( null == obj || !getClass().equals( obj.getClass() ) )
+ {
+ return false;
+ }
+
+ FlexibleScopeDependencySelector that = (FlexibleScopeDependencySelector) obj;
+ return transitive == that.transitive && included.equals( that.included )
+ && excluded.equals( that.excluded );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hash = 17;
+ hash = hash * 31 + ( transitive ? 1 : 0 );
+ hash = hash * 31 + included.hashCode();
+ hash = hash * 31 + excluded.hashCode();
+ return hash;
+ }
+
+ public FlexibleScopeDependencySelector includeScope( final String scope )
+ {
+ included.add( scope );
+ return this;
+ }
+
+ public FlexibleScopeDependencySelector excludeScope( final String scope )
+ {
+ excluded.add( scope );
+ return this;
+ }
+
+ public FlexibleScopeDependencySelector setTransitive( final boolean transitive )
+ {
+ this.transitive = transitive;
+ return this;
+ }
+}
Propchange: maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/FlexibleScopeDependencySelector.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/collect/BareBonesDependencyCollector.java
URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/collect/BareBonesDependencyCollector.java?rev=1161723&view=auto
==============================================================================
--- maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/collect/BareBonesDependencyCollector.java (added)
+++ maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/collect/BareBonesDependencyCollector.java Thu Aug 25 20:03:54 2011
@@ -0,0 +1,713 @@
+package org.apache.maven.mae.depgraph.impl.collect;
+
+/*******************************************************************************
+ * Copyright (c) 2010-2011 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Apache License v2.0 which accompanies this distribution.
+ * The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * The Apache License v2.0 is available at
+ * http://www.apache.org/licenses/LICENSE-2.0.html
+ * You may elect to redistribute this code under either of these licenses.
+ *******************************************************************************/
+
+import static org.sonatype.aether.util.artifact.ArtifacIdUtils.toId;
+
+import org.apache.log4j.Logger;
+import org.apache.maven.mae.project.session.ProjectToolsSession;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.sonatype.aether.RepositoryException;
+import org.sonatype.aether.RepositorySystemSession;
+import org.sonatype.aether.RequestTrace;
+import org.sonatype.aether.artifact.Artifact;
+import org.sonatype.aether.artifact.ArtifactType;
+import org.sonatype.aether.artifact.ArtifactTypeRegistry;
+import org.sonatype.aether.collection.CollectRequest;
+import org.sonatype.aether.collection.CollectResult;
+import org.sonatype.aether.collection.DependencyCollectionContext;
+import org.sonatype.aether.collection.DependencyCollectionException;
+import org.sonatype.aether.collection.DependencyGraphTransformationContext;
+import org.sonatype.aether.collection.DependencyGraphTransformer;
+import org.sonatype.aether.collection.DependencyManagement;
+import org.sonatype.aether.collection.DependencyManager;
+import org.sonatype.aether.collection.DependencySelector;
+import org.sonatype.aether.collection.DependencyTraverser;
+import org.sonatype.aether.graph.Dependency;
+import org.sonatype.aether.graph.DependencyFilter;
+import org.sonatype.aether.graph.DependencyNode;
+import org.sonatype.aether.impl.ArtifactDescriptorReader;
+import org.sonatype.aether.impl.DependencyCollector;
+import org.sonatype.aether.impl.RemoteRepositoryManager;
+import org.sonatype.aether.impl.VersionRangeResolver;
+import org.sonatype.aether.impl.internal.DefaultDependencyCollector;
+import org.sonatype.aether.repository.ArtifactRepository;
+import org.sonatype.aether.repository.RemoteRepository;
+import org.sonatype.aether.resolution.ArtifactDescriptorException;
+import org.sonatype.aether.resolution.ArtifactDescriptorRequest;
+import org.sonatype.aether.resolution.ArtifactDescriptorResult;
+import org.sonatype.aether.resolution.VersionRangeRequest;
+import org.sonatype.aether.resolution.VersionRangeResolutionException;
+import org.sonatype.aether.resolution.VersionRangeResult;
+import org.sonatype.aether.spi.locator.Service;
+import org.sonatype.aether.spi.locator.ServiceLocator;
+import org.sonatype.aether.util.DefaultRepositorySystemSession;
+import org.sonatype.aether.util.DefaultRequestTrace;
+import org.sonatype.aether.util.artifact.ArtifactProperties;
+import org.sonatype.aether.version.Version;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * {@link DependencyCollector} implementation based on {@link DefaultDependencyCollector}, but which uses a more
+ * aggressively graph-oriented approach. This centralizes and de-dupes references to {@link Artifact} and
+ * {@link RemoteRepository} instances, in order to reduce the memory consumption.
+ *
+ * @author Benjamin Bentmann
+ * @author John Casey
+ */
+@Component( role = DependencyCollector.class, hint = BareBonesDependencyCollector.HINT )
+public class BareBonesDependencyCollector
+ implements DependencyCollector, Service
+{
+
+ public static final String HINT = "bare-bones";
+
+ private static final Logger logger = Logger.getLogger( BareBonesDependencyCollector.class );
+
+ @Requirement
+ private RemoteRepositoryManager remoteRepositoryManager;
+
+ @Requirement
+ private ArtifactDescriptorReader descriptorReader;
+
+ @Requirement
+ private VersionRangeResolver versionRangeResolver;
+
+ public BareBonesDependencyCollector()
+ {
+ // enables default constructor
+ }
+
+ public BareBonesDependencyCollector( final Logger logger, final RemoteRepositoryManager remoteRepositoryManager,
+ final ArtifactDescriptorReader artifactDescriptorReader,
+ final VersionRangeResolver versionRangeResolver )
+ {
+ setRemoteRepositoryManager( remoteRepositoryManager );
+ setArtifactDescriptorReader( artifactDescriptorReader );
+ setVersionRangeResolver( versionRangeResolver );
+ }
+
+ @Override
+ public void initService( final ServiceLocator locator )
+ {
+ setRemoteRepositoryManager( locator.getService( RemoteRepositoryManager.class ) );
+ setArtifactDescriptorReader( locator.getService( ArtifactDescriptorReader.class ) );
+ setVersionRangeResolver( locator.getService( VersionRangeResolver.class ) );
+ }
+
+ public BareBonesDependencyCollector setRemoteRepositoryManager( final RemoteRepositoryManager remoteRepositoryManager )
+ {
+ if ( remoteRepositoryManager == null )
+ {
+ throw new IllegalArgumentException( "remote repository manager has not been specified" );
+ }
+ this.remoteRepositoryManager = remoteRepositoryManager;
+ return this;
+ }
+
+ public BareBonesDependencyCollector setArtifactDescriptorReader( final ArtifactDescriptorReader artifactDescriptorReader )
+ {
+ if ( artifactDescriptorReader == null )
+ {
+ throw new IllegalArgumentException( "artifact descriptor reader has not been specified" );
+ }
+ descriptorReader = artifactDescriptorReader;
+ return this;
+ }
+
+ public BareBonesDependencyCollector setVersionRangeResolver( final VersionRangeResolver versionRangeResolver )
+ {
+ if ( versionRangeResolver == null )
+ {
+ throw new IllegalArgumentException( "version range resolver has not been specified" );
+ }
+ this.versionRangeResolver = versionRangeResolver;
+ return this;
+ }
+
+ @Override
+ public CollectResult collectDependencies( RepositorySystemSession session, final CollectRequest request )
+ throws DependencyCollectionException
+ {
+ session = optimizeSession( session );
+
+ final RequestTrace trace = DefaultRequestTrace.newChild( request.getTrace(), request );
+
+ final CollectResult result = new CollectResult( request );
+
+ final ProjectToolsSession toolsSession =
+ (ProjectToolsSession) session.getData().get( ProjectToolsSession.SESSION_KEY );
+
+ DependencySelector depSelector = toolsSession == null ? null : toolsSession.getDependencySelector();
+ if ( depSelector == null )
+ {
+ depSelector = session.getDependencySelector();
+ }
+
+ final DependencyManager depManager = session.getDependencyManager();
+ final DependencyTraverser depTraverser = session.getDependencyTraverser();
+
+ Dependency root = request.getRoot();
+ List<RemoteRepository> repositories = request.getRepositories();
+ List<Dependency> dependencies = request.getDependencies();
+ List<Dependency> managedDependencies = request.getManagedDependencies();
+
+ final SlimDepGraph graph = new SlimDepGraph( session );
+ SlimDependencyEdge edge = null;
+ if ( root != null )
+ {
+ VersionRangeResult rangeResult;
+ try
+ {
+ final VersionRangeRequest rangeRequest =
+ new VersionRangeRequest( root.getArtifact(), request.getRepositories(), request.getRequestContext() );
+ rangeRequest.setTrace( trace );
+ rangeResult = versionRangeResolver.resolveVersionRange( session, rangeRequest );
+
+ if ( rangeResult.getVersions().isEmpty() )
+ {
+ throw new VersionRangeResolutionException( rangeResult, "No versions available for "
+ + root.getArtifact() + " within specified range" );
+ }
+ }
+ catch ( final VersionRangeResolutionException e )
+ {
+ result.addException( e );
+ throw new DependencyCollectionException( result );
+ }
+
+ final Version version = rangeResult.getVersions().get( rangeResult.getVersions().size() - 1 );
+ root = root.setArtifact( root.getArtifact().setVersion( version.toString() ) );
+
+ ArtifactDescriptorResult descriptorResult;
+ try
+ {
+ final ArtifactDescriptorRequest descriptorRequest = new ArtifactDescriptorRequest();
+ descriptorRequest.setArtifact( root.getArtifact() );
+ descriptorRequest.setRepositories( request.getRepositories() );
+ descriptorRequest.setRequestContext( request.getRequestContext() );
+ descriptorRequest.setTrace( trace );
+ if ( isLackingDescriptor( root.getArtifact() ) )
+ {
+ descriptorResult = new ArtifactDescriptorResult( descriptorRequest );
+ }
+ else
+ {
+ descriptorResult = descriptorReader.readArtifactDescriptor( session, descriptorRequest );
+ }
+ }
+ catch ( final ArtifactDescriptorException e )
+ {
+ result.addException( e );
+ throw new DependencyCollectionException( result );
+ }
+
+ root = root.setArtifact( descriptorResult.getArtifact() );
+
+ repositories =
+ remoteRepositoryManager.aggregateRepositories( session, repositories,
+ descriptorResult.getRepositories(), true );
+ dependencies = mergeDeps( dependencies, descriptorResult.getDependencies() );
+ managedDependencies = mergeDeps( managedDependencies, descriptorResult.getManagedDependencies() );
+
+ final SlimDependencyNode node = new SlimDependencyNode( toId( descriptorResult.getArtifact() ), graph );
+ node.setAliases( descriptorResult.getAliases() );
+ node.setRepositories( request.getRepositories() );
+
+ edge = new SlimDependencyEdge( node, graph );
+ edge.setDependency( root );
+ edge.setRequestContext( request.getRequestContext() );
+ edge.setRelocations( descriptorResult.getRelocations() );
+ edge.setVersionConstraint( rangeResult.getVersionConstraint() );
+ edge.setVersion( version );
+ }
+ else
+ {
+ edge = new SlimDependencyEdge( new SlimDependencyNode( SlimDependencyNode.UNKNOWN_ROOT_ID, graph ), graph );
+ }
+
+ result.setRoot( edge );
+
+ final boolean traverse = ( root == null ) || depTraverser.traverseDependency( root );
+
+ if ( traverse && !dependencies.isEmpty() )
+ {
+ final LinkedList<SlimDependencyEdge> edges = new LinkedList<SlimDependencyEdge>();
+ edges.addFirst( edge );
+
+ final DependencyCollectionContext context = new CollectionContext( session, root, managedDependencies );
+
+ final DepGraphCache pool = new DepGraphCache( session );
+ process( session, toolsSession, trace, result, edges, dependencies, repositories,
+ depSelector.deriveChildSelector( context ), depManager.deriveChildManager( context ),
+ depTraverser.deriveChildTraverser( context ), pool, graph );
+ }
+
+ final DependencyGraphTransformer transformer = session.getDependencyGraphTransformer();
+ try
+ {
+ final DependencyGraphTransformationContext context = new GraphTransformationContext( session );
+ result.setRoot( transformer.transformGraph( edge, context ) );
+ }
+ catch ( final RepositoryException e )
+ {
+ result.addException( e );
+ }
+
+ if ( !result.getExceptions().isEmpty() )
+ {
+ throw new DependencyCollectionException( result );
+ }
+
+ return result;
+ }
+
+ private RepositorySystemSession optimizeSession( final RepositorySystemSession session )
+ {
+ final DefaultRepositorySystemSession optimized = new DefaultRepositorySystemSession( session );
+ optimized.setArtifactTypeRegistry( new TypeRegistry( session ) );
+ return optimized;
+ }
+
+ private List<Dependency> mergeDeps( final List<Dependency> dominant, final List<Dependency> recessive )
+ {
+ List<Dependency> result;
+ if ( dominant == null || dominant.isEmpty() )
+ {
+ result = recessive;
+ }
+ else if ( recessive == null || recessive.isEmpty() )
+ {
+ result = dominant;
+ }
+ else
+ {
+ result = new ArrayList<Dependency>( dominant.size() + recessive.size() );
+ final Collection<String> ids = new HashSet<String>();
+ for ( final Dependency dependency : dominant )
+ {
+ ids.add( getId( dependency.getArtifact() ) );
+ result.add( dependency );
+ }
+ for ( final Dependency dependency : recessive )
+ {
+ if ( !ids.contains( getId( dependency.getArtifact() ) ) )
+ {
+ result.add( dependency );
+ }
+ }
+ }
+ return result;
+ }
+
+ private String getId( final Artifact a )
+ {
+ return a.getGroupId() + ':' + a.getArtifactId() + ':' + a.getClassifier() + ':' + a.getExtension();
+ }
+
+ private boolean process( final RepositorySystemSession session, final ProjectToolsSession toolsSession,
+ final RequestTrace trace, final CollectResult result,
+ final LinkedList<SlimDependencyEdge> edges, final List<Dependency> dependencies,
+ final List<RemoteRepository> repositories, final DependencySelector depSelector,
+ final DependencyManager depManager, final DependencyTraverser depTraverser,
+ final DepGraphCache pool, final SlimDepGraph graph )
+ throws DependencyCollectionException
+ {
+ boolean cycle = false;
+
+ final DependencyFilter filter = toolsSession == null ? null : toolsSession.getDependencyFilter();
+
+ nextDependency: for ( Dependency dependency : dependencies )
+ {
+ boolean disableVersionManagement = false;
+
+ List<Artifact> relocations = Collections.emptyList();
+
+ thisDependency: while ( true )
+ {
+ if ( !depSelector.selectDependency( dependency ) )
+ {
+ logger.warn( "SELECT - Excluding from dependency graph: " + dependency.getArtifact() );
+ continue nextDependency;
+ }
+
+ final DependencyManagement depMngt = depManager.manageDependency( dependency );
+ String premanagedVersion = null;
+ String premanagedScope = null;
+
+ if ( depMngt != null )
+ {
+ if ( depMngt.getVersion() != null && !disableVersionManagement )
+ {
+ final Artifact artifact = dependency.getArtifact();
+ premanagedVersion = artifact.getVersion();
+ dependency = dependency.setArtifact( artifact.setVersion( depMngt.getVersion() ) );
+ }
+ if ( depMngt.getProperties() != null )
+ {
+ final Artifact artifact = dependency.getArtifact();
+ dependency = dependency.setArtifact( artifact.setProperties( depMngt.getProperties() ) );
+ }
+ if ( depMngt.getScope() != null )
+ {
+ premanagedScope = dependency.getScope();
+ dependency = dependency.setScope( depMngt.getScope() );
+ }
+ if ( depMngt.getExclusions() != null )
+ {
+ dependency = dependency.setExclusions( depMngt.getExclusions() );
+ }
+ }
+ disableVersionManagement = false;
+
+ final boolean noDescriptor = isLackingDescriptor( dependency.getArtifact() );
+
+ final boolean traverse = !noDescriptor && depTraverser.traverseDependency( dependency );
+
+ VersionRangeResult rangeResult;
+ try
+ {
+ final VersionRangeRequest rangeRequest = new VersionRangeRequest();
+ rangeRequest.setArtifact( dependency.getArtifact() );
+ rangeRequest.setRepositories( repositories );
+ rangeRequest.setRequestContext( result.getRequest().getRequestContext() );
+ rangeRequest.setTrace( trace );
+
+ final Object key = pool.toKey( rangeRequest );
+ rangeResult = pool.getConstraint( key, rangeRequest );
+ if ( rangeResult == null )
+ {
+ rangeResult = versionRangeResolver.resolveVersionRange( session, rangeRequest );
+ pool.putConstraint( key, rangeResult );
+ }
+
+ if ( rangeResult.getVersions().isEmpty() )
+ {
+ throw new VersionRangeResolutionException( rangeResult, "No versions available for "
+ + dependency.getArtifact() + " within specified range" );
+ }
+ }
+ catch ( final VersionRangeResolutionException e )
+ {
+ result.addException( e );
+ continue nextDependency;
+ }
+
+ final List<Version> versions = new ArrayList<Version>( rangeResult.getVersions() );
+ Collections.reverse( versions );
+
+ for ( final Version version : versions )
+ {
+ final Artifact originalArtifact = dependency.getArtifact().setVersion( version.toString() );
+ Dependency d = dependency.setArtifact( originalArtifact );
+
+ ArtifactDescriptorResult descriptorResult;
+ try
+ {
+ final ArtifactDescriptorRequest descriptorRequest = new ArtifactDescriptorRequest();
+ descriptorRequest.setArtifact( d.getArtifact() );
+ descriptorRequest.setRepositories( repositories );
+ descriptorRequest.setRequestContext( result.getRequest().getRequestContext() );
+ descriptorRequest.setTrace( trace );
+
+ if ( noDescriptor )
+ {
+ descriptorResult = new ArtifactDescriptorResult( descriptorRequest );
+ }
+ else
+ {
+ final Object key = pool.toKey( descriptorRequest );
+ descriptorResult = pool.getDescriptor( key, descriptorRequest );
+ if ( descriptorResult == null )
+ {
+ descriptorResult = descriptorReader.readArtifactDescriptor( session, descriptorRequest );
+ pool.putDescriptor( key, descriptorResult );
+ }
+ }
+ }
+ catch ( final ArtifactDescriptorException e )
+ {
+ result.addException( e );
+ continue;
+ }
+
+ d = d.setArtifact( descriptorResult.getArtifact() );
+
+ if ( findDuplicate( edges, d.getArtifact() ) != null )
+ {
+ cycle = true;
+ continue nextDependency;
+ }
+
+ if ( !descriptorResult.getRelocations().isEmpty() )
+ {
+ relocations = descriptorResult.getRelocations();
+
+ disableVersionManagement =
+ originalArtifact.getGroupId().equals( d.getArtifact().getGroupId() )
+ && originalArtifact.getArtifactId().equals( d.getArtifact().getArtifactId() );
+
+ dependency = d;
+ continue thisDependency;
+ }
+
+ d = pool.intern( d.setArtifact( graph.intern( d.getArtifact() ) ) );
+
+ DependencySelector childSelector = null;
+ DependencyManager childManager = null;
+ DependencyTraverser childTraverser = null;
+ List<RemoteRepository> childRepos = null;
+ final String key = toId( d.getArtifact() );
+
+ boolean recurse = traverse && !descriptorResult.getDependencies().isEmpty();
+ if ( recurse )
+ {
+ final DependencyCollectionContext context =
+ new CollectionContext( session, d, descriptorResult.getManagedDependencies() );
+
+ childSelector = depSelector.deriveChildSelector( context );
+ childManager = depManager.deriveChildManager( context );
+ childTraverser = depTraverser.deriveChildTraverser( context );
+
+ childRepos =
+ remoteRepositoryManager.aggregateRepositories( session, repositories,
+ descriptorResult.getRepositories(), true );
+ }
+
+ List<RemoteRepository> repos;
+ final ArtifactRepository repo = rangeResult.getRepository( version );
+ if ( repo instanceof RemoteRepository )
+ {
+ repos = Collections.singletonList( (RemoteRepository) repo );
+ }
+ else if ( repo == null )
+ {
+ repos = repositories;
+ }
+ else
+ {
+ repos = Collections.emptyList();
+ }
+
+ SlimDependencyNode child = graph.getNode( key );
+ if ( child == null )
+ {
+ child = new SlimDependencyNode( key, graph );
+ child.setAliases( descriptorResult.getAliases() );
+ child.setRepositories( repos );
+ }
+ else
+ {
+ recurse = false;
+
+ if ( repos.size() < child.getRepositories().size() )
+ {
+ child.setRepositories( repos );
+ }
+ }
+
+ final SlimDependencyNode node = edges.getFirst().getTo();
+
+ final SlimDependencyEdge edge = new SlimDependencyEdge( node, child, graph );
+ edge.setDependency( d );
+ edge.setScope( d.getScope() );
+ edge.setPremanagedScope( premanagedScope );
+ edge.setPremanagedVersion( premanagedVersion );
+ edge.setRelocations( relocations );
+ edge.setVersionConstraint( rangeResult.getVersionConstraint() );
+ edge.setVersion( version );
+ edge.setRequestContext( result.getRequest().getRequestContext() );
+
+ final List<DependencyNode> parents = new ArrayList<DependencyNode>();
+ parents.add( edges.getFirst() );
+
+ if ( filter != null && !filter.accept( edge, parents ) )
+ {
+ logger.warn( "FILTER - Excluding from dependency graph: " + edge.getDependency().getArtifact() );
+ graph.removeEdge( edge );
+ continue nextDependency;
+ }
+
+ if ( recurse )
+ {
+ edges.addFirst( edge );
+
+ if ( process( session, toolsSession, trace, result, edges, descriptorResult.getDependencies(), childRepos,
+ childSelector, childManager, childTraverser, pool, graph ) )
+ {
+ cycle = true;
+ continue nextDependency;
+ }
+
+ edges.removeFirst();
+ }
+ }
+
+ break;
+ }
+ }
+
+ return cycle;
+ }
+
+ private SlimDependencyEdge findDuplicate( final List<SlimDependencyEdge> edges, final Artifact artifact )
+ {
+ for ( final SlimDependencyEdge edge : edges )
+ {
+ final Dependency dependency = edge.getDependency();
+ if ( dependency == null )
+ {
+ break;
+ }
+
+ final Artifact a = dependency.getArtifact();
+ if ( !a.getArtifactId().equals( artifact.getArtifactId() ) )
+ {
+ continue;
+ }
+ if ( !a.getGroupId().equals( artifact.getGroupId() ) )
+ {
+ continue;
+ }
+ if ( !a.getBaseVersion().equals( artifact.getBaseVersion() ) )
+ {
+ continue;
+ }
+ if ( !a.getExtension().equals( artifact.getExtension() ) )
+ {
+ continue;
+ }
+ if ( !a.getClassifier().equals( artifact.getClassifier() ) )
+ {
+ continue;
+ }
+
+ return edge;
+ }
+
+ return null;
+ }
+
+ private boolean isLackingDescriptor( final Artifact artifact )
+ {
+ return artifact.getProperty( ArtifactProperties.LOCAL_PATH, null ) != null;
+ }
+
+ private static final class CollectionContext
+ implements DependencyCollectionContext
+ {
+
+ private final RepositorySystemSession session;
+
+ private final Dependency dependency;
+
+ private final List<Dependency> managedDependencies;
+
+ CollectionContext( final RepositorySystemSession session, final Dependency dependency,
+ final List<Dependency> managedDependencies )
+ {
+ this.session = session;
+ this.dependency = dependency;
+ this.managedDependencies = managedDependencies;
+ }
+
+ @Override
+ public RepositorySystemSession getSession()
+ {
+ return session;
+ }
+
+ @Override
+ public Dependency getDependency()
+ {
+ return dependency;
+ }
+
+ @Override
+ public List<Dependency> getManagedDependencies()
+ {
+ return managedDependencies;
+ }
+
+ }
+
+ private static final class GraphTransformationContext
+ implements DependencyGraphTransformationContext
+ {
+
+ private final RepositorySystemSession session;
+
+ private final Map<Object, Object> ctx = new HashMap<Object, Object>();
+
+ GraphTransformationContext( final RepositorySystemSession session )
+ {
+ this.session = session;
+ }
+
+ @Override
+ public RepositorySystemSession getSession()
+ {
+ return session;
+ }
+
+ @Override
+ public Object get( final Object key )
+ {
+ return ctx.get( key );
+ }
+
+ @Override
+ public Object put( final Object key, final Object value )
+ {
+ return ctx.put( key, value );
+ }
+
+ }
+
+ private static final class TypeRegistry
+ implements ArtifactTypeRegistry
+ {
+ private final ArtifactTypeRegistry delegate;
+
+ private final Map<String, ArtifactType> types = new HashMap<String, ArtifactType>();
+
+ TypeRegistry( final RepositorySystemSession session )
+ {
+ delegate = session.getArtifactTypeRegistry();
+ }
+
+ @Override
+ public ArtifactType get( final String typeId )
+ {
+ ArtifactType type = types.get( typeId );
+
+ if ( type == null )
+ {
+ type = delegate.get( typeId );
+ types.put( typeId, type );
+ }
+
+ return type;
+ }
+ }
+
+}
Propchange: maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/collect/BareBonesDependencyCollector.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/collect/DepGraphCache.java
URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/collect/DepGraphCache.java?rev=1161723&view=auto
==============================================================================
--- maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/collect/DepGraphCache.java (added)
+++ maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/collect/DepGraphCache.java Thu Aug 25 20:03:54 2011
@@ -0,0 +1,511 @@
+package org.apache.maven.mae.depgraph.impl.collect;
+
+/*******************************************************************************
+ * Copyright (c) 2010-2011 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Apache License v2.0 which accompanies this distribution.
+ * The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * The Apache License v2.0 is available at
+ * http://www.apache.org/licenses/LICENSE-2.0.html
+ * You may elect to redistribute this code under either of these licenses.
+ *******************************************************************************/
+
+import static org.sonatype.aether.util.artifact.ArtifacIdUtils.toId;
+
+import org.sonatype.aether.RepositoryCache;
+import org.sonatype.aether.RepositorySystemSession;
+import org.sonatype.aether.artifact.Artifact;
+import org.sonatype.aether.collection.DependencyManager;
+import org.sonatype.aether.collection.DependencySelector;
+import org.sonatype.aether.collection.DependencyTraverser;
+import org.sonatype.aether.graph.Dependency;
+import org.sonatype.aether.repository.ArtifactRepository;
+import org.sonatype.aether.repository.RemoteRepository;
+import org.sonatype.aether.resolution.ArtifactDescriptorRequest;
+import org.sonatype.aether.resolution.ArtifactDescriptorResult;
+import org.sonatype.aether.resolution.VersionRangeRequest;
+import org.sonatype.aether.resolution.VersionRangeResult;
+import org.sonatype.aether.version.Version;
+import org.sonatype.aether.version.VersionConstraint;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * Based on DataPool in aether-impl, this cache provides the ability to clear the cache in the
+ * {@link RepositorySystemSession}, along with tracking for {@link RemoteRepository} instances, and NOT including
+ * tracking for nodes.
+ *
+ * @author Benjamin Bentmann
+ * @author John Casey
+ */
+public final class DepGraphCache
+{
+
+ private static final String ARTIFACT_POOL = DepGraphCache.class.getName() + "$Artifact";
+
+ private static final String DEPENDENCY_POOL = DepGraphCache.class.getName() + "$Dependency";
+
+ private static final String REPOSITORY_POOL = DepGraphCache.class.getName() + "$Repository";
+
+ private static final String DESCRIPTORS = DepGraphCache.class.getName() + "$Descriptors";
+
+ private ObjectPool<String, Artifact> artifacts;
+
+ private ObjectPool<Dependency, Dependency> dependencies;
+
+ private ObjectPool<RemoteRepository, RemoteRepository> repositories;
+
+ private Map<Object, Descriptor> descriptors;
+
+ private final Map<Object, Constraint> constraints = new WeakHashMap<Object, Constraint>();
+
+ @SuppressWarnings( "unchecked" )
+ DepGraphCache( final RepositorySystemSession session )
+ {
+ final RepositoryCache cache = session.getCache();
+
+ if ( cache != null )
+ {
+ artifacts = (ObjectPool<String, Artifact>) cache.get( session, ARTIFACT_POOL );
+ dependencies = (ObjectPool<Dependency, Dependency>) cache.get( session, DEPENDENCY_POOL );
+ repositories = (ObjectPool<RemoteRepository, RemoteRepository>) cache.get( session, REPOSITORY_POOL );
+ descriptors = (Map<Object, Descriptor>) cache.get( session, DESCRIPTORS );
+ }
+
+ if ( artifacts == null )
+ {
+ artifacts = new ObjectPool<String, Artifact>();
+ if ( cache != null )
+ {
+ cache.put( session, ARTIFACT_POOL, artifacts );
+ }
+ }
+
+ if ( dependencies == null )
+ {
+ dependencies = new ObjectPool<Dependency, Dependency>();
+ if ( cache != null )
+ {
+ cache.put( session, DEPENDENCY_POOL, dependencies );
+ }
+ }
+
+ if ( repositories == null )
+ {
+ repositories = new ObjectPool<RemoteRepository, RemoteRepository>();
+ if ( cache != null )
+ {
+ cache.put( session, DEPENDENCY_POOL, repositories );
+ }
+ }
+
+ if ( descriptors == null )
+ {
+ descriptors = Collections.synchronizedMap( new WeakHashMap<Object, Descriptor>( 256 ) );
+ if ( cache != null )
+ {
+ cache.put( session, DESCRIPTORS, descriptors );
+ }
+ }
+ }
+
+ public static void clear( final RepositorySystemSession session )
+ {
+ synchronized ( session )
+ {
+ final RepositoryCache cache = session.getCache();
+
+ if ( cache != null )
+ {
+ cache.put( session, ARTIFACT_POOL, null );
+ cache.put( session, DEPENDENCY_POOL, null );
+ cache.put( session, REPOSITORY_POOL, null );
+ cache.put( session, DESCRIPTORS, null );
+ }
+ }
+ }
+
+ synchronized void setArtifact( final Artifact artifact )
+ {
+ final String id = toId( artifact );
+ artifacts.set( id, artifact );
+ }
+
+ Artifact getArtifact( final String key )
+ {
+ return artifacts.get( key );
+ }
+
+ Artifact intern( final Artifact artifact )
+ {
+ return artifacts.intern( toId( artifact ), artifact );
+ }
+
+ Dependency intern( final Dependency dependency )
+ {
+ return dependencies.intern( dependency, dependency );
+ }
+
+ RemoteRepository intern( final RemoteRepository repo )
+ {
+ return repositories.intern( repo, repo );
+ }
+
+ Object toKey( final ArtifactDescriptorRequest request )
+ {
+ return request.getArtifact();
+ }
+
+ ArtifactDescriptorResult getDescriptor( final Object key, final ArtifactDescriptorRequest request )
+ {
+ final Descriptor descriptor = descriptors.get( key );
+ if ( descriptor != null )
+ {
+ return descriptor.toResult( request );
+ }
+ return null;
+ }
+
+ void putDescriptor( final Object key, final ArtifactDescriptorResult result )
+ {
+ descriptors.put( key, new Descriptor( result ) );
+ }
+
+ Object toKey( final VersionRangeRequest request )
+ {
+ return new ConstraintKey( request );
+ }
+
+ VersionRangeResult getConstraint( final Object key, final VersionRangeRequest request )
+ {
+ final Constraint constraint = constraints.get( key );
+ if ( constraint != null )
+ {
+ return constraint.toResult( request );
+ }
+ return null;
+ }
+
+ void putConstraint( final Object key, final VersionRangeResult result )
+ {
+ constraints.put( key, new Constraint( result ) );
+ }
+
+ Object toKey( final Artifact artifact, final List<RemoteRepository> repositories )
+ {
+ return new NodeKey( artifact, repositories );
+ }
+
+ Object toKey( final Artifact artifact, final List<RemoteRepository> repositories,
+ final DependencySelector selector, final DependencyManager manager,
+ final DependencyTraverser traverser )
+ {
+ return new GraphKey( artifact, repositories, selector, manager, traverser );
+ }
+
+ static class Descriptor
+ {
+
+ final Artifact artifact;
+
+ final Map<String, Object> properties;
+
+ final List<Artifact> relocations;
+
+ final List<RemoteRepository> repositories;
+
+ final List<Dependency> dependencies;
+
+ final List<Dependency> managedDependencies;
+
+ public Descriptor( final ArtifactDescriptorResult result )
+ {
+ artifact = result.getArtifact();
+ properties = result.getProperties();
+ relocations = result.getRelocations();
+ dependencies = result.getDependencies();
+ managedDependencies = result.getManagedDependencies();
+ repositories = clone( result.getRepositories() );
+ }
+
+ public ArtifactDescriptorResult toResult( final ArtifactDescriptorRequest request )
+ {
+ final ArtifactDescriptorResult result = new ArtifactDescriptorResult( request );
+ result.setArtifact( artifact );
+ result.setProperties( properties );
+ result.setRelocations( relocations );
+ result.setDependencies( dependencies );
+ result.setManagedDependencies( dependencies );
+ result.setRepositories( clone( repositories ) );
+ return result;
+ }
+
+ private static List<RemoteRepository> clone( final List<RemoteRepository> repositories )
+ {
+ final List<RemoteRepository> clones = new ArrayList<RemoteRepository>( repositories.size() );
+ for ( final RemoteRepository repository : repositories )
+ {
+ final RemoteRepository clone = new RemoteRepository( repository );
+ clone.setMirroredRepositories( new ArrayList<RemoteRepository>( repository.getMirroredRepositories() ) );
+ clones.add( clone );
+ }
+ return clones;
+ }
+
+ }
+
+ static class Constraint
+ {
+
+ final Map<Version, ArtifactRepository> repositories;
+
+ final VersionConstraint versionConstraint;
+
+ public Constraint( final VersionRangeResult result )
+ {
+ versionConstraint = result.getVersionConstraint();
+ repositories = new LinkedHashMap<Version, ArtifactRepository>();
+ for ( final Version version : result.getVersions() )
+ {
+ repositories.put( version, result.getRepository( version ) );
+ }
+ }
+
+ public VersionRangeResult toResult( final VersionRangeRequest request )
+ {
+ final VersionRangeResult result = new VersionRangeResult( request );
+ for ( final Map.Entry<Version, ArtifactRepository> entry : repositories.entrySet() )
+ {
+ result.addVersion( entry.getKey() );
+ result.setRepository( entry.getKey(), entry.getValue() );
+ }
+ result.setVersionConstraint( versionConstraint );
+ return result;
+ }
+
+ }
+
+ static class ConstraintKey
+ {
+
+ private final Artifact artifact;
+
+ private final List<RemoteRepository> repositories;
+
+ private final int hashCode;
+
+ public ConstraintKey( final VersionRangeRequest request )
+ {
+ artifact = request.getArtifact();
+ repositories = request.getRepositories();
+ hashCode = artifact.hashCode();
+ }
+
+ @Override
+ public boolean equals( final Object obj )
+ {
+ if ( obj == this )
+ {
+ return true;
+ }
+ else if ( !( obj instanceof ConstraintKey ) )
+ {
+ return false;
+ }
+ final ConstraintKey that = (ConstraintKey) obj;
+ return artifact.equals( that.artifact ) && equals( repositories, that.repositories );
+ }
+
+ private static boolean equals( final Collection<RemoteRepository> repos1,
+ final Collection<RemoteRepository> repos2 )
+ {
+ if ( repos1.size() != repos2.size() )
+ {
+ return false;
+ }
+ for ( Iterator<RemoteRepository> it1 = repos1.iterator(), it2 = repos2.iterator(); it1.hasNext(); )
+ {
+ final RemoteRepository repo1 = it1.next();
+ final RemoteRepository repo2 = it2.next();
+ if ( repo1.isRepositoryManager() != repo2.isRepositoryManager() )
+ {
+ return false;
+ }
+ if ( repo1.isRepositoryManager() )
+ {
+ if ( !equals( repo1.getMirroredRepositories(), repo2.getMirroredRepositories() ) )
+ {
+ return false;
+ }
+ }
+ else if ( !repo1.getUrl().equals( repo2.getUrl() ) )
+ {
+ return false;
+ }
+ else if ( repo1.getPolicy( true ).isEnabled() != repo2.getPolicy( true ).isEnabled() )
+ {
+ return false;
+ }
+ else if ( repo1.getPolicy( false ).isEnabled() != repo2.getPolicy( false ).isEnabled() )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return hashCode;
+ }
+
+ }
+
+ static class NodeKey
+ {
+
+ private final Artifact artifact;
+
+ private final List<RemoteRepository> repositories;
+
+ private final int hashCode;
+
+ public NodeKey( final Artifact artifact, final List<RemoteRepository> repositories )
+ {
+ this.artifact = artifact;
+ this.repositories = repositories;
+
+ int hash = 17;
+ hash = hash * 31 + artifact.hashCode();
+ hash = hash * 31 + repositories.hashCode();
+ hashCode = hash;
+ }
+
+ @Override
+ public boolean equals( final Object obj )
+ {
+ if ( obj == this )
+ {
+ return true;
+ }
+ else if ( !( obj instanceof NodeKey ) )
+ {
+ return false;
+ }
+ final NodeKey that = (NodeKey) obj;
+ return artifact.equals( that.artifact ) && repositories.equals( that.repositories );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return hashCode;
+ }
+
+ }
+
+ static class GraphKey
+ {
+
+ private final Artifact artifact;
+
+ private final List<RemoteRepository> repositories;
+
+ private final DependencySelector selector;
+
+ private final DependencyManager manager;
+
+ private final DependencyTraverser traverser;
+
+ private final int hashCode;
+
+ public GraphKey( final Artifact artifact, final List<RemoteRepository> repositories,
+ final DependencySelector selector, final DependencyManager manager,
+ final DependencyTraverser traverser )
+ {
+ this.artifact = artifact;
+ this.repositories = repositories;
+ this.selector = selector;
+ this.manager = manager;
+ this.traverser = traverser;
+
+ int hash = 17;
+ hash = hash * 31 + artifact.hashCode();
+ hash = hash * 31 + repositories.hashCode();
+ hash = hash * 31 + selector.hashCode();
+ hash = hash * 31 + manager.hashCode();
+ hash = hash * 31 + traverser.hashCode();
+ hashCode = hash;
+ }
+
+ @Override
+ public boolean equals( final Object obj )
+ {
+ if ( obj == this )
+ {
+ return true;
+ }
+ else if ( !( obj instanceof GraphKey ) )
+ {
+ return false;
+ }
+ final GraphKey that = (GraphKey) obj;
+ return artifact.equals( that.artifact ) && repositories.equals( that.repositories )
+ && selector.equals( that.selector ) && manager.equals( that.manager )
+ && traverser.equals( that.traverser );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return hashCode;
+ }
+
+ }
+
+ static final class ObjectPool<K, V>
+ {
+
+ private final Map<K, WeakReference<V>> objects = new WeakHashMap<K, WeakReference<V>>( 256 );
+
+ synchronized V intern( final K id, final V object )
+ {
+ final WeakReference<V> pooledRef = objects.get( id );
+ if ( pooledRef != null )
+ {
+ final V pooled = pooledRef.get();
+ if ( pooled != null )
+ {
+ return pooled;
+ }
+ }
+
+ objects.put( id, new WeakReference<V>( object ) );
+ return object;
+ }
+
+ void set( final K id, final V object )
+ {
+ objects.put( id, new WeakReference<V>( object ) );
+ }
+
+ V get( final K id )
+ {
+ final WeakReference<V> ref = objects.get( id );
+ return ref == null ? null : ref.get();
+ }
+
+ }
+
+}
Propchange: maven/sandbox/trunk/mae/mae-components/mae-dependency-grapher/src/main/java/org/apache/maven/mae/depgraph/impl/collect/DepGraphCache.java
------------------------------------------------------------------------------
svn:eol-style = native