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.shade.resource;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.StringReader;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.jar.JarEntry;
27  import java.util.jar.JarOutputStream;
28  
29  import org.apache.maven.plugins.shade.relocation.Relocator;
30  import org.jdom2.Attribute;
31  import org.jdom2.Content;
32  import org.jdom2.Document;
33  import org.jdom2.Element;
34  import org.jdom2.JDOMException;
35  import org.jdom2.input.SAXBuilder;
36  import org.jdom2.output.Format;
37  import org.jdom2.output.XMLOutputter;
38  import org.xml.sax.EntityResolver;
39  import org.xml.sax.InputSource;
40  import org.xml.sax.SAXException;
41  
42  /**
43   * Appends multiple occurrences of some XML file.
44   */
45  public class XmlAppendingTransformer extends AbstractCompatibilityTransformer {
46      public static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";
47  
48      boolean ignoreDtd = true;
49  
50      String resource;
51  
52      Document doc;
53  
54      private long time = Long.MIN_VALUE;
55  
56      public boolean canTransformResource(String r) {
57          return resource != null && resource.equalsIgnoreCase(r);
58      }
59  
60      public void processResource(String resource, InputStream is, List<Relocator> relocators, long time)
61              throws IOException {
62          Document r;
63          try {
64              SAXBuilder builder = new SAXBuilder(false);
65              builder.setExpandEntities(false);
66              if (ignoreDtd) {
67                  builder.setEntityResolver(new EntityResolver() {
68                      public InputSource resolveEntity(String publicId, String systemId)
69                              throws SAXException, IOException {
70                          return new InputSource(new StringReader(""));
71                      }
72                  });
73              }
74              r = builder.build(is);
75          } catch (JDOMException e) {
76              throw new RuntimeException("Error processing resource " + resource + ": " + e.getMessage(), e);
77          }
78  
79          if (doc == null) {
80              doc = r;
81          } else {
82              Element root = r.getRootElement();
83  
84              for (Iterator<Attribute> itr = root.getAttributes().iterator(); itr.hasNext(); ) {
85                  Attribute a = itr.next();
86                  itr.remove();
87  
88                  Element mergedEl = doc.getRootElement();
89                  Attribute mergedAtt = mergedEl.getAttribute(a.getName(), a.getNamespace());
90                  if (mergedAtt == null) {
91                      mergedEl.setAttribute(a);
92                  }
93              }
94  
95              for (Iterator<Element> itr = root.getChildren().iterator(); itr.hasNext(); ) {
96                  Content n = itr.next();
97                  itr.remove();
98  
99                  doc.getRootElement().addContent(n);
100             }
101         }
102 
103         if (time > this.time) {
104             this.time = time;
105         }
106     }
107 
108     public boolean hasTransformedResource() {
109         return doc != null;
110     }
111 
112     public void modifyOutputStream(JarOutputStream jos) throws IOException {
113         JarEntry jarEntry = new JarEntry(resource);
114         jarEntry.setTime(time);
115         jos.putNextEntry(jarEntry);
116 
117         new XMLOutputter(Format.getPrettyFormat()).output(doc, jos);
118 
119         doc = null;
120     }
121 }