| package org.apache.maven.archiva.repository.project.filters; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import org.apache.commons.collections.CollectionUtils; |
| import org.apache.commons.lang.StringUtils; |
| import org.apache.maven.archiva.model.ArchivaModelCloner; |
| import org.apache.maven.archiva.model.ArchivaProjectModel; |
| import org.apache.maven.archiva.model.ArtifactReference; |
| import org.apache.maven.archiva.model.CiManagement; |
| import org.apache.maven.archiva.model.Dependency; |
| import org.apache.maven.archiva.model.Exclusion; |
| import org.apache.maven.archiva.model.Individual; |
| import org.apache.maven.archiva.model.IssueManagement; |
| import org.apache.maven.archiva.model.License; |
| import org.apache.maven.archiva.model.MailingList; |
| import org.apache.maven.archiva.model.Organization; |
| import org.apache.maven.archiva.model.ProjectRepository; |
| import org.apache.maven.archiva.model.Scm; |
| import org.apache.maven.archiva.model.VersionedReference; |
| import org.apache.maven.archiva.repository.project.ProjectModelException; |
| import org.apache.maven.archiva.repository.project.ProjectModelFilter; |
| import org.codehaus.plexus.evaluator.DefaultExpressionEvaluator; |
| import org.codehaus.plexus.evaluator.EvaluatorException; |
| import org.codehaus.plexus.evaluator.ExpressionEvaluator; |
| import org.codehaus.plexus.evaluator.ExpressionSource; |
| import org.codehaus.plexus.evaluator.sources.PropertiesExpressionSource; |
| import org.codehaus.plexus.evaluator.sources.SystemPropertyExpressionSource; |
| |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Properties; |
| import java.util.Set; |
| |
| /** |
| * ProjectModelExpressionFilter |
| * |
| * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a> |
| * @version $Id$ |
| * @plexus.component role="org.apache.maven.archiva.repository.project.ProjectModelFilter" |
| * role-hint="expression" |
| * instantiation-strategy="per-lookup" |
| */ |
| public class ProjectModelExpressionFilter |
| implements ProjectModelFilter |
| { |
| private ExpressionEvaluator evaluator = new DefaultExpressionEvaluator(); |
| |
| /** |
| * Find and Evaluate the Expressions present in the model. |
| * |
| * @param model the model to correct. |
| */ |
| public ArchivaProjectModel filter( final ArchivaProjectModel model ) |
| throws ProjectModelException |
| { |
| Properties props = new Properties(); |
| |
| if ( model.getProperties() != null ) |
| { |
| props.putAll( model.getProperties() ); |
| } |
| |
| ArchivaProjectModel ret = ArchivaModelCloner.clone( model ); |
| |
| // TODO: should probably clone evaluator to prevent threading issues. |
| synchronized ( evaluator ) |
| { |
| // TODO: create .resetSources() method in ExpressionEvaluator project on plexus side. |
| // Remove previous expression sources. |
| List<ExpressionSource> oldSources = new ArrayList<ExpressionSource>(); |
| oldSources.addAll( evaluator.getExpressionSourceList() ); |
| for ( ExpressionSource exprSrc : oldSources ) |
| { |
| evaluator.removeExpressionSource( exprSrc ); |
| } |
| |
| // Setup new sources (based on current model) |
| PropertiesExpressionSource propsSource = new PropertiesExpressionSource(); |
| propsSource.setProperties( props ); |
| evaluator.addExpressionSource( propsSource ); |
| |
| // Add system properties to the mix. |
| evaluator.addExpressionSource( new SystemPropertyExpressionSource() ); |
| |
| try |
| { |
| // Setup some common properties. |
| VersionedReference parent = model.getParentProject(); |
| if ( parent != null ) |
| { |
| String parentGroupId = StringUtils.defaultString( evaluator.expand( parent.getGroupId() ) ); |
| String parentArtifactId = StringUtils.defaultString( evaluator.expand( parent.getArtifactId() ) ); |
| String parentVersion = StringUtils.defaultString( evaluator.expand( parent.getVersion() ) ); |
| |
| props.setProperty( "parent.groupId", parentGroupId ); |
| props.setProperty( "parent.artifactId", parentArtifactId ); |
| props.setProperty( "parent.version", parentVersion ); |
| } |
| |
| String groupId = StringUtils.defaultString( evaluator.expand( model.getGroupId() ) ); |
| String artifactId = StringUtils.defaultString( evaluator.expand( model.getArtifactId() ) ); |
| String version = StringUtils.defaultString( evaluator.expand( model.getVersion() ) ); |
| String name = StringUtils.defaultString( evaluator.expand( model.getName() ) ); |
| |
| |
| /* Archiva doesn't need to handle a full expression language with object tree walking |
| * as the requirements within Archiva are much smaller, a quick replacement of the |
| * important fields (groupId, artifactId, version, name) are handled specifically. |
| */ |
| props.setProperty( "pom.groupId", groupId ); |
| props.setProperty( "pom.artifactId", artifactId ); |
| props.setProperty( "pom.version", version ); |
| props.setProperty( "pom.name", name ); |
| props.setProperty( "project.groupId", groupId ); |
| props.setProperty( "project.artifactId", artifactId ); |
| props.setProperty( "project.version", version ); |
| props.setProperty( "project.name", name ); |
| |
| // Evaluate everything. |
| ret.setVersion( evaluator.expand( ret.getVersion() ) ); |
| ret.setGroupId( evaluator.expand( ret.getGroupId() ) ); |
| ret.setName( evaluator.expand( ret.getName() ) ); |
| ret.setDescription( evaluator.expand( ret.getDescription() ) ); |
| ret.setPackaging( evaluator.expand( ret.getPackaging() ) ); |
| ret.setUrl( evaluator.expand( ret.getUrl() ) ); |
| |
| evaluateParentProject( evaluator, ret.getParentProject() ); |
| |
| evaluateBuildExtensions( evaluator, ret.getBuildExtensions() ); |
| evaluateCiManagement( evaluator, ret.getCiManagement() ); |
| evaluateDependencyList( evaluator, ret.getDependencies() ); |
| evaluateDependencyList( evaluator, ret.getDependencyManagement() ); |
| evaluateIndividuals( evaluator, ret.getIndividuals() ); |
| evaluateIssueManagement( evaluator, ret.getIssueManagement() ); |
| evaluateLicenses( evaluator, ret.getLicenses() ); |
| evaluateMailingLists( evaluator, ret.getMailingLists() ); |
| evaluateOrganization( evaluator, ret.getOrganization() ); |
| evaluatePlugins( evaluator, ret.getPlugins() ); |
| evaluateRelocation( evaluator, ret.getRelocation() ); |
| evaluateReports( evaluator, ret.getReports() ); |
| evaluateRepositories( evaluator, ret.getRepositories() ); |
| evaluateScm( evaluator, ret.getScm() ); |
| } |
| catch ( EvaluatorException e ) |
| { |
| throw new ProjectModelException( "Unable to evaluate expression in model: " + e.getMessage(), e ); |
| } |
| } |
| |
| return ret; |
| } |
| |
| private void evaluateArtifactReferenceList( ExpressionEvaluator eval, List<ArtifactReference> refs ) |
| throws EvaluatorException |
| { |
| if ( CollectionUtils.isEmpty( refs ) ) |
| { |
| return; |
| } |
| |
| for ( ArtifactReference ref : refs ) |
| { |
| ref.setGroupId( eval.expand( ref.getGroupId() ) ); |
| ref.setArtifactId( eval.expand( ref.getArtifactId() ) ); |
| ref.setVersion( eval.expand( ref.getVersion() ) ); |
| ref.setClassifier( eval.expand( ref.getClassifier() ) ); |
| ref.setType( eval.expand( ref.getType() ) ); |
| } |
| } |
| |
| private void evaluateBuildExtensions( ExpressionEvaluator eval, List<ArtifactReference> buildExtensions ) |
| throws EvaluatorException |
| { |
| if ( CollectionUtils.isEmpty( buildExtensions ) ) |
| { |
| return; |
| } |
| |
| for ( ArtifactReference ref : buildExtensions ) |
| { |
| ref.setGroupId( eval.expand( ref.getGroupId() ) ); |
| ref.setArtifactId( eval.expand( ref.getArtifactId() ) ); |
| ref.setVersion( eval.expand( ref.getVersion() ) ); |
| ref.setClassifier( eval.expand( ref.getClassifier() ) ); |
| ref.setType( eval.expand( ref.getType() ) ); |
| } |
| } |
| |
| private void evaluateCiManagement( ExpressionEvaluator eval, CiManagement ciManagement ) |
| throws EvaluatorException |
| { |
| if ( ciManagement == null ) |
| { |
| return; |
| } |
| |
| ciManagement.setSystem( eval.expand( ciManagement.getSystem() ) ); |
| ciManagement.setUrl( eval.expand( ciManagement.getUrl() ) ); |
| } |
| |
| private void evaluateDependencyList( ExpressionEvaluator eval, List<Dependency> dependencies ) |
| throws EvaluatorException |
| { |
| if ( CollectionUtils.isEmpty( dependencies ) ) |
| { |
| return; |
| } |
| |
| for ( Dependency dependency : dependencies ) |
| { |
| dependency.setGroupId( eval.expand( dependency.getGroupId() ) ); |
| dependency.setArtifactId( eval.expand( dependency.getArtifactId() ) ); |
| dependency.setVersion( eval.expand( dependency.getVersion() ) ); |
| dependency.setScope( eval.expand( dependency.getScope() ) ); |
| dependency.setType( eval.expand( dependency.getType() ) ); |
| dependency.setUrl( eval.expand( dependency.getUrl() ) ); |
| |
| evaluateExclusions( eval, dependency.getExclusions() ); |
| } |
| } |
| |
| private void evaluateExclusions( ExpressionEvaluator eval, List<Exclusion> exclusions ) |
| throws EvaluatorException |
| { |
| if ( CollectionUtils.isEmpty( exclusions ) ) |
| { |
| return; |
| } |
| |
| for ( Exclusion exclusion : exclusions ) |
| { |
| exclusion.setGroupId( eval.expand( exclusion.getGroupId() ) ); |
| exclusion.setArtifactId( eval.expand( exclusion.getArtifactId() ) ); |
| } |
| } |
| |
| private void evaluateIndividuals( ExpressionEvaluator eval, List<Individual> individuals ) |
| throws EvaluatorException |
| { |
| if ( CollectionUtils.isEmpty( individuals ) ) |
| { |
| return; |
| } |
| |
| for ( Individual individual : individuals ) |
| { |
| individual.setPrincipal( eval.expand( individual.getPrincipal() ) ); |
| individual.setName( eval.expand( individual.getName() ) ); |
| individual.setEmail( eval.expand( individual.getEmail() ) ); |
| individual.setTimezone( eval.expand( individual.getTimezone() ) ); |
| individual.setOrganization( eval.expand( individual.getOrganization() ) ); |
| individual.setOrganizationUrl( eval.expand( individual.getOrganizationUrl() ) ); |
| individual.setUrl( eval.expand( individual.getUrl() ) ); |
| |
| evaluateProperties( eval, individual.getProperties() ); |
| evaluateStringList( eval, individual.getRoles() ); |
| } |
| } |
| |
| private void evaluateIssueManagement( ExpressionEvaluator eval, IssueManagement issueManagement ) |
| throws EvaluatorException |
| { |
| if ( issueManagement == null ) |
| { |
| return; |
| } |
| |
| issueManagement.setSystem( eval.expand( issueManagement.getSystem() ) ); |
| issueManagement.setUrl( eval.expand( issueManagement.getUrl() ) ); |
| } |
| |
| private void evaluateLicenses( ExpressionEvaluator eval, List<License> licenses ) |
| throws EvaluatorException |
| { |
| if ( CollectionUtils.isEmpty( licenses ) ) |
| { |
| return; |
| } |
| |
| for ( License license : licenses ) |
| { |
| license.setName( eval.expand( license.getName() ) ); |
| license.setUrl( eval.expand( license.getUrl() ) ); |
| license.setComments( eval.expand( license.getComments() ) ); |
| } |
| } |
| |
| private void evaluateMailingLists( ExpressionEvaluator eval, List<MailingList> mailingLists ) |
| throws EvaluatorException |
| { |
| if ( CollectionUtils.isEmpty( mailingLists ) ) |
| { |
| return; |
| } |
| |
| for ( MailingList mlist : mailingLists ) |
| { |
| mlist.setName( eval.expand( mlist.getName() ) ); |
| mlist.setSubscribeAddress( eval.expand( mlist.getSubscribeAddress() ) ); |
| mlist.setUnsubscribeAddress( eval.expand( mlist.getUnsubscribeAddress() ) ); |
| mlist.setPostAddress( eval.expand( mlist.getPostAddress() ) ); |
| mlist.setMainArchiveUrl( eval.expand( mlist.getMainArchiveUrl() ) ); |
| |
| evaluateStringList( eval, mlist.getOtherArchives() ); |
| } |
| } |
| |
| private void evaluateOrganization( ExpressionEvaluator eval, Organization organization ) |
| throws EvaluatorException |
| { |
| if ( organization == null ) |
| { |
| return; |
| } |
| |
| organization.setName( eval.expand( organization.getName() ) ); |
| organization.setUrl( eval.expand( organization.getUrl() ) ); |
| organization.setFavicon( eval.expand( organization.getFavicon() ) ); |
| } |
| |
| private void evaluateParentProject( ExpressionEvaluator eval, VersionedReference parentProject ) |
| throws EvaluatorException |
| { |
| if ( parentProject == null ) |
| { |
| return; |
| } |
| |
| parentProject.setGroupId( eval.expand( parentProject.getGroupId() ) ); |
| parentProject.setArtifactId( eval.expand( parentProject.getArtifactId() ) ); |
| parentProject.setVersion( eval.expand( parentProject.getVersion() ) ); |
| } |
| |
| private void evaluatePlugins( ExpressionEvaluator eval, List<ArtifactReference> plugins ) |
| throws EvaluatorException |
| { |
| evaluateArtifactReferenceList( eval, plugins ); |
| } |
| |
| private void evaluateProperties( ExpressionEvaluator eval, Properties props ) |
| throws EvaluatorException |
| { |
| if ( props == null ) |
| { |
| return; |
| } |
| |
| // Only evaluate the values, not the keys. |
| |
| // Collect the key names. (Done ahead of time to prevent iteration / concurrent modification exceptions) |
| Set<String> keys = new HashSet<String>(); |
| for ( Object obj : props.keySet() ) |
| { |
| keys.add( (String) obj ); |
| } |
| |
| // Evaluate all of the values. |
| for ( String key : keys ) |
| { |
| String value = props.getProperty( key ); |
| props.setProperty( key, eval.expand( value ) ); |
| } |
| } |
| |
| private void evaluateRelocation( ExpressionEvaluator eval, VersionedReference relocation ) |
| throws EvaluatorException |
| { |
| if ( relocation == null ) |
| { |
| return; |
| } |
| |
| relocation.setGroupId( eval.expand( relocation.getGroupId() ) ); |
| relocation.setArtifactId( eval.expand( relocation.getArtifactId() ) ); |
| relocation.setVersion( eval.expand( relocation.getVersion() ) ); |
| } |
| |
| private void evaluateReports( ExpressionEvaluator eval, List<ArtifactReference> reports ) |
| throws EvaluatorException |
| { |
| evaluateArtifactReferenceList( eval, reports ); |
| } |
| |
| private void evaluateRepositories( ExpressionEvaluator eval, List<ProjectRepository> repositories ) |
| throws EvaluatorException |
| { |
| if ( CollectionUtils.isEmpty( repositories ) ) |
| { |
| return; |
| } |
| |
| for ( ProjectRepository repository : repositories ) |
| { |
| repository.setId( eval.expand( repository.getId() ) ); |
| repository.setLayout( eval.expand( repository.getLayout() ) ); |
| repository.setName( eval.expand( repository.getName() ) ); |
| repository.setUrl( eval.expand( repository.getUrl() ) ); |
| } |
| } |
| |
| private void evaluateScm( ExpressionEvaluator eval, Scm scm ) |
| throws EvaluatorException |
| { |
| if ( scm == null ) |
| { |
| return; |
| } |
| |
| scm.setConnection( eval.expand( scm.getConnection() ) ); |
| scm.setDeveloperConnection( eval.expand( scm.getDeveloperConnection() ) ); |
| scm.setUrl( eval.expand( scm.getUrl() ) ); |
| } |
| |
| private void evaluateStringList( ExpressionEvaluator eval, List<String> strings ) |
| throws EvaluatorException |
| { |
| if ( CollectionUtils.isEmpty( strings ) ) |
| { |
| return; |
| } |
| |
| // Create new list to hold post-evaluated strings. |
| List<String> evaluated = new ArrayList<String>(); |
| |
| // Evaluate them all |
| for ( String str : strings ) |
| { |
| evaluated.add( eval.expand( str ) ); |
| } |
| |
| // Populate the original list with the post-evaluated list. |
| strings.clear(); |
| strings.addAll( evaluated ); |
| } |
| } |