]> source.dussan.org Git - archiva.git/blob
02c3b41574fb89986890bae83d75b827bb2a433b
[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.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.ArtifactReference;
27 import org.apache.maven.archiva.model.CiManagement;
28 import org.apache.maven.archiva.model.Dependency;
29 import org.apache.maven.archiva.model.Exclusion;
30 import org.apache.maven.archiva.model.Individual;
31 import org.apache.maven.archiva.model.IssueManagement;
32 import org.apache.maven.archiva.model.License;
33 import org.apache.maven.archiva.model.MailingList;
34 import org.apache.maven.archiva.model.Organization;
35 import org.apache.maven.archiva.model.ProjectRepository;
36 import org.apache.maven.archiva.model.Scm;
37 import org.apache.maven.archiva.model.VersionedReference;
38 import org.apache.maven.archiva.repository.project.ProjectModelException;
39 import org.apache.maven.archiva.repository.project.ProjectModelFilter;
40 import org.codehaus.plexus.evaluator.DefaultExpressionEvaluator;
41 import org.codehaus.plexus.evaluator.EvaluatorException;
42 import org.codehaus.plexus.evaluator.ExpressionEvaluator;
43 import org.codehaus.plexus.evaluator.ExpressionSource;
44 import org.codehaus.plexus.evaluator.sources.PropertiesExpressionSource;
45 import org.codehaus.plexus.evaluator.sources.SystemPropertyExpressionSource;
46
47 import java.util.ArrayList;
48 import java.util.HashSet;
49 import java.util.List;
50 import java.util.Properties;
51 import java.util.Set;
52
53 /**
54  * ProjectModelExpressionFilter 
55  *
56  * @version $Id$
57  * @plexus.component role="org.apache.maven.archiva.repository.project.ProjectModelFilter"
58  *                   role-hint="expression" 
59  *                   instantiation-strategy="per-lookup"
60  */
61 public class ProjectModelExpressionFilter
62     implements ProjectModelFilter
63 {
64     private ExpressionEvaluator evaluator = new DefaultExpressionEvaluator();
65
66     /**
67      * Find and Evaluate the Expressions present in the model.
68      * 
69      * @param model the model to correct.
70      */
71     @SuppressWarnings("unchecked")
72     public ArchivaProjectModel filter( final ArchivaProjectModel model )
73         throws ProjectModelException
74     {
75         Properties props = new Properties();
76
77         if ( model.getProperties() != null )
78         {
79             props.putAll( model.getProperties() );
80         }
81
82         ArchivaProjectModel ret = ArchivaModelCloner.clone( model );
83
84         // TODO: should probably clone evaluator to prevent threading issues.
85         synchronized ( evaluator )
86         {
87             // TODO: create .resetSources() method in ExpressionEvaluator project on plexus side.
88             // Remove previous expression sources.
89             List<ExpressionSource> oldSources = new ArrayList<ExpressionSource>();
90             oldSources.addAll( evaluator.getExpressionSourceList() );
91             for ( ExpressionSource exprSrc : oldSources )
92             {
93                 evaluator.removeExpressionSource( exprSrc );
94             }
95
96             // Setup new sources (based on current model)
97             PropertiesExpressionSource propsSource = new PropertiesExpressionSource();
98             propsSource.setProperties( props );
99             evaluator.addExpressionSource( propsSource );
100
101             // Add system properties to the mix. 
102             evaluator.addExpressionSource( new SystemPropertyExpressionSource() );
103
104             try
105             {
106                 // Setup some common properties.
107                 VersionedReference parent = model.getParentProject();
108                 if ( parent != null )
109                 {
110                     String parentGroupId = StringUtils.defaultString( evaluator.expand( parent.getGroupId() ) );
111                     String parentArtifactId = StringUtils.defaultString( evaluator.expand( parent.getArtifactId() ) );
112                     String parentVersion = StringUtils.defaultString( evaluator.expand( parent.getVersion() ) );
113
114                     props.setProperty( "parent.groupId", parentGroupId );
115                     props.setProperty( "parent.artifactId", parentArtifactId );
116                     props.setProperty( "parent.version", parentVersion );
117                 }
118
119                 String groupId = StringUtils.defaultString( evaluator.expand( model.getGroupId() ) );
120                 String artifactId = StringUtils.defaultString( evaluator.expand( model.getArtifactId() ) );
121                 String version = StringUtils.defaultString( evaluator.expand( model.getVersion() ) );
122                 String name = StringUtils.defaultString( evaluator.expand( model.getName() ) );
123                 
124
125                 /* Archiva doesn't need to handle a full expression language with object tree walking
126                  * as the requirements within Archiva are much smaller, a quick replacement of the
127                  * important fields (groupId, artifactId, version, name) are handled specifically. 
128                  */
129                 props.setProperty( "pom.groupId",  groupId );
130                 props.setProperty( "pom.artifactId", artifactId );
131                 props.setProperty( "pom.version", version );
132                 props.setProperty( "pom.name", name );
133                 props.setProperty( "project.groupId",  groupId );
134                 props.setProperty( "project.artifactId", artifactId );
135                 props.setProperty( "project.version", version );
136                 props.setProperty( "project.name", name );
137
138                 // Evaluate everything.
139                 ret.setVersion( evaluator.expand( ret.getVersion() ) );
140                 ret.setGroupId( evaluator.expand( ret.getGroupId() ) );
141                 ret.setName( evaluator.expand( ret.getName() ) );
142                 ret.setDescription( evaluator.expand( ret.getDescription() ) );
143                 ret.setPackaging( evaluator.expand( ret.getPackaging() ) );
144                 ret.setUrl( evaluator.expand( ret.getUrl() ) );
145
146                 evaluateParentProject( evaluator, ret.getParentProject() );
147
148                 evaluateBuildExtensions( evaluator, ret.getBuildExtensions() );
149                 evaluateCiManagement( evaluator, ret.getCiManagement() );
150                 evaluateDependencyList( evaluator, ret.getDependencies() );
151                 evaluateDependencyList( evaluator, ret.getDependencyManagement() );
152                 evaluateIndividuals( evaluator, ret.getIndividuals() );
153                 evaluateIssueManagement( evaluator, ret.getIssueManagement() );
154                 evaluateLicenses( evaluator, ret.getLicenses() );
155                 evaluateMailingLists( evaluator, ret.getMailingLists() );
156                 evaluateOrganization( evaluator, ret.getOrganization() );
157                 evaluatePlugins( evaluator, ret.getPlugins() );
158                 evaluateRelocation( evaluator, ret.getRelocation() );
159                 evaluateReports( evaluator, ret.getReports() );
160                 evaluateRepositories( evaluator, ret.getRepositories() );
161                 evaluateScm( evaluator, ret.getScm() );
162             }
163             catch ( EvaluatorException e )
164             {
165                 throw new ProjectModelException( "Unable to evaluate expression in model: " + e.getMessage(), e );
166             }
167         }
168
169         return ret;
170     }
171
172     private void evaluateArtifactReferenceList( ExpressionEvaluator eval, List<ArtifactReference> refs )
173         throws EvaluatorException
174     {
175         if ( CollectionUtils.isEmpty( refs ) )
176         {
177             return;
178         }
179
180         for ( ArtifactReference ref : refs )
181         {
182             ref.setGroupId( eval.expand( ref.getGroupId() ) );
183             ref.setArtifactId( eval.expand( ref.getArtifactId() ) );
184             ref.setVersion( eval.expand( ref.getVersion() ) );
185             ref.setClassifier( eval.expand( ref.getClassifier() ) );
186             ref.setType( eval.expand( ref.getType() ) );
187         }
188     }
189
190     private void evaluateBuildExtensions( ExpressionEvaluator eval, List<ArtifactReference> buildExtensions )
191         throws EvaluatorException
192     {
193         if ( CollectionUtils.isEmpty( buildExtensions ) )
194         {
195             return;
196         }
197
198         for ( ArtifactReference ref : buildExtensions )
199         {
200             ref.setGroupId( eval.expand( ref.getGroupId() ) );
201             ref.setArtifactId( eval.expand( ref.getArtifactId() ) );
202             ref.setVersion( eval.expand( ref.getVersion() ) );
203             ref.setClassifier( eval.expand( ref.getClassifier() ) );
204             ref.setType( eval.expand( ref.getType() ) );
205         }
206     }
207
208     private void evaluateCiManagement( ExpressionEvaluator eval, CiManagement ciManagement )
209         throws EvaluatorException
210     {
211         if ( ciManagement == null )
212         {
213             return;
214         }
215
216         ciManagement.setSystem( eval.expand( ciManagement.getSystem() ) );
217         ciManagement.setUrl( eval.expand( ciManagement.getUrl() ) );
218     }
219
220     private void evaluateDependencyList( ExpressionEvaluator eval, List<Dependency> dependencies )
221         throws EvaluatorException
222     {
223         if ( CollectionUtils.isEmpty( dependencies ) )
224         {
225             return;
226         }
227
228         for ( Dependency dependency : dependencies )
229         {
230             dependency.setGroupId( eval.expand( dependency.getGroupId() ) );
231             dependency.setArtifactId( eval.expand( dependency.getArtifactId() ) );
232             dependency.setVersion( eval.expand( dependency.getVersion() ) );
233             dependency.setScope( eval.expand( dependency.getScope() ) );
234             dependency.setType( eval.expand( dependency.getType() ) );
235             dependency.setUrl( eval.expand( dependency.getUrl() ) );
236
237             evaluateExclusions( eval, dependency.getExclusions() );
238         }
239     }
240
241     private void evaluateExclusions( ExpressionEvaluator eval, List<Exclusion> exclusions )
242         throws EvaluatorException
243     {
244         if ( CollectionUtils.isEmpty( exclusions ) )
245         {
246             return;
247         }
248
249         for ( Exclusion exclusion : exclusions )
250         {
251             exclusion.setGroupId( eval.expand( exclusion.getGroupId() ) );
252             exclusion.setArtifactId( eval.expand( exclusion.getArtifactId() ) );
253         }
254     }
255
256     private void evaluateIndividuals( ExpressionEvaluator eval, List<Individual> individuals )
257         throws EvaluatorException
258     {
259         if ( CollectionUtils.isEmpty( individuals ) )
260         {
261             return;
262         }
263
264         for ( Individual individual : individuals )
265         {
266             individual.setPrincipal( eval.expand( individual.getPrincipal() ) );
267             individual.setName( eval.expand( individual.getName() ) );
268             individual.setEmail( eval.expand( individual.getEmail() ) );
269             individual.setTimezone( eval.expand( individual.getTimezone() ) );
270             individual.setOrganization( eval.expand( individual.getOrganization() ) );
271             individual.setOrganizationUrl( eval.expand( individual.getOrganizationUrl() ) );
272             individual.setUrl( eval.expand( individual.getUrl() ) );
273
274             evaluateProperties( eval, individual.getProperties() );
275             evaluateStringList( eval, individual.getRoles() );
276         }
277     }
278
279     private void evaluateIssueManagement( ExpressionEvaluator eval, IssueManagement issueManagement )
280         throws EvaluatorException
281     {
282         if ( issueManagement == null )
283         {
284             return;
285         }
286
287         issueManagement.setSystem( eval.expand( issueManagement.getSystem() ) );
288         issueManagement.setUrl( eval.expand( issueManagement.getUrl() ) );
289     }
290
291     private void evaluateLicenses( ExpressionEvaluator eval, List<License> licenses )
292         throws EvaluatorException
293     {
294         if ( CollectionUtils.isEmpty( licenses ) )
295         {
296             return;
297         }
298
299         for ( License license : licenses )
300         {
301             license.setName( eval.expand( license.getName() ) );
302             license.setUrl( eval.expand( license.getUrl() ) );
303             license.setComments( eval.expand( license.getComments() ) );
304         }
305     }
306
307     private void evaluateMailingLists( ExpressionEvaluator eval, List<MailingList> mailingLists )
308         throws EvaluatorException
309     {
310         if ( CollectionUtils.isEmpty( mailingLists ) )
311         {
312             return;
313         }
314
315         for ( MailingList mlist : mailingLists )
316         {
317             mlist.setName( eval.expand( mlist.getName() ) );
318             mlist.setSubscribeAddress( eval.expand( mlist.getSubscribeAddress() ) );
319             mlist.setUnsubscribeAddress( eval.expand( mlist.getUnsubscribeAddress() ) );
320             mlist.setPostAddress( eval.expand( mlist.getPostAddress() ) );
321             mlist.setMainArchiveUrl( eval.expand( mlist.getMainArchiveUrl() ) );
322
323             evaluateStringList( eval, mlist.getOtherArchives() );
324         }
325     }
326
327     private void evaluateOrganization( ExpressionEvaluator eval, Organization organization )
328         throws EvaluatorException
329     {
330         if ( organization == null )
331         {
332             return;
333         }
334
335         organization.setName( eval.expand( organization.getName() ) );
336         organization.setUrl( eval.expand( organization.getUrl() ) );
337         organization.setFavicon( eval.expand( organization.getFavicon() ) );
338     }
339
340     private void evaluateParentProject( ExpressionEvaluator eval, VersionedReference parentProject )
341         throws EvaluatorException
342     {
343         if ( parentProject == null )
344         {
345             return;
346         }
347
348         parentProject.setGroupId( eval.expand( parentProject.getGroupId() ) );
349         parentProject.setArtifactId( eval.expand( parentProject.getArtifactId() ) );
350         parentProject.setVersion( eval.expand( parentProject.getVersion() ) );
351     }
352
353     private void evaluatePlugins( ExpressionEvaluator eval, List<ArtifactReference> plugins )
354         throws EvaluatorException
355     {
356         evaluateArtifactReferenceList( eval, plugins );
357     }
358
359     private void evaluateProperties( ExpressionEvaluator eval, Properties props )
360         throws EvaluatorException
361     {
362         if ( props == null )
363         {
364             return;
365         }
366
367         // Only evaluate the values, not the keys.
368
369         // Collect the key names. (Done ahead of time to prevent iteration / concurrent modification exceptions)
370         Set<String> keys = new HashSet<String>();
371         for ( Object obj : props.keySet() )
372         {
373             keys.add( (String) obj );
374         }
375
376         // Evaluate all of the values.
377         for ( String key : keys )
378         {
379             String value = props.getProperty( key );
380             props.setProperty( key, eval.expand( value ) );
381         }
382     }
383
384     private void evaluateRelocation( ExpressionEvaluator eval, VersionedReference relocation )
385         throws EvaluatorException
386     {
387         if ( relocation == null )
388         {
389             return;
390         }
391
392         relocation.setGroupId( eval.expand( relocation.getGroupId() ) );
393         relocation.setArtifactId( eval.expand( relocation.getArtifactId() ) );
394         relocation.setVersion( eval.expand( relocation.getVersion() ) );
395     }
396
397     private void evaluateReports( ExpressionEvaluator eval, List<ArtifactReference> reports )
398         throws EvaluatorException
399     {
400         evaluateArtifactReferenceList( eval, reports );
401     }
402
403     private void evaluateRepositories( ExpressionEvaluator eval, List<ProjectRepository> repositories )
404         throws EvaluatorException
405     {
406         if ( CollectionUtils.isEmpty( repositories ) )
407         {
408             return;
409         }
410
411         for ( ProjectRepository repository : repositories )
412         {
413             repository.setId( eval.expand( repository.getId() ) );
414             repository.setLayout( eval.expand( repository.getLayout() ) );
415             repository.setName( eval.expand( repository.getName() ) );
416             repository.setUrl( eval.expand( repository.getUrl() ) );
417         }
418     }
419
420     private void evaluateScm( ExpressionEvaluator eval, Scm scm )
421         throws EvaluatorException
422     {
423         if ( scm == null )
424         {
425             return;
426         }
427
428         scm.setConnection( eval.expand( scm.getConnection() ) );
429         scm.setDeveloperConnection( eval.expand( scm.getDeveloperConnection() ) );
430         scm.setUrl( eval.expand( scm.getUrl() ) );
431     }
432
433     private void evaluateStringList( ExpressionEvaluator eval, List<String> strings )
434         throws EvaluatorException
435     {
436         if ( CollectionUtils.isEmpty( strings ) )
437         {
438             return;
439         }
440
441         // Create new list to hold post-evaluated strings.
442         List<String> evaluated = new ArrayList<String>();
443
444         // Evaluate them all
445         for ( String str : strings )
446         {
447             evaluated.add( eval.expand( str ) );
448         }
449
450         // Populate the original list with the post-evaluated list.
451         strings.clear();
452         strings.addAll( evaluated );
453     }
454 }