001 package org.apache.maven.repository.metadata;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import java.util.ArrayList;
023 import java.util.Arrays;
024 import java.util.Comparator;
025 import java.util.List;
026
027 import org.apache.maven.artifact.ArtifactScopeEnum;
028 import org.codehaus.plexus.component.annotations.Component;
029 import org.codehaus.plexus.component.annotations.Requirement;
030
031 /**
032 * default implementation of the metadata classpath transformer
033 *
034 * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
035 *
036 */
037 @Component( role = ClasspathTransformation.class )
038 public class DefaultClasspathTransformation
039 implements ClasspathTransformation
040 {
041 @Requirement
042 GraphConflictResolver conflictResolver;
043
044 //----------------------------------------------------------------------------------------------------
045 public ClasspathContainer transform( MetadataGraph dirtyGraph, ArtifactScopeEnum scope, boolean resolve )
046 throws MetadataGraphTransformationException
047 {
048 try
049 {
050 if ( dirtyGraph == null || dirtyGraph.isEmpty() )
051 {
052 return null;
053 }
054
055 MetadataGraph cleanGraph = conflictResolver.resolveConflicts( dirtyGraph, scope );
056
057 if ( cleanGraph == null || cleanGraph.isEmpty() )
058 {
059 return null;
060 }
061
062 ClasspathContainer cpc = new ClasspathContainer( scope );
063 if ( cleanGraph.isEmptyEdges() )
064 {
065 // single entry in the classpath, populated from itself
066 ArtifactMetadata amd = cleanGraph.getEntry().getMd();
067 cpc.add( amd );
068 }
069 else
070 {
071 ClasspathGraphVisitor v = new ClasspathGraphVisitor( cleanGraph, cpc );
072 MetadataGraphVertex entry = cleanGraph.getEntry();
073 ArtifactMetadata md = entry.getMd();
074 // entry point
075 v.visit( entry ); // , md.getVersion(), md.getArtifactUri() );
076 }
077
078 return cpc;
079 }
080 catch ( GraphConflictResolutionException e )
081 {
082 throw new MetadataGraphTransformationException( e );
083 }
084 }
085
086 //===================================================================================================
087 /**
088 * Helper class to traverse graph. Required to make the containing method thread-safe
089 * and yet use class level data to lessen stack usage in recursion
090 */
091 private class ClasspathGraphVisitor
092 {
093 MetadataGraph graph;
094
095 ClasspathContainer cpc;
096
097 List<MetadataGraphVertex> visited;
098
099 // -----------------------------------------------------------------------
100 protected ClasspathGraphVisitor( MetadataGraph cleanGraph, ClasspathContainer cpc )
101 {
102 this.cpc = cpc;
103 this.graph = cleanGraph;
104
105 visited = new ArrayList<MetadataGraphVertex>( cleanGraph.getVertices().size() );
106 }
107
108 // -----------------------------------------------------------------------
109 protected void visit( MetadataGraphVertex node ) // , String version, String artifactUri )
110 {
111 ArtifactMetadata md = node.getMd();
112 if ( visited.contains( node ) )
113 {
114 return;
115 }
116
117 cpc.add( md );
118 //
119 // TreeSet<MetadataGraphEdge> deps = new TreeSet<MetadataGraphEdge>(
120 // new Comparator<MetadataGraphEdge>()
121 // {
122 // public int compare( MetadataGraphEdge e1
123 // , MetadataGraphEdge e2
124 // )
125 // {
126 // if( e1.getDepth() == e2.getDepth() )
127 // {
128 // if( e2.getPomOrder() == e1.getPomOrder() )
129 // return e1.getTarget().toString().compareTo(e2.getTarget().toString() );
130 //
131 // return e2.getPomOrder() - e1.getPomOrder();
132 // }
133 //
134 // return e2.getDepth() - e1.getDepth();
135 // }
136 // }
137 // );
138
139 List<MetadataGraphEdge> exits = graph.getExcidentEdges( node );
140
141 if ( exits != null && exits.size() > 0 )
142 {
143 MetadataGraphEdge[] sortedExits = exits.toArray( new MetadataGraphEdge[exits.size()] );
144 Arrays.sort( sortedExits
145 ,
146 new Comparator<MetadataGraphEdge>()
147 {
148 public int compare( MetadataGraphEdge e1
149 , MetadataGraphEdge e2
150 )
151 {
152 if ( e1.getDepth() == e2.getDepth() )
153 {
154 if ( e2.getPomOrder() == e1.getPomOrder() )
155 {
156 return e1.getTarget().toString().compareTo( e2.getTarget().toString() );
157 }
158 return e2.getPomOrder() - e1.getPomOrder();
159 }
160
161 return e2.getDepth() - e1.getDepth();
162 }
163 }
164 );
165
166 for ( MetadataGraphEdge e : sortedExits )
167 {
168 MetadataGraphVertex targetNode = e.getTarget();
169 targetNode.getMd().setArtifactScope( e.getScope() );
170 targetNode.getMd().setWhy( e.getSource().getMd().toString() );
171 visit( targetNode );
172 }
173 }
174
175 }
176 //-----------------------------------------------------------------------
177 //-----------------------------------------------------------------------
178 }
179 //----------------------------------------------------------------------------------------------------
180 //----------------------------------------------------------------------------------------------------
181 }
182
183
184