Coverage Report - org.apache.maven.archiva.repository.project.filters.EffectiveProjectModelFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
EffectiveProjectModelFilter
0%
0/94
0%
0/26
0
 
 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.Dependency;
 27  
 import org.apache.maven.archiva.model.IssueManagement;
 28  
 import org.apache.maven.archiva.model.VersionedReference;
 29  
 import org.apache.maven.archiva.repository.project.ProjectModelException;
 30  
 import org.apache.maven.archiva.repository.project.ProjectModelFilter;
 31  
 import org.apache.maven.archiva.repository.project.ProjectModelMerge;
 32  
 import org.apache.maven.archiva.repository.project.ProjectModelResolverFactory;
 33  
 import org.codehaus.plexus.cache.Cache;
 34  
 
 35  
 import java.util.HashMap;
 36  
 import java.util.Iterator;
 37  
 import java.util.List;
 38  
 import java.util.Map;
 39  
 
 40  
 /**
 41  
  * Builder for the Effective Project Model.  
 42  
  *
 43  
  * @version $Id: EffectiveProjectModelFilter.java 778121 2009-05-24 11:04:35Z oching $
 44  
  * @plexus.component role="org.apache.maven.archiva.repository.project.ProjectModelFilter" 
 45  
  *                   role-hint="effective" 
 46  
  */
 47  0
 public class EffectiveProjectModelFilter
 48  
     implements ProjectModelFilter
 49  
 {
 50  0
     private ProjectModelFilter expressionFilter = new ProjectModelExpressionFilter();
 51  
 
 52  
     /**
 53  
      * @plexus.requirement
 54  
      */
 55  
     private ProjectModelResolverFactory resolverFactory;
 56  
 
 57  
     /**
 58  
      * @plexus.requirement role-hint="effective-project-cache"
 59  
      */
 60  
     private Cache effectiveProjectCache;
 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 filter( final ArchivaProjectModel project )
 75  
         throws ProjectModelException
 76  
     {
 77  0
         if ( project == null )
 78  
         {
 79  0
             return null;
 80  
         }
 81  
 
 82  0
         if ( resolverFactory.getCurrentResolverStack().isEmpty() )
 83  
         {
 84  0
             throw new IllegalStateException( "Unable to build effective pom with no project model resolvers defined." );
 85  
         }
 86  
 
 87  
         ArchivaProjectModel effectiveProject;
 88  0
         String projectKey = toProjectKey( project );
 89  
 
 90  0
         synchronized ( effectiveProjectCache )
 91  
         {
 92  0
             if ( effectiveProjectCache.hasKey( projectKey ) )
 93  
             {
 94  0
                 DEBUG( "Fetching (from cache/projectKey): " + projectKey );
 95  0
                 effectiveProject = (ArchivaProjectModel) effectiveProjectCache.get( projectKey );
 96  0
                 return effectiveProject;
 97  
             }
 98  0
         }
 99  
 
 100  
         // Clone submitted project (so that we don't mess with it) 
 101  0
         effectiveProject = ArchivaModelCloner.clone( project );
 102  
         
 103  0
         DEBUG( "Starting build of effective with: " + effectiveProject );
 104  
 
 105  
         // Merge in all the parent poms.
 106  0
         effectiveProject = mergeParent( effectiveProject );
 107  
 
 108  
         // Setup Expression Evaluation pieces.
 109  0
         effectiveProject = expressionFilter.filter( effectiveProject );
 110  
 
 111  
         // Resolve dependency versions from dependency management.
 112  0
         applyDependencyManagement( effectiveProject );
 113  
 
 114  
         // groupId or version could be updated by parent or expressions
 115  0
         projectKey = toProjectKey( effectiveProject );
 116  
         
 117  
         // Do not add project into cache if it contains no groupId and
 118  
         // version information
 119  0
         if ( effectiveProject.getGroupId() != null && effectiveProject.getVersion() != null )
 120  
         {
 121  0
             synchronized ( effectiveProjectCache )
 122  
             {
 123  0
                 DEBUG( "Putting (to cache/projectKey): " + projectKey );
 124  0
                 effectiveProjectCache.put( projectKey, effectiveProject );
 125  0
             }
 126  
         }
 127  
 
 128  
         // Return what we got.
 129  0
         return effectiveProject;
 130  
     }
 131  
 
 132  
     private void applyDependencyManagement( ArchivaProjectModel pom )
 133  
     {
 134  0
         if ( CollectionUtils.isEmpty( pom.getDependencyManagement() )
 135  
             || CollectionUtils.isEmpty( pom.getDependencies() ) )
 136  
         {
 137  
             // Nothing to do. All done!
 138  0
             return;
 139  
         }
 140  
 
 141  0
         Map<String, Dependency> managedDependencies = createDependencyMap( pom.getDependencyManagement() );
 142  0
         Iterator<Dependency> it = pom.getDependencies().iterator();
 143  0
         while ( it.hasNext() )
 144  
         {
 145  0
             Dependency dep = it.next();
 146  0
             String key = toVersionlessDependencyKey( dep );
 147  
 
 148  
             // Do we need to do anything?
 149  0
             if ( managedDependencies.containsKey( key ) )
 150  
             {
 151  0
                 Dependency mgmtDep = (Dependency) managedDependencies.get( key );
 152  
 
 153  0
                 dep.setVersion( mgmtDep.getVersion() );
 154  0
                 dep.setScope( mgmtDep.getScope() );
 155  0
                 dep.setExclusions( ProjectModelMerge.mergeExclusions( dep.getExclusions(), mgmtDep.getExclusions() ) );
 156  
             }
 157  0
         }
 158  0
     }
 159  
 
 160  
     private ArchivaProjectModel mergeParent( ArchivaProjectModel pom )
 161  
         throws ProjectModelException
 162  
     {
 163  
         ArchivaProjectModel mixedProject;
 164  
 
 165  0
         DEBUG( "Project: " + toProjectKey( pom ) );
 166  
 
 167  0
         if ( pom.getParentProject() != null )
 168  
         {
 169  
             // Use parent reference.
 170  0
             VersionedReference parentRef = pom.getParentProject();
 171  
 
 172  0
             String parentKey = VersionedReference.toKey( parentRef );
 173  
 
 174  0
             DEBUG( "Has parent: " + parentKey );
 175  
 
 176  
             ArchivaProjectModel parentProject;
 177  
 
 178  0
             synchronized ( effectiveProjectCache )
 179  
             {
 180  
                 // is the pre-merged parent in the cache? 
 181  0
                 if ( effectiveProjectCache.hasKey( parentKey ) )
 182  
                 {
 183  0
                     DEBUG( "Fetching (from cache/parentKey): " + parentKey );
 184  
                     // Use the one from the cache.
 185  0
                     parentProject = (ArchivaProjectModel) effectiveProjectCache.get( parentKey );
 186  
                 }
 187  
                 else
 188  
                 {
 189  
                     // Look it up, using resolvers.
 190  0
                     parentProject = this.resolverFactory.getCurrentResolverStack().findProject( parentRef );
 191  
                 }
 192  0
             }
 193  
 
 194  0
             if ( parentProject != null )
 195  
             {
 196  
                 // Merge the pom with the parent pom.
 197  0
                 parentProject = mergeParent( parentProject );
 198  0
                 parentProject = expressionFilter.filter( parentProject );
 199  
 
 200  
                 // Cache the pre-merged parent.
 201  0
                 synchronized ( effectiveProjectCache )
 202  
                 {
 203  0
                     DEBUG( "Putting (to cache/parentKey/merged): " + parentKey );
 204  
                     // Add the merged parent pom to the cache.
 205  0
                     effectiveProjectCache.put( parentKey, parentProject );
 206  0
                 }
 207  
 
 208  
                 // Now merge the parent with the current
 209  0
                 mixedProject = ProjectModelMerge.merge( pom, parentProject );
 210  
             }
 211  
             else
 212  
             {
 213  
                 // Shortcircuit due to missing parent pom.
 214  
                 // TODO: Document this via a monitor.
 215  0
                 mixedProject = mixinSuperPom( pom );
 216  
 
 217  
                 // Cache the non-existant parent.
 218  0
                 synchronized ( effectiveProjectCache )
 219  
                 {
 220  0
                     DEBUG( "Putting (to cache/parentKey/basicPom): " + parentKey );
 221  
                     // Add the basic pom to cache.
 222  0
                     effectiveProjectCache.put( parentKey, createBasicPom( parentRef ) );
 223  0
                 }
 224  
             }
 225  0
         }
 226  
         else
 227  
         {
 228  0
             DEBUG( "No parent found" );
 229  
 
 230  
             /* Mix in the super-pom.
 231  
              * 
 232  
              * Super POM from maven/components contains many things.
 233  
              * However, for purposes of archiva, only the <repositories>
 234  
              * and <pluginRepositories> sections are of any value.
 235  
              */
 236  
 
 237  0
             mixedProject = mixinSuperPom( pom );
 238  
         }
 239  
 
 240  0
         return mixedProject;
 241  
     }
 242  
 
 243  
     private ArchivaProjectModel createBasicPom( VersionedReference ref )
 244  
     {
 245  0
         ArchivaProjectModel model = new ArchivaProjectModel();
 246  0
         model.setGroupId( ref.getGroupId() );
 247  0
         model.setArtifactId( ref.getArtifactId() );
 248  0
         model.setVersion( ref.getVersion() );
 249  0
         model.setPackaging( "jar" );
 250  
 
 251  0
         return model;
 252  
     }
 253  
 
 254  
     /**
 255  
      * Super POM from maven/components contains many things.
 256  
      * However, for purposes of archiva, only the <repositories>
 257  
      * and <pluginRepositories> sections are of any value.
 258  
      * 
 259  
      * @param pom
 260  
      * @return
 261  
      */
 262  
     private ArchivaProjectModel mixinSuperPom( ArchivaProjectModel pom )
 263  
     {
 264  
         // TODO: add super pom repositories.
 265  0
         DEBUG( "Mix in Super POM: " + pom );
 266  
 
 267  0
         return pom;
 268  
     }
 269  
 
 270  
     private static Map<String, Dependency> createDependencyMap( List<Dependency> dependencies )
 271  
     {
 272  0
         Map<String, Dependency> ret = new HashMap<String, Dependency>();
 273  
 
 274  0
         Iterator<Dependency> it = dependencies.iterator();
 275  0
         while ( it.hasNext() )
 276  
         {
 277  0
             Dependency dep = it.next();
 278  0
             String key = toVersionlessDependencyKey( dep );
 279  0
             ret.put( key, dep );
 280  0
         }
 281  
 
 282  0
         return ret;
 283  
     }
 284  
 
 285  
     private static String toVersionlessDependencyKey( Dependency dep )
 286  
     {
 287  0
         StringBuffer key = new StringBuffer();
 288  
 
 289  0
         key.append( dep.getGroupId() ).append( ":" ).append( dep.getArtifactId() );
 290  0
         key.append( StringUtils.defaultString( dep.getClassifier() ) ).append( ":" );
 291  0
         key.append( dep.getType() );
 292  
 
 293  0
         return key.toString();
 294  
     }
 295  
 
 296  
     private String toProjectKey( ArchivaProjectModel project )
 297  
     {
 298  0
         StringBuffer key = new StringBuffer();
 299  
 
 300  0
         key.append( project.getGroupId() ).append( ":" );
 301  0
         key.append( project.getArtifactId() ).append( ":" );
 302  0
         key.append( project.getVersion() );
 303  
 
 304  0
         return key.toString();
 305  
     }
 306  
 
 307  
     private void DEBUG( String msg )
 308  
     {
 309  
         // Used in debugging of this object.
 310  
         // System.out.println( "[EffectiveProjectModelFilter] " + msg );
 311  0
     }
 312  
 }