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.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.File;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.nio.charset.Charset;
28 import java.nio.charset.StandardCharsets;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collections;
32 import java.util.List;
33 import java.util.jar.JarEntry;
34 import java.util.jar.JarFile;
35 import java.util.jar.JarOutputStream;
36
37 import org.apache.maven.plugins.shade.relocation.Relocator;
38 import org.apache.maven.plugins.shade.relocation.SimpleRelocator;
39 import org.junit.Test;
40
41 import static org.junit.Assert.assertEquals;
42 import static org.junit.Assert.assertNotNull;
43 import static org.junit.Assert.assertTrue;
44
45
46
47
48 public class ServiceResourceTransformerTest {
49 private final String newline = "\n";
50
51 private final List<Relocator> relocators = new ArrayList<>();
52
53 @Test
54 public void relocatedClasses() throws Exception {
55 SimpleRelocator relocator =
56 new SimpleRelocator("org.foo", "borg.foo", null, Arrays.asList("org.foo.exclude.*"));
57 relocators.add(relocator);
58
59 String content = "org.foo.Service\norg.foo.exclude.OtherService\n";
60 byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8);
61 InputStream contentStream = new ByteArrayInputStream(contentBytes);
62 String contentResource = "META-INF/services/org.foo.something.another";
63 String contentResourceShaded = "META-INF/services/borg.foo.something.another";
64
65 ServicesResourceTransformer xformer = new ServicesResourceTransformer();
66 xformer.processResource(contentResource, contentStream, relocators, 0);
67 contentStream.close();
68
69 File tempJar = File.createTempFile("shade.", ".jar");
70 tempJar.deleteOnExit();
71 FileOutputStream fos = new FileOutputStream(tempJar);
72 try (JarOutputStream jos = new JarOutputStream(fos)) {
73 xformer.modifyOutputStream(jos);
74 jos.close();
75
76 JarFile jarFile = new JarFile(tempJar);
77 JarEntry jarEntry = jarFile.getJarEntry(contentResourceShaded);
78 assertNotNull(jarEntry);
79 try (InputStream entryStream = jarFile.getInputStream(jarEntry)) {
80 String xformedContent = toString(entryStream, StandardCharsets.UTF_8);
81 assertEquals("borg.foo.Service" + newline + "org.foo.exclude.OtherService" + newline, xformedContent);
82 } finally {
83 jarFile.close();
84 }
85 } finally {
86 tempJar.delete();
87 }
88 }
89
90 @Test
91 public void mergeRelocatedFiles() throws Exception {
92 SimpleRelocator relocator =
93 new SimpleRelocator("org.foo", "borg.foo", null, Collections.singletonList("org.foo.exclude.*"));
94 relocators.add(relocator);
95
96 String content = "org.foo.Service" + newline + "org.foo.exclude.OtherService" + newline;
97 String contentShaded = "borg.foo.Service" + newline + "org.foo.exclude.OtherService" + newline;
98 byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8);
99 String contentResource = "META-INF/services/org.foo.something.another";
100 String contentResourceShaded = "META-INF/services/borg.foo.something.another";
101
102 ServicesResourceTransformer xformer = new ServicesResourceTransformer();
103
104 try (InputStream contentStream = new ByteArrayInputStream(contentBytes)) {
105 xformer.processResource(contentResource, contentStream, relocators, 0);
106 }
107
108 try (InputStream contentStream = new ByteArrayInputStream(contentBytes)) {
109 xformer.processResource(contentResourceShaded, contentStream, relocators, 0);
110 }
111
112 File tempJar = File.createTempFile("shade.", ".jar");
113 tempJar.deleteOnExit();
114 FileOutputStream fos = new FileOutputStream(tempJar);
115 try (JarOutputStream jos = new JarOutputStream(fos)) {
116 xformer.modifyOutputStream(jos);
117 jos.close();
118
119 JarFile jarFile = new JarFile(tempJar);
120 JarEntry jarEntry = jarFile.getJarEntry(contentResourceShaded);
121 assertNotNull(jarEntry);
122 try (InputStream entryStream = jarFile.getInputStream(jarEntry)) {
123 String xformedContent = toString(entryStream, StandardCharsets.UTF_8);
124 assertEquals(contentShaded, xformedContent);
125 } finally {
126 jarFile.close();
127 }
128 } finally {
129 tempJar.delete();
130 }
131 }
132
133 @Test
134 public void concatanationAppliedMultipleTimes() throws Exception {
135 SimpleRelocator relocator = new SimpleRelocator("org.eclipse", "org.eclipse1234", null, null);
136 relocators.add(relocator);
137
138 String content = "org.eclipse.osgi.launch.EquinoxFactory\n";
139 byte[] contentBytes = content.getBytes("UTF-8");
140 InputStream contentStream = new ByteArrayInputStream(contentBytes);
141 String contentResource = "META-INF/services/org.osgi.framework.launch.FrameworkFactory";
142
143 ServicesResourceTransformer xformer = new ServicesResourceTransformer();
144 xformer.processResource(contentResource, contentStream, relocators, 0);
145 contentStream.close();
146
147 File tempJar = File.createTempFile("shade.", ".jar");
148 tempJar.deleteOnExit();
149 FileOutputStream fos = new FileOutputStream(tempJar);
150 try (JarOutputStream jos = new JarOutputStream(fos)) {
151 xformer.modifyOutputStream(jos);
152 jos.close();
153
154 JarFile jarFile = new JarFile(tempJar);
155 JarEntry jarEntry = jarFile.getJarEntry(contentResource);
156 assertNotNull(jarEntry);
157 try (InputStream entryStream = jarFile.getInputStream(jarEntry)) {
158 String xformedContent = toString(entryStream, StandardCharsets.UTF_8);
159 assertEquals("org.eclipse1234.osgi.launch.EquinoxFactory" + newline, xformedContent);
160 } finally {
161 jarFile.close();
162 }
163 } finally {
164 tempJar.delete();
165 }
166 }
167
168 @Test
169 public void concatenation() throws Exception {
170 SimpleRelocator relocator = new SimpleRelocator("org.foo", "borg.foo", null, null);
171 relocators.add(relocator);
172
173 String content = "org.foo.Service\n";
174 byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8);
175 InputStream contentStream = new ByteArrayInputStream(contentBytes);
176 String contentResource = "META-INF/services/org.something.another";
177
178 ServicesResourceTransformer xformer = new ServicesResourceTransformer();
179 xformer.processResource(contentResource, contentStream, relocators, 0);
180 contentStream.close();
181
182 content = "org.blah.Service\n";
183 contentBytes = content.getBytes(StandardCharsets.UTF_8);
184 contentStream = new ByteArrayInputStream(contentBytes);
185 contentResource = "META-INF/services/org.something.another";
186
187 xformer.processResource(contentResource, contentStream, relocators, 0);
188 contentStream.close();
189
190 File tempJar = File.createTempFile("shade.", ".jar");
191 tempJar.deleteOnExit();
192 FileOutputStream fos = new FileOutputStream(tempJar);
193 try (JarOutputStream jos = new JarOutputStream(fos)) {
194 xformer.modifyOutputStream(jos);
195 jos.close();
196
197 JarFile jarFile = new JarFile(tempJar);
198 JarEntry jarEntry = jarFile.getJarEntry(contentResource);
199 assertNotNull(jarEntry);
200 try (InputStream entryStream = jarFile.getInputStream(jarEntry)) {
201 String xformedContent = toString(entryStream, StandardCharsets.UTF_8);
202
203 String[] classes = xformedContent.split("\r?\n");
204 boolean h1 = false;
205 boolean h2 = false;
206 for (String name : classes) {
207 if ("org.blah.Service".equals(name)) {
208 h1 = true;
209 } else if ("borg.foo.Service".equals(name)) {
210 h2 = true;
211 }
212 }
213 assertTrue(h1 && h2);
214 } finally {
215 jarFile.close();
216 }
217 } finally {
218 tempJar.delete();
219 }
220 }
221
222 private static String toString(InputStream stream, Charset charset) throws IOException {
223 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
224 byte[] data = new byte[8192];
225 int read;
226 while ((read = stream.read(data, 0, data.length)) != -1) {
227 buffer.write(data, 0, read);
228 }
229 return new String(buffer.toByteArray(), charset);
230 }
231 }