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.BufferedReader;
23 import java.io.ByteArrayInputStream;
24 import java.io.ByteArrayOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.PrintWriter;
29 import java.io.StringReader;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.jar.JarEntry;
34 import java.util.jar.JarOutputStream;
35
36 import org.apache.commons.io.IOUtils;
37 import org.apache.maven.plugins.shade.relocation.Relocator;
38
39 import com.google.common.io.LineReader;
40
41
42
43
44
45
46
47
48 public class ServicesResourceTransformer
49 implements ResourceTransformer
50 {
51
52 private static final String SERVICES_PATH = "META-INF/services";
53
54 private Map<String, ServiceStream> serviceEntries = new HashMap<String, ServiceStream>();
55
56 private List<Relocator> relocators;
57
58 public boolean canTransformResource( String resource )
59 {
60 if ( resource.startsWith( SERVICES_PATH ) )
61 {
62 return true;
63 }
64
65 return false;
66 }
67
68 public void processResource( String resource, InputStream is, final List<Relocator> relocators )
69 throws IOException
70 {
71 ServiceStream out = serviceEntries.get( resource );
72 if ( out == null )
73 {
74 out = new ServiceStream();
75 serviceEntries.put( resource, out );
76 }
77
78 final ServiceStream fout = out;
79
80 final String content = IOUtils.toString( is );
81 StringReader reader = new StringReader( content );
82 LineReader lineReader = new LineReader( reader );
83 String line;
84 while ( ( line = lineReader.readLine() ) != null )
85 {
86 String relContent = line;
87 for ( Relocator relocator : relocators )
88 {
89 if ( relocator.canRelocateClass( relContent ) )
90 {
91 relContent = relocator.applyToSourceContent( relContent );
92 }
93 }
94 fout.append( relContent + "\n" );
95 }
96
97 if ( this.relocators == null )
98 {
99 this.relocators = relocators;
100 }
101 }
102 public boolean hasTransformedResource()
103 {
104 return serviceEntries.size() > 0;
105 }
106
107 public void modifyOutputStream( JarOutputStream jos )
108 throws IOException
109 {
110 for ( Map.Entry<String, ServiceStream> entry : serviceEntries.entrySet() )
111 {
112 String key = entry.getKey();
113 ServiceStream data = entry.getValue();
114
115 if ( relocators != null )
116 {
117 key = key.substring( SERVICES_PATH.length() + 1 );
118 for ( Relocator relocator : relocators )
119 {
120 if ( relocator.canRelocateClass( key ) )
121 {
122 key = relocator.relocateClass( key );
123 break;
124 }
125 }
126
127 key = SERVICES_PATH + '/' + key;
128 }
129
130 jos.putNextEntry( new JarEntry( key ) );
131
132
133
134 PrintWriter writer = new PrintWriter( jos );
135 InputStreamReader streamReader = new InputStreamReader( data.toInputStream() );
136 BufferedReader reader = new BufferedReader( streamReader );
137 String className;
138
139 while ( ( className = reader.readLine() ) != null )
140 {
141
142 if ( relocators != null )
143 {
144 for ( Relocator relocator : relocators )
145 {
146
147 if ( relocator.canRelocateClass( className ) )
148 {
149 className = relocator.applyToSourceContent( className );
150 break;
151 }
152 }
153 }
154
155 writer.println( className );
156 writer.flush();
157 }
158
159 reader.close();
160 data.reset();
161 }
162 }
163
164 static class ServiceStream
165 extends ByteArrayOutputStream
166 {
167
168 ServiceStream()
169 {
170 super( 1024 );
171 }
172
173 public void append( String content )
174 throws IOException
175 {
176 if ( count > 0 && buf[count - 1] != '\n' && buf[count - 1] != '\r' )
177 {
178 write( '\n' );
179 }
180
181 byte[] contentBytes = content.getBytes( "UTF-8" );
182 this.write( contentBytes );
183 }
184
185 public InputStream toInputStream()
186 {
187 return new ByteArrayInputStream( buf, 0, count );
188 }
189
190 }
191
192 }