View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.invoker;
20  
21  /*
22   * Licensed to the Apache Software Foundation (ASF) under one
23   * or more contributor license agreements.  See the NOTICE file
24   * distributed with this work for additional information
25   * regarding copyright ownership.  The ASF licenses this file
26   * to you under the Apache License, Version 2.0 (the
27   * "License"); you may not use this file except in compliance
28   * with the License.  You may obtain a copy of the License at
29   *
30   *   http://www.apache.org/licenses/LICENSE-2.0
31   *
32   * Unless required by applicable law or agreed to in writing,
33   * software distributed under the License is distributed on an
34   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
35   * KIND, either express or implied.  See the License for the
36   * specific language governing permissions and limitations
37   * under the License.
38   */
39  
40  import java.io.File;
41  import java.io.IOException;
42  import java.io.Reader;
43  import java.io.Writer;
44  import java.text.SimpleDateFormat;
45  import java.util.Collection;
46  import java.util.Date;
47  import java.util.LinkedHashSet;
48  import java.util.Set;
49  import java.util.TimeZone;
50  
51  import org.apache.maven.artifact.Artifact;
52  import org.codehaus.plexus.util.ReaderFactory;
53  import org.codehaus.plexus.util.WriterFactory;
54  import org.codehaus.plexus.util.xml.Xpp3Dom;
55  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
56  import org.codehaus.plexus.util.xml.Xpp3DomUtils;
57  import org.codehaus.plexus.util.xml.Xpp3DomWriter;
58  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
59  
60  /**
61   * Provides utility methods for artifact metadata processing.
62   *
63   * @author Benjamin Bentmann
64   */
65  class MetadataUtils {
66  
67      /**
68       * Creates local metadata files for the specified artifact. The goal is to simulate the installation of the artifact
69       * by a local build, thereby decoupling the forked builds from the inderministic collection of remote repositories
70       * that are available to the main build and from which the artifact was originally resolved.
71       *
72       * @param file The artifact's file in the local test repository, must not be <code>null</code>.
73       * @param artifact The artifact to create metadata for, must not be <code>null</code>.
74       * @throws IOException If the metadata could not be created.
75       */
76      public static void createMetadata(File file, Artifact artifact) throws IOException {
77          TimeZone tz = java.util.TimeZone.getTimeZone("UTC");
78          SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmss");
79          fmt.setTimeZone(tz);
80          String timestamp = fmt.format(new Date());
81  
82          if (artifact.isSnapshot()) {
83              File metadataFile = new File(file.getParentFile(), "maven-metadata-local.xml");
84  
85              Xpp3Dom metadata = new Xpp3Dom("metadata");
86              addChild(metadata, "groupId", artifact.getGroupId());
87              addChild(metadata, "artifactId", artifact.getArtifactId());
88              addChild(metadata, "version", artifact.getBaseVersion());
89              Xpp3Dom versioning = new Xpp3Dom("versioning");
90              versioning.addChild(addChild(new Xpp3Dom("snapshot"), "localCopy", "true"));
91              addChild(versioning, "lastUpdated", timestamp);
92              metadata.addChild(versioning);
93  
94              writeMetadata(metadataFile, metadata);
95          }
96  
97          File metadataFile = new File(file.getParentFile().getParentFile(), "maven-metadata-local.xml");
98  
99          Set<String> allVersions = new LinkedHashSet<>();
100 
101         Xpp3Dom metadata = readMetadata(metadataFile);
102 
103         if (metadata != null) {
104             Xpp3Dom versioning = metadata.getChild("versioning");
105             if (versioning != null) {
106                 Xpp3Dom versions = versioning.getChild("versions");
107                 if (versions != null) {
108 
109                     Xpp3Dom[] children = versions.getChildren("version");
110                     for (Xpp3Dom aChildren : children) {
111                         allVersions.add(aChildren.getValue());
112                     }
113                 }
114             }
115         }
116 
117         allVersions.add(artifact.getBaseVersion());
118 
119         metadata = new Xpp3Dom("metadata");
120         addChild(metadata, "groupId", artifact.getGroupId());
121         addChild(metadata, "artifactId", artifact.getArtifactId());
122         Xpp3Dom versioning = new Xpp3Dom("versioning");
123         versioning.addChild(addChildren(new Xpp3Dom("versions"), "version", allVersions));
124         addChild(versioning, "lastUpdated", timestamp);
125         metadata.addChild(versioning);
126 
127         metadata = Xpp3DomUtils.mergeXpp3Dom(metadata, readMetadata(metadataFile));
128 
129         writeMetadata(metadataFile, metadata);
130     }
131 
132     private static Xpp3Dom addChild(Xpp3Dom parent, String childName, String childValue) {
133         Xpp3Dom child = new Xpp3Dom(childName);
134         child.setValue(childValue);
135         parent.addChild(child);
136         return parent;
137     }
138 
139     private static Xpp3Dom addChildren(Xpp3Dom parent, String childName, Collection<String> childValues) {
140         for (String childValue : childValues) {
141             addChild(parent, childName, childValue);
142         }
143         return parent;
144     }
145 
146     private static Xpp3Dom readMetadata(File metadataFile) throws IOException {
147         if (!metadataFile.isFile()) {
148             return null;
149         }
150 
151         try (Reader reader = ReaderFactory.newXmlReader(metadataFile)) {
152             return Xpp3DomBuilder.build(reader);
153         } catch (XmlPullParserException e) {
154             throw new IOException(e.getMessage(), e);
155         }
156     }
157 
158     private static void writeMetadata(File metadataFile, Xpp3Dom metadata) throws IOException {
159         metadataFile.getParentFile().mkdirs();
160 
161         try (Writer writer = WriterFactory.newXmlWriter(metadataFile)) {
162             Xpp3DomWriter.write(writer, metadata);
163         }
164     }
165 }