View Javadoc
1   /*
2    * Licensed under the Apache License, Version 2.0 (the "License");
3    * you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at
5    *
6    * http://www.apache.org/licenses/LICENSE-2.0
7    *
8    * Unless required by applicable law or agreed to in writing, software
9    * distributed under the License is distributed on an "AS IS" BASIS,
10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11   * See the License for the specific language governing permissions and
12   * limitations under the License.
13   */
14  
15  package org.basepom.inline.mojo;
16  
17  import static java.lang.String.format;
18  
19  import java.io.IOException;
20  import java.io.StringReader;
21  import java.io.Writer;
22  import java.util.List;
23  import javax.xml.stream.XMLInputFactory;
24  import javax.xml.stream.XMLStreamException;
25  import javax.xml.stream.XMLStreamReader;
26  
27  import com.google.common.base.Strings;
28  import com.google.common.collect.Iterables;
29  import org.eclipse.aether.graph.Dependency;
30  import org.eclipse.aether.util.artifact.JavaScopes;
31  import org.jdom2.Content;
32  import org.jdom2.Content.CType;
33  import org.jdom2.Document;
34  import org.jdom2.Element;
35  import org.jdom2.JDOMException;
36  import org.jdom2.Namespace;
37  import org.jdom2.Text;
38  import org.jdom2.filter.Filters;
39  import org.jdom2.input.StAXStreamBuilder;
40  import org.jdom2.output.Format;
41  import org.jdom2.output.LineSeparator;
42  import org.jdom2.output.XMLOutputter;
43  import org.jdom2.xpath.XPathExpression;
44  import org.jdom2.xpath.XPathFactory;
45  
46  final class PomUtil {
47  
48      private final Document pomDocument;
49  
50      PomUtil(String pomText) throws XMLStreamException, JDOMException {
51          final XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
52          final XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(new StringReader(pomText));
53          final StAXStreamBuilder builder = new StAXStreamBuilder();
54          this.pomDocument = builder.build(reader);
55      }
56  
57      void writePom(Writer writer) throws IOException {
58          // this is a hack because jdom2 has the annoying habit of removing a newline between
59          // a leading comment and the root element.
60          if (pomDocument.getContentSize() > 1
61                  && pomDocument.getContent(0).getCType() == CType.Comment
62                  && pomDocument.getContent(1).getCType() == CType.Element) {
63              this.pomDocument.addContent(1, new Text("\n"));
64          }
65  
66          XMLOutputter xml = new XMLOutputter();
67          xml.setFormat(Format.getPrettyFormat()
68                  .setLineSeparator(LineSeparator.SYSTEM));
69          xml.output(pomDocument, writer);
70          writer.flush();
71      }
72  
73      void removeDependency(Dependency dependency) {
74          Namespace pomNs = Namespace.getNamespace("pom", pomDocument.getRootElement().getNamespaceURI());
75          XPathFactory xpathFactory = XPathFactory.instance();
76          final var artifact = dependency.getArtifact();
77          String xpathExpression;
78  
79          if (Strings.emptyToNull(artifact.getClassifier()) == null) {
80              xpathExpression =
81                      format("//pom:dependencies/pom:dependency[pom:artifactId[text() = '%s'] and pom:groupId[text() = '%s'] and not(pom:classifier) ]",
82                              artifact.getArtifactId(), artifact.getGroupId());
83          } else {
84              xpathExpression =
85                      format("//pom:dependencies/pom:dependency[pom:artifactId[text() = '%s'] and pom:groupId[text() = '%s'] and pom:classifier[text() = '%s']]",
86                              artifact.getArtifactId(), artifact.getGroupId(), artifact.getClassifier());
87          }
88  
89          XPathExpression<Content> dependencies = xpathFactory.compile(xpathExpression, Filters.content(), null, pomNs);
90          List<Content> contents = dependencies.evaluate(pomDocument.getRootElement());
91          for (Content content : contents) {
92              content.getParentElement().removeContent(content);
93          }
94      }
95  
96      void addDependency(Dependency dependency) {
97          Namespace pomNs = Namespace.getNamespace("pom", pomDocument.getRootElement().getNamespaceURI());
98          XPathFactory xpathFactory = XPathFactory.instance();
99  
100         XPathExpression<Content> dependencies = xpathFactory.compile("/pom:project/pom:dependencies", Filters.content(), null, pomNs);
101         Content content = Iterables.getOnlyElement(dependencies.evaluate(pomDocument.getRootElement()));
102 
103         Namespace newNs = pomDocument.getRootElement().getNamespace();
104 
105         Element dependencyElement = new Element("dependency", newNs);
106         dependencyElement.addContent(new Element("groupId", newNs).addContent(dependency.getArtifact().getGroupId()));
107         dependencyElement.addContent(new Element("artifactId", newNs).addContent(dependency.getArtifact().getArtifactId()));
108         dependencyElement.addContent(new Element("version", newNs).addContent(dependency.getArtifact().getVersion()));
109 
110         String scope = dependency.getScope();
111         if (Strings.emptyToNull(scope) != null && !JavaScopes.COMPILE.equals(scope)) {
112             dependencyElement.addContent(new Element("scope", newNs).addContent(scope));
113         }
114 
115         if (dependency.isOptional()) {
116             dependencyElement.addContent(new Element("optional", newNs).addContent("true"));
117         }
118 
119         ((Element) content).addContent(dependencyElement);
120     }
121 }