Skip to content

Commit

Permalink
Refactor ConfigurationChecker
Browse files Browse the repository at this point in the history
  • Loading branch information
robinlefever committed Jan 27, 2023
1 parent ad82f08 commit 98309c9
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
* This pass performs configuration checks for which class pools or resource information
* should already have been initialized.
*/
public class AfterInitConfigurationChecker implements Pass
public class AfterInitConfigurationVerifier implements Pass
{
private final Configuration configuration;

private static final Logger logger = LogManager.getLogger(AfterInitConfigurationChecker.class);
private static final Logger logger = LogManager.getLogger(AfterInitConfigurationVerifier.class);

public AfterInitConfigurationChecker(Configuration configuration)
public AfterInitConfigurationVerifier(Configuration configuration)
{
this.configuration = configuration;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@
*
* @author Eric Lafortune
*/
public class ConfigurationChecker
public class ConfigurationVerifier
{
private static final Logger logger = LogManager.getLogger(ConfigurationChecker.class);
private static final Logger logger = LogManager.getLogger(ConfigurationVerifier.class);

private final Configuration configuration;


/**
* Creates a new ConfigurationChecker with the given configuration.
* Creates a new ConfigurationVerifier with the given configuration.
*/
public ConfigurationChecker(Configuration configuration)
public ConfigurationVerifier(Configuration configuration)
{
this.configuration = configuration;
}
Expand All @@ -62,14 +62,39 @@ public void check() throws IOException
throw new IOException("The input is empty. You have to specify one or more '-injars' options.");
}

checkInputJarFirst(programJars);

checkOutputJarFilter(programJars);

// Check for conflicts between input/output entries of the class paths.
checkConflicts(programJars, programJars);
checkConflicts(programJars, libraryJars);
checkConflicts(libraryJars, libraryJars);

printNotes(configuration, programJars, logger);
}


/**
* Checks that the input application is specified before any input libraries.
*/
private void checkInputJarFirst(ClassPath programJars) throws IOException
{
// Check that the first jar is an input jar.
ClassPathEntry firstEntry = programJars.get(0);
if (firstEntry.isOutput())
{
throw new IOException("The output jar [" + firstEntry.getName() +
"] must be specified after an input jar, or it will be empty.");
"] must be specified after an input jar, or it will be empty.");
}
}


/**
* Checks that the first of two subsequent output jars has a filter.
*/
private void checkOutputJarFilter(ClassPath programJars) throws IOException
{
// Check that the first of two subsequent the output jars has a filter.
for (int index = 0; index < programJars.size() - 1; index++)
{
Expand All @@ -82,12 +107,70 @@ public void check() throws IOException
"] must have a filter, or all subsequent output jars will be empty.");
}
}
}

// Check for conflicts between input/output entries of the class paths.
checkConflicts(programJars, programJars);
checkConflicts(programJars, libraryJars);
checkConflicts(libraryJars, libraryJars);

/**
* Performs some sanity checks on the class paths.
*/
private void checkConflicts(ClassPath classPath1,
ClassPath classPath2)
throws IOException
{
if (classPath1 == null ||
classPath2 == null)
{
return;
}

for (int index1 = 0; index1 < classPath1.size(); index1++)
{
ClassPathEntry entry1 = classPath1.get(index1);

for (int index2 = 0; index2 < classPath2.size(); index2++)
{
if (classPath1 != classPath2 || index1 != index2)
{
ClassPathEntry entry2 = classPath2.get(index2);

if (entry2.getName().equals(entry1.getName()))
{
if (entry1.isOutput())
{
if (entry2.isOutput())
{
// Output / output.
throw new IOException("The same output jar ["+entry1.getName()+"] is specified twice.");
}
else
{
// Output / input.
throw new IOException("Input jars and output jars must be different ["+entry1.getName()+"].");
}
}
else
{
if (entry2.isOutput())
{
// Input / output.
throw new IOException("Input jars and output jars must be different ["+entry1.getName()+"].");
}
else if (!entry1.isFiltered() ||
!entry2.isFiltered())
{
// Input / input.
throw new IOException("The same input jar ["+entry1.getName()+"] is specified twice.");
}
}
}
}
}
}
}


private void printNotes(Configuration configuration, ClassPath programJars, Logger logger) throws IOException
{
// Print out some general notes if necessary.
if ((configuration.note == null ||
!configuration.note.isEmpty()))
Expand Down Expand Up @@ -166,63 +249,4 @@ public void check() throws IOException
}
}
}


/**
* Performs some sanity checks on the class paths.
*/
private void checkConflicts(ClassPath classPath1,
ClassPath classPath2)
throws IOException
{
if (classPath1 == null ||
classPath2 == null)
{
return;
}

for (int index1 = 0; index1 < classPath1.size(); index1++)
{
ClassPathEntry entry1 = classPath1.get(index1);

for (int index2 = 0; index2 < classPath2.size(); index2++)
{
if (classPath1 != classPath2 || index1 != index2)
{
ClassPathEntry entry2 = classPath2.get(index2);

if (entry2.getName().equals(entry1.getName()))
{
if (entry1.isOutput())
{
if (entry2.isOutput())
{
// Output / output.
throw new IOException("The same output jar ["+entry1.getName()+"] is specified twice.");
}
else
{
// Output / input.
throw new IOException("Input jars and output jars must be different ["+entry1.getName()+"].");
}
}
else
{
if (entry2.isOutput())
{
// Input / output.
throw new IOException("Input jars and output jars must be different ["+entry1.getName()+"].");
}
else if (!entry1.isFiltered() ||
!entry2.isFiltered())
{
// Input / input.
throw new IOException("The same input jar ["+entry1.getName()+"] is specified twice.");
}
}
}
}
}
}
}
}
4 changes: 2 additions & 2 deletions base/src/main/java/proguard/ProGuard.java
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ private void printConfiguration() throws IOException
*/
private void checkConfiguration() throws IOException
{
new ConfigurationChecker(configuration).check();
new ConfigurationVerifier(configuration).check();
}


Expand Down Expand Up @@ -386,7 +386,7 @@ private void stripKotlinMetadataAnnotations() throws Exception
*/
private void checkConfigurationAfterInitialization() throws Exception
{
passRunner.run(new AfterInitConfigurationChecker(configuration), appView);
passRunner.run(new AfterInitConfigurationVerifier(configuration), appView);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import java.util.UUID
/**
* Test the after init checks.
*/
class AfterInitConfigurationCheckerTest : FreeSpec({
class AfterInitConfigurationVerifierTest : FreeSpec({

// Mock a program class with the given class file version.
class FakeClass(version: Int) : ProgramClass(version, 1, emptyArray(), 1, -1, -1) {
Expand All @@ -45,7 +45,7 @@ class AfterInitConfigurationCheckerTest : FreeSpec({
view.programClassPool.addClass(FakeClass(CLASS_VERSION_12))

val exception = shouldThrow<RuntimeException> {
AfterInitConfigurationChecker(configuration).execute(view)
AfterInitConfigurationVerifier(configuration).execute(view)
}
exception.message shouldContain "-target can only be used with class file versions <= 55 (Java 11)."
exception.message shouldContain "The input classes contain version 56 class files which cannot be backported to target version (50)."
Expand All @@ -56,7 +56,7 @@ class AfterInitConfigurationCheckerTest : FreeSpec({
view.programClassPool.addClass(FakeClass(CLASS_VERSION_11))

shouldNotThrow<RuntimeException> {
AfterInitConfigurationChecker(configuration).execute(view)
AfterInitConfigurationVerifier(configuration).execute(view)
}
}

Expand All @@ -65,7 +65,7 @@ class AfterInitConfigurationCheckerTest : FreeSpec({
view.programClassPool.addClass(FakeClass(CLASS_VERSION_1_6))

shouldNotThrow<RuntimeException> {
AfterInitConfigurationChecker(configuration).execute(view)
AfterInitConfigurationVerifier(configuration).execute(view)
}
}
}
Expand All @@ -83,7 +83,7 @@ class AfterInitConfigurationCheckerTest : FreeSpec({
addClass(FakeClass(CLASS_VERSION_17))
}

shouldNotThrow<RuntimeException> { AfterInitConfigurationChecker(configuration).execute(view) }
shouldNotThrow<RuntimeException> { AfterInitConfigurationVerifier(configuration).execute(view) }
}

"It should print a warning" {
Expand All @@ -94,7 +94,7 @@ class AfterInitConfigurationCheckerTest : FreeSpec({
}

val output = getLogOutputOf {
AfterInitConfigurationChecker(configuration).execute(view)
AfterInitConfigurationVerifier(configuration).execute(view)
}
output shouldContain "-target is deprecated when using class file above"
}
Expand All @@ -107,7 +107,7 @@ class AfterInitConfigurationCheckerTest : FreeSpec({
}

val exception = shouldThrow<RuntimeException> {
AfterInitConfigurationChecker(configuration).execute(view)
AfterInitConfigurationVerifier(configuration).execute(view)
}

exception.message shouldContain "-target can only be used with class file versions <= 55 (Java 11)."
Expand All @@ -126,7 +126,7 @@ class AfterInitConfigurationCheckerTest : FreeSpec({
view.programClassPool.addClass(FakeClass(CLASS_VERSION_12))

shouldNotThrow<RuntimeException> {
AfterInitConfigurationChecker(configuration).execute(view)
AfterInitConfigurationVerifier(configuration).execute(view)
}
}

Expand All @@ -135,7 +135,7 @@ class AfterInitConfigurationCheckerTest : FreeSpec({
view.programClassPool.addClass(FakeClass(CLASS_VERSION_11))

shouldNotThrow<RuntimeException> {
AfterInitConfigurationChecker(configuration).execute(view)
AfterInitConfigurationVerifier(configuration).execute(view)
}
}

Expand All @@ -144,7 +144,7 @@ class AfterInitConfigurationCheckerTest : FreeSpec({
view.programClassPool.addClass(FakeClass(CLASS_VERSION_1_6))

shouldNotThrow<RuntimeException> {
AfterInitConfigurationChecker(configuration).execute(view)
AfterInitConfigurationVerifier(configuration).execute(view)
}
}
}
Expand Down

0 comments on commit 98309c9

Please sign in to comment.