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.ProjectModelFilter;
29 import org.apache.maven.archiva.repository.project.ProjectModelMerge;
30 import org.apache.maven.archiva.repository.project.ProjectModelResolver;
32 import java.util.ArrayList;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
39 * Builder for the Effective Project Model.
41 * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
43 * @plexus.component role="org.apache.maven.archiva.repository.project.ProjectModelFilter"
44 * role-hint="effective"
45 * instantiation-strategy="per-lookup"
47 public class EffectiveProjectModelFilter implements ProjectModelFilter
50 * @plexus.requirement role-hint="expression"
52 private ProjectModelFilter expressionFilter;
54 private List projectModelResolvers;
56 public EffectiveProjectModelFilter()
58 projectModelResolvers = new ArrayList();
61 public void addProjectModelResolver( ProjectModelResolver resolver )
63 if ( resolver == null )
68 this.projectModelResolvers.add( resolver );
72 * Take the provided {@link ArchivaProjectModel} and build the effective {@link ArchivaProjectModel}.
75 * 1) Expand any expressions / properties.
76 * 2) Walk the parent project references and merge.
77 * 3) Apply dependency management settings.
79 * @param project the project to create the effective {@link ArchivaProjectModel} from.
80 * @return a the effective {@link ArchivaProjectModel}.
81 * @throws ProjectModelException if there was a problem building the effective pom.
83 public ArchivaProjectModel filter( final ArchivaProjectModel project )
84 throws ProjectModelException
86 if ( project == null )
91 if ( this.projectModelResolvers.isEmpty() )
93 throw new IllegalStateException( "Unable to build effective pom with no project model resolvers defined." );
96 // Clone submitted project (so that we don't mess with it)
97 ArchivaProjectModel effectiveProject = ArchivaModelCloner.clone( project );
99 // Setup Expression Evaluation pieces.
100 effectiveProject = expressionFilter.filter( effectiveProject );
102 debug( "Starting build of effective with: " + effectiveProject );
104 // Merge in all the parent poms.
105 effectiveProject = mergeParent( effectiveProject );
107 // Resolve dependency versions from dependency management.
108 applyDependencyManagement( effectiveProject );
110 // Return what we got.
111 return effectiveProject;
114 public void removeResolver( ProjectModelResolver resolver )
116 this.projectModelResolvers.remove( resolver );
119 private void applyDependencyManagement( ArchivaProjectModel pom )
121 if ( ( pom.getDependencyManagement() == null ) || ( pom.getDependencies() == null ) )
123 // Nothing to do. All done!
127 if ( pom.getDependencyManagement().isEmpty() || pom.getDependencies().isEmpty() )
129 // Nothing to do. All done!
133 Map managedDependencies = createDependencyMap( pom.getDependencyManagement() );
134 Iterator it = pom.getDependencies().iterator();
135 while ( it.hasNext() )
137 Dependency dep = (Dependency) it.next();
138 String key = toVersionlessDependencyKey( dep );
140 // Do we need to do anything?
141 if ( managedDependencies.containsKey( key ) )
143 Dependency mgmtDep = (Dependency) managedDependencies.get( key );
145 dep.setVersion( mgmtDep.getVersion() );
146 dep.setScope( mgmtDep.getScope() );
147 dep.setExclusions( ProjectModelMerge.mergeExclusions( dep.getExclusions(), mgmtDep.getExclusions() ) );
152 private void debug( String msg )
154 System.out.println( "## " + msg );
157 private ArchivaProjectModel findProject( VersionedReference projectRef )
159 debug( "Trying to find project: " + projectRef );
160 Iterator it = this.projectModelResolvers.iterator();
162 while ( it.hasNext() )
164 ProjectModelResolver resolver = (ProjectModelResolver) it.next();
168 debug( "Trying to find in " + resolver.getClass().getName() );
169 ArchivaProjectModel model = resolver.resolveProjectModel( projectRef );
173 debug( "Found it!: " + model );
176 debug( "Not found." );
178 catch ( ProjectModelException e )
180 // TODO: trigger notifier of problem?
185 // TODO: Document that project was not found. (Use monitor?)
190 private ArchivaProjectModel mergeParent( ArchivaProjectModel pom )
191 throws ProjectModelException
193 ArchivaProjectModel mixedProject;
195 debug( "Parent: " + pom.getParentProject() );
197 if ( pom.getParentProject() != null )
199 // Use parent reference.
200 VersionedReference parentRef = pom.getParentProject();
202 debug( "Has parent: " + parentRef );
204 // Find parent using resolvers.
205 ArchivaProjectModel parentProject = findProject( parentRef );
207 if ( parentProject != null )
209 parentProject = expressionFilter.filter( parentProject );
210 parentProject = mergeParent( parentProject );
211 mixedProject = ProjectModelMerge.merge( pom, parentProject );
215 // Shortcircuit due to missing parent pom.
216 // TODO: Document this via monitor.
217 mixedProject = mixinSuperPom( pom );
222 debug( "No parent found" );
224 /* Mix in the super-pom.
226 * Super POM from maven/components contains many things.
227 * However, for purposes of archiva, only the <repositories>
228 * and <pluginRepositories> sections are of any value.
231 mixedProject = mixinSuperPom( pom );
238 * Super POM from maven/components contains many things.
239 * However, for purposes of archiva, only the <repositories>
240 * and <pluginRepositories> sections are of any value.
245 private ArchivaProjectModel mixinSuperPom( ArchivaProjectModel pom )
247 // TODO: add super pom repositories.
248 debug( "Mix in Super POM: " + pom );
253 private static Map createDependencyMap( List dependencies )
255 Map ret = new HashMap();
257 Iterator it = dependencies.iterator();
258 while ( it.hasNext() )
260 Dependency dep = (Dependency) it.next();
261 String key = toVersionlessDependencyKey( dep );
268 private static String toVersionlessDependencyKey( Dependency dep )
270 StringBuffer key = new StringBuffer();
272 key.append( dep.getGroupId() ).append( ":" ).append( dep.getArtifactId() );
273 key.append( StringUtils.defaultString( dep.getClassifier() ) ).append( ":" );
274 key.append( dep.getType() );
276 return key.toString();