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.collections.CollectionUtils;
23 import org.apache.commons.lang.StringUtils;
24 import org.apache.maven.archiva.model.ArchivaModelCloner;
25 import org.apache.maven.archiva.model.ArchivaProjectModel;
26 import org.apache.maven.archiva.model.Dependency;
27 import org.apache.maven.archiva.model.VersionedReference;
28 import org.apache.maven.archiva.repository.project.ProjectModelException;
29 import org.apache.maven.archiva.repository.project.ProjectModelFilter;
30 import org.apache.maven.archiva.repository.project.ProjectModelMerge;
31 import org.apache.maven.archiva.repository.project.ProjectModelResolverFactory;
32 import org.codehaus.plexus.logging.AbstractLogEnabled;
33 import org.codehaus.plexus.logging.Logger;
34 import org.codehaus.plexus.logging.console.ConsoleLogger;
36 import java.util.HashMap;
37 import java.util.Iterator;
38 import java.util.List;
42 * Builder for the Effective Project Model.
44 * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
46 * @plexus.component role="org.apache.maven.archiva.repository.project.ProjectModelFilter"
47 * role-hint="effective"
49 public class EffectiveProjectModelFilter
50 extends AbstractLogEnabled
51 implements ProjectModelFilter
53 private ProjectModelFilter expressionFilter = new ProjectModelExpressionFilter();
58 private ProjectModelResolverFactory resolverFactory;
61 * Take the provided {@link ArchivaProjectModel} and build the effective {@link ArchivaProjectModel}.
64 * 1) Expand any expressions / properties.
65 * 2) Walk the parent project references and merge.
66 * 3) Apply dependency management settings.
68 * @param project the project to create the effective {@link ArchivaProjectModel} from.
69 * @return a the effective {@link ArchivaProjectModel}.
70 * @throws ProjectModelException if there was a problem building the effective pom.
72 public ArchivaProjectModel filter( final ArchivaProjectModel project )
73 throws ProjectModelException
75 if ( project == null )
80 if ( resolverFactory.getCurrentResolverStack().isEmpty() )
82 throw new IllegalStateException( "Unable to build effective pom with no project model resolvers defined." );
85 // Clone submitted project (so that we don't mess with it)
86 ArchivaProjectModel effectiveProject = ArchivaModelCloner.clone( project );
88 // Setup Expression Evaluation pieces.
89 effectiveProject = expressionFilter.filter( effectiveProject );
91 getLogger().debug( "Starting build of effective with: " + effectiveProject );
93 // Merge in all the parent poms.
94 effectiveProject = mergeParent( effectiveProject );
96 // Resolve dependency versions from dependency management.
97 applyDependencyManagement( effectiveProject );
99 // Return what we got.
100 return effectiveProject;
103 private Logger logger;
105 protected Logger getLogger()
107 if ( logger == null )
109 logger = super.getLogger();
110 if ( logger == null )
112 logger = new ConsoleLogger( ConsoleLogger.LEVEL_INFO, this.getClass().getName() );
119 private void applyDependencyManagement( ArchivaProjectModel pom )
121 if ( CollectionUtils.isEmpty( pom.getDependencyManagement() )
122 || CollectionUtils.isEmpty( pom.getDependencies() ) )
124 // Nothing to do. All done!
128 Map managedDependencies = createDependencyMap( pom.getDependencyManagement() );
129 Iterator it = pom.getDependencies().iterator();
130 while ( it.hasNext() )
132 Dependency dep = (Dependency) it.next();
133 String key = toVersionlessDependencyKey( dep );
135 // Do we need to do anything?
136 if ( managedDependencies.containsKey( key ) )
138 Dependency mgmtDep = (Dependency) managedDependencies.get( key );
140 dep.setVersion( mgmtDep.getVersion() );
141 dep.setScope( mgmtDep.getScope() );
142 dep.setExclusions( ProjectModelMerge.mergeExclusions( dep.getExclusions(), mgmtDep.getExclusions() ) );
147 private ArchivaProjectModel mergeParent( ArchivaProjectModel pom )
148 throws ProjectModelException
150 ArchivaProjectModel mixedProject;
152 getLogger().debug( "Parent: " + pom.getParentProject() );
154 if ( pom.getParentProject() != null )
156 // Use parent reference.
157 VersionedReference parentRef = pom.getParentProject();
159 getLogger().debug( "Has parent: " + parentRef );
161 // Find parent using resolvers.
162 ArchivaProjectModel parentProject = this.resolverFactory.getCurrentResolverStack().findProject( parentRef );
164 if ( parentProject != null )
166 parentProject = expressionFilter.filter( parentProject );
167 parentProject = mergeParent( parentProject );
168 mixedProject = ProjectModelMerge.merge( pom, parentProject );
172 // Shortcircuit due to missing parent pom.
173 // TODO: Document this via monitor.
174 mixedProject = mixinSuperPom( pom );
179 getLogger().debug( "No parent found" );
181 /* Mix in the super-pom.
183 * Super POM from maven/components contains many things.
184 * However, for purposes of archiva, only the <repositories>
185 * and <pluginRepositories> sections are of any value.
188 mixedProject = mixinSuperPom( pom );
195 * Super POM from maven/components contains many things.
196 * However, for purposes of archiva, only the <repositories>
197 * and <pluginRepositories> sections are of any value.
202 private ArchivaProjectModel mixinSuperPom( ArchivaProjectModel pom )
204 // TODO: add super pom repositories.
205 getLogger().debug( "Mix in Super POM: " + pom );
210 private static Map createDependencyMap( List dependencies )
212 Map ret = new HashMap();
214 Iterator it = dependencies.iterator();
215 while ( it.hasNext() )
217 Dependency dep = (Dependency) it.next();
218 String key = toVersionlessDependencyKey( dep );
225 private static String toVersionlessDependencyKey( Dependency dep )
227 StringBuffer key = new StringBuffer();
229 key.append( dep.getGroupId() ).append( ":" ).append( dep.getArtifactId() );
230 key.append( StringUtils.defaultString( dep.getClassifier() ) ).append( ":" );
231 key.append( dep.getType() );
233 return key.toString();