]> source.dussan.org Git - archiva.git/blob
549c049a09234f132093c2a03adac24047acf795
[archiva.git] /
1 package org.apache.maven.archiva.repository.project.filters;
2
3 /*
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
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
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
19  * under the License.
20  */
21
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;
30
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36
37 /**
38  * Builder for the Effective Project Model.  
39  *
40  * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
41  * @version $Id$
42  */
43 public class EffectiveProjectModelBuilder
44 {
45     private List projectModelResolvers;
46
47     public EffectiveProjectModelBuilder()
48     {
49         projectModelResolvers = new ArrayList();
50     }
51
52     public void addProjectModelResolver( ProjectModelResolver resolver )
53     {
54         if ( resolver == null )
55         {
56             return;
57         }
58
59         this.projectModelResolvers.add( resolver );
60     }
61
62     /**
63      * Take the provided {@link ArchivaProjectModel} and build the effective {@link ArchivaProjectModel}.
64      * 
65      * Steps:
66      * 1) Expand any expressions / properties.
67      * 2) Walk the parent project references and merge.
68      * 3) Apply dependency management settings.
69      * 
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.
73      */
74     public ArchivaProjectModel buildEffectiveProjectModel( ArchivaProjectModel project )
75         throws ProjectModelException
76     {
77         if ( project == null )
78         {
79             return null;
80         }
81
82         if ( this.projectModelResolvers.isEmpty() )
83         {
84             throw new IllegalStateException( "Unable to build effective pom with no project model resolvers defined." );
85         }
86
87         // Clone submitted project (so that we don't mess with it) 
88         ArchivaProjectModel effectiveProject = ArchivaModelCloner.clone( project );
89
90         // Setup Expression Evaluation pieces.
91         ProjectModelExpressionExpander.evaluateExpressions( effectiveProject );
92
93         debug( "Starting build of effective with: " + effectiveProject );
94
95         // Merge in all the parent poms.
96         effectiveProject = mergeParent( effectiveProject );
97
98         // Resolve dependency versions from dependency management.
99         applyDependencyManagement( effectiveProject );
100
101         // Return what we got.
102         return effectiveProject;
103     }
104
105     public void removeResolver( ProjectModelResolver resolver )
106     {
107         this.projectModelResolvers.remove( resolver );
108     }
109
110     private void applyDependencyManagement( ArchivaProjectModel pom )
111     {
112         if ( ( pom.getDependencyManagement() == null ) || ( pom.getDependencies() == null ) )
113         {
114             // Nothing to do. All done!
115             return;
116         }
117         
118         if ( pom.getDependencyManagement().isEmpty() || pom.getDependencies().isEmpty() )
119         {
120             // Nothing to do. All done!
121             return;
122         }
123
124         Map managedDependencies = createDependencyMap( pom.getDependencyManagement() );
125         Iterator it = pom.getDependencies().iterator();
126         while ( it.hasNext() )
127         {
128             Dependency dep = (Dependency) it.next();
129             String key = toVersionlessDependencyKey( dep );
130
131             // Do we need to do anything?
132             if ( managedDependencies.containsKey( key ) )
133             {
134                 Dependency mgmtDep = (Dependency) managedDependencies.get( key );
135
136                 dep.setVersion( mgmtDep.getVersion() );
137                 dep.setScope( mgmtDep.getScope() );
138                 dep.setExclusions( ProjectModelMerge.mergeExclusions( dep.getExclusions(), mgmtDep.getExclusions() ) );
139             }
140         }
141     }
142
143     private void debug( String msg )
144     {
145         System.out.println( "## " + msg );
146     }
147
148     private ArchivaProjectModel findProject( VersionedReference projectRef )
149     {
150         debug( "Trying to find project: " + projectRef );
151         Iterator it = this.projectModelResolvers.iterator();
152
153         while ( it.hasNext() )
154         {
155             ProjectModelResolver resolver = (ProjectModelResolver) it.next();
156
157             try
158             {
159                 debug( "Trying to find in " + resolver.getClass().getName() );
160                 ArchivaProjectModel model = resolver.resolveProjectModel( projectRef );
161
162                 if ( model != null )
163                 {
164                     debug( "Found it!: " + model );
165                     return model;
166                 }
167                 debug( "Not found." );
168             }
169             catch ( ProjectModelException e )
170             {
171                 // TODO: trigger notifier of problem?
172                 e.printStackTrace();
173             }
174         }
175
176         // TODO: Document that project was not found. (Use monitor?)
177
178         return null;
179     }
180
181     private ArchivaProjectModel mergeParent( ArchivaProjectModel pom )
182         throws ProjectModelException
183     {
184         ArchivaProjectModel mixedProject;
185
186         debug( "Parent: " + pom.getParentProject() );
187
188         if ( pom.getParentProject() != null )
189         {
190             // Use parent reference.
191             VersionedReference parentRef = pom.getParentProject();
192
193             debug( "Has parent: " + parentRef );
194
195             // Find parent using resolvers.
196             ArchivaProjectModel parentProject = findProject( parentRef );
197
198             if ( parentProject != null )
199             {
200                 ProjectModelExpressionExpander.evaluateExpressions( parentProject );
201                 parentProject = mergeParent( parentProject );
202                 mixedProject = ProjectModelMerge.merge( pom, parentProject );
203             }
204             else
205             {
206                 // Shortcircuit due to missing parent pom.
207                 // TODO: Document this via monitor.
208                 mixedProject = mixinSuperPom( pom );
209             }
210         }
211         else
212         {
213             debug( "No parent found" );
214
215             /* Mix in the super-pom.
216              * 
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.
220              */
221
222             mixedProject = mixinSuperPom( pom );
223         }
224
225         return mixedProject;
226     }
227
228     /**
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.
232      * 
233      * @param pom
234      * @return
235      */
236     private ArchivaProjectModel mixinSuperPom( ArchivaProjectModel pom )
237     {
238         // TODO: add super pom repositories.
239         debug( "Mix in Super POM: " + pom );
240
241         return pom;
242     }
243
244     private static Map createDependencyMap( List dependencies )
245     {
246         Map ret = new HashMap();
247
248         Iterator it = dependencies.iterator();
249         while ( it.hasNext() )
250         {
251             Dependency dep = (Dependency) it.next();
252             String key = toVersionlessDependencyKey( dep );
253             ret.put( key, dep );
254         }
255
256         return ret;
257     }
258
259     private static String toVersionlessDependencyKey( Dependency dep )
260     {
261         StringBuffer key = new StringBuffer();
262
263         key.append( dep.getGroupId() ).append( ":" ).append( dep.getArtifactId() );
264         key.append( StringUtils.defaultString( dep.getClassifier() ) ).append( ":" );
265         key.append( dep.getType() );
266
267         return key.toString();
268     }
269 }