View Javadoc

1   package org.apache.maven.plugins.shade.relocation;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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   * @author Jason van Zyl
32   * @author Mauro Talevi
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; // not used for raw string relocator
68              this.shadedPattern = null; // not used for raw string relocator
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      private static Set<String> normalizePatterns( Collection<String> patterns )
100     {
101         Set<String> normalized = null;
102 
103         if ( patterns != null && !patterns.isEmpty() )
104         {
105             normalized = new LinkedHashSet<String>();
106 
107             for ( String pattern : patterns )
108             {
109 
110                 String classPattern = pattern.replace( '.', '/' );
111 
112                 normalized.add( classPattern );
113 
114                 if ( classPattern.endsWith( "/*" ) )
115                 {
116                     String packagePattern = classPattern.substring( 0, classPattern.lastIndexOf( '/' ) );
117                     normalized.add( packagePattern );
118                 }
119             }
120         }
121 
122         return normalized;
123     }
124 
125     private boolean isIncluded( String path )
126     {
127         if ( includes != null && !includes.isEmpty() )
128         {
129             for ( String include : includes )
130             {
131                 if ( SelectorUtils.matchPath( include, path, true ) )
132                 {
133                     return true;
134                 }
135             }
136             return false;
137         }
138         return true;
139     }
140 
141     private boolean isExcluded( String path )
142     {
143         if ( excludes != null && !excludes.isEmpty() )
144         {
145             for ( String exclude : excludes )
146             {
147                 if ( SelectorUtils.matchPath( exclude, path, true ) )
148                 {
149                     return true;
150                 }
151             }
152         }
153         return false;
154     }
155 
156     public boolean canRelocatePath( String path )
157     {
158         if ( rawString )
159         {
160             return Pattern.compile( pathPattern ).matcher( path ).find();
161         }
162 
163         if ( path.endsWith( ".class" ) )
164         {
165             path = path.substring( 0, path.length() - 6 );
166         }
167 
168         if ( !isIncluded( path ) || isExcluded( path ) )
169         {
170             return false;
171         }
172 
173         // Allow for annoying option of an extra / on the front of a path. See MSHADE-119; comes from getClass().getResource("/a/b/c.properties").
174         return path.startsWith( pathPattern ) || path.startsWith ( "/" + pathPattern );
175     }
176 
177     public boolean canRelocateClass( String clazz )
178     {
179         return !rawString && clazz.indexOf( '/' ) < 0 && canRelocatePath( clazz.replace( '.', '/' ) );
180     }
181 
182     public String relocatePath( String path )
183     {
184         if ( rawString )
185         {
186             return path.replaceAll( pathPattern, shadedPathPattern );
187         }
188         else
189         {
190             return path.replaceFirst( pathPattern, shadedPathPattern );
191         }
192     }
193 
194     public String relocateClass( String clazz )
195     {
196         return clazz.replaceFirst( pattern, shadedPattern );
197     }
198 
199 	public String applyToSourceContent(String sourceContent)
200 	{
201         if ( rawString )
202         {
203         	return sourceContent;
204         }
205         else
206         {
207             return sourceContent.replaceAll( "\\b" + pattern, shadedPattern );
208         }
209 	}
210 }