1 package org.apache.maven.archiva.repository.project.filters;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.commons.lang.StringUtils;
23 import org.apache.maven.archiva.model.ArchivaModelCloner;
24 import org.apache.maven.archiva.model.ArchivaProjectModel;
25 import org.apache.maven.archiva.model.Dependency;
26 import org.apache.maven.archiva.model.VersionedReference;
27 import org.apache.maven.archiva.repository.project.ProjectModelException;
28 import org.apache.maven.archiva.repository.project.ProjectModelMerge;
29 import org.apache.maven.archiva.repository.project.ProjectModelResolver;
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
38 * Builder for the Effective Project Model.
40 * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
43 public class EffectiveProjectModelBuilder
45 private List projectModelResolvers;
47 public EffectiveProjectModelBuilder()
49 projectModelResolvers = new ArrayList();
52 public void addProjectModelResolver( ProjectModelResolver resolver )
54 if ( resolver == null )
59 this.projectModelResolvers.add( resolver );
63 * Take the provided {@link ArchivaProjectModel} and build the effective {@link ArchivaProjectModel}.
66 * 1) Expand any expressions / properties.
67 * 2) Walk the parent project references and merge.
68 * 3) Apply dependency management settings.
70 * @param project the project to create the effective {@link ArchivaProjectModel} from.
71 * @return a the effective {@link ArchivaProjectModel}.
72 * @throws ProjectModelException if there was a problem building the effective pom.
74 public ArchivaProjectModel buildEffectiveProjectModel( ArchivaProjectModel project )
75 throws ProjectModelException
77 if ( project == null )
82 if ( this.projectModelResolvers.isEmpty() )
84 throw new IllegalStateException( "Unable to build effective pom with no project model resolvers defined." );
87 // Clone submitted project (so that we don't mess with it)
88 ArchivaProjectModel effectiveProject = ArchivaModelCloner.clone( project );
90 // Setup Expression Evaluation pieces.
91 ProjectModelExpressionExpander.evaluateExpressions( effectiveProject );
93 debug( "Starting build of effective with: " + effectiveProject );
95 // Merge in all the parent poms.
96 effectiveProject = mergeParent( effectiveProject );
98 // Resolve dependency versions from dependency management.
99 applyDependencyManagement( effectiveProject );
101 // Return what we got.
102 return effectiveProject;
105 public void removeResolver( ProjectModelResolver resolver )
107 this.projectModelResolvers.remove( resolver );
110 private void applyDependencyManagement( ArchivaProjectModel pom )
112 if ( ( pom.getDependencyManagement() == null ) || ( pom.getDependencies() == null ) )
114 // Nothing to do. All done!
118 if ( pom.getDependencyManagement().isEmpty() || pom.getDependencies().isEmpty() )
120 // Nothing to do. All done!
124 Map managedDependencies = createDependencyMap( pom.getDependencyManagement() );
125 Iterator it = pom.getDependencies().iterator();
126 while ( it.hasNext() )
128 Dependency dep = (Dependency) it.next();
129 String key = toVersionlessDependencyKey( dep );
131 // Do we need to do anything?
132 if ( managedDependencies.containsKey( key ) )
134 Dependency mgmtDep = (Dependency) managedDependencies.get( key );
136 dep.setVersion( mgmtDep.getVersion() );
137 dep.setScope( mgmtDep.getScope() );
138 dep.setExclusions( ProjectModelMerge.mergeExclusions( dep.getExclusions(), mgmtDep.getExclusions() ) );
143 private void debug( String msg )
145 System.out.println( "## " + msg );
148 private ArchivaProjectModel findProject( VersionedReference projectRef )
150 debug( "Trying to find project: " + projectRef );
151 Iterator it = this.projectModelResolvers.iterator();
153 while ( it.hasNext() )
155 ProjectModelResolver resolver = (ProjectModelResolver) it.next();
159 debug( "Trying to find in " + resolver.getClass().getName() );
160 ArchivaProjectModel model = resolver.resolveProjectModel( projectRef );
164 debug( "Found it!: " + model );
167 debug( "Not found." );
169 catch ( ProjectModelException e )
171 // TODO: trigger notifier of problem?
176 // TODO: Document that project was not found. (Use monitor?)
181 private ArchivaProjectModel mergeParent( ArchivaProjectModel pom )
182 throws ProjectModelException
184 ArchivaProjectModel mixedProject;
186 debug( "Parent: " + pom.getParentProject() );
188 if ( pom.getParentProject() != null )
190 // Use parent reference.
191 VersionedReference parentRef = pom.getParentProject();
193 debug( "Has parent: " + parentRef );
195 // Find parent using resolvers.
196 ArchivaProjectModel parentProject = findProject( parentRef );
198 if ( parentProject != null )
200 ProjectModelExpressionExpander.evaluateExpressions( parentProject );
201 parentProject = mergeParent( parentProject );
202 mixedProject = ProjectModelMerge.merge( pom, parentProject );
206 // Shortcircuit due to missing parent pom.
207 // TODO: Document this via monitor.
208 mixedProject = mixinSuperPom( pom );
213 debug( "No parent found" );
215 /* Mix in the super-pom.
217 * Super POM from maven/components contains many things.
218 * However, for purposes of archiva, only the <repositories>
219 * and <pluginRepositories> sections are of any value.
222 mixedProject = mixinSuperPom( pom );
229 * Super POM from maven/components contains many things.
230 * However, for purposes of archiva, only the <repositories>
231 * and <pluginRepositories> sections are of any value.
236 private ArchivaProjectModel mixinSuperPom( ArchivaProjectModel pom )
238 // TODO: add super pom repositories.
239 debug( "Mix in Super POM: " + pom );
244 private static Map createDependencyMap( List dependencies )
246 Map ret = new HashMap();
248 Iterator it = dependencies.iterator();
249 while ( it.hasNext() )
251 Dependency dep = (Dependency) it.next();
252 String key = toVersionlessDependencyKey( dep );
259 private static String toVersionlessDependencyKey( Dependency dep )
261 StringBuffer key = new StringBuffer();
263 key.append( dep.getGroupId() ).append( ":" ).append( dep.getArtifactId() );
264 key.append( StringUtils.defaultString( dep.getClassifier() ) ).append( ":" );
265 key.append( dep.getType() );
267 return key.toString();