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