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 @Override
53 public boolean canTransformResource(String resource) {
54 return PLUGIN_XML_PATH.equals(resource);
55 }
56
57 @Override
58 public void processResource(String resource, InputStream is, List<Relocator> relocators, long time)
59 throws IOException {
60 Xpp3Dom newDom;
61
62 try {
63 BufferedInputStream bis = new BufferedInputStream(is) {
64 @Override
65 public void close() throws IOException {
66
67 }
68 };
69
70 Reader reader = ReaderFactory.newXmlReader(bis);
71
72 newDom = Xpp3DomBuilder.build(reader);
73 } catch (Exception e) {
74 throw new IOException("Error parsing plugin.xml in " + is, e);
75 }
76
77
78 if (newDom.getChild("mojos") == null) {
79 return;
80 }
81
82 if (time > this.time) {
83 this.time = time;
84 }
85
86 for (Xpp3Dom mojo : newDom.getChild("mojos").getChildren("mojo")) {
87
88 String impl = getValue(mojo, "implementation");
89 impl = getRelocatedClass(impl, relocators);
90 setValue(mojo, "implementation", impl);
91
92 Xpp3Dom parameters = mojo.getChild("parameters");
93 if (parameters != null) {
94 for (Xpp3Dom parameter : parameters.getChildren()) {
95 String type = getValue(parameter, "type");
96 type = getRelocatedClass(type, relocators);
97 setValue(parameter, "type", type);
98 }
99 }
100
101 Xpp3Dom configuration = mojo.getChild("configuration");
102 if (configuration != null) {
103 for (Xpp3Dom configurationEntry : configuration.getChildren()) {
104 String implementation = getAttribute(configurationEntry, "implementation");
105 implementation = getRelocatedClass(implementation, relocators);
106 setAttribute(configurationEntry, "implementation", implementation);
107 }
108 }
109
110 Xpp3Dom requirements = mojo.getChild("requirements");
111 if (requirements != null && requirements.getChildCount() > 0) {
112 for (Xpp3Dom requirement : requirements.getChildren()) {
113 String requiredRole = getValue(requirement, "role");
114 requiredRole = getRelocatedClass(requiredRole, relocators);
115 setValue(requirement, "role", requiredRole);
116 }
117 }
118 mojos.add(mojo);
119 }
120 }
121
122 @Override
123 public void modifyOutputStream(JarOutputStream jos) throws IOException {
124 byte[] data = getTransformedResource();
125
126 JarEntry jarEntry = new JarEntry(PLUGIN_XML_PATH);
127 jarEntry.setTime(time);
128 jos.putNextEntry(jarEntry);
129
130 jos.write(data);
131
132 mojos.clear();
133 }
134
135 @Override
136 public boolean hasTransformedResource() {
137 return !mojos.isEmpty();
138 }
139
140 byte[] getTransformedResource() throws IOException {
141 ByteArrayOutputStream baos = new ByteArrayOutputStream(1024 * 4);
142
143 try (Writer writer = WriterFactory.newXmlWriter(baos)) {
144 Xpp3Dom dom = new Xpp3Dom("plugin");
145
146 Xpp3Dom componentDom = new Xpp3Dom("mojos");
147
148 dom.addChild(componentDom);
149
150 for (Xpp3Dom mojo : mojos) {
151 componentDom.addChild(mojo);
152 }
153
154 Xpp3DomWriter.write(writer, dom);
155 }
156
157 return baos.toByteArray();
158 }
159
160 private String getRelocatedClass(String className, List<Relocator> relocators) {
161 if (className != null && className.length() > 0 && relocators != null) {
162 for (Relocator relocator : relocators) {
163 if (relocator.canRelocateClass(className)) {
164 return relocator.relocateClass(className);
165 }
166 }
167 }
168
169 return className;
170 }
171
172 private static String getValue(Xpp3Dom dom, String element) {
173 Xpp3Dom child = dom.getChild(element);
174
175 return (child != null && child.getValue() != null) ? child.getValue() : "";
176 }
177
178 private static void setValue(Xpp3Dom dom, String element, String value) {
179 Xpp3Dom child = dom.getChild(element);
180
181 if (child == null || value == null || value.length() <= 0) {
182 return;
183 }
184
185 child.setValue(value);
186 }
187
188 private static String getAttribute(Xpp3Dom dom, String attribute) {
189 return (dom.getAttribute(attribute) != null) ? dom.getAttribute(attribute) : "";
190 }
191
192 private static void setAttribute(Xpp3Dom dom, String attribute, String value) {
193 String attr = dom.getAttribute(attribute);
194
195 if (attr == null || value == null || value.length() <= 0) {
196 return;
197 }
198
199 dom.setAttribute(attribute, value);
200 }
201 }