View Javadoc

1   package org.apache.maven.plugin.war.overlay;
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.maven.artifact.Artifact;
23  import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
24  import org.apache.maven.plugin.war.Overlay;
25  import org.apache.maven.project.MavenProject;
26  import org.codehaus.plexus.util.StringUtils;
27  
28  import java.util.ArrayList;
29  import java.util.Arrays;
30  import java.util.Iterator;
31  import java.util.List;
32  import java.util.ListIterator;
33  import java.util.Set;
34  
35  /**
36   * Manages the overlays.
37   *
38   * @author Stephane Nicoll
39   * 
40   * @version $Id: OverlayManager.java 985595 2010-08-14 22:29:50Z dennisl $
41   */
42  public class OverlayManager
43  {
44      private final List overlays;
45  
46      private final MavenProject project;
47  
48      private final List artifactsOverlays;
49  
50      /**
51       * Creates a manager with the specified overlays.
52       * <p/>
53       * Note that the list is potentially updated by the
54       * manager so a new list is created based on the overlays.
55       *
56       * @param overlays        the overlays
57       * @param project         the maven project
58       * @param defaultIncludes the default includes to use
59       * @param defaultExcludes the default excludes to use
60       * @param currentProjectOverlay the overlay for the current project
61       * @throws InvalidOverlayConfigurationException
62       *          if the config is invalid
63       */
64      public OverlayManager( List overlays, MavenProject project, String defaultIncludes, String defaultExcludes,
65                             Overlay currentProjectOverlay )
66          throws InvalidOverlayConfigurationException
67      {
68          this.overlays = new ArrayList();
69          if ( overlays != null )
70          {
71              this.overlays.addAll( overlays );
72          }
73          this.project = project;
74  
75          this.artifactsOverlays = getOverlaysAsArtifacts();
76  
77          // Initialize
78          initialize( defaultIncludes, defaultExcludes, currentProjectOverlay );
79  
80      }
81  
82  
83      /**
84       * Returns the resolved overlays.
85       *
86       * @return the overlays
87       */
88      public List getOverlays()
89      {
90          return overlays;
91      }
92  
93      /**
94       * Returns the id of the resolved overlays.
95       *
96       * @return the overlay ids
97       */
98      public List getOverlayIds()
99      {
100         final Iterator it = overlays.iterator();
101         final List result = new ArrayList();
102         while ( it.hasNext() )
103         {
104             Overlay overlay = (Overlay) it.next();
105             result.add( overlay.getId() );
106         }
107         return result;
108 
109     }
110 
111     /**
112      * Intializes the manager and validates the overlays configuration.
113      *
114      * @param defaultIncludes the default includes to use
115      * @param defaultExcludes the default excludes to use
116      * @param currentProjectOverlay  the overlay for the current project
117      * @throws InvalidOverlayConfigurationException
118      *          if the configuration is invalid
119      */
120     void initialize( String defaultIncludes, String defaultExcludes, Overlay currentProjectOverlay )
121         throws InvalidOverlayConfigurationException
122     {
123 
124         // Build the list of configured artifacts and makes sure that each overlay
125         // refer to a valid artifact
126         final List configuredWarArtifacts = new ArrayList();
127         final ListIterator it = overlays.listIterator();
128         while ( it.hasNext() )
129         {
130             Overlay overlay = (Overlay) it.next();
131             if ( overlay == null )
132             {
133                 throw new InvalidOverlayConfigurationException( "overlay could not be null." );
134             }
135             // If it's the current project, return the project instance
136             if ( overlay.isCurrentProject() )
137             {
138                 overlay = currentProjectOverlay;
139                 it.set( overlay );
140             }
141             // default includes/excludes - only if the overlay uses the default settings
142             if ( Arrays.equals( Overlay.DEFAULT_INCLUDES, overlay.getIncludes() )
143                 && Arrays.equals( Overlay.DEFAULT_EXCLUDES, overlay.getExcludes() ) )
144             {
145                 overlay.setIncludes( defaultIncludes );
146                 overlay.setExcludes( defaultExcludes );
147             }
148 
149             final Artifact artifact = getAssociatedArtifact( overlay );
150             if ( artifact != null )
151             {
152                 configuredWarArtifacts.add( artifact );
153                 overlay.setArtifact( artifact );
154             }
155         }
156 
157         // Build the list of missing overlays
158         final Iterator it2 = artifactsOverlays.iterator();
159         while ( it2.hasNext() )
160         {
161             Artifact artifact = (Artifact) it2.next();
162             if ( !configuredWarArtifacts.contains( artifact ) )
163             {
164                 // Add a default overlay for the given artifact which will be applied after
165                 // the ones that have been configured
166                 overlays.add( new DefaultOverlay( artifact, defaultIncludes, defaultExcludes ) );
167             }
168         }
169 
170         // Final validation, make sure that the current project is in there. Otherwise add it first
171         final Iterator it3 = overlays.iterator();
172         while ( it3.hasNext() )
173         {
174             Overlay overlay = (Overlay) it3.next();
175             if ( overlay.equals( currentProjectOverlay ) )
176             {
177                 return;
178             }
179         }
180         overlays.add( 0, currentProjectOverlay );
181     }
182 
183     /**
184      * Returns the Artifact associated to the specified overlay.
185      * <p/>
186      * If the overlay defines the current project, <tt>null</tt> is
187      * returned. If no artifact could not be found for the overlay
188      * a InvalidOverlayConfigurationException is thrown.
189      *
190      * @param overlay an overlay
191      * @return the artifact associated to the overlay
192      * @throws org.apache.maven.plugin.war.overlay.InvalidOverlayConfigurationException
193      *          if the overlay does not have an associated artifact
194      */
195     Artifact getAssociatedArtifact( final Overlay overlay )
196         throws InvalidOverlayConfigurationException
197     {
198         if ( overlay.isCurrentProject() )
199         {
200             return null;
201         }
202 
203         for ( Iterator iterator = artifactsOverlays.iterator(); iterator.hasNext(); )
204         {
205             // Handle classifier dependencies properly (clash management)
206             Artifact artifact = (Artifact) iterator.next();
207             if ( compareOverlayWithArtifact( overlay, artifact ) )
208             {
209                 return artifact;
210             }
211         }
212 
213         // maybe its a project dependencies zip or an other type
214         Set projectArtifacts = this.project.getDependencyArtifacts();
215         if ( projectArtifacts != null )
216         {
217             for ( Iterator iterator = projectArtifacts.iterator(); iterator.hasNext(); )
218             {
219                 Artifact artifact = (Artifact) iterator.next();
220                 if ( compareOverlayWithArtifact( overlay, artifact ) )
221                 {
222                     return artifact;
223                 }
224             }
225         }
226         throw new InvalidOverlayConfigurationException(
227             "overlay [" + overlay + "] is not a dependency of the project." );
228 
229     }
230 
231     /**
232      * compare groupId && artifactId && Type && classifier
233      * @param overlay the overlay
234      * @param artifact the artifact
235      * @return boolean true if equals
236      */
237     private boolean compareOverlayWithArtifact( Overlay overlay, Artifact artifact )
238     {
239         return ( StringUtils.equals( overlay.getGroupId(), artifact.getGroupId() )
240             && StringUtils.equals( overlay.getArtifactId(), artifact.getArtifactId() )
241             && StringUtils.equals( overlay.getType(), artifact.getType() )
242             && StringUtils.equals( overlay.getClassifier(), artifact.getClassifier() ) );
243     }
244 
245     /**
246      * Returns a list of WAR {@link org.apache.maven.artifact.Artifact} describing
247      * the overlays of the current project.
248      *
249      * @return the overlays as artifacts objects
250      */
251     private List getOverlaysAsArtifacts()
252     {
253         ScopeArtifactFilter filter = new ScopeArtifactFilter( Artifact.SCOPE_RUNTIME );
254         final Set artifacts = project.getArtifacts();
255         final Iterator it = artifacts.iterator();
256 
257         final List result = new ArrayList();
258         while ( it.hasNext() )
259         {
260             Artifact artifact = (Artifact) it.next();
261             if ( !artifact.isOptional() && filter.include( artifact ) && ( "war".equals( artifact.getType() ) ) )
262             {
263                 result.add( artifact );
264             }
265         }
266         return result;
267     }
268 }