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.IOException;
23 import java.io.InputStream;
24 import java.nio.charset.StandardCharsets;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Scanner;
30 import java.util.jar.JarEntry;
31 import java.util.jar.JarOutputStream;
32
33 import org.apache.commons.io.IOUtils;
34 import org.apache.maven.plugins.shade.relocation.Relocator;
35
36
37
38
39
40
41
42
43 public class ServicesResourceTransformer
44 extends AbstractCompatibilityTransformer
45 {
46 private static final String SERVICES_PATH = "META-INF/services";
47
48 private final Map<String, ArrayList<String>> serviceEntries = new HashMap<>();
49
50 private long time = Long.MIN_VALUE;
51
52 public boolean canTransformResource( String resource )
53 {
54 return resource.startsWith( SERVICES_PATH );
55 }
56
57 public void processResource( String resource, InputStream is, final List<Relocator> relocators, long time )
58 throws IOException
59 {
60 resource = resource.substring( SERVICES_PATH.length() + 1 );
61 for ( Relocator relocator : relocators )
62 {
63 if ( relocator.canRelocateClass( resource ) )
64 {
65 resource = relocator.relocateClass( resource );
66 break;
67 }
68 }
69 resource = SERVICES_PATH + '/' + resource;
70
71 ArrayList<String> out = serviceEntries.computeIfAbsent( resource, k -> new ArrayList<>() );
72
73 Scanner scanner = new Scanner( is, StandardCharsets.UTF_8.name() );
74 while ( scanner.hasNextLine() )
75 {
76 String relContent = scanner.nextLine();
77 for ( Relocator relocator : relocators )
78 {
79 if ( relocator.canRelocateClass( relContent ) )
80 {
81 relContent = relocator.applyToSourceContent( relContent );
82 }
83 }
84 out.add( relContent );
85 }
86
87 if ( time > this.time )
88 {
89 this.time = time;
90 }
91 }
92
93 public boolean hasTransformedResource()
94 {
95 return !serviceEntries.isEmpty();
96 }
97
98 public void modifyOutputStream( JarOutputStream jos )
99 throws IOException
100 {
101 for ( Map.Entry<String, ArrayList<String>> entry : serviceEntries.entrySet() )
102 {
103 String key = entry.getKey();
104 ArrayList<String> data = entry.getValue();
105
106 JarEntry jarEntry = new JarEntry( key );
107 jarEntry.setTime( time );
108 jos.putNextEntry( jarEntry );
109
110 IOUtils.writeLines( data, "\n", jos, StandardCharsets.UTF_8 );
111 jos.flush();
112 data.clear();
113 }
114 }
115 }