1 package org.apache.maven.plugins.shade.relocation;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.codehaus.plexus.util.SelectorUtils;
23
24 import java.util.Collection;
25 import java.util.LinkedHashSet;
26 import java.util.List;
27 import java.util.Set;
28 import java.util.regex.Pattern;
29
30
31
32
33
34 public class SimpleRelocator
35 implements Relocator
36 {
37
38 private final String pattern;
39
40 private final String pathPattern;
41
42 private final String shadedPattern;
43
44 private final String shadedPathPattern;
45
46 private final Set<String> includes;
47
48 private final Set<String> excludes;
49
50 private final boolean rawString;
51
52 public SimpleRelocator( String patt, String shadedPattern, List<String> includes, List<String> excludes )
53 {
54 this( patt, shadedPattern, includes, excludes, false );
55 }
56
57 public SimpleRelocator( String patt, String shadedPattern, List<String> includes, List<String> excludes,
58 boolean rawString )
59 {
60 this.rawString = rawString;
61
62 if ( rawString )
63 {
64 this.pathPattern = patt;
65 this.shadedPathPattern = shadedPattern;
66
67 this.pattern = null;
68 this.shadedPattern = null;
69 }
70 else
71 {
72 if ( patt == null )
73 {
74 this.pattern = "";
75 this.pathPattern = "";
76 }
77 else
78 {
79 this.pattern = patt.replace( '/', '.' );
80 this.pathPattern = patt.replace( '.', '/' );
81 }
82
83 if ( shadedPattern != null )
84 {
85 this.shadedPattern = shadedPattern.replace( '/', '.' );
86 this.shadedPathPattern = shadedPattern.replace( '.', '/' );
87 }
88 else
89 {
90 this.shadedPattern = "hidden." + this.pattern;
91 this.shadedPathPattern = "hidden/" + this.pathPattern;
92 }
93 }
94
95 this.includes = normalizePatterns( includes );
96 this.excludes = normalizePatterns( excludes );
97
98
99 if ( includes != null && !includes.isEmpty() )
100 {
101 this.includes.addAll( includes );
102 }
103
104 if ( excludes != null && !excludes.isEmpty() )
105 {
106 this.excludes.addAll( excludes );
107 }
108 }
109
110 private static Set<String> normalizePatterns( Collection<String> patterns )
111 {
112 Set<String> normalized = null;
113
114 if ( patterns != null && !patterns.isEmpty() )
115 {
116 normalized = new LinkedHashSet<>();
117
118 for ( String pattern : patterns )
119 {
120
121 String classPattern = pattern.replace( '.', '/' );
122
123 normalized.add( classPattern );
124
125 if ( classPattern.endsWith( "/*" ) )
126 {
127 String packagePattern = classPattern.substring( 0, classPattern.lastIndexOf( '/' ) );
128 normalized.add( packagePattern );
129 }
130 }
131 }
132
133 return normalized;
134 }
135
136 private boolean isIncluded( String path )
137 {
138 if ( includes != null && !includes.isEmpty() )
139 {
140 for ( String include : includes )
141 {
142 if ( SelectorUtils.matchPath( include, path, true ) )
143 {
144 return true;
145 }
146 }
147 return false;
148 }
149 return true;
150 }
151
152 private boolean isExcluded( String path )
153 {
154 if ( excludes != null && !excludes.isEmpty() )
155 {
156 for ( String exclude : excludes )
157 {
158 if ( SelectorUtils.matchPath( exclude, path, true ) )
159 {
160 return true;
161 }
162 }
163 }
164 return false;
165 }
166
167 public boolean canRelocatePath( String path )
168 {
169 if ( rawString )
170 {
171 return Pattern.compile( pathPattern ).matcher( path ).find();
172 }
173
174 if ( path.endsWith( ".class" ) )
175 {
176 path = path.substring( 0, path.length() - 6 );
177 }
178
179
180
181 if ( !path.isEmpty() && path.charAt( 0 ) == '/' )
182 {
183 path = path.substring( 1 );
184 }
185
186 return isIncluded( path ) && !isExcluded( path ) && path.startsWith( pathPattern );
187 }
188
189 public boolean canRelocateClass( String clazz )
190 {
191 return !rawString && clazz.indexOf( '/' ) < 0 && canRelocatePath( clazz.replace( '.', '/' ) );
192 }
193
194 public String relocatePath( String path )
195 {
196 if ( rawString )
197 {
198 return path.replaceAll( pathPattern, shadedPathPattern );
199 }
200 else
201 {
202 return path.replaceFirst( pathPattern, shadedPathPattern );
203 }
204 }
205
206 public String relocateClass( String clazz )
207 {
208 return clazz.replaceFirst( pattern, shadedPattern );
209 }
210
211 public String applyToSourceContent( String sourceContent )
212 {
213 if ( rawString )
214 {
215 return sourceContent;
216 }
217 else
218 {
219 return sourceContent.replaceAll( "\\b" + pattern, shadedPattern );
220 }
221 }
222 }