Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MSHADE-396] Improve SourceContent Shading #100

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
Expand Down Expand Up @@ -121,7 +122,7 @@ public SimpleRelocator( String patt, String shadedPattern, List<String> includes
sourcePackageExcludes.add( exclude.substring( pattern.length() ).replaceFirst( "[.][*]$", "" ) );
}
// Excludes should be subpackages of the global pattern
else if ( exclude.startsWith( pathPattern ) )
if ( exclude.startsWith( pathPattern ) )
{
sourcePathExcludes.add( exclude.substring( pathPattern.length() ).replaceFirst( "[/][*]$", "" ) );
}
Expand Down Expand Up @@ -230,45 +231,71 @@ public String relocateClass( String clazz )

public String applyToSourceContent( String sourceContent )
{
if ( rawString )
{
return sourceContent;
}
else
if ( !rawString )
{
sourceContent = shadeSourceWithExcludes( sourceContent, pattern, shadedPattern, sourcePackageExcludes );
return shadeSourceWithExcludes( sourceContent, pathPattern, shadedPathPattern, sourcePathExcludes );
sourceContent = shadeSourceWithExcludes( sourceContent, pathPattern, shadedPathPattern,
sourcePathExcludes );
}
return sourceContent;
}

private String shadeSourceWithExcludes( String sourceContent, String patternFrom, String patternTo,
Set<String> excludedPatterns )
{
// Usually shading makes package names a bit longer, so make buffer 10% bigger than original source
StringBuilder shadedSourceContent = new StringBuilder( sourceContent.length() * 11 / 10 );
boolean isFirstSnippet = true;
// Make sure that search pattern starts at word boundary and we look for literal ".", not regex jokers
for ( String snippet : sourceContent.split( "\\b" + patternFrom.replace( ".", "[.]" ) ) )

int index = 0;
// Make sure that we look for literal ".", not regex jokers
Matcher matcher = Pattern.compile( patternFrom.replace( ".", "[.]" ) ).matcher( sourceContent );
while ( matcher.find( index ) )
{
boolean doExclude = false;
for ( String excludedPattern : excludedPatterns )
shadedSourceContent.append( sourceContent.substring( index, matcher.start() ) );
index = matcher.end();
if ( matcher.start() > 1 )
{
if ( snippet.startsWith( excludedPattern ) )
char before = sourceContent.charAt( matcher.start() - 1 );
/*
* Exclude the following situation
* Pattern: "io"
* Content: java.io.IOException;
* Content: private String myException;
* We found "io" in "java.io" or myException, which should be excluded
*/
if ( '.' == before || Character.isLetter( before ) )
{
doExclude = true;
break;
}
}
if ( isFirstSnippet )
char after = sourceContent.charAt( matcher.end() );
/*
* If next char is not a "." nor a "/" we need to exclude
* Pattern: io
* Content: private String ioInput
* Content: String io, val;
* We found io in "ioInput" or "io,", which should be excluded
*/
if ( '.' != after && '/' != after )
{
shadedSourceContent.append( snippet );
isFirstSnippet = false;
}
else
doExclude = true;
}

if ( !doExclude )
{
shadedSourceContent.append( doExclude ? patternFrom : patternTo ).append( snippet );
for ( String excludedPattern : excludedPatterns )
{
if ( sourceContent.startsWith( excludedPattern, index ) )
{
doExclude = true;
break;
}
}
}
shadedSourceContent.append( doExclude ? patternFrom : patternTo );
}
shadedSourceContent.append( sourceContent.substring( index ) );
return shadedSourceContent.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,15 @@ public void testRelocateMavenFiles()
"import org.apache.maven.In;\n" +
"import org.apache.maven.e.InE;\n" +
"import org.apache.maven.f.g.InFG;\n" +
"import java.io.IOException;\n" +
"\n" +
"public class MyClass {\n" +
" private org.apache.maven.exclude1.x.X myX;\n" +
" private org.apache.maven.h.H;\n" +
" private String ioInput;\n" +
"\n" +
" public void doSomething() {\n" +
" String io, val;\n" +
" String noRelocation = \"NoWordBoundaryXXXorg.apache.maven.In\";\n" +
" String relocationPackage = \"org.apache.maven.In\";\n" +
" String relocationPath = \"org/apache/maven/In\";\n" +
Expand All @@ -225,12 +228,15 @@ public void testRelocateMavenFiles()
"import com.acme.maven.In;\n" +
"import com.acme.maven.e.InE;\n" +
"import com.acme.maven.f.g.InFG;\n" +
"import java.io.IOException;\n" +
"\n" +
"public class MyClass {\n" +
" private org.apache.maven.exclude1.x.X myX;\n" +
" private com.acme.maven.h.H;\n" +
" private String ioInput;\n" +
"\n" +
" public void doSomething() {\n" +
" String io, val;\n" +
" String noRelocation = \"NoWordBoundaryXXXorg.apache.maven.In\";\n" +
" String relocationPackage = \"com.acme.maven.In\";\n" +
" String relocationPath = \"com/acme/maven/In\";\n" +
Expand All @@ -255,4 +261,15 @@ public void testRelocateSourceWithExcludes()
Arrays.asList( "irrelevant.exclude", "org.apache.maven.exclude1", "org.apache.maven.sub.exclude2" ) );
assertEquals( relocatedFile, relocator.applyToSourceContent( sourceFile ) );
}

@Test
public void testRelocateSourceWithMultipleRelocators()
{
SimpleRelocator relocator = new SimpleRelocator( "org.apache.maven", "com.acme.maven",
Arrays.asList( "foo.bar", "zot.baz" ),
Arrays.asList( "irrelevant.exclude", "org.apache.maven.exclude1", "org.apache.maven.sub.exclude2" ) );

SimpleRelocator relocatorPackage = new SimpleRelocator( "io", "shaded.io", null, null);
assertEquals( relocatedFile, relocatorPackage.applyToSourceContent( relocator.applyToSourceContent( sourceFile ) ) );
}
}