1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.shade.resource;
20
21 import java.io.BufferedInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.Reader;
26 import java.io.Writer;
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.jar.JarEntry;
30 import java.util.jar.JarOutputStream;
31
32 import org.apache.maven.plugins.shade.relocation.Relocator;
33 import org.codehaus.plexus.util.ReaderFactory;
34 import org.codehaus.plexus.util.WriterFactory;
35 import org.codehaus.plexus.util.xml.Xpp3Dom;
36 import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
37 import org.codehaus.plexus.util.xml.Xpp3DomWriter;
38
39
40
41
42
43
44
45 public class PluginXmlResourceTransformer extends AbstractCompatibilityTransformer {
46 private List<Xpp3Dom> mojos = new ArrayList<>();
47
48 private long time = Long.MIN_VALUE;
49
50 public static final String PLUGIN_XML_PATH = "META-INF/maven/plugin.xml";
51
52 public boolean canTransformResource(String resource) {
53 return PLUGIN_XML_PATH.equals(resource);
54 }
55
56 public void processResource(String resource, InputStream is, List<Relocator> relocators, long time)
57 throws IOException {
58 Xpp3Dom newDom;
59
60 try {
61 BufferedInputStream bis = new BufferedInputStream(is) {
62 public void close() throws IOException {
63
64 }
65 };
66
67 Reader reader = ReaderFactory.newXmlReader(bis);
68
69 newDom = Xpp3DomBuilder.build(reader);
70 } catch (Exception e) {
71 throw new IOException("Error parsing plugin.xml in " + is, e);
72 }
73
74
75 if (newDom.getChild("mojos") == null) {
76 return;
77 }
78
79 if (time > this.time) {
80 this.time = time;
81 }
82
83 for (Xpp3Dom mojo : newDom.getChild("mojos").getChildren("mojo")) {
84
85 String impl = getValue(mojo, "implementation");
86 impl = getRelocatedClass(impl, relocators);
87 setValue(mojo, "implementation", impl);
88
89 Xpp3Dom parameters = mojo.getChild("parameters");
90 if (parameters != null) {
91 for (Xpp3Dom parameter : parameters.getChildren()) {
92 String type = getValue(parameter, "type");
93 type = getRelocatedClass(type, relocators);
94 setValue(parameter, "type", type);
95 }
96 }
97
98 Xpp3Dom configuration = mojo.getChild("configuration");
99 if (configuration != null) {
100 for (Xpp3Dom configurationEntry : configuration.getChildren()) {
101 String implementation = getAttribute(configurationEntry, "implementation");
102 implementation = getRelocatedClass(implementation, relocators);
103 setAttribute(configurationEntry, "implementation", implementation);
104 }
105 }
106
107 Xpp3Dom requirements = mojo.getChild("requirements");
108 if (requirements != null && requirements.getChildCount() > 0) {
109 for (Xpp3Dom requirement : requirements.getChildren()) {
110 String requiredRole = getValue(requirement, "role");
111 requiredRole = getRelocatedClass(requiredRole, relocators);
112 setValue(requirement, "role", requiredRole);
113 }
114 }
115 mojos.add(mojo);
116 }
117 }
118
119 public void modifyOutputStream(JarOutputStream jos) throws IOException {
120 byte[] data = getTransformedResource();
121
122 JarEntry jarEntry = new JarEntry(PLUGIN_XML_PATH);
123 jarEntry.setTime(time);
124 jos.putNextEntry(jarEntry);
125
126 jos.write(data);
127
128 mojos.clear();
129 }
130
131 public boolean hasTransformedResource() {
132 return !mojos.isEmpty();
133 }
134
135 byte[] getTransformedResource() throws IOException {
136 ByteArrayOutputStream baos = new ByteArrayOutputStream(1024 * 4);
137
138 try (Writer writer = WriterFactory.newXmlWriter(baos)) {
139 Xpp3Dom dom = new Xpp3Dom("plugin");
140
141 Xpp3Dom componentDom = new Xpp3Dom("mojos");
142
143 dom.addChild(componentDom);
144
145 for (Xpp3Dom mojo : mojos) {
146 componentDom.addChild(mojo);
147 }
148
149 Xpp3DomWriter.write(writer, dom);
150 }
151
152 return baos.toByteArray();
153 }
154
155 private String getRelocatedClass(String className, List<Relocator> relocators) {
156 if (className != null && className.length() > 0 && relocators != null) {
157 for (Relocator relocator : relocators) {
158 if (relocator.canRelocateClass(className)) {
159 return relocator.relocateClass(className);
160 }
161 }
162 }
163
164 return className;
165 }
166
167 private static String getValue(Xpp3Dom dom, String element) {
168 Xpp3Dom child = dom.getChild(element);
169
170 return (child != null && child.getValue() != null) ? child.getValue() : "";
171 }
172
173 private static void setValue(Xpp3Dom dom, String element, String value) {
174 Xpp3Dom child = dom.getChild(element);
175
176 if (child == null || value == null || value.length() <= 0) {
177 return;
178 }
179
180 child.setValue(value);
181 }
182
183 private static String getAttribute(Xpp3Dom dom, String attribute) {
184 return (dom.getAttribute(attribute) != null) ? dom.getAttribute(attribute) : "";
185 }
186
187 private static void setAttribute(Xpp3Dom dom, String attribute, String value) {
188 String attr = dom.getAttribute(attribute);
189
190 if (attr == null || value == null || value.length() <= 0) {
191 return;
192 }
193
194 dom.setAttribute(attribute, value);
195 }
196 }