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