View Javadoc
1   package org.apache.maven.plugin.invoker;
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 java.io.File;
23  import java.io.IOException;
24  import java.io.Reader;
25  import java.io.Writer;
26  import java.text.SimpleDateFormat;
27  import java.util.Collection;
28  import java.util.Date;
29  import java.util.LinkedHashSet;
30  import java.util.Set;
31  import java.util.TimeZone;
32  
33  import org.apache.maven.artifact.Artifact;
34  import org.codehaus.plexus.util.IOUtil;
35  import org.codehaus.plexus.util.ReaderFactory;
36  import org.codehaus.plexus.util.WriterFactory;
37  import org.codehaus.plexus.util.xml.Xpp3Dom;
38  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
39  import org.codehaus.plexus.util.xml.Xpp3DomUtils;
40  import org.codehaus.plexus.util.xml.Xpp3DomWriter;
41  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
42  
43  /**
44   * Provides utility methods for artifact metadata processing.
45   * 
46   * @author Benjamin Bentmann
47   */
48  class MetadataUtils
49  {
50  
51      /**
52       * Creates local metadata files for the specified artifact. The goal is to simulate the installation of the artifact
53       * by a local build, thereby decoupling the forked builds from the inderministic collection of remote repositories
54       * that are available to the main build and from which the artifact was originally resolved.
55       * 
56       * @param file The artifact's file in the local test repository, must not be <code>null</code>.
57       * @param artifact The artifact to create metadata for, must not be <code>null</code>.
58       * @throws IOException If the metadata could not be created.
59       */
60      public static void createMetadata( File file, Artifact artifact )
61          throws IOException
62      {
63          TimeZone tz = java.util.TimeZone.getTimeZone( "UTC" );
64          SimpleDateFormat fmt = new SimpleDateFormat( "yyyyMMddHHmmss" );
65          fmt.setTimeZone( tz );
66          String timestamp = fmt.format( new Date() );
67  
68          if ( artifact.isSnapshot() )
69          {
70              File metadataFile = new File( file.getParentFile(), "maven-metadata-local.xml" );
71  
72              Xpp3Dom metadata = new Xpp3Dom( "metadata" );
73              addChild( metadata, "groupId", artifact.getGroupId() );
74              addChild( metadata, "artifactId", artifact.getArtifactId() );
75              addChild( metadata, "version", artifact.getBaseVersion() );
76              Xpp3Dom versioning = new Xpp3Dom( "versioning" );
77              versioning.addChild( addChild( new Xpp3Dom( "snapshot" ), "localCopy", "true" ) );
78              addChild( versioning, "lastUpdated", timestamp );
79              metadata.addChild( versioning );
80  
81              writeMetadata( metadataFile, metadata );
82          }
83  
84          File metadataFile = new File( file.getParentFile().getParentFile(), "maven-metadata-local.xml" );
85  
86          Set<String> allVersions = new LinkedHashSet<String>();
87  
88          Xpp3Dom metadata = readMetadata( metadataFile );
89  
90          if ( metadata != null )
91          {
92              Xpp3Dom versioning = metadata.getChild( "versioning" );
93              if ( versioning != null )
94              {
95                  Xpp3Dom versions = versioning.getChild( "versions" );
96                  if ( versions != null )
97                  {
98  
99                      Xpp3Dom[] children = versions.getChildren( "version" );
100                     for ( Xpp3Dom aChildren : children )
101                     {
102                         allVersions.add( aChildren.getValue() );
103                     }
104                 }
105             }
106         }
107 
108         allVersions.add( artifact.getBaseVersion() );
109 
110         metadata = new Xpp3Dom( "metadata" );
111         addChild( metadata, "groupId", artifact.getGroupId() );
112         addChild( metadata, "artifactId", artifact.getArtifactId() );
113         Xpp3Dom versioning = new Xpp3Dom( "versioning" );
114         versioning.addChild( addChildren( new Xpp3Dom( "versions" ), "version", allVersions ) );
115         addChild( versioning, "lastUpdated", timestamp );
116         metadata.addChild( versioning );
117 
118         metadata = Xpp3DomUtils.mergeXpp3Dom( metadata, readMetadata( metadataFile ) );
119 
120         writeMetadata( metadataFile, metadata );
121     }
122 
123     private static Xpp3Dom addChild( Xpp3Dom parent, String childName, String childValue )
124     {
125         Xpp3Dom child = new Xpp3Dom( childName );
126         child.setValue( childValue );
127         parent.addChild( child );
128         return parent;
129     }
130 
131     private static Xpp3Dom addChildren( Xpp3Dom parent, String childName, Collection<String> childValues )
132     {
133         for ( String childValue : childValues )
134         {
135             addChild( parent, childName, childValue );
136         }
137         return parent;
138     }
139 
140     private static Xpp3Dom readMetadata( File metadataFile )
141         throws IOException
142     {
143         if ( !metadataFile.isFile() )
144         {
145             return null;
146         }
147 
148         Reader reader = ReaderFactory.newXmlReader( metadataFile );
149         try
150         {
151             try
152             {
153                 return Xpp3DomBuilder.build( reader );
154             }
155             catch ( XmlPullParserException e )
156             {
157                 throw (IOException) new IOException( e.getMessage() ).initCause( e );
158             }
159         }
160         finally
161         {
162             IOUtil.close( reader );
163         }
164     }
165 
166     private static void writeMetadata( File metadataFile, Xpp3Dom metadata )
167         throws IOException
168     {
169         metadataFile.getParentFile().mkdirs();
170 
171         Writer writer = WriterFactory.newXmlWriter( metadataFile );
172         try
173         {
174             Xpp3DomWriter.write( writer, metadata );
175         }
176         finally
177         {
178             IOUtil.close( writer );
179         }
180     }
181 
182 }