From de69eebe1674e705f549452098b18950687b9665 Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sat, 23 Dec 2023 11:14:22 +0100 Subject: [PATCH 01/22] Changed to Junit5 --- pom.xml | 6 +- .../fuin/utils4j/CancelableVolatileTest.java | 2 +- .../fuin/utils4j/ChangeTrackingMapTest.java | 10 +- .../utils4j/ChangeTrackingUniqueListTest.java | 10 +- .../ClasspathURLStreamHandlerTest.java | 2 +- .../IllegalNullArgumentExceptionTest.java | 4 +- .../InvokeMethodFailedExceptionTest.java | 2 +- .../org/fuin/utils4j/JandexUtilsTest.java | 2 +- .../utils4j/LockingFailedExceptionTest.java | 2 +- .../org/fuin/utils4j/MergeExceptionTest.java | 4 +- .../PropertiesFilePreferencesTest.java | 10 +- .../org/fuin/utils4j/PropertiesFileTest.java | 16 +- .../org/fuin/utils4j/PropertiesUtilsTest.java | 41 ++--- .../java/org/fuin/utils4j/PropertyTest.java | 2 +- .../RandomAccessFileInputStreamTest.java | 17 +-- .../RandomAccessFileOutputStreamTest.java | 14 +- .../java/org/fuin/utils4j/Utils4JTest.java | 142 +++++++----------- .../fuin/utils4j/VariableResolverTest.java | 2 +- .../java/org/fuin/utils4j/WaitHelperTest.java | 29 ++-- .../fuin/utils4j/classpath/HandlerTest.java | 3 +- .../fileprocessor/FileHandlerResultTest.java | 3 +- .../utils4j/fileprocessor/FileOrderTest.java | 2 +- .../fileprocessor/FileProcessorTest.java | 2 +- .../fuin/utils4j/filter/AndFilterTest.java | 4 +- .../utils4j/filter/BooleanFilterTest.java | 2 +- .../filter/BooleanPropertyFilterTest.java | 2 +- .../utils4j/filter/IntegerFilterTest.java | 52 +++---- .../filter/IntegerPropertyFilterTest.java | 54 +++---- .../fuin/utils4j/filter/ListFilterTest.java | 2 +- .../org/fuin/utils4j/filter/OrFilterTest.java | 4 +- .../utils4j/filter/PropertyFilterTest.java | 4 +- .../utils4j/filter/RegExprFilterTest.java | 4 +- .../filter/RegExprPropertyFilterTest.java | 2 +- .../fuin/utils4j/filter/StringFilterTest.java | 2 +- .../filter/StringPropertyFilterTest.java | 2 +- .../fuin/utils4j/filter/TokenFilterTest.java | 2 +- .../filter/TokenPropertyFilterTest.java | 2 +- .../org/fuin/utils4j/jaxb/CDataJaxbTest.java | 2 +- .../utils4j/jaxb/UnmarshallerBuilderTest.java | 4 +- 39 files changed, 206 insertions(+), 265 deletions(-) diff --git a/pom.xml b/pom.xml index e840097..cf2d16a 100644 --- a/pom.xml +++ b/pom.xml @@ -54,9 +54,9 @@ - junit - junit - 4.13.2 + org.junit.jupiter + junit-jupiter + 5.10.1 test diff --git a/src/test/java/org/fuin/utils4j/CancelableVolatileTest.java b/src/test/java/org/fuin/utils4j/CancelableVolatileTest.java index f3b3686..3501e82 100644 --- a/src/test/java/org/fuin/utils4j/CancelableVolatileTest.java +++ b/src/test/java/org/fuin/utils4j/CancelableVolatileTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; // CHECKSTYLE:OFF public class CancelableVolatileTest { diff --git a/src/test/java/org/fuin/utils4j/ChangeTrackingMapTest.java b/src/test/java/org/fuin/utils4j/ChangeTrackingMapTest.java index f81b92f..4d95bc9 100644 --- a/src/test/java/org/fuin/utils4j/ChangeTrackingMapTest.java +++ b/src/test/java/org/fuin/utils4j/ChangeTrackingMapTest.java @@ -24,9 +24,9 @@ import java.util.Map; import java.util.StringTokenizer; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public class ChangeTrackingMapTest { @@ -51,13 +51,13 @@ private Map toMap(final String keyValues) { return map; } - @Before + @BeforeEach public final void beforeMethod() { initialEmptyMap = new ChangeTrackingMap(new HashMap()); initialFilledMap = new ChangeTrackingMap(toMap("one=1,two=2,three=3")); } - @After + @AfterEach public final void afterMethod() { initialFilledMap = null; initialEmptyMap = null; diff --git a/src/test/java/org/fuin/utils4j/ChangeTrackingUniqueListTest.java b/src/test/java/org/fuin/utils4j/ChangeTrackingUniqueListTest.java index c47b4aa..f108cf4 100644 --- a/src/test/java/org/fuin/utils4j/ChangeTrackingUniqueListTest.java +++ b/src/test/java/org/fuin/utils4j/ChangeTrackingUniqueListTest.java @@ -23,9 +23,9 @@ import java.util.ArrayList; import java.util.List; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public class ChangeTrackingUniqueListTest { @@ -34,14 +34,14 @@ public class ChangeTrackingUniqueListTest { private ChangeTrackingUniqueList initialFilledList; - @Before + @BeforeEach public final void beforeMethod() { initialEmptyList = new ChangeTrackingUniqueList(new ArrayList()); initialFilledList = new ChangeTrackingUniqueList(toList("one", "two", "three")); } - @After + @AfterEach public final void afterMethod() { initialFilledList = null; initialEmptyList = null; diff --git a/src/test/java/org/fuin/utils4j/ClasspathURLStreamHandlerTest.java b/src/test/java/org/fuin/utils4j/ClasspathURLStreamHandlerTest.java index 867d91e..9b71211 100644 --- a/src/test/java/org/fuin/utils4j/ClasspathURLStreamHandlerTest.java +++ b/src/test/java/org/fuin/utils4j/ClasspathURLStreamHandlerTest.java @@ -22,7 +22,7 @@ import java.net.MalformedURLException; import java.net.URL; -import org.junit.Test; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public class ClasspathURLStreamHandlerTest { diff --git a/src/test/java/org/fuin/utils4j/IllegalNullArgumentExceptionTest.java b/src/test/java/org/fuin/utils4j/IllegalNullArgumentExceptionTest.java index 235f336..6694a12 100644 --- a/src/test/java/org/fuin/utils4j/IllegalNullArgumentExceptionTest.java +++ b/src/test/java/org/fuin/utils4j/IllegalNullArgumentExceptionTest.java @@ -17,9 +17,9 @@ */ package org.fuin.utils4j; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Test; -import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; /** * Tests for IllegalNullArgumentException. diff --git a/src/test/java/org/fuin/utils4j/InvokeMethodFailedExceptionTest.java b/src/test/java/org/fuin/utils4j/InvokeMethodFailedExceptionTest.java index c25868e..64fa4d4 100644 --- a/src/test/java/org/fuin/utils4j/InvokeMethodFailedExceptionTest.java +++ b/src/test/java/org/fuin/utils4j/InvokeMethodFailedExceptionTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; // CHECKSTYLE:OFF public class InvokeMethodFailedExceptionTest { diff --git a/src/test/java/org/fuin/utils4j/JandexUtilsTest.java b/src/test/java/org/fuin/utils4j/JandexUtilsTest.java index dd68e2a..5a416df 100644 --- a/src/test/java/org/fuin/utils4j/JandexUtilsTest.java +++ b/src/test/java/org/fuin/utils4j/JandexUtilsTest.java @@ -27,7 +27,7 @@ import org.jboss.jandex.DotName; import org.jboss.jandex.Index; import org.jboss.jandex.Indexer; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests for {@link JandexUtils}. diff --git a/src/test/java/org/fuin/utils4j/LockingFailedExceptionTest.java b/src/test/java/org/fuin/utils4j/LockingFailedExceptionTest.java index df4ed33..b13d324 100644 --- a/src/test/java/org/fuin/utils4j/LockingFailedExceptionTest.java +++ b/src/test/java/org/fuin/utils4j/LockingFailedExceptionTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; // CHECKSTYLE:OFF public class LockingFailedExceptionTest { diff --git a/src/test/java/org/fuin/utils4j/MergeExceptionTest.java b/src/test/java/org/fuin/utils4j/MergeExceptionTest.java index 8a8ee7a..aeca5a0 100644 --- a/src/test/java/org/fuin/utils4j/MergeExceptionTest.java +++ b/src/test/java/org/fuin/utils4j/MergeExceptionTest.java @@ -17,12 +17,12 @@ */ package org.fuin.utils4j; +import org.junit.jupiter.api.Test; + import static org.assertj.core.api.Assertions.assertThat; import java.io.File; -import org.junit.Test; - //CHECKSTYLE:OFF public final class MergeExceptionTest { diff --git a/src/test/java/org/fuin/utils4j/PropertiesFilePreferencesTest.java b/src/test/java/org/fuin/utils4j/PropertiesFilePreferencesTest.java index 7686afd..2743018 100644 --- a/src/test/java/org/fuin/utils4j/PropertiesFilePreferencesTest.java +++ b/src/test/java/org/fuin/utils4j/PropertiesFilePreferencesTest.java @@ -25,21 +25,21 @@ import java.util.prefs.Preferences; import org.apache.commons.io.FileUtils; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public final class PropertiesFilePreferencesTest { private static File baseDir; - @BeforeClass + @BeforeAll public static void beforeClass() throws IOException { baseDir = new File(Utils4J.getTempDir(), "test-prop-file-pref"); } - @Before + @BeforeEach public final void beforeMethod() throws IOException { FileUtils.deleteDirectory(baseDir); baseDir.mkdirs(); diff --git a/src/test/java/org/fuin/utils4j/PropertiesFileTest.java b/src/test/java/org/fuin/utils4j/PropertiesFileTest.java index c17a505..7886e43 100644 --- a/src/test/java/org/fuin/utils4j/PropertiesFileTest.java +++ b/src/test/java/org/fuin/utils4j/PropertiesFileTest.java @@ -18,7 +18,7 @@ package org.fuin.utils4j; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; +import static org.assertj.core.api.Assertions.fail; import java.io.File; import java.io.FileWriter; @@ -29,10 +29,10 @@ import java.util.Properties; import org.fuin.utils4j.MergeException.Problem; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; //CHECKSTYLE:OFF public class PropertiesFileTest { @@ -43,13 +43,13 @@ public class PropertiesFileTest { private PropertiesFile propFile; - @BeforeClass + @BeforeAll public static void beforeClass() throws IOException { testFile = new File(Utils4J.getTempDir(), "PropertiesFileTest.properties"); dir = new File("src/test/resources/" + Utils4J.getPackagePath(PropertiesFileTest.class)); } - @Before + @BeforeEach public final void beforeMethod() throws IOException { // Create the initial content createPropertiesFile(); @@ -57,7 +57,7 @@ public final void beforeMethod() throws IOException { propFile = new PropertiesFile(testFile); } - @After + @AfterEach public final void afterMethod() throws IOException { propFile = null; } diff --git a/src/test/java/org/fuin/utils4j/PropertiesUtilsTest.java b/src/test/java/org/fuin/utils4j/PropertiesUtilsTest.java index ffa468a..1e4469e 100644 --- a/src/test/java/org/fuin/utils4j/PropertiesUtilsTest.java +++ b/src/test/java/org/fuin/utils4j/PropertiesUtilsTest.java @@ -17,8 +17,7 @@ */ package org.fuin.utils4j; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; +import org.junit.jupiter.api.Test; import java.io.File; import java.io.FileNotFoundException; @@ -26,7 +25,8 @@ import java.net.MalformedURLException; import java.util.Properties; -import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; /** * Tests for {@link PropertiesUtils}. @@ -47,13 +47,11 @@ public final void testLoadPropertiesClassString() { @Test public final void testLoadPropertiesClassStringNonExisting() { - try { + assertThatThrownBy(() -> { PropertiesUtils.loadProperties(PropertiesUtilsTest.class, "DoesNotExist.properties"); - fail(); - } catch (final IllegalArgumentException ex) { - assertThat(ex.getMessage()).contains("Resource"); - assertThat(ex.getMessage()).contains("not found"); - } + }).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Resource") + .hasMessageContaining("not found"); } @Test @@ -90,14 +88,12 @@ public final void testSaveProperties() throws IOException { @Test public final void testSavePropertiesNonExistingParentDirectory() throws IOException { - try { + assertThatThrownBy(() -> { final File parentDir = new File("thisdoesnotexist"); PropertiesUtils.saveProperties(new File(parentDir, "dummy.properties"), new Properties(), "COMMENT"); - fail(); - } catch (final IllegalArgumentException ex) { - assertThat(ex.getMessage()).contains("The parent directory"); - assertThat(ex.getMessage()).contains("does not exist"); - } + }).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("The parent directory") + .hasMessageContaining("does not exist"); } @Test @@ -105,12 +101,9 @@ public final void testSavePropertiesIOexception() throws LockingFailedException, final File testFile = File.createTempFile(this.getClass().getSimpleName() + "-", ".properties"); try { testFile.setReadOnly(); - try { + assertThatThrownBy(() -> { PropertiesUtils.saveProperties(testFile, new Properties(), "COMMENT"); - fail(); - } catch (final RuntimeException ex) { - assertThat(ex).hasCauseInstanceOf(FileNotFoundException.class); - } + }).hasCauseInstanceOf(FileNotFoundException.class); } finally { testFile.delete(); } @@ -147,12 +140,10 @@ public final void testLoadPropertiesStringString() throws MalformedURLException @Test public final void testLoadPropertiesStringStringIllegalUrl() throws MalformedURLException { - try { + assertThatThrownBy(() -> { PropertiesUtils.loadProperties("no-url", "dummy.properties"); - fail(); - } catch (final IllegalArgumentException ex) { - assertThat(ex.getMessage()).contains("The argument 'srcUrl' is not a valid URL"); - } + }).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("The argument 'srcUrl' is not a valid URL"); } } // CHECKSTYLE:ON diff --git a/src/test/java/org/fuin/utils4j/PropertyTest.java b/src/test/java/org/fuin/utils4j/PropertyTest.java index 445c780..739204e 100644 --- a/src/test/java/org/fuin/utils4j/PropertyTest.java +++ b/src/test/java/org/fuin/utils4j/PropertyTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; import nl.jqno.equalsverifier.EqualsVerifier; diff --git a/src/test/java/org/fuin/utils4j/RandomAccessFileInputStreamTest.java b/src/test/java/org/fuin/utils4j/RandomAccessFileInputStreamTest.java index 287a105..1937e22 100644 --- a/src/test/java/org/fuin/utils4j/RandomAccessFileInputStreamTest.java +++ b/src/test/java/org/fuin/utils4j/RandomAccessFileInputStreamTest.java @@ -18,15 +18,14 @@ package org.fuin.utils4j; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeAll; //CHECKSTYLE:OFF public final class RandomAccessFileInputStreamTest { @@ -35,7 +34,7 @@ public final class RandomAccessFileInputStreamTest { private RandomAccessFileInputStream inputStream; - @BeforeClass + @BeforeAll public static void beforeClass() throws IOException { final File dir = new File("src/test/resources/" + Utils4J.getPackagePath(RandomAccessFileInputStreamTest.class)); file = new File(dir, "RandomAccessFileInputStreamData.bin"); @@ -44,12 +43,12 @@ public static void beforeClass() throws IOException { } } - @Before + @BeforeEach public final void beforeMethod() throws FileNotFoundException { inputStream = new RandomAccessFileInputStream(file, "r"); } - @After + @AfterEach public final void afterMethod() throws IOException { inputStream.close(); inputStream = null; @@ -111,9 +110,9 @@ public final void testMarkSupported() { assertThat(inputStream.markSupported()).isTrue(); } - @Test(expected = IOException.class) + @Test public final void testResetWithoutMark() throws IOException { - inputStream.reset(); + assertThatThrownBy(() -> inputStream.reset()).isInstanceOf(IOException.class); } @Test diff --git a/src/test/java/org/fuin/utils4j/RandomAccessFileOutputStreamTest.java b/src/test/java/org/fuin/utils4j/RandomAccessFileOutputStreamTest.java index 527c1b9..08d64f7 100644 --- a/src/test/java/org/fuin/utils4j/RandomAccessFileOutputStreamTest.java +++ b/src/test/java/org/fuin/utils4j/RandomAccessFileOutputStreamTest.java @@ -25,10 +25,10 @@ import java.io.IOException; import org.apache.commons.io.FileUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; //CHECKSTYLE:OFF public class RandomAccessFileOutputStreamTest { @@ -39,7 +39,7 @@ public class RandomAccessFileOutputStreamTest { private RandomAccessFileOutputStream outputStream; - @BeforeClass + @BeforeAll public static void beforeClass() throws IOException { final File dir = new File("src/test/resources/" + Utils4J.getPackagePath(RandomAccessFileOutputStream.class)); file = new File(Utils4J.getTempDir(), "RandomAccessFileOutputStreamData.bin"); @@ -49,12 +49,12 @@ public static void beforeClass() throws IOException { } } - @Before + @BeforeEach public final void beforeMethod() throws IOException { file.delete(); } - @After + @AfterEach public final void afterMethod() throws IOException { outputStream.close(); outputStream = null; diff --git a/src/test/java/org/fuin/utils4j/Utils4JTest.java b/src/test/java/org/fuin/utils4j/Utils4JTest.java index 818e452..7cb04d4 100644 --- a/src/test/java/org/fuin/utils4j/Utils4JTest.java +++ b/src/test/java/org/fuin/utils4j/Utils4JTest.java @@ -17,8 +17,10 @@ */ package org.fuin.utils4j; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; +import org.apache.commons.io.FileUtils; +import org.fuin.utils4j.test.ClassWithPrivateConstructor; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import java.io.File; import java.io.FileNotFoundException; @@ -27,18 +29,10 @@ import java.net.MalformedURLException; import java.net.URL; import java.nio.channels.FileLock; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TimeZone; +import java.util.*; -import org.apache.commons.io.FileUtils; -import org.fuin.utils4j.test.ClassWithPrivateConstructor; -import org.junit.BeforeClass; -import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; /** * Tests for Utils4J. @@ -52,7 +46,7 @@ public class Utils4JTest { private static final Map vars = new HashMap<>(); - @BeforeClass + @BeforeAll public static void beforeClass() { vars.put("one", "1"); vars.put("two", "2"); @@ -157,22 +151,16 @@ public final void testCheckValidFileOK() { @Test public final void testCheckValidFileNotExisting() { - try { + assertThatThrownBy(() -> { Utils4J.checkValidFile(new File(TEST_PROPERTIES_FILE.getParentFile(), "foobar.txt")); - fail(); - } catch (final IllegalArgumentException ex) { - // OK - } + }).isInstanceOf(IllegalArgumentException.class); } @Test public final void testCheckValidFileDirectory() { - try { + assertThatThrownBy(() -> { Utils4J.checkValidFile(TEST_PROPERTIES_FILE.getParentFile()); - fail(); - } catch (final IllegalArgumentException ex) { - // OK - } + }).isInstanceOf(IllegalArgumentException.class); } @Test @@ -182,22 +170,16 @@ public final void testCheckValidDirOK() { @Test public final void testCheckValidDirNotExisting() { - try { + assertThatThrownBy(() -> { Utils4J.checkValidDir(new File(TEST_PROPERTIES_FILE.getParentFile(), "foobar")); - fail(); - } catch (final IllegalArgumentException ex) { - // OK - } + }).isInstanceOf(IllegalArgumentException.class); } @Test public final void testCheckValidDirFile() { - try { + assertThatThrownBy(() -> { Utils4J.checkValidDir(TEST_PROPERTIES_FILE); - fail(); - } catch (final IllegalArgumentException ex) { - // OK - } + }).isInstanceOf(IllegalArgumentException.class); } @Test @@ -208,32 +190,23 @@ public final void testCreateInstanceOK() { @Test public final void testCreateInstanceClassNotFound() { - try { + assertThatThrownBy(() -> { Utils4J.createInstance("x.y.Z"); - fail(); - } catch (final RuntimeException ex) { - assertThat(ex.getCause()).isInstanceOf(ClassNotFoundException.class); - } + }).hasCauseInstanceOf(ClassNotFoundException.class); } @Test public final void testCreateInstanceInstantiationProblem() { - try { + assertThatThrownBy(() -> { Utils4J.createInstance(Cancelable.class.getName()); - fail(); - } catch (final RuntimeException ex) { - assertThat(ex.getCause()).isInstanceOf(NoSuchMethodException.class); - } + }).hasCauseInstanceOf(NoSuchMethodException.class); } @Test public final void testCreateInstanceIllegalAccess() { - try { + assertThatThrownBy(() -> { Utils4J.createInstance(ClassWithPrivateConstructor.class.getName()); - fail(); - } catch (final RuntimeException ex) { - assertThat(ex.getCause()).isInstanceOf(IllegalAccessException.class); - } + }).hasCauseInstanceOf(IllegalAccessException.class); } @Test @@ -294,12 +267,9 @@ public final void testGetRelativePathSame() { @Test public final void testGetRelativePathNotInsideBaseDir() { - try { + assertThatThrownBy(() -> { Utils4J.getRelativePath(TEST_PROPERTIES_FILE.getParentFile(), TEST_PROPERTIES_FILE.getParentFile().getParentFile()); - fail(); - } catch (final IllegalArgumentException ex) { - // OK - } + }).isInstanceOf(IllegalArgumentException.class); } @Test @@ -309,12 +279,9 @@ public final void testCheckNotNullOK() { @Test public final void testCheckNotNullFail() { - try { + assertThatThrownBy(() -> { Utils4J.checkNotNull("name", null); - fail(); - } catch (final IllegalArgumentException ex) { - // OK - } + }).isInstanceOf(IllegalArgumentException.class); } @Test @@ -324,12 +291,9 @@ public final void testCheckNotEmptyOK() { @Test public final void testCheckNotEmptyFail() { - try { + assertThatThrownBy(() -> { Utils4J.checkNotEmpty("name", ""); - fail(); - } catch (final IllegalArgumentException ex) { - // OK - } + }).isInstanceOf(IllegalArgumentException.class); } @Test @@ -340,12 +304,9 @@ public final void testInvokeOK() throws InvokeMethodFailedException { @Test public final void testInvokeFail() throws InvokeMethodFailedException { - try { + assertThatThrownBy(() -> { Utils4J.invoke(new IllegalNullArgumentException("abc"), "getArgument", new Class[] { String.class }, new Object[] { "" }); - fail(); - } catch (final InvokeMethodFailedException ex) { - // OK - } + }).isInstanceOf(InvokeMethodFailedException.class); } @Test @@ -511,34 +472,37 @@ public final void testLockRandomAccessFile() throws IOException { } - @Test(expected = LockingFailedException.class) - public final void testLockRandomAccessFileFailed() throws Exception { + @Test + public final void testLockRandomAccessFileFailed() { - final File file = File.createTempFile("testLockRandomAccessFile", ".bin"); + assertThatThrownBy(() -> { - try { + final File file = File.createTempFile("testLockRandomAccessFile", ".bin"); - final ExceptionContainer ec1 = new ExceptionContainer(); - // First holds a lock for one second - final Thread thread1 = new Thread(createLockRunnable(file, ec1, 3, 100, 1000)); + try { - final ExceptionContainer ec2 = new ExceptionContainer(); - // Second makes only one try to get the lock - final Thread thread2 = new Thread(createLockRunnable(file, ec2, 1, 0, 0)); + final ExceptionContainer ec1 = new ExceptionContainer(); + // First holds a lock for one second + final Thread thread1 = new Thread(createLockRunnable(file, ec1, 3, 100, 1000)); - // Start both threads to simulate a concurrent lock - startAndWaitUntilFinished(thread1, thread2); + final ExceptionContainer ec2 = new ExceptionContainer(); + // Second makes only one try to get the lock + final Thread thread2 = new Thread(createLockRunnable(file, ec2, 1, 0, 0)); - // Check results - assertThat(ec1.exception).isNull(); - if (ec2.exception != null) { - throw ec2.exception; + // Start both threads to simulate a concurrent lock + startAndWaitUntilFinished(thread1, thread2); + + // Check results + assertThat(ec1.exception).isNull(); + if (ec2.exception != null) { + throw ec2.exception; + } + + } finally { + file.delete(); } - fail("Expected " + LockingFailedException.class.getName()); - } finally { - file.delete(); - } + }).isInstanceOf(LockingFailedException.class); } diff --git a/src/test/java/org/fuin/utils4j/VariableResolverTest.java b/src/test/java/org/fuin/utils4j/VariableResolverTest.java index 644b0c3..726e42e 100644 --- a/src/test/java/org/fuin/utils4j/VariableResolverTest.java +++ b/src/test/java/org/fuin/utils4j/VariableResolverTest.java @@ -25,7 +25,7 @@ import java.util.HashMap; import java.util.Map; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Test for {@link VariableResolver}. diff --git a/src/test/java/org/fuin/utils4j/WaitHelperTest.java b/src/test/java/org/fuin/utils4j/WaitHelperTest.java index 6caf5b4..bb37b44 100644 --- a/src/test/java/org/fuin/utils4j/WaitHelperTest.java +++ b/src/test/java/org/fuin/utils4j/WaitHelperTest.java @@ -17,14 +17,14 @@ */ package org.fuin.utils4j; -import static org.junit.Assert.fail; +import org.junit.jupiter.api.Test; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThatThrownBy; /** * Tests for {@link WaitHelper}. @@ -60,16 +60,13 @@ public final void testWaitUntilNoMoreExceptionFAILURE() { final AtomicInteger counter = new AtomicInteger(0); // TEST - try { + assertThatThrownBy(() -> { testee.waitUntilNoMoreException(() -> { if (counter.getAndIncrement() < 2) { throw new RuntimeException(new FileNotFoundException("dummy" + counter.get())); } }, expectedExceptions); - fail(); - } catch (final IllegalStateException ex) { - // OK - } + }).isInstanceOf(IllegalStateException.class); } @Test @@ -81,17 +78,12 @@ public final void testWaitUntilNoMoreExceptionUnexpectedException() { expectedExceptions.add(FileNotFoundException.class); // TEST - try { + assertThatThrownBy(() -> { testee.waitUntilNoMoreException(() -> { throw new ClassCastException("dummy"); }, expectedExceptions); - fail(); - } catch (final ClassCastException ex) { - if (!ex.getMessage().equals("dummy")) { - throw ex; - } - // OK - } + }).isInstanceOf(ClassCastException.class) + .hasMessage("dummy"); } @Test @@ -122,14 +114,11 @@ public final void testWaitUntilResultFAILURE() throws Exception { expectedValues.add(1); // TEST - try { + assertThatThrownBy(() -> { testee.waitUntilResult(() -> { return null; }, expectedValues); - fail(); - } catch (final IllegalStateException ex) { - // OK - } + }).isInstanceOf(IllegalStateException.class); } diff --git a/src/test/java/org/fuin/utils4j/classpath/HandlerTest.java b/src/test/java/org/fuin/utils4j/classpath/HandlerTest.java index f8a17ef..6f387e5 100644 --- a/src/test/java/org/fuin/utils4j/classpath/HandlerTest.java +++ b/src/test/java/org/fuin/utils4j/classpath/HandlerTest.java @@ -25,8 +25,7 @@ import java.util.List; import org.apache.commons.io.IOUtils; -import org.fuin.utils4j.classpath.Handler; -import org.junit.Test; +import org.junit.jupiter.api.Test; // CHECKSTYLE:OFF public class HandlerTest { diff --git a/src/test/java/org/fuin/utils4j/fileprocessor/FileHandlerResultTest.java b/src/test/java/org/fuin/utils4j/fileprocessor/FileHandlerResultTest.java index 49b5caf..2b02faa 100644 --- a/src/test/java/org/fuin/utils4j/fileprocessor/FileHandlerResultTest.java +++ b/src/test/java/org/fuin/utils4j/fileprocessor/FileHandlerResultTest.java @@ -20,8 +20,7 @@ import static org.assertj.core.api.Assertions.assertThat; import nl.jqno.equalsverifier.EqualsVerifier; import nl.jqno.equalsverifier.Warning; - -import org.junit.Test; +import org.junit.jupiter.api.Test; // CHECKSTYLE:OFF public class FileHandlerResultTest { diff --git a/src/test/java/org/fuin/utils4j/fileprocessor/FileOrderTest.java b/src/test/java/org/fuin/utils4j/fileprocessor/FileOrderTest.java index ba09a9e..c9b5448 100644 --- a/src/test/java/org/fuin/utils4j/fileprocessor/FileOrderTest.java +++ b/src/test/java/org/fuin/utils4j/fileprocessor/FileOrderTest.java @@ -21,7 +21,7 @@ import nl.jqno.equalsverifier.EqualsVerifier; import nl.jqno.equalsverifier.Warning; -import org.junit.Test; +import org.junit.jupiter.api.Test; // CHECKSTYLE:OFF public class FileOrderTest { diff --git a/src/test/java/org/fuin/utils4j/fileprocessor/FileProcessorTest.java b/src/test/java/org/fuin/utils4j/fileprocessor/FileProcessorTest.java index 8408c35..e754877 100644 --- a/src/test/java/org/fuin/utils4j/fileprocessor/FileProcessorTest.java +++ b/src/test/java/org/fuin/utils4j/fileprocessor/FileProcessorTest.java @@ -23,7 +23,7 @@ import java.util.ArrayList; import java.util.List; -import org.junit.Test; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public class FileProcessorTest { diff --git a/src/test/java/org/fuin/utils4j/filter/AndFilterTest.java b/src/test/java/org/fuin/utils4j/filter/AndFilterTest.java index 4809faa..4d786fe 100644 --- a/src/test/java/org/fuin/utils4j/filter/AndFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/AndFilterTest.java @@ -17,11 +17,11 @@ */ package org.fuin.utils4j.filter; +import org.junit.jupiter.api.Test; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; - //CHECKSTYLE:OFF public class AndFilterTest extends ListFilterTest { diff --git a/src/test/java/org/fuin/utils4j/filter/BooleanFilterTest.java b/src/test/java/org/fuin/utils4j/filter/BooleanFilterTest.java index 1465637..f8b85da 100644 --- a/src/test/java/org/fuin/utils4j/filter/BooleanFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/BooleanFilterTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public class BooleanFilterTest { diff --git a/src/test/java/org/fuin/utils4j/filter/BooleanPropertyFilterTest.java b/src/test/java/org/fuin/utils4j/filter/BooleanPropertyFilterTest.java index 50bfe2f..213e9af 100644 --- a/src/test/java/org/fuin/utils4j/filter/BooleanPropertyFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/BooleanPropertyFilterTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public class BooleanPropertyFilterTest extends PropertyFilterTest { diff --git a/src/test/java/org/fuin/utils4j/filter/IntegerFilterTest.java b/src/test/java/org/fuin/utils4j/filter/IntegerFilterTest.java index de54562..e7ef0ca 100644 --- a/src/test/java/org/fuin/utils4j/filter/IntegerFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/IntegerFilterTest.java @@ -19,58 +19,58 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public class IntegerFilterTest { @Test public final void testCompliesLT() { - final Filter filter = new IntegerFilter(IntegerFilter.Operator.LT, new Integer(2)); - assertThat(filter.complies(new Integer(1))).isTrue(); - assertThat(filter.complies(new Integer(2))).isFalse(); - assertThat(filter.complies(new Integer(3))).isFalse(); + final Filter filter = new IntegerFilter(IntegerFilter.Operator.LT, 2); + assertThat(filter.complies(1)).isTrue(); + assertThat(filter.complies(2)).isFalse(); + assertThat(filter.complies(3)).isFalse(); } @Test public final void testCompliesLTE() { - final Filter filter = new IntegerFilter(IntegerFilter.Operator.LTE, new Integer(2)); - assertThat(filter.complies(new Integer(1))).isTrue(); - assertThat(filter.complies(new Integer(2))).isTrue(); - assertThat(filter.complies(new Integer(3))).isFalse(); + final Filter filter = new IntegerFilter(IntegerFilter.Operator.LTE, 2); + assertThat(filter.complies(1)).isTrue(); + assertThat(filter.complies(2)).isTrue(); + assertThat(filter.complies(3)).isFalse(); } @Test public final void testCompliesEQ() { - final Filter filter = new IntegerFilter(IntegerFilter.Operator.EQ, new Integer(2)); - assertThat(filter.complies(new Integer(1))).isFalse(); - assertThat(filter.complies(new Integer(2))).isTrue(); - assertThat(filter.complies(new Integer(3))).isFalse(); + final Filter filter = new IntegerFilter(IntegerFilter.Operator.EQ, 2); + assertThat(filter.complies(1)).isFalse(); + assertThat(filter.complies(2)).isTrue(); + assertThat(filter.complies(3)).isFalse(); } @Test public final void testCompliesGT() { - final Filter filter = new IntegerFilter(IntegerFilter.Operator.GT, new Integer(2)); - assertThat(filter.complies(new Integer(1))).isFalse(); - assertThat(filter.complies(new Integer(2))).isFalse(); - assertThat(filter.complies(new Integer(3))).isTrue(); + final Filter filter = new IntegerFilter(IntegerFilter.Operator.GT, 2); + assertThat(filter.complies(1)).isFalse(); + assertThat(filter.complies(2)).isFalse(); + assertThat(filter.complies(3)).isTrue(); } @Test public final void testCompliesGTE() { - final Filter filter = new IntegerFilter(IntegerFilter.Operator.GTE, new Integer(2)); - assertThat(filter.complies(new Integer(1))).isFalse(); - assertThat(filter.complies(new Integer(2))).isTrue(); - assertThat(filter.complies(new Integer(3))).isTrue(); + final Filter filter = new IntegerFilter(IntegerFilter.Operator.GTE, 2); + assertThat(filter.complies(1)).isFalse(); + assertThat(filter.complies(2)).isTrue(); + assertThat(filter.complies(3)).isTrue(); } @Test public final void testToString() { - assertThat("" + new IntegerFilter(IntegerFilter.Operator.LT, new Integer(2))).isEqualTo(" < 2"); - assertThat("" + new IntegerFilter(IntegerFilter.Operator.LTE, new Integer(2))).isEqualTo(" <= 2"); - assertThat("" + new IntegerFilter(IntegerFilter.Operator.EQ, new Integer(2))).isEqualTo(" = 2"); - assertThat("" + new IntegerFilter(IntegerFilter.Operator.GT, new Integer(2))).isEqualTo(" > 2"); - assertThat("" + new IntegerFilter(IntegerFilter.Operator.GTE, new Integer(2))).isEqualTo(" >= 2"); + assertThat("" + new IntegerFilter(IntegerFilter.Operator.LT, 2)).isEqualTo(" < 2"); + assertThat("" + new IntegerFilter(IntegerFilter.Operator.LTE, 2)).isEqualTo(" <= 2"); + assertThat("" + new IntegerFilter(IntegerFilter.Operator.EQ, 2)).isEqualTo(" = 2"); + assertThat("" + new IntegerFilter(IntegerFilter.Operator.GT, 2)).isEqualTo(" > 2"); + assertThat("" + new IntegerFilter(IntegerFilter.Operator.GTE, 2)).isEqualTo(" >= 2"); } } diff --git a/src/test/java/org/fuin/utils4j/filter/IntegerPropertyFilterTest.java b/src/test/java/org/fuin/utils4j/filter/IntegerPropertyFilterTest.java index 8b5571b..e5e3a56 100644 --- a/src/test/java/org/fuin/utils4j/filter/IntegerPropertyFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/IntegerPropertyFilterTest.java @@ -19,67 +19,67 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public class IntegerPropertyFilterTest extends PropertyFilterTest { @Override protected final PropertyFilter createTestee(final String propertyName) { - return new IntegerPropertyFilter(propertyName, ComparableFilter.Operator.EQ, new Integer(1)); + return new IntegerPropertyFilter(propertyName, ComparableFilter.Operator.EQ, Integer.valueOf(1)); } @Test public final void testCompliesLT() { - final Filter filter = new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.LT, new Integer(2)); - assertThat(filter.complies(new TestObject(new Integer(1)))).isTrue(); - assertThat(filter.complies(new TestObject(new Integer(2)))).isFalse(); - assertThat(filter.complies(new TestObject(new Integer(3)))).isFalse(); + final Filter filter = new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.LT, Integer.valueOf(2)); + assertThat(filter.complies(new TestObject(Integer.valueOf(1)))).isTrue(); + assertThat(filter.complies(new TestObject(Integer.valueOf(2)))).isFalse(); + assertThat(filter.complies(new TestObject(Integer.valueOf(3)))).isFalse(); } @Test public final void testCompliesLTE() { - final Filter filter = new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.LTE, new Integer(2)); - assertThat(filter.complies(new TestObject(new Integer(1)))).isTrue(); - assertThat(filter.complies(new TestObject(new Integer(2)))).isTrue(); - assertThat(filter.complies(new TestObject(new Integer(3)))).isFalse(); + final Filter filter = new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.LTE, Integer.valueOf(2)); + assertThat(filter.complies(new TestObject(Integer.valueOf(1)))).isTrue(); + assertThat(filter.complies(new TestObject(Integer.valueOf(2)))).isTrue(); + assertThat(filter.complies(new TestObject(Integer.valueOf(3)))).isFalse(); } @Test public final void testCompliesEQ() { - final Filter filter = new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.EQ, new Integer(2)); - assertThat(filter.complies(new TestObject(new Integer(1)))).isFalse(); - assertThat(filter.complies(new TestObject(new Integer(2)))).isTrue(); - assertThat(filter.complies(new TestObject(new Integer(3)))).isFalse(); + final Filter filter = new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.EQ, Integer.valueOf(2)); + assertThat(filter.complies(new TestObject(Integer.valueOf(1)))).isFalse(); + assertThat(filter.complies(new TestObject(Integer.valueOf(2)))).isTrue(); + assertThat(filter.complies(new TestObject(Integer.valueOf(3)))).isFalse(); } @Test public final void testCompliesGT() { - final Filter filter = new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.GT, new Integer(2)); - assertThat(filter.complies(new TestObject(new Integer(1)))).isFalse(); - assertThat(filter.complies(new TestObject(new Integer(2)))).isFalse(); - assertThat(filter.complies(new TestObject(new Integer(3)))).isTrue(); + final Filter filter = new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.GT, Integer.valueOf(2)); + assertThat(filter.complies(new TestObject(Integer.valueOf(1)))).isFalse(); + assertThat(filter.complies(new TestObject(Integer.valueOf(2)))).isFalse(); + assertThat(filter.complies(new TestObject(Integer.valueOf(3)))).isTrue(); } @Test public final void testCompliesGTE() { - final Filter filter = new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.GTE, new Integer(2)); - assertThat(filter.complies(new TestObject(new Integer(1)))).isFalse(); - assertThat(filter.complies(new TestObject(new Integer(2)))).isTrue(); - assertThat(filter.complies(new TestObject(new Integer(3)))).isTrue(); + final Filter filter = new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.GTE, Integer.valueOf(2)); + assertThat(filter.complies(new TestObject(Integer.valueOf(1)))).isFalse(); + assertThat(filter.complies(new TestObject(Integer.valueOf(2)))).isTrue(); + assertThat(filter.complies(new TestObject(Integer.valueOf(3)))).isTrue(); } @Test public final void testToString() { - assertThat("" + new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.LT, new Integer(2))) + assertThat("" + new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.LT, Integer.valueOf(2))) .isEqualTo(INTEGER_PROPERTY_NAME + " < 2"); - assertThat("" + new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.LTE, new Integer(2))) + assertThat("" + new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.LTE, Integer.valueOf(2))) .isEqualTo(INTEGER_PROPERTY_NAME + " <= 2"); - assertThat("" + new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.EQ, new Integer(2))) + assertThat("" + new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.EQ, Integer.valueOf(2))) .isEqualTo(INTEGER_PROPERTY_NAME + " = 2"); - assertThat("" + new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.GT, new Integer(2))) + assertThat("" + new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.GT, Integer.valueOf(2))) .isEqualTo(INTEGER_PROPERTY_NAME + " > 2"); - assertThat("" + new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.GTE, new Integer(2))) + assertThat("" + new IntegerPropertyFilter(INTEGER_PROPERTY_NAME, ComparableFilter.Operator.GTE, Integer.valueOf(2))) .isEqualTo(INTEGER_PROPERTY_NAME + " >= 2"); } diff --git a/src/test/java/org/fuin/utils4j/filter/ListFilterTest.java b/src/test/java/org/fuin/utils4j/filter/ListFilterTest.java index c20ce18..e7cc6eb 100644 --- a/src/test/java/org/fuin/utils4j/filter/ListFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/ListFilterTest.java @@ -23,7 +23,7 @@ import java.util.ArrayList; import java.util.List; -import org.junit.Test; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public abstract class ListFilterTest { diff --git a/src/test/java/org/fuin/utils4j/filter/OrFilterTest.java b/src/test/java/org/fuin/utils4j/filter/OrFilterTest.java index 6007a5f..be576c2 100644 --- a/src/test/java/org/fuin/utils4j/filter/OrFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/OrFilterTest.java @@ -17,11 +17,11 @@ */ package org.fuin.utils4j.filter; +import org.junit.jupiter.api.Test; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; - //CHECKSTYLE:OFF public class OrFilterTest extends ListFilterTest { diff --git a/src/test/java/org/fuin/utils4j/filter/PropertyFilterTest.java b/src/test/java/org/fuin/utils4j/filter/PropertyFilterTest.java index 5e7a808..4c0b5da 100644 --- a/src/test/java/org/fuin/utils4j/filter/PropertyFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/PropertyFilterTest.java @@ -17,9 +17,9 @@ */ package org.fuin.utils4j.filter; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Test; -import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; //CHECKSTYLE:OFF public abstract class PropertyFilterTest { diff --git a/src/test/java/org/fuin/utils4j/filter/RegExprFilterTest.java b/src/test/java/org/fuin/utils4j/filter/RegExprFilterTest.java index 912ecfb..bc54f8a 100644 --- a/src/test/java/org/fuin/utils4j/filter/RegExprFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/RegExprFilterTest.java @@ -17,9 +17,9 @@ */ package org.fuin.utils4j.filter; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Test; -import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; //CHECKSTYLE:OFF public class RegExprFilterTest { diff --git a/src/test/java/org/fuin/utils4j/filter/RegExprPropertyFilterTest.java b/src/test/java/org/fuin/utils4j/filter/RegExprPropertyFilterTest.java index 3aa513d..dc0eddd 100644 --- a/src/test/java/org/fuin/utils4j/filter/RegExprPropertyFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/RegExprPropertyFilterTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public class RegExprPropertyFilterTest extends PropertyFilterTest { diff --git a/src/test/java/org/fuin/utils4j/filter/StringFilterTest.java b/src/test/java/org/fuin/utils4j/filter/StringFilterTest.java index 8bacfce..c427e31 100644 --- a/src/test/java/org/fuin/utils4j/filter/StringFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/StringFilterTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public class StringFilterTest { diff --git a/src/test/java/org/fuin/utils4j/filter/StringPropertyFilterTest.java b/src/test/java/org/fuin/utils4j/filter/StringPropertyFilterTest.java index 19c1f59..9d2195e 100644 --- a/src/test/java/org/fuin/utils4j/filter/StringPropertyFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/StringPropertyFilterTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public class StringPropertyFilterTest extends PropertyFilterTest { diff --git a/src/test/java/org/fuin/utils4j/filter/TokenFilterTest.java b/src/test/java/org/fuin/utils4j/filter/TokenFilterTest.java index 8dbe98d..a5adc32 100644 --- a/src/test/java/org/fuin/utils4j/filter/TokenFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/TokenFilterTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public class TokenFilterTest { diff --git a/src/test/java/org/fuin/utils4j/filter/TokenPropertyFilterTest.java b/src/test/java/org/fuin/utils4j/filter/TokenPropertyFilterTest.java index 0a0c118..172e5ca 100644 --- a/src/test/java/org/fuin/utils4j/filter/TokenPropertyFilterTest.java +++ b/src/test/java/org/fuin/utils4j/filter/TokenPropertyFilterTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; //CHECKSTYLE:OFF public class TokenPropertyFilterTest extends PropertyFilterTest { diff --git a/src/test/java/org/fuin/utils4j/jaxb/CDataJaxbTest.java b/src/test/java/org/fuin/utils4j/jaxb/CDataJaxbTest.java index b58b67f..7288af9 100644 --- a/src/test/java/org/fuin/utils4j/jaxb/CDataJaxbTest.java +++ b/src/test/java/org/fuin/utils4j/jaxb/CDataJaxbTest.java @@ -27,7 +27,7 @@ import jakarta.xml.bind.JAXBContext; -import org.junit.Test; +import org.junit.jupiter.api.Test; // CHECKSTYLE:OFF public class CDataJaxbTest { diff --git a/src/test/java/org/fuin/utils4j/jaxb/UnmarshallerBuilderTest.java b/src/test/java/org/fuin/utils4j/jaxb/UnmarshallerBuilderTest.java index f912a64..0e3e174 100644 --- a/src/test/java/org/fuin/utils4j/jaxb/UnmarshallerBuilderTest.java +++ b/src/test/java/org/fuin/utils4j/jaxb/UnmarshallerBuilderTest.java @@ -18,7 +18,7 @@ package org.fuin.utils4j.jaxb; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; +import static org.assertj.core.api.Assertions.fail; import java.util.ArrayList; import java.util.List; @@ -33,7 +33,7 @@ import jakarta.xml.bind.Unmarshaller; import jakarta.xml.bind.annotation.adapters.XmlAdapter; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.xml.sax.SAXParseException; /** From 39fae1a836a432b1dc7e18293fc3175eeb2f1cf7 Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sat, 23 Dec 2023 11:26:18 +0100 Subject: [PATCH 02/22] Updated Maven Wrapper --- .mvn/wrapper/maven-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index f3283b0..346d645 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar From 680cc581569ee22ae96b8572259710c986d58455 Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sat, 23 Dec 2023 11:43:40 +0100 Subject: [PATCH 03/22] Code cleanup --- .../org/fuin/utils4j/ChangeTrackingMap.java | 7 +--- .../utils4j/ChangeTrackingUniqueList.java | 7 +--- .../java/org/fuin/utils4j/JandexUtils.java | 4 +- .../java/org/fuin/utils4j/PropertiesFile.java | 15 +------ .../org/fuin/utils4j/PropertiesUtils.java | 14 ++----- .../utils4j/RandomAccessFileInputStream.java | 6 +-- .../utils4j/RandomAccessFileOutputStream.java | 6 +-- src/main/java/org/fuin/utils4j/Utils4J.java | 39 ++++--------------- .../org/fuin/utils4j/VariableResolver.java | 8 +--- .../fuin/utils4j/filter/ComparableFilter.java | 4 +- .../fuin/utils4j/filter/RegExprFilter.java | 4 +- .../org/fuin/utils4j/filter/StringFilter.java | 4 +- .../java/org/fuin/utils4j/jaxb/JaxbUtils.java | 14 ++----- .../utils4j/jaxb/UnmarshallerBuilder.java | 22 +++-------- .../fuin/utils4j/CancelableVolatileTest.java | 4 +- .../fuin/utils4j/ChangeTrackingMapTest.java | 29 +++++++------- .../utils4j/ChangeTrackingUniqueListTest.java | 9 ++--- .../ClasspathURLStreamHandlerTest.java | 4 +- .../InvokeMethodFailedExceptionTest.java | 4 +- .../org/fuin/utils4j/JandexUtilsTest.java | 10 ++--- .../utils4j/LockingFailedExceptionTest.java | 4 +- .../org/fuin/utils4j/MergeExceptionTest.java | 4 +- .../PropertiesFilePreferencesTest.java | 10 ++--- .../org/fuin/utils4j/PropertiesFileTest.java | 14 +++---- .../java/org/fuin/utils4j/PropertyTest.java | 7 ++-- .../RandomAccessFileInputStreamTest.java | 10 +++-- .../RandomAccessFileOutputStreamTest.java | 12 +++--- .../java/org/fuin/utils4j/TestHelper.java | 4 +- .../fuin/utils4j/VariableResolverTest.java | 9 ++--- .../fuin/utils4j/classpath/HandlerTest.java | 6 +-- .../utils4j/examples/CDataJaxbExample.java | 16 ++++---- .../examples/ChangeTrackingMapExample.java | 4 +- .../ChangeTrackingUniqueListExample.java | 4 +- .../utils4j/examples/ClasspathURLExample.java | 4 +- .../FindJarsAndClassesInClasspath.java | 4 +- .../utils4j/examples/LockFileExample.java | 6 +-- ...opertiesFilePreferencesFactoryExample.java | 4 +- .../examples/VariableResolverExample.java | 4 +- .../utils4j/examples/WaitHelperExample.java | 4 +- .../fuin/utils4j/examples/ZipDirExample.java | 8 +--- .../examples/filter/SimpleFilterExample.java | 8 +--- .../fileprocessor/FileHandlerResultTest.java | 3 +- .../utils4j/fileprocessor/FileOrderTest.java | 4 +- .../fileprocessor/FileProcessorTest.java | 17 ++++---- .../fuin/utils4j/filter/AndFilterTest.java | 1 - .../utils4j/filter/BooleanFilterTest.java | 8 ++-- .../filter/BooleanPropertyFilterTest.java | 8 ++-- .../utils4j/filter/IntegerFilterTest.java | 4 +- .../filter/IntegerPropertyFilterTest.java | 4 +- .../fuin/utils4j/filter/ListFilterTest.java | 5 +-- .../org/fuin/utils4j/filter/OrFilterTest.java | 1 - .../filter/RegExprPropertyFilterTest.java | 4 +- .../fuin/utils4j/filter/StringFilterTest.java | 4 +- .../filter/StringPropertyFilterTest.java | 4 +- .../fuin/utils4j/filter/TokenFilterTest.java | 4 +- .../filter/TokenPropertyFilterTest.java | 4 +- .../org/fuin/utils4j/jaxb/CDataJaxbTest.java | 14 +++---- src/test/java/org/fuin/utils4j/jaxb/MyId.java | 4 +- .../utils4j/jaxb/UnmarshallerBuilderTest.java | 20 +++++----- .../org/fuin/utils4j/test-schema.xsd | 7 ++-- 60 files changed, 188 insertions(+), 292 deletions(-) diff --git a/src/main/java/org/fuin/utils4j/ChangeTrackingMap.java b/src/main/java/org/fuin/utils4j/ChangeTrackingMap.java index 3b68437..c4e3b8d 100644 --- a/src/main/java/org/fuin/utils4j/ChangeTrackingMap.java +++ b/src/main/java/org/fuin/utils4j/ChangeTrackingMap.java @@ -17,12 +17,7 @@ */ package org.fuin.utils4j; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * A wrapper for maps that keeps track of all changes made to the map since construction. Only adding, replacing or deleting elements is diff --git a/src/main/java/org/fuin/utils4j/ChangeTrackingUniqueList.java b/src/main/java/org/fuin/utils4j/ChangeTrackingUniqueList.java index 23798aa..bb7d7ed 100644 --- a/src/main/java/org/fuin/utils4j/ChangeTrackingUniqueList.java +++ b/src/main/java/org/fuin/utils4j/ChangeTrackingUniqueList.java @@ -17,12 +17,7 @@ */ package org.fuin.utils4j; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; +import java.util.*; /** * A wrapper for lists that keeps track of all changes made to the list since construction. Only adding, replacing or deleting elements is diff --git a/src/main/java/org/fuin/utils4j/JandexUtils.java b/src/main/java/org/fuin/utils4j/JandexUtils.java index 59be380..e600b62 100644 --- a/src/main/java/org/fuin/utils4j/JandexUtils.java +++ b/src/main/java/org/fuin/utils4j/JandexUtils.java @@ -17,6 +17,8 @@ */ package org.fuin.utils4j; +import org.jboss.jandex.Indexer; + import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -25,8 +27,6 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; -import org.jboss.jandex.Indexer; - /** * Utilities related to Jandex. */ diff --git a/src/main/java/org/fuin/utils4j/PropertiesFile.java b/src/main/java/org/fuin/utils4j/PropertiesFile.java index de161e3..9ad5a1e 100644 --- a/src/main/java/org/fuin/utils4j/PropertiesFile.java +++ b/src/main/java/org/fuin/utils4j/PropertiesFile.java @@ -17,20 +17,9 @@ */ package org.fuin.utils4j; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.LineNumberReader; -import java.io.OutputStreamWriter; -import java.io.Writer; +import java.io.*; import java.nio.channels.FileLock; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Properties; +import java.util.*; /** * A properties file that is capable of merging concurrent changes made by another JVM or another process. diff --git a/src/main/java/org/fuin/utils4j/PropertiesUtils.java b/src/main/java/org/fuin/utils4j/PropertiesUtils.java index 5fdacbf..becdac5 100644 --- a/src/main/java/org/fuin/utils4j/PropertiesUtils.java +++ b/src/main/java/org/fuin/utils4j/PropertiesUtils.java @@ -17,21 +17,13 @@ */ package org.fuin.utils4j; -import static org.fuin.utils4j.Utils4J.checkNotNull; -import static org.fuin.utils4j.Utils4J.checkValidFile; -import static org.fuin.utils4j.Utils4J.createUrl; -import static org.fuin.utils4j.Utils4J.getPackagePath; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.util.Properties; +import static org.fuin.utils4j.Utils4J.*; + /** * Utilities related to the {@link Properties} class. */ diff --git a/src/main/java/org/fuin/utils4j/RandomAccessFileInputStream.java b/src/main/java/org/fuin/utils4j/RandomAccessFileInputStream.java index 81961b8..10d5904 100644 --- a/src/main/java/org/fuin/utils4j/RandomAccessFileInputStream.java +++ b/src/main/java/org/fuin/utils4j/RandomAccessFileInputStream.java @@ -17,11 +17,7 @@ */ package org.fuin.utils4j; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; +import java.io.*; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; diff --git a/src/main/java/org/fuin/utils4j/RandomAccessFileOutputStream.java b/src/main/java/org/fuin/utils4j/RandomAccessFileOutputStream.java index 4f58c8e..fcc4f96 100644 --- a/src/main/java/org/fuin/utils4j/RandomAccessFileOutputStream.java +++ b/src/main/java/org/fuin/utils4j/RandomAccessFileOutputStream.java @@ -17,11 +17,7 @@ */ package org.fuin.utils4j; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.OutputStream; -import java.io.RandomAccessFile; +import java.io.*; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; diff --git a/src/main/java/org/fuin/utils4j/Utils4J.java b/src/main/java/org/fuin/utils4j/Utils4J.java index 729a4bb..5ec08b4 100644 --- a/src/main/java/org/fuin/utils4j/Utils4J.java +++ b/src/main/java/org/fuin/utils4j/Utils4J.java @@ -17,25 +17,12 @@ */ package org.fuin.utils4j; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedWriter; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileFilter; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.RandomAccessFile; -import java.io.Reader; -import java.io.Writer; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import java.io.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; @@ -48,25 +35,13 @@ import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.function.Predicate; import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; -import javax.crypto.Cipher; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.PBEParameterSpec; - /** * Common utility methods for use in Java applications and libraries. */ diff --git a/src/main/java/org/fuin/utils4j/VariableResolver.java b/src/main/java/org/fuin/utils4j/VariableResolver.java index 1113dbb..ac623dd 100644 --- a/src/main/java/org/fuin/utils4j/VariableResolver.java +++ b/src/main/java/org/fuin/utils4j/VariableResolver.java @@ -17,13 +17,7 @@ */ package org.fuin.utils4j; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * Resolves the references from variable values to other variable names. diff --git a/src/main/java/org/fuin/utils4j/filter/ComparableFilter.java b/src/main/java/org/fuin/utils4j/filter/ComparableFilter.java index 4a1a641..c5f78ad 100644 --- a/src/main/java/org/fuin/utils4j/filter/ComparableFilter.java +++ b/src/main/java/org/fuin/utils4j/filter/ComparableFilter.java @@ -17,12 +17,12 @@ */ package org.fuin.utils4j.filter; +import org.fuin.utils4j.Utils4J; + import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.fuin.utils4j.Utils4J; - /** * Defines a filter on a Comparable value. */ diff --git a/src/main/java/org/fuin/utils4j/filter/RegExprFilter.java b/src/main/java/org/fuin/utils4j/filter/RegExprFilter.java index 500820e..4bbbf27 100644 --- a/src/main/java/org/fuin/utils4j/filter/RegExprFilter.java +++ b/src/main/java/org/fuin/utils4j/filter/RegExprFilter.java @@ -43,10 +43,10 @@ public class RegExprFilter implements Filter { private static final String[] TYPES = new String[] { "matches", "lookingAt", "find" }; /** Compiled pattern. */ - private Pattern p = null; + private Pattern p; /** String pattern to apply. */ - private String pattern = null; + private String pattern; /** Type of matching. */ private int type = 1; diff --git a/src/main/java/org/fuin/utils4j/filter/StringFilter.java b/src/main/java/org/fuin/utils4j/filter/StringFilter.java index 42460ed..e7d17da 100644 --- a/src/main/java/org/fuin/utils4j/filter/StringFilter.java +++ b/src/main/java/org/fuin/utils4j/filter/StringFilter.java @@ -17,12 +17,12 @@ */ package org.fuin.utils4j.filter; +import org.fuin.utils4j.Utils4J; + import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.fuin.utils4j.Utils4J; - /** * Defines a filter on a String. */ diff --git a/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java b/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java index fb5cd1e..207226d 100644 --- a/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java +++ b/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java @@ -17,24 +17,16 @@ */ package org.fuin.utils4j.jaxb; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.io.StringWriter; -import java.io.Writer; - -import javax.xml.stream.XMLStreamWriter; - import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.Marshaller; import jakarta.xml.bind.Unmarshaller; import jakarta.xml.bind.annotation.adapters.XmlAdapter; - import org.fuin.utils4j.Utils4J; +import javax.xml.stream.XMLStreamWriter; +import java.io.*; + /** * JAXB releated functions. */ diff --git a/src/main/java/org/fuin/utils4j/jaxb/UnmarshallerBuilder.java b/src/main/java/org/fuin/utils4j/jaxb/UnmarshallerBuilder.java index 5ff750d..b16cc7c 100644 --- a/src/main/java/org/fuin/utils4j/jaxb/UnmarshallerBuilder.java +++ b/src/main/java/org/fuin/utils4j/jaxb/UnmarshallerBuilder.java @@ -1,27 +1,16 @@ package org.fuin.utils4j.jaxb; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import jakarta.xml.bind.*; +import jakarta.xml.bind.annotation.adapters.XmlAdapter; +import org.fuin.utils4j.Utils4J; +import org.xml.sax.SAXException; import javax.xml.XMLConstants; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; - -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.JAXBException; -import jakarta.xml.bind.PropertyException; -import jakarta.xml.bind.Unmarshaller; -import jakarta.xml.bind.ValidationEventHandler; -import jakarta.xml.bind.annotation.adapters.XmlAdapter; - -import org.fuin.utils4j.Utils4J; -import org.xml.sax.SAXException; +import java.util.*; /** * Builder that helps creating an {@link Unmarshaller} instance. @@ -290,6 +279,7 @@ private static void setProperties(final Unmarshaller unmarshaller, final Map - - + targetNamespace="http://www.fuin.org/utils4j"> + + From fbeb56010bbfa6a8686526787f13385fb528e85e Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Tue, 26 Dec 2023 10:01:20 +0100 Subject: [PATCH 04/22] Switched to Java 17 and added marshaller builder --- .github/workflows/maven.yml | 4 +- README.md | 3 +- pom.xml | 10 +- .../java/org/fuin/utils4j/jaxb/JaxbUtils.java | 81 +++++ .../fuin/utils4j/jaxb/MarshallerBuilder.java | 332 ++++++++++++++++++ .../utils4j/jaxb/MarshallerBuilderTest.java | 232 ++++++++++++ .../java/org/fuin/utils4j/jaxb/MyClass.java | 1 + 7 files changed, 655 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/fuin/utils4j/jaxb/MarshallerBuilder.java create mode 100644 src/test/java/org/fuin/utils4j/jaxb/MarshallerBuilderTest.java diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9a711c5..4662abe 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -23,10 +23,10 @@ jobs: with: fetch-depth: 0 - - name: Set up JDK 11 + - name: Set up JDK uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'zulu' cache: maven diff --git a/README.md b/README.md index e4d252e..0538164 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,8 @@ A small Java library that contains several helpful utility classes. [![Java Development Kit 11](https://img.shields.io/badge/JDK-11-green.svg)](https://openjdk.java.net/projects/jdk/11/) ## Versions -- 0.12.x (or later) = **Java 11** with new **jakarta** namespace +- 0.13.x (or later) = **Java 17** +- 0.12.0 = **Java 11** with new **jakarta** namespace - 0.11.x = **Java 11** before namespace change from 'javax' to 'jakarta' - 0.9.x/0.10.x = **Java 8** - 0.8 (or previous) = **Java 1.4.2** diff --git a/pom.xml b/pom.xml index cf2d16a..f7f317e 100644 --- a/pom.xml +++ b/pom.xml @@ -7,12 +7,12 @@ org.fuin pom - 1.8.0 + 1.9.0 utils4j bundle - 0.12.1-SNAPSHOT + 0.13.0-SNAPSHOT A small Java library that contains several helpful utility classes. http://www.fuin.org/utils4j/ @@ -75,9 +75,9 @@ - xmlunit - xmlunit - 1.6 + org.xmlunit + xmlunit-core + 2.8.2 test diff --git a/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java b/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java index 207226d..b42763f 100644 --- a/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java +++ b/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java @@ -53,6 +53,7 @@ private JaxbUtils() { * * @param * Type of the data. + * @deprecated Use method {@link #marshal(Marshaller, Object)} together with {@link MarshallerBuilder} instead */ public static String marshal(final T data, final Class... classesToBeBound) { return marshal(data, null, classesToBeBound); @@ -72,6 +73,7 @@ public static String marshal(final T data, final Class... classesToBeBoun * * @param * Type of the data. + * @deprecated Use method {@link #marshal(Marshaller, Object)} together with {@link MarshallerBuilder} instead */ public static String marshal(final T data, final XmlAdapter[] adapters, final Class... classesToBeBound) { if (data == null) { @@ -97,6 +99,7 @@ public static String marshal(final T data, final XmlAdapter[] adapters * * @param * Type of the data. + * @deprecated Use method {@link #marshal(Marshaller, Object)} together with {@link MarshallerBuilder} instead */ public static String marshal(final JAXBContext ctx, final T data) { return marshal(ctx, data, null); @@ -116,6 +119,7 @@ public static String marshal(final JAXBContext ctx, final T data) { * * @param * Type of the data. + * @deprecated Use method {@link #marshal(Marshaller, Object)} together with {@link MarshallerBuilder} instead */ public static String marshal(final JAXBContext ctx, final T data, final XmlAdapter[] adapters) { if (data == null) { @@ -140,6 +144,7 @@ public static String marshal(final JAXBContext ctx, final T data, final XmlA * * @param * Type of the data to write. + * @deprecated Use method {@link #marshal(Marshaller, Object, Writer)} together with {@link MarshallerBuilder} instead */ public static void marshal(final JAXBContext ctx, final T data, final XmlAdapter[] adapters, final Writer writer) { if (data == null) { @@ -172,6 +177,7 @@ public static void marshal(final JAXBContext ctx, final T data, final XmlAda * * @param * Type of the data to write. + * @deprecated Use method {@link #marshal(Marshaller, Object, XMLStreamWriter)} together with {@link MarshallerBuilder} instead */ public static void marshal(final JAXBContext ctx, final T data, final XmlAdapter[] adapters, final XMLStreamWriter writer) { if (data == null) { @@ -368,4 +374,79 @@ public static T unmarshal(final Unmarshaller unmarshaller, final File file) } } + /** + * Convenience method to marshals the given data to string. A null data argument returns null. + * + * @param marshaller + * Marshaller to use - Cannot be null. + * @param data + * Data to serialize or null. + * + * @return XML data or null. + * + * @param + * Type of the data. + */ + public static String marshal(final Marshaller marshaller, final T data) { + Utils4J.checkNotNull("marshaller", marshaller); + if (data == null) { + return null; + } + final StringWriter writer = new StringWriter(); + marshal(marshaller, data, writer); + return writer.toString(); + } + + /** + * Convenience method to marshals the given data using a writer. A null data argument returns null. + * + * @param marshaller + * Marshaller to use - Cannot be null. + * @param data + * Data to serialize or null. + * @param writer + * Writer to use. + * + * @param + * Type of the data to write. + */ + public static void marshal(final Marshaller marshaller, final T data, final Writer writer) { + Utils4J.checkNotNull("marshaller", marshaller); + Utils4J.checkNotNull("writer", writer); + if (data == null) { + return; + } + try { + marshaller.marshal(data, writer); + } catch (final JAXBException ex) { + throw new RuntimeException(ERROR_MARSHALLING_TEST_DATA, ex); + } + } + + /** + * Convenience method to marshals the given data using an XML stream writer. A null data argument returns null. + * + * @param marshaller + * Marshaller to use - Cannot be null. + * @param data + * Data to serialize or null. + * @param writer + * Writer to use. + * + * @param + * Type of the data to write. + */ + public static void marshal(final Marshaller marshaller, final T data, final XMLStreamWriter writer) { + Utils4J.checkNotNull("marshaller", marshaller); + Utils4J.checkNotNull("writer", writer); + if (data == null) { + return; + } + try { + marshaller.marshal(data, writer); + } catch (final JAXBException ex) { + throw new RuntimeException(ERROR_MARSHALLING_TEST_DATA, ex); + } + } + } diff --git a/src/main/java/org/fuin/utils4j/jaxb/MarshallerBuilder.java b/src/main/java/org/fuin/utils4j/jaxb/MarshallerBuilder.java new file mode 100644 index 0000000..4e0a9fb --- /dev/null +++ b/src/main/java/org/fuin/utils4j/jaxb/MarshallerBuilder.java @@ -0,0 +1,332 @@ +package org.fuin.utils4j.jaxb; + +import jakarta.xml.bind.*; +import jakarta.xml.bind.annotation.adapters.XmlAdapter; +import org.fuin.utils4j.Utils4J; +import org.xml.sax.SAXException; + +import javax.xml.XMLConstants; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import java.util.*; + +/** + * Builder that helps creating an {@link Marshaller} instance. + */ +public class MarshallerBuilder { + + private final Set> adapters; + + private final Set schemaSources; + + private final Set> classesToBeBound; + + private final Map properties; + + private Marshaller.Listener listener; + + private ValidationEventHandler handler; + + private boolean formattedOutput; + + private JAXBContext ctx; + + + /** + * Default constructor. + */ + public MarshallerBuilder() { + adapters = new HashSet<>(); + schemaSources = new HashSet<>(); + classesToBeBound = new HashSet<>(); + properties = new HashMap<>(); + } + + /** + * Use a predefined context. An alternative would be to let the build create a JAXB context internally by using method + * {@link #addClassToBeBound(Class)}, {@link #addClassesToBeBound(Class...)} or {@link #addClassesToBeBound(Collection)}. + * + * @param ctx Context to use for unmarshalling. + * @return The builder. + */ + public MarshallerBuilder withContext(final JAXBContext ctx) { + this.ctx = ctx; + return this; + } + + /** + * Sets a listener for the marshaller. + * + * @param listener Listener to attach. + * @return The builder. + */ + public MarshallerBuilder withListener(final Marshaller.Listener listener) { + this.listener = listener; + return this; + } + + /** + * Sets a validation event handler for the marshaller. + * + * @param handler + * Handler to attach. + * + * @return The builder. + */ + public MarshallerBuilder withHandler(final ValidationEventHandler handler) { + this.handler = handler; + return this; + } + + /** + * Adds a class to the internal {@link JAXBContext}. + * + * @param clasz Class to add. + * @return The builder. + */ + public MarshallerBuilder addClassToBeBound(Class clasz) { + Utils4J.checkNotNull("clasz", clasz); + classesToBeBound.add(clasz); + return this; + } + + /** + * Adds an array of classes to the internal {@link JAXBContext}. + * + * @param classes Classes to add. + * @return The builder. + */ + public MarshallerBuilder addClassesToBeBound(Class... classes) { + Utils4J.checkNotNull("classes", classes); + Arrays.asList(classes).forEach(this::addClassToBeBound); + return this; + } + + /** + * Adds a list of classes to the internal {@link JAXBContext}. + * + * @param classes Classes to add. + * @return The builder. + */ + public MarshallerBuilder addClassesToBeBound(final Collection> classes) { + Utils4J.checkNotNull("classes", classes); + classes.forEach(this::addClassToBeBound); + return this; + } + + /** + * Adds an XML adapter to the internal {@link JAXBContext}. + * + * @param adapter Adapter to add. + * @return The builder. + */ + public MarshallerBuilder addAdapter(final XmlAdapter adapter) { + Utils4J.checkNotNull("adapter", adapter); + adapters.add(adapter); + return this; + } + + /** + * Adds an array of XML adapters to the internal {@link JAXBContext}. + * + * @param adapters Adapters to add. + * @return The builder. + */ + public MarshallerBuilder addAdapters(final XmlAdapter... adapters) { + Utils4J.checkNotNull("adapters", adapters); + Arrays.asList(adapters).forEach(this::addAdapter); + return this; + } + + /** + * Adds a list of XML adapters to the internal {@link JAXBContext}. + * + * @param adapters Adapters to add. + * @return The builder. + */ + public MarshallerBuilder addAdapters(final Collection> adapters) { + Utils4J.checkNotNull("adapters", adapters); + adapters.forEach(this::addAdapter); + return this; + } + + /** + * Adds a schema to validate while unmarshalling. + * + * @param source Source to add. + * @return The builder. + */ + public MarshallerBuilder addSchema(Source source) { + Utils4J.checkNotNull("source", source); + schemaSources.add(source); + return this; + } + + /** + * Adds an array of schemas to validate while unmarshalling. + * + * @param sources Sources to add. + * @return The builder. + */ + public MarshallerBuilder addSchemas(Source... sources) { + Utils4J.checkNotNull("sources", sources); + Arrays.asList(sources).forEach(this::addSchema); + return this; + } + + /** + * Adds a list of schemas to validate while unmarshalling. + * + * @param sources Sources to add. + * @return The builder. + */ + public MarshallerBuilder addSchemas(final Collection sources) { + Utils4J.checkNotNull("sources", sources); + sources.forEach(this::addSchema); + return this; + } + + /** + * Adds a schema in the classpath to validate while unmarshalling. + * + * @param xsdPath Schema path and name to add. + * @return The builder. + */ + public MarshallerBuilder addClasspathSchema(final String xsdPath) { + Utils4J.checkNotNull("xsdPath", xsdPath); + addSchema(new StreamSource(getClass().getResourceAsStream(xsdPath))); + return this; + } + + /** + * Adds an array of schemas in the classpath to validate while unmarshalling. + * + * @param xsdPaths Schema paths and names to add. + * @return The builder. + */ + public MarshallerBuilder addClasspathSchemas(String... xsdPaths) { + Utils4J.checkNotNull("xsdPaths", xsdPaths); + Arrays.asList(xsdPaths).forEach(this::addClasspathSchema); + return this; + } + + /** + * Adds a list of schemas in the classpath to validate while unmarshalling. + * + * @param xsdPaths Schema paths and names to add. + * @return The builder. + */ + public MarshallerBuilder addClasspathSchemas(final Collection xsdPaths) { + Utils4J.checkNotNull("xsdPaths", xsdPaths); + xsdPaths.forEach(this::addClasspathSchema); + return this; + } + + /** + * Sets the marshaller to pretty-print the output. + * + * @return The builder. + */ + public MarshallerBuilder prettyPrint() { + addProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + return this; + } + + /** + * Adds a property to the marshaller. + * + * @param name Name to add. Cannot be null. + * @param value Value to add. Cannot be null. + * @return The builder. + */ + public MarshallerBuilder addProperty(String name, Object value) { + Utils4J.checkNotNull("name", name); + Utils4J.checkNotNull("value", value); + properties.put(name, value); + return this; + } + + private static void setProperties(final Marshaller marshaller, final Map map) { + map.forEach((name, value) -> { + try { + marshaller.setProperty(name, value); + } catch (final PropertyException ex) { + throw new IllegalArgumentException("Failed to set property '" + name + "' to: " + value, ex); + } + }); + } + + private Schema createSchema() { + final SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + try { + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + return factory.newSchema(schemaSources.toArray(new Source[schemaSources.size()])); + } catch (final SAXException ex) { + throw new RuntimeException("Failed to create schema", ex); + } + } + + private JAXBContext getCtx() { + if (!classesToBeBound.isEmpty()) { + if (ctx != null) { + throw new IllegalStateException("A JAXBContext (ctx) and a list of classes (classesToBeBound) was provided. " + + "You can only use one of them, not both."); + } + return createContext(classesToBeBound); + } + if (ctx != null) { + return ctx; + } + throw new IllegalStateException("Either the JAXBContext (ctx) or a list of classes (classesToBeBound) must be provided"); + } + + private static Marshaller createMarshaller(final JAXBContext ctx) { + try { + return ctx.createMarshaller(); + } catch (final JAXBException ex) { + throw new RuntimeException("Failed to create marshaller", ex); + } + } + + private static void setEventHandler(final Marshaller marshaller, final ValidationEventHandler handler) { + try { + marshaller.setEventHandler(handler); + } catch (final JAXBException ex) { + throw new RuntimeException("Failed to set marshaller's event handler", ex); + } + } + + private static JAXBContext createContext(final Set> classesToBeBound) { + try { + return JAXBContext.newInstance(classesToBeBound.toArray(new Class[classesToBeBound.size()])); + } catch (final JAXBException ex) { + throw new RuntimeException("Failed to create JAXB context with classes: " + classesToBeBound, ex); + } + } + + /** + * Builds the final instance based on the builder's setting. + * + * @return New instance. + */ + public Marshaller build() { + final Marshaller marshaller = createMarshaller(getCtx()); + adapters.forEach(marshaller::setAdapter); + if (handler != null) { + setEventHandler(marshaller, handler); + } + if (!schemaSources.isEmpty()) { + marshaller.setSchema(createSchema()); + } + if (!properties.isEmpty()) { + setProperties(marshaller, properties); + } + if (listener != null) { + marshaller.setListener(listener); + } + return marshaller; + } + +} diff --git a/src/test/java/org/fuin/utils4j/jaxb/MarshallerBuilderTest.java b/src/test/java/org/fuin/utils4j/jaxb/MarshallerBuilderTest.java new file mode 100644 index 0000000..de4adc1 --- /dev/null +++ b/src/test/java/org/fuin/utils4j/jaxb/MarshallerBuilderTest.java @@ -0,0 +1,232 @@ +/** + * Copyright (C) 2015 Michael Schnell. All rights reserved. + * http://www.fuin.org/ + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) any + * later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see http://www.gnu.org/licenses/. + */ +package org.fuin.utils4j.jaxb; + +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBException; +import jakarta.xml.bind.MarshalException; +import jakarta.xml.bind.Marshaller; +import jakarta.xml.bind.annotation.adapters.XmlAdapter; +import org.junit.jupiter.api.Test; +import org.xml.sax.SAXParseException; +import org.xmlunit.builder.DiffBuilder; +import org.xmlunit.diff.Diff; + +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.assertj.core.api.Assertions.*; + +/** + * Test for the {@link MarshallerBuilder} class. + */ +public class MarshallerBuilderTest { + + @Test + public void testWithContext() throws JAXBException { + + // PREPARE + final JAXBContext ctx = JAXBContext.newInstance(MyClass.class); + final MyId myId = new MyId(1); + final MyClass myClass = new MyClass(myId, "abc"); + + // TEST + final Marshaller marshaller = new MarshallerBuilder().withContext(ctx).addAdapters(new MyId.Adapter()).build(); + + // VERIFY + final String copyXml = JaxbUtils.marshal(marshaller, myClass); + final Diff documentDiff = DiffBuilder.compare(getValidXml()).withTest(copyXml).ignoreWhitespace().build(); + assertThat(documentDiff.hasDifferences()).describedAs(documentDiff.toString()).isFalse(); + + } + + @Test + public void testWithClassesToBeBound() throws JAXBException { + + // PREPARE + final Class[] classesToBeBound = new Class[] { MyClass.class }; + final MyId myId = new MyId(1); + final MyClass myClass = new MyClass(myId, "abc"); + + // TEST + final List> adapters = new ArrayList<>(); + adapters.add(new MyId.Adapter()); + final Marshaller marshaller = new MarshallerBuilder().addClassesToBeBound(classesToBeBound).addAdapters(adapters).build(); + + // VERIFY + final String copyXml = JaxbUtils.marshal(marshaller, myClass); + final Diff documentDiff = DiffBuilder.compare(getValidXml()).withTest(copyXml).ignoreWhitespace().build(); + assertThat(documentDiff.hasDifferences()).describedAs(documentDiff.toString()).isFalse(); + + } + + @Test + public void testClasspathSchema() throws JAXBException { + + // PREPARE + final List> classesToBeBound = new ArrayList<>(); + classesToBeBound.add(MyClass.class); + final String xsd = "/org/fuin/utils4j/test-schema.xsd"; + final List schemas = new ArrayList<>(); + schemas.add(xsd); + final MyId myId = new MyId(1); + final MyClass myClass = new MyClass(myId, "abc"); + + // TEST + final Marshaller marshaller = new MarshallerBuilder().addClassesToBeBound(classesToBeBound) + .addClasspathSchemas("/org/fuin/utils4j/test-schema.xsd") + .addClasspathSchemas(schemas) // Second add does not harm anything + .addAdapter(new MyId.Adapter()) + .build(); + + // VERIFY + final String copyXml = JaxbUtils.marshal(marshaller, myClass); + final Diff documentDiff = DiffBuilder.compare(getValidXml()).withTest(copyXml).ignoreWhitespace().build(); + assertThat(documentDiff.hasDifferences()).describedAs(documentDiff.toString()).isFalse(); + + } + + @Test + public void testAddSchemas() throws JAXBException { + + // PREPARE + final JAXBContext ctx = JAXBContext.newInstance(MyClass.class); + final StreamSource xsd = new StreamSource(getClass().getResourceAsStream("/org/fuin/utils4j/test-schema.xsd")); + final List schemas = new ArrayList<>(); + schemas.add(xsd); + final MyId myId = new MyId(1); + final MyClass myClass = new MyClass(myId, "abc"); + + // TEST + final Marshaller marshaller = new MarshallerBuilder() + .withContext(ctx) + .addAdapters(new MyId.Adapter()) + .addSchemas(xsd) + .addSchemas(schemas) // Second add does not harm anything + .build(); + + // VERIFY + final String copyXml = JaxbUtils.marshal(marshaller, myClass); + final Diff documentDiff = DiffBuilder.compare(getValidXml()).withTest(copyXml).ignoreWhitespace().build(); + assertThat(documentDiff.hasDifferences()).describedAs(documentDiff.toString()).isFalse(); + + } + + @Test + public void testClassesAndContextFailure() throws JAXBException { + try { + new MarshallerBuilder().withContext(JAXBContext.newInstance(MyClass.class)).addClassToBeBound(MyClass.class).build(); + fail("Expected exception"); + } catch (final IllegalStateException ex) { + assertThat(ex.getMessage()).isEqualTo( + "A JAXBContext (ctx) and a list of classes (classesToBeBound) was provided. You can only use one of them, not both."); + } + } + + @Test + public void testNoClassesAndNoContext() throws JAXBException { + try { + new MarshallerBuilder().build(); + fail("Expected exception"); + } catch (final IllegalStateException ex) { + assertThat(ex.getMessage()).isEqualTo("Either the JAXBContext (ctx) or a list of classes (classesToBeBound) must be provided"); + } + } + + @Test + public void testAddPropertyOK() { + new MarshallerBuilder().addClassToBeBound(MyClass.class).addProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true).build(); + } + + @Test + public void testAddPropertyFailure() { + assertThatThrownBy(() -> { + new MarshallerBuilder().addClassToBeBound(MyClass.class).addProperty("bla", "blub").build(); + }).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Failed to set property 'bla' to: blub"); + } + + @Test + public void testWithEventHandler() throws JAXBException { + + // PREPARE + final JAXBContext ctx = JAXBContext.newInstance(MyClass.class); + final MyId myId = new MyId(1); + final MyClass myClass = new MyClass(myId, "abc"); + + // TEST + final AtomicBoolean result = new AtomicBoolean(false); + final Marshaller marshaller = new MarshallerBuilder().withContext(ctx).addAdapters(new MyId.Adapter()) + .addClasspathSchema("/org/fuin/utils4j/test-schema.xsd") + .withHandler(event -> { + result.set(true); + return true; + }).build(); + + // VERIFY + final String copyXml = JaxbUtils.marshal(marshaller, myClass); + final Diff documentDiff = DiffBuilder.compare(getValidXml()).withTest(copyXml).ignoreWhitespace().build(); + assertThat(documentDiff.hasDifferences()).describedAs(documentDiff.toString()).isFalse(); + + } + + @Test + public void testWithListener() throws JAXBException { + + // PREPARE + final JAXBContext ctx = JAXBContext.newInstance(MyClass.class); + final MyId myId = new MyId(1); + final MyClass myClass = new MyClass(myId, "abc"); + + // TEST + final AtomicBoolean beforeCalled = new AtomicBoolean(false); + final AtomicBoolean afterCalled = new AtomicBoolean(false); + final Marshaller marshaller = new MarshallerBuilder().withContext(ctx).addAdapters(new MyId.Adapter()) + .withListener(new Marshaller.Listener() { + public void beforeMarshal(Object source) { + beforeCalled.set(true); + } + public void afterMarshal(Object source) { + afterCalled.set(true); + } + }).build(); + + // VERIFY + JaxbUtils.marshal(marshaller, myClass); + assertThat(beforeCalled.get()).isTrue(); + assertThat(afterCalled.get()).isTrue(); + + } + + private static String getValidXml() { + return "" + + ""; + } + + private static String getInvalidXml() { + return "" + + ""; + + } + +} diff --git a/src/test/java/org/fuin/utils4j/jaxb/MyClass.java b/src/test/java/org/fuin/utils4j/jaxb/MyClass.java index 4685b7b..31d9f57 100644 --- a/src/test/java/org/fuin/utils4j/jaxb/MyClass.java +++ b/src/test/java/org/fuin/utils4j/jaxb/MyClass.java @@ -11,6 +11,7 @@ public class MyClass { @XmlJavaTypeAdapter(value = MyId.Adapter.class) private MyId id; + @XmlAttribute(name = "name") private String name; protected MyClass() { From be21ca2e33d8891f19c96daa09b97281e8113bda Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Wed, 27 Dec 2023 11:28:24 +0100 Subject: [PATCH 05/22] Prepare next iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f7f317e..69a5b70 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ utils4j bundle - 0.13.0-SNAPSHOT + 0.14.0-SNAPSHOT A small Java library that contains several helpful utility classes. http://www.fuin.org/utils4j/ From bc4e97a958e24a68e78bb83400a7913ebcf350db Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Wed, 27 Dec 2023 11:32:19 +0100 Subject: [PATCH 06/22] Fixed Java version in doc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0538164..f92f202 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A small Java library that contains several helpful utility classes. [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.fuin/utils4j/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.fuin/utils4j/) [![Javadocs](https://www.javadoc.io/badge/org.fuin/utils4j.svg)](https://www.javadoc.io/doc/org.fuin/utils4j) [![LGPLv3 License](http://img.shields.io/badge/license-LGPLv3-blue.svg)](https://www.gnu.org/licenses/lgpl.html) -[![Java Development Kit 11](https://img.shields.io/badge/JDK-11-green.svg)](https://openjdk.java.net/projects/jdk/11/) +[![Java Development Kit 17](https://img.shields.io/badge/JDK-17-green.svg)](https://openjdk.java.net/projects/jdk/17/) ## Versions - 0.13.x (or later) = **Java 17** From 8c9033dacc4e08f0ec50aeee47528b4f5d5d243a Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sun, 14 Jan 2024 07:34:57 +0100 Subject: [PATCH 07/22] With Maven 3.9 `maven.config` requires each flag on a separate line See: https://issues.apache.org/jira/browse/MNG-7684 --- .mvn/maven.config | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.mvn/maven.config b/.mvn/maven.config index d023e53..fd083ed 100644 --- a/.mvn/maven.config +++ b/.mvn/maven.config @@ -1 +1,2 @@ --s settings.xml \ No newline at end of file +-s +settings.xml \ No newline at end of file From 6ee8bea405f02a319699b9518d6eed6374ef287a Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sun, 14 Jan 2024 07:35:13 +0100 Subject: [PATCH 08/22] Fixed missing https --- settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.xml b/settings.xml index b3ba5b6..311de47 100644 --- a/settings.xml +++ b/settings.xml @@ -66,7 +66,7 @@ sonatype.oss.snapshots Sonatype OSS Snapshot Repository - http://oss.sonatype.org/content/repositories/snapshots + https://oss.sonatype.org/content/repositories/snapshots false From d58b8786961c1a2a7580c906fa37181ed8142b45 Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sun, 21 Jan 2024 07:31:48 +0100 Subject: [PATCH 09/22] Added some more utility methods --- .../java/org/fuin/utils4j/JandexUtils.java | 29 ++++++++++++++++++- src/main/java/org/fuin/utils4j/Utils4J.java | 16 ++++++++++ .../org/fuin/utils4j/JandexUtilsTest.java | 28 ++++++++++++++++++ .../java/org/fuin/utils4j/Utils4JTest.java | 13 +++++++++ 4 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/fuin/utils4j/JandexUtils.java b/src/main/java/org/fuin/utils4j/JandexUtils.java index e600b62..f8e97fc 100644 --- a/src/main/java/org/fuin/utils4j/JandexUtils.java +++ b/src/main/java/org/fuin/utils4j/JandexUtils.java @@ -17,11 +17,14 @@ */ package org.fuin.utils4j; +import org.jboss.jandex.DotName; +import org.jboss.jandex.Index; import org.jboss.jandex.Indexer; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; @@ -68,7 +71,20 @@ public static boolean indexClassFile(final Indexer indexer, final List kno } /** - * Indexes all classes in a directory or it's sub directories. + * Indexes all classes in a directory or it's subdirectories. + * + * @param dir + * Directory to analyze. + * @return Index of all classes in the directory. + */ + public static Index indexDir(final File dir) { + final Indexer indexer = new Indexer(); + indexDir(indexer, new ArrayList<>(), dir); + return indexer.complete(); + } + + /** + * Indexes all classes in a directory or it's subdirectories. * * @param indexer * Indexer to use. @@ -166,4 +182,15 @@ public static void indexFiles(final List files, final Indexer indexer, fin } + /** + * Loads the class using the current thread's context class loader. + * + * @param name Name of the class to load. + * + * @return Loaded class. + */ + public static Class loadClass(DotName name) { + return Utils4J.loadClass(name.toString()); + } + } diff --git a/src/main/java/org/fuin/utils4j/Utils4J.java b/src/main/java/org/fuin/utils4j/Utils4J.java index 5ec08b4..99d27f6 100644 --- a/src/main/java/org/fuin/utils4j/Utils4J.java +++ b/src/main/java/org/fuin/utils4j/Utils4J.java @@ -1623,4 +1623,20 @@ public static interface UnzipInputStreamWrapper { } + /** + * Loads the class using the current thread's context class loader. + * + * @param name Name of the class to load. + * + * @return Loaded class. + */ + public static Class loadClass(String name) { + try { + return Thread.currentThread().getContextClassLoader().loadClass(name); + } catch (final ClassNotFoundException ex) { + throw new RuntimeException("Failed to load class: " + name, ex); + } + } + + } diff --git a/src/test/java/org/fuin/utils4j/JandexUtilsTest.java b/src/test/java/org/fuin/utils4j/JandexUtilsTest.java index 867873c..43f5de1 100644 --- a/src/test/java/org/fuin/utils4j/JandexUtilsTest.java +++ b/src/test/java/org/fuin/utils4j/JandexUtilsTest.java @@ -28,6 +28,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; /** * Tests for {@link JandexUtils}. @@ -54,6 +55,21 @@ public final void testIndexClassFile() { } + @Test + public final void testIndexDirSimple() { + + // PREPARE + final File classesDir = new File("target/classes"); + + // TEST + final Index index = JandexUtils.indexDir(classesDir); + + // VERIFY + assertThat(index.getClassByName(DotName.createSimple(JandexUtils.class.getName()))).isNotNull(); + assertThat(index.getClassByName(DotName.createSimple(Utils4J.class.getName()))).isNotNull(); + + } + @Test public final void testIndexDir() { @@ -114,5 +130,17 @@ public final void testIndexClasspath() throws IOException { } + @Test + public final void loadClassOK() { + assertThat(JandexUtils.loadClass(DotName.createSimple(Utils4J.class))).isEqualTo(Utils4J.class); + } + + @Test + public final void loadClassFailure() { + assertThatThrownBy(() -> JandexUtils.loadClass(DotName.createSimple("a.b.c.d.DoesNotExist"))) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Failed to load class"); + } + } // CHECKSTYLE:ON diff --git a/src/test/java/org/fuin/utils4j/Utils4JTest.java b/src/test/java/org/fuin/utils4j/Utils4JTest.java index 7cb04d4..e0e5fdc 100644 --- a/src/test/java/org/fuin/utils4j/Utils4JTest.java +++ b/src/test/java/org/fuin/utils4j/Utils4JTest.java @@ -876,5 +876,18 @@ public void testClasspathFiles() throws IOException { } + @Test + public final void loadClassOK() { + assertThat(Utils4J.loadClass(Utils4J.class.getName())).isEqualTo(Utils4J.class); + } + + @Test + public final void loadClassFailure() { + assertThatThrownBy(() -> Utils4J.loadClass("a.b.c.d.DoesNotExist")) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Failed to load class"); + } + + } // CHECKSTYLE:ON From e7ab6c3d216620b3fdd004db645d4cafde663fb8 Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sun, 21 Jan 2024 08:57:15 +0100 Subject: [PATCH 10/22] Added new methods --- .../java/org/fuin/utils4j/JandexUtils.java | 98 ++++++++++++++++-- .../org/fuin/utils4j/JandexUtilsTest.java | 71 +++++++++++-- src/test/resources/sample.index | Bin 0 -> 1218 bytes 3 files changed, 155 insertions(+), 14 deletions(-) create mode 100644 src/test/resources/sample.index diff --git a/src/main/java/org/fuin/utils4j/JandexUtils.java b/src/main/java/org/fuin/utils4j/JandexUtils.java index f8e97fc..9ec88a9 100644 --- a/src/main/java/org/fuin/utils4j/JandexUtils.java +++ b/src/main/java/org/fuin/utils4j/JandexUtils.java @@ -17,13 +17,10 @@ */ package org.fuin.utils4j; -import org.jboss.jandex.DotName; -import org.jboss.jandex.Index; -import org.jboss.jandex.Indexer; +import org.jboss.jandex.*; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; +import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; @@ -35,6 +32,11 @@ */ public final class JandexUtils { + /** + * Default location of the Jandex index file. + */ + public static final String DEFAULT_JANDEX_INDEX_FILE = "META-INF/jandex.idx"; + /** * Private default constructor. */ @@ -193,4 +195,88 @@ public static Class loadClass(DotName name) { return Utils4J.loadClass(name.toString()); } + /** + * Writes the index to a file. + * Wraps the possible {@link IOException} into a {@link RuntimeException}. + * + * @param file File to write to. + * @param index Index to save. + */ + public static void writeIndexR(final File file, final Index index) { + try { + writeIndex(file, index); + } catch (final IOException ex) { + throw new RuntimeException("Failed to write index to: " + file, ex); + } + } + + /** + * Writes the index to a file. + * + * @param file File to write to. + * @param index Index to save. + * @throws IOException Failed to write to the file. + */ + public static void writeIndex(final File file, final Index index) throws IOException { + try (final OutputStream out = new FileOutputStream(file)) { + new IndexWriter(out).write(index); + } + } + + /** + * Loads the index from standard "META-INF/jandex.idx" location. + * Wraps the possible {@link IOException} into a {@link RuntimeException}. + * + * @return Index. + */ + public static Index loadIndexResourceR() { + try { + return loadIndexResource(); + } catch (final IOException ex) { + throw new RuntimeException("Failed to load: " + DEFAULT_JANDEX_INDEX_FILE, ex); + } + } + + /** + * Loads the index from standard "META-INF/jandex.idx" location. + * + * @return Index. + * @throws IOException Failed to load the resource. + */ + public static Index loadIndexResource() throws IOException { + return loadIndexResource(DEFAULT_JANDEX_INDEX_FILE); + } + + /** + * Loads the index from a resource in the classpath. + * Wraps the possible {@link IOException} into a {@link RuntimeException}. + * + * @param indexFilePathAndName Path and name of the index file resource. + * @return Index. + */ + public static Index loadIndexResourceR(final String indexFilePathAndName) { + try { + return loadIndexResource(indexFilePathAndName); + } catch (final IOException ex) { + throw new RuntimeException("Failed to write index to: " + indexFilePathAndName, ex); + } + } + + /** + * Loads the index from a resource in the classpath. + * + * @param indexFilePathAndName Path and name of the index file resource. + * @return Index. + * @throws IOException Failed to load the resource. + */ + public static Index loadIndexResource(final String indexFilePathAndName) throws IOException { + final URL url = Thread.currentThread().getContextClassLoader().getResource(indexFilePathAndName); + if (url == null) { + throw new FileNotFoundException("Resource not found: " + indexFilePathAndName); + } + try (final InputStream input = url.openStream()) { + return new IndexReader(input).read(); + } + } + } diff --git a/src/test/java/org/fuin/utils4j/JandexUtilsTest.java b/src/test/java/org/fuin/utils4j/JandexUtilsTest.java index 43f5de1..907eee0 100644 --- a/src/test/java/org/fuin/utils4j/JandexUtilsTest.java +++ b/src/test/java/org/fuin/utils4j/JandexUtilsTest.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -36,12 +37,18 @@ // CHECKSTYLE:OFF public class JandexUtilsTest { + private static final File TARGET_DIR = new File("target"); + + private static final File CLASSES_DIR = new File(TARGET_DIR, "classes"); + + private static final File TEST_CLASSES_DIR = new File(TARGET_DIR, "test-classes"); + @Test public final void testIndexClassFile() { // PREPARE final List knownFiles = new ArrayList(); - final File classFile = new File("target/classes/" + JandexUtils.class.getName().replace('.', '/') + ".class"); + final File classFile = new File(CLASSES_DIR, JandexUtils.class.getName().replace('.', '/') + ".class"); final Indexer indexer = new Indexer(); // TEST @@ -58,11 +65,8 @@ public final void testIndexClassFile() { @Test public final void testIndexDirSimple() { - // PREPARE - final File classesDir = new File("target/classes"); - // TEST - final Index index = JandexUtils.indexDir(classesDir); + final Index index = JandexUtils.indexDir(CLASSES_DIR); // VERIFY assertThat(index.getClassByName(DotName.createSimple(JandexUtils.class.getName()))).isNotNull(); @@ -74,8 +78,8 @@ public final void testIndexDirSimple() { public final void testIndexDir() { // PREPARE - final File jandexClassFile = new File("target/classes/" + JandexUtils.class.getName().replace('.', '/') + ".class"); - final File utils4JClassFile = new File("target/classes/" + Utils4J.class.getName().replace('.', '/') + ".class"); + final File jandexClassFile = new File(CLASSES_DIR, JandexUtils.class.getName().replace('.', '/') + ".class"); + final File utils4JClassFile = new File(CLASSES_DIR, Utils4J.class.getName().replace('.', '/') + ".class"); final List knownFiles = new ArrayList(); final File classesDir = new File("target/classes"); final Indexer indexer = new Indexer(); @@ -115,7 +119,7 @@ public final void testIndexJar() { public final void testIndexClasspath() throws IOException { // PREPARE - final File jandexClassFile = new File("target/classes/" + JandexUtils.class.getName().replace('.', '/') + ".class") + final File jandexClassFile = new File(CLASSES_DIR, JandexUtils.class.getName().replace('.', '/') + ".class") .getCanonicalFile(); final List knownFiles = new ArrayList(); final Indexer indexer = new Indexer(); @@ -142,5 +146,56 @@ public final void loadClassFailure() { .hasMessageContaining("Failed to load class"); } + @Test + void testWriteIndexR() throws IOException { + + // PREPARE + final Indexer indexer = new Indexer(); + indexer.indexClass(JandexUtils.class); + final Index index = indexer.complete(); + final String filename = this.getClass().getSimpleName() + ".index"; + final File file = new File(CLASSES_DIR, filename); + file.delete(); + + // TEST + JandexUtils.writeIndexR(file, index); + + // VERIFY + assertThat(file).exists(); + final Index result = JandexUtils.loadIndexResourceR(filename); + assertThat(result.getClassByName(JandexUtils.class.getName())).isNotNull(); + assertThat(result.getClassByName(JandexUtils.class.getName()).name().toString()).isEqualTo(JandexUtils.class.getName()); + + } + + @Test + public final void loadIndexResource() throws IOException { + final Index index = JandexUtils.loadIndexResource("sample.index"); + assertThat(index.getClassByName(JandexUtils.class.getName())).isNotNull(); + assertThat(index.getClassByName(JandexUtils.class.getName()).name().toString()).isEqualTo(JandexUtils.class.getName()); + } + + @Test + public final void loadIndexResourceR() { + final Index index = JandexUtils.loadIndexResourceR("sample.index"); + assertThat(index.getClassByName(JandexUtils.class.getName())).isNotNull(); + assertThat(index.getClassByName(JandexUtils.class.getName()).name().toString()).isEqualTo(JandexUtils.class.getName()); + } + + @Test + public final void loadIndexResourceFailure() { + assertThatThrownBy(() -> JandexUtils.loadIndexResource("does-not-exist.index")) + .isInstanceOf(FileNotFoundException.class) + .hasMessage("Resource not found: does-not-exist.index"); + } + + @Test + public final void loadIndexResourceRFailure() { + assertThatThrownBy(() -> JandexUtils.loadIndexResourceR("does-not-exist.index")) + .isInstanceOf(RuntimeException.class) + .hasRootCauseInstanceOf(FileNotFoundException.class) + .hasRootCauseMessage("Resource not found: does-not-exist.index"); + } + } // CHECKSTYLE:ON diff --git a/src/test/resources/sample.index b/src/test/resources/sample.index new file mode 100644 index 0000000000000000000000000000000000000000..7aa843fa74a6859cb1db50a2e7ccf2ed8255c046 GIT binary patch literal 1218 zcmZXU+in{-5Qb;CTyoErWGl9lC~?{{t(^#Hfm{{=j95lxsBz%LNbdq#qT`h%uCRyL zd9_~j**aVqaf;p$GsBsGz99+z{m;{W3;?*d15s{g=Jq&Wn2KAyG+W>Nce=hhw6nJq z3>Sr-y;Njvo6cpSS#%W zcaKKLhv$NuTPbZv_p z>#QoeZnX8(1(p{e9enj_4)Mq~ z%exjJsGb->tjoY}v4LMUxrKnRN46#bKFO>4Zl;g!n%sb=_kc9*{V{pxXJepc0`W;p zdG0!cJSuAUYQUdg6jcR&dvG95FXm=igKRsKuve6yLAEuoPJl18C3l@vL3mh}`fE!g za{HyYHqbe1Y@IL7JxzC_mlrcl_oOe^CoqH#>#>NZ;&CvDF#Co5$hr6_co{uN`q@S& z>Ahe>?s-AbJ&4&8{`6PI4)~VvgNM<660%(`;W^u3n{1E&9R0vD_Ka@}5j=`imIB1! z0h0hjAVUs-p${+sIB;760b~dvMgaQ&v_lp2)_jjkpV6D+(i2>Gl1of5#fLIEjsy$RMQDvyMQKhI3P)SrBR9mQCpn8mI6BS40qe@VDsGgu2 zpo&pNsQRb`)kYygz!(B{A#iq*#DE+^XCo3aBxJHQrDdlF%sDbZ@I>5)j`MsPjFIzT zofo%xPM3L{^5T9MQu4ezZ)@EL(S0!+-)%_PBo4N2+V)Qp;^N>_QXEBOdw|()Mn9AK XjnW((tyvNZ4E#8Yn3qbv4G8}NXRHI5 literal 0 HcmV?d00001 From c5039d026a1a26ced5fc29db55f74e2546df5a84 Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sun, 21 Jan 2024 11:52:47 +0100 Subject: [PATCH 11/22] Moved reader/writer methods into separate classes --- .../fuin/utils4j/JandexIndexFileReader.java | 164 ++++++++++++++++++ .../fuin/utils4j/JandexIndexFileWriter.java | 45 +++++ .../java/org/fuin/utils4j/JandexUtils.java | 97 +---------- .../utils4j/JandexIndexFileReaderTest.java | 66 +++++++ .../utils4j/JandexIndexFileWriterTest.java | 63 +++++++ .../org/fuin/utils4j/JandexUtilsTest.java | 52 ------ 6 files changed, 344 insertions(+), 143 deletions(-) create mode 100644 src/main/java/org/fuin/utils4j/JandexIndexFileReader.java create mode 100644 src/main/java/org/fuin/utils4j/JandexIndexFileWriter.java create mode 100644 src/test/java/org/fuin/utils4j/JandexIndexFileReaderTest.java create mode 100644 src/test/java/org/fuin/utils4j/JandexIndexFileWriterTest.java diff --git a/src/main/java/org/fuin/utils4j/JandexIndexFileReader.java b/src/main/java/org/fuin/utils4j/JandexIndexFileReader.java new file mode 100644 index 0000000..ddce9b1 --- /dev/null +++ b/src/main/java/org/fuin/utils4j/JandexIndexFileReader.java @@ -0,0 +1,164 @@ +package org.fuin.utils4j; + +import org.jboss.jandex.CompositeIndex; +import org.jboss.jandex.IndexReader; +import org.jboss.jandex.IndexView; + +import java.io.*; +import java.net.URL; +import java.util.*; + +/** + * Helps to read Jandex index files. + */ +public final class JandexIndexFileReader { + + private final List files; + + private final List resources; + + private JandexIndexFileReader() { + this.files = new ArrayList<>(); + this.resources = new ArrayList<>(); + } + + /** + * Loads the configured index files. + * + * @return Index created from all index files. + * @throws IOException Failed to read index files or resources. + */ + public IndexView load() throws IOException { + final List indexes = new ArrayList<>(); + for (final File file : files) { + indexes.add(loadFile(file)); + } + for (final String resource : resources) { + indexes.add(loadResources(resource)); + } + return CompositeIndex.create(indexes); + } + + /** + * Loads the configured index files. + * Wraps the possible {@link IOException} into a {@link RuntimeException}. + * + * @return Index created from all index files. + */ + public IndexView loadR() { + try { + return load(); + } catch (final IOException ex) { + throw new RuntimeException("Failed to read index files or resources", ex); + } + } + + private IndexView loadFile(final File file) throws IOException { + try (final InputStream input = new FileInputStream(file)) { + return new IndexReader(input).read(); + } + } + + private IndexView loadResources(final String indexFilePathAndName) throws IOException { + final Enumeration enu = Thread.currentThread().getContextClassLoader().getResources(indexFilePathAndName); + final List indexes = new ArrayList<>(); + final List resources = Collections.list(enu); + for (final URL url : resources) { + try (final InputStream input = url.openStream()) { + indexes.add(new IndexReader(input).read()); + } + } + return CompositeIndex.create(indexes); + } + + /** + * Creates a new instance of the outer class. + */ + public static final class Builder { + + private JandexIndexFileReader delegate; + + /** + * Default constructor. + */ + public Builder() { + this.delegate = new JandexIndexFileReader(); + } + + /** + * Adds one or more files. + * + * @param files Index files to read (must exist). + * @return Builder. + */ + public Builder addFiles(final File...files) { + return addFiles(Arrays.asList(files)); + } + + /** + * Adds one or more files. + * + * @param files Index files to read (must exist). + * @return Builder. + */ + public Builder addFiles(final List files) { + for (final File file : Objects.requireNonNull(files, "files==null")) { + if (!file.exists()) { + throw new IllegalStateException("Index file does not exist: " + file); + } + if (!file.isFile()) { + throw new IllegalStateException("No file: " + file); + } + delegate.files.add(Objects.requireNonNull(file, "file==null")); + } + return this; + } + + /** + * Adds a default resource named "META-INF/jandex.idx". + * + * @return Builder. + */ + public Builder addDefaultResource() { + addResources("META-INF/jandex.idx"); + return this; + } + + /** + * Adds one or more resources. + * + * @return Builder. + */ + public Builder addResources(final String...resources) { + return addResources(Arrays.asList(resources)); + } + + /** + * Adds one or more resources. + * + * @return Builder. + */ + public Builder addResources(final List resources) { + for (final String resource : Objects.requireNonNull(resources, "resources==null")) { + delegate.resources.add(Objects.requireNonNull(resource, "resource==null")); + } + return this; + } + + /** + * Builds an instance of the outer class. + * + * @return New instance. + */ + public JandexIndexFileReader build() { + if (delegate.resources.isEmpty() && delegate.files.isEmpty()) { + addDefaultResource(); + } + final JandexIndexFileReader tmp = delegate; + delegate = new JandexIndexFileReader(); + return tmp; + } + + } + +} diff --git a/src/main/java/org/fuin/utils4j/JandexIndexFileWriter.java b/src/main/java/org/fuin/utils4j/JandexIndexFileWriter.java new file mode 100644 index 0000000..9a3708e --- /dev/null +++ b/src/main/java/org/fuin/utils4j/JandexIndexFileWriter.java @@ -0,0 +1,45 @@ +package org.fuin.utils4j; + +import org.jboss.jandex.*; + +import java.io.*; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; + +/** + * Helps to write Jandex index files. + */ +public final class JandexIndexFileWriter { + + /** + * Writes the index to a file. + * Wraps the possible {@link IOException} into a {@link RuntimeException}. + * + * @param file File to write to. + * @param index Index to save. + */ + public void writeIndexR(final File file, final Index index) { + try { + writeIndex(file, index); + } catch (final IOException ex) { + throw new RuntimeException("Failed to write index to: " + file, ex); + } + } + + /** + * Writes the index to a file. + * + * @param file File to write to. + * @param index Index to save. + * @throws IOException Failed to write to the file. + */ + public void writeIndex(final File file, final Index index) throws IOException { + try (final OutputStream out = new FileOutputStream(file)) { + new IndexWriter(out).write(index); + } + } + +} diff --git a/src/main/java/org/fuin/utils4j/JandexUtils.java b/src/main/java/org/fuin/utils4j/JandexUtils.java index 9ec88a9..1749729 100644 --- a/src/main/java/org/fuin/utils4j/JandexUtils.java +++ b/src/main/java/org/fuin/utils4j/JandexUtils.java @@ -17,10 +17,13 @@ */ package org.fuin.utils4j; -import org.jboss.jandex.*; +import org.jboss.jandex.DotName; +import org.jboss.jandex.Index; +import org.jboss.jandex.Indexer; -import java.io.*; -import java.net.URL; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; @@ -32,11 +35,6 @@ */ public final class JandexUtils { - /** - * Default location of the Jandex index file. - */ - public static final String DEFAULT_JANDEX_INDEX_FILE = "META-INF/jandex.idx"; - /** * Private default constructor. */ @@ -195,88 +193,5 @@ public static Class loadClass(DotName name) { return Utils4J.loadClass(name.toString()); } - /** - * Writes the index to a file. - * Wraps the possible {@link IOException} into a {@link RuntimeException}. - * - * @param file File to write to. - * @param index Index to save. - */ - public static void writeIndexR(final File file, final Index index) { - try { - writeIndex(file, index); - } catch (final IOException ex) { - throw new RuntimeException("Failed to write index to: " + file, ex); - } - } - - /** - * Writes the index to a file. - * - * @param file File to write to. - * @param index Index to save. - * @throws IOException Failed to write to the file. - */ - public static void writeIndex(final File file, final Index index) throws IOException { - try (final OutputStream out = new FileOutputStream(file)) { - new IndexWriter(out).write(index); - } - } - - /** - * Loads the index from standard "META-INF/jandex.idx" location. - * Wraps the possible {@link IOException} into a {@link RuntimeException}. - * - * @return Index. - */ - public static Index loadIndexResourceR() { - try { - return loadIndexResource(); - } catch (final IOException ex) { - throw new RuntimeException("Failed to load: " + DEFAULT_JANDEX_INDEX_FILE, ex); - } - } - - /** - * Loads the index from standard "META-INF/jandex.idx" location. - * - * @return Index. - * @throws IOException Failed to load the resource. - */ - public static Index loadIndexResource() throws IOException { - return loadIndexResource(DEFAULT_JANDEX_INDEX_FILE); - } - - /** - * Loads the index from a resource in the classpath. - * Wraps the possible {@link IOException} into a {@link RuntimeException}. - * - * @param indexFilePathAndName Path and name of the index file resource. - * @return Index. - */ - public static Index loadIndexResourceR(final String indexFilePathAndName) { - try { - return loadIndexResource(indexFilePathAndName); - } catch (final IOException ex) { - throw new RuntimeException("Failed to write index to: " + indexFilePathAndName, ex); - } - } - - /** - * Loads the index from a resource in the classpath. - * - * @param indexFilePathAndName Path and name of the index file resource. - * @return Index. - * @throws IOException Failed to load the resource. - */ - public static Index loadIndexResource(final String indexFilePathAndName) throws IOException { - final URL url = Thread.currentThread().getContextClassLoader().getResource(indexFilePathAndName); - if (url == null) { - throw new FileNotFoundException("Resource not found: " + indexFilePathAndName); - } - try (final InputStream input = url.openStream()) { - return new IndexReader(input).read(); - } - } } diff --git a/src/test/java/org/fuin/utils4j/JandexIndexFileReaderTest.java b/src/test/java/org/fuin/utils4j/JandexIndexFileReaderTest.java new file mode 100644 index 0000000..c418963 --- /dev/null +++ b/src/test/java/org/fuin/utils4j/JandexIndexFileReaderTest.java @@ -0,0 +1,66 @@ +/** + * Copyright (C) 2015 Michael Schnell. All rights reserved. + * http://www.fuin.org/ + *

+ * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) any + * later version. + *

+ * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + *

+ * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see http://www.gnu.org/licenses/. + */ +package org.fuin.utils4j; + +import org.fuin.utils4j.JandexIndexFileReader.Builder; + +import org.jboss.jandex.IndexView; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link JandexIndexFileReader} class. + */ +public class JandexIndexFileReaderTest { + + @Test + public final void loadIndexFile() throws IOException { + final IndexView index = new Builder().addFiles(new File("src/test/resources/sample.index")).build().load(); + assertThat(index.getClassByName(JandexUtils.class.getName())).isNotNull(); + assertThat(index.getClassByName(JandexUtils.class.getName()).name().toString()).isEqualTo(JandexUtils.class.getName()); + } + + @Test + public final void loadIndexResource() throws IOException { + final IndexView index = new Builder().addResources("sample.index").build().load(); + assertThat(index.getClassByName(JandexUtils.class.getName())).isNotNull(); + assertThat(index.getClassByName(JandexUtils.class.getName()).name().toString()).isEqualTo(JandexUtils.class.getName()); + } + + @Test + public final void loadIndexResourceR() { + final IndexView index = new Builder().addResources("sample.index").build().loadR(); + assertThat(index.getClassByName(JandexUtils.class.getName())).isNotNull(); + assertThat(index.getClassByName(JandexUtils.class.getName()).name().toString()).isEqualTo(JandexUtils.class.getName()); + } + + @Test + public final void loadIndexResourceFailure() throws IOException { + assertThat(new Builder().addResources("does-not-exist.index").build().load().getKnownClasses()).isEmpty(); + } + + @Test + public final void loadIndexResourceRFailure() { + assertThat(new Builder().addResources("does-not-exist.index").build().loadR().getKnownClasses()).isEmpty(); + } + +} diff --git a/src/test/java/org/fuin/utils4j/JandexIndexFileWriterTest.java b/src/test/java/org/fuin/utils4j/JandexIndexFileWriterTest.java new file mode 100644 index 0000000..a8cae24 --- /dev/null +++ b/src/test/java/org/fuin/utils4j/JandexIndexFileWriterTest.java @@ -0,0 +1,63 @@ +/** + * Copyright (C) 2015 Michael Schnell. All rights reserved. + * http://www.fuin.org/ + *

+ * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) any + * later version. + *

+ * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + *

+ * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see http://www.gnu.org/licenses/. + */ +package org.fuin.utils4j; + +import org.jboss.jandex.Index; +import org.jboss.jandex.IndexView; +import org.jboss.jandex.Indexer; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link JandexIndexFileWriter}. + */ +public class JandexIndexFileWriterTest { + + private static final File TARGET_DIR = new File("target"); + + private static final File CLASSES_DIR = new File(TARGET_DIR, "classes"); + + private static final File TEST_CLASSES_DIR = new File(TARGET_DIR, "test-classes"); + + @Test + void testWriteIndexR() throws IOException { + + // PREPARE + final Indexer indexer = new Indexer(); + indexer.indexClass(JandexUtils.class); + final Index index = indexer.complete(); + final String filename = this.getClass().getSimpleName() + ".index"; + final File file = new File(TEST_CLASSES_DIR, filename); + file.delete(); + + // TEST + new JandexIndexFileWriter().writeIndexR(file, index); + + // VERIFY + assertThat(file).exists(); + final IndexView result = new JandexIndexFileReader.Builder().addResources(filename).build().loadR(); + assertThat(result.getClassByName(JandexUtils.class.getName())).isNotNull(); + assertThat(result.getClassByName(JandexUtils.class.getName()).name().toString()).isEqualTo(JandexUtils.class.getName()); + + } + +} diff --git a/src/test/java/org/fuin/utils4j/JandexUtilsTest.java b/src/test/java/org/fuin/utils4j/JandexUtilsTest.java index 907eee0..16bcf64 100644 --- a/src/test/java/org/fuin/utils4j/JandexUtilsTest.java +++ b/src/test/java/org/fuin/utils4j/JandexUtilsTest.java @@ -23,7 +23,6 @@ import org.junit.jupiter.api.Test; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -146,56 +145,5 @@ public final void loadClassFailure() { .hasMessageContaining("Failed to load class"); } - @Test - void testWriteIndexR() throws IOException { - - // PREPARE - final Indexer indexer = new Indexer(); - indexer.indexClass(JandexUtils.class); - final Index index = indexer.complete(); - final String filename = this.getClass().getSimpleName() + ".index"; - final File file = new File(CLASSES_DIR, filename); - file.delete(); - - // TEST - JandexUtils.writeIndexR(file, index); - - // VERIFY - assertThat(file).exists(); - final Index result = JandexUtils.loadIndexResourceR(filename); - assertThat(result.getClassByName(JandexUtils.class.getName())).isNotNull(); - assertThat(result.getClassByName(JandexUtils.class.getName()).name().toString()).isEqualTo(JandexUtils.class.getName()); - - } - - @Test - public final void loadIndexResource() throws IOException { - final Index index = JandexUtils.loadIndexResource("sample.index"); - assertThat(index.getClassByName(JandexUtils.class.getName())).isNotNull(); - assertThat(index.getClassByName(JandexUtils.class.getName()).name().toString()).isEqualTo(JandexUtils.class.getName()); - } - - @Test - public final void loadIndexResourceR() { - final Index index = JandexUtils.loadIndexResourceR("sample.index"); - assertThat(index.getClassByName(JandexUtils.class.getName())).isNotNull(); - assertThat(index.getClassByName(JandexUtils.class.getName()).name().toString()).isEqualTo(JandexUtils.class.getName()); - } - - @Test - public final void loadIndexResourceFailure() { - assertThatThrownBy(() -> JandexUtils.loadIndexResource("does-not-exist.index")) - .isInstanceOf(FileNotFoundException.class) - .hasMessage("Resource not found: does-not-exist.index"); - } - - @Test - public final void loadIndexResourceRFailure() { - assertThatThrownBy(() -> JandexUtils.loadIndexResourceR("does-not-exist.index")) - .isInstanceOf(RuntimeException.class) - .hasRootCauseInstanceOf(FileNotFoundException.class) - .hasRootCauseMessage("Resource not found: does-not-exist.index"); - } - } // CHECKSTYLE:ON From 0b8cc2bcfe8c9509c14e692ec5670a4bcce09916 Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sun, 21 Jan 2024 14:02:18 +0100 Subject: [PATCH 12/22] Include Jandex index file into JAR --- pom.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pom.xml b/pom.xml index 69a5b70..91fec81 100644 --- a/pom.xml +++ b/pom.xml @@ -141,6 +141,20 @@ jacoco-maven-plugin + + io.smallrye + jandex-maven-plugin + 3.0.6 + + + make-index + + jandex + + + + + From 58bf72dd7fb99b5e968f1929d4a2d954948b3cfb Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sat, 10 Feb 2024 17:44:21 +0100 Subject: [PATCH 13/22] Updated build actions --- .github/workflows/maven.yml | 10 +++++----- .gitignore | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 4662abe..f081061 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -19,12 +19,12 @@ jobs: steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '17' distribution: 'zulu' @@ -34,21 +34,21 @@ jobs: run: java -version && ./mvnw -version && gpg --version - name: Cache SonarCloud packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache Maven packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 - name: Import GPG key - uses: crazy-max/ghaction-import-gpg@v5 + uses: crazy-max/ghaction-import-gpg@v6 with: gpg_private_key: ${{ secrets.OSS_SONATYPE_GPG_PRIVATE_KEY }} passphrase: ${{ secrets.OSS_SONATYPE_GPG_PASSPHRASE }} diff --git a/.gitignore b/.gitignore index 3dbc3f0..0906061 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ target META-INF *.log +*.iml pom.xml.versionsBackup From 268c55440733d97db805bf33d38112ff5d1ed358 Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sat, 10 Feb 2024 17:49:22 +0100 Subject: [PATCH 14/22] Updated dependencies --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 91fec81..8a05b56 100644 --- a/pom.xml +++ b/pom.xml @@ -56,28 +56,28 @@ org.junit.jupiter junit-jupiter - 5.10.1 + 5.10.2 test org.assertj assertj-core - 3.24.2 + 3.25.3 test nl.jqno.equalsverifier equalsverifier - 3.15.4 + 3.15.6 test org.xmlunit xmlunit-core - 2.8.2 + 2.9.1 test From a241a52e34ad9f2747df4b2e5d614336458533ec Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sun, 11 Feb 2024 07:50:50 +0100 Subject: [PATCH 15/22] Added some classes from units4j to prepare archiving that project --- .../org/fuin/utils4j/MultipleCommands.java | 118 ++++++++++++++++++ .../java/org/fuin/utils4j/TestCommand.java | 61 +++++++++ .../java/org/fuin/utils4j/TestOmitted.java | 42 +++++++ src/main/java/org/fuin/utils4j/Utils4J.java | 20 +++ .../fuin/utils4j/MultipleCommandsTest.java | 106 ++++++++++++++++ .../java/org/fuin/utils4j/Utils4JTest.java | 28 +++++ 6 files changed, 375 insertions(+) create mode 100644 src/main/java/org/fuin/utils4j/MultipleCommands.java create mode 100644 src/main/java/org/fuin/utils4j/TestCommand.java create mode 100644 src/main/java/org/fuin/utils4j/TestOmitted.java create mode 100644 src/test/java/org/fuin/utils4j/MultipleCommandsTest.java diff --git a/src/main/java/org/fuin/utils4j/MultipleCommands.java b/src/main/java/org/fuin/utils4j/MultipleCommands.java new file mode 100644 index 0000000..777e47d --- /dev/null +++ b/src/main/java/org/fuin/utils4j/MultipleCommands.java @@ -0,0 +1,118 @@ +/** + * Copyright (C) 2015 Michael Schnell. All rights reserved. + * http://www.fuin.org/ + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) any + * later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see http://www.gnu.org/licenses/. + */ +package org.fuin.utils4j; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Combines multiple test commands into one. + * + * @param + * Type of the test context. + */ +public final class MultipleCommands implements TestCommand { + + private final List> commands; + + /** + * Default constructor. + */ + public MultipleCommands() { + super(); + this.commands = new ArrayList<>(); + } + + /** + * Constructor with command array. + * + * @param commands + * One or more commands to execute. Not {@literal null}. + */ + @SafeVarargs + public MultipleCommands(final TestCommand... commands) { + this(Arrays.asList(commands)); + } + + /** + * Constructor with command list. + * + * @param commands + * List of commands to execute. Not {@literal null}. + */ + public MultipleCommands(final List> commands) { + super(); + Utils4J.checkNotNull("commands", commands); + this.commands = new ArrayList<>(commands); + } + + /** + * Adds a new command. + * + * @param command + * Command to add. Not {@literal null}. + */ + public void add(final TestCommand command) { + this.commands.add(command); + } + + @Override + public void init(final CONTEXT context) { + for (final TestCommand command : commands) { + command.init(context); + } + } + + @Override + public final void execute() { + for (final TestCommand command : commands) { + command.execute(); + } + } + + @Override + public final boolean isSuccessful() { + for (final TestCommand command : commands) { + if (!command.isSuccessful()) { + return false; + } + } + return true; + } + + @Override + public final String getFailureDescription() { + final StringBuilder sb = new StringBuilder(); + for (final TestCommand command : commands) { + if (!command.isSuccessful()) { + sb.append(command.getFailureDescription()); + sb.append("\n"); + } + } + return sb.toString(); + } + + @Override + public final void verify() { + if (!isSuccessful()) { + throw new RuntimeException("There was at least one failure:\n" + getFailureDescription()); + } + } + +} diff --git a/src/main/java/org/fuin/utils4j/TestCommand.java b/src/main/java/org/fuin/utils4j/TestCommand.java new file mode 100644 index 0000000..b3dc59f --- /dev/null +++ b/src/main/java/org/fuin/utils4j/TestCommand.java @@ -0,0 +1,61 @@ +/** + * Copyright (C) 2015 Michael Schnell. All rights reserved. + * http://www.fuin.org/ + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) any + * later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see http://www.gnu.org/licenses/. + */ +package org.fuin.utils4j; + +/** + * A command used in a test scenario. + * + * @param + * Type of the context. + */ +public interface TestCommand { + + /** + * Initializes the command before executing it. + * + * @param context + * Context with specific information that may be used by the command. Not {@literal null}. + */ + public void init(CONTEXT context); + + /** + * Executes the command. Exceptions will be catched used for creating a nice failure description. They are also logged. + */ + public void execute(); + + /** + * Returns if the command execution was successful. If this method is called before {@link #execute()} was executed, an illegal state + * exception will be thrown. + * + * @return TRUE if it was successful, else FALSE if it was a failure. + */ + public boolean isSuccessful(); + + /** + * Returns a description of the failure condition. + * + * @return Expected and current result. + */ + public String getFailureDescription(); + + /** + * Verifies that the command was successful and throws a runtime exception otherwise. + */ + public void verify(); + +} diff --git a/src/main/java/org/fuin/utils4j/TestOmitted.java b/src/main/java/org/fuin/utils4j/TestOmitted.java new file mode 100644 index 0000000..3fb92b6 --- /dev/null +++ b/src/main/java/org/fuin/utils4j/TestOmitted.java @@ -0,0 +1,42 @@ +/** + * Copyright (C) 2015 Michael Schnell. All rights reserved. + * http://www.fuin.org/ + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) any + * later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see http://www.gnu.org/licenses/. + */ +package org.fuin.utils4j; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * States that the annotated test class contains no tests by intention. + * This avoids test failures when test coverage checks are done. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface TestOmitted { + + /** + * Short description why the test class was not implemented. + * + * @return Explanation why the test was skipped + */ + String value(); + +} diff --git a/src/main/java/org/fuin/utils4j/Utils4J.java b/src/main/java/org/fuin/utils4j/Utils4J.java index 99d27f6..f623105 100644 --- a/src/main/java/org/fuin/utils4j/Utils4J.java +++ b/src/main/java/org/fuin/utils4j/Utils4J.java @@ -23,6 +23,7 @@ import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; import java.io.*; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; @@ -1638,5 +1639,24 @@ public static Class loadClass(String name) { } } + /** + * Sets a private field in an object by using reflection. + * + * @param obj + * Object with the attribute to set. + * @param name + * Name of the attribute to set. + * @param value + * Value to set for the attribute. + */ + public static void setPrivateField(final Object obj, final String name, final Object value) { + try { + final Field field = obj.getClass().getDeclaredField(name); + field.setAccessible(true); + field.set(obj, value); + } catch (final Exception ex) { + throw new RuntimeException("Couldn't set field '" + name + "' in class '" + obj.getClass() + "'", ex); + } + } } diff --git a/src/test/java/org/fuin/utils4j/MultipleCommandsTest.java b/src/test/java/org/fuin/utils4j/MultipleCommandsTest.java new file mode 100644 index 0000000..147412c --- /dev/null +++ b/src/test/java/org/fuin/utils4j/MultipleCommandsTest.java @@ -0,0 +1,106 @@ +/** + * Copyright (C) 2015 Michael Schnell. All rights reserved. + * http://www.fuin.org/ + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) any + * later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see http://www.gnu.org/licenses/. + */ +package org.fuin.utils4j; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +//CHECKSTYLE:OFF Test code +public class MultipleCommandsTest { + + @Test + public void testCreate() { + + final MyCmd cmd1 = new MyCmd(true, null); + final MultipleCommands testee1 = new MultipleCommands<>(cmd1); + testee1.init("Hello1"); + testee1.execute(); + + assertThat(testee1.getFailureDescription()).isEmpty(); + assertThat(testee1.isSuccessful()).isTrue(); + assertThat(cmd1.getContext()).isEqualTo("Hello1"); + assertThat(cmd1.isExecuted()).isTrue();; + + final MyCmd cmd2 = new MyCmd(false, "Oops"); + final MultipleCommands testee2 = new MultipleCommands<>(cmd1, cmd2); + testee2.init("Hello2"); + testee2.execute(); + + assertThat(testee2.isSuccessful()).isFalse(); + assertThat(testee2.getFailureDescription()).isEqualTo("Oops\n"); + assertThat(cmd1.getContext()).isEqualTo("Hello2"); + assertThat(cmd1.isExecuted()).isTrue();; + assertThat(cmd2.getContext()).isEqualTo("Hello2"); + assertThat(cmd2.isExecuted()).isTrue();; + + } + + public static final class MyCmd implements TestCommand { + + private String context; + + private boolean executed; + + private boolean successful; + + private String failureDescription; + + public MyCmd(boolean successful, String failureDescription) { + super(); + this.successful = successful; + this.failureDescription = failureDescription; + } + + @Override + public void init(String context) { + this.context = context; + } + + @Override + public void execute() { + executed = true; + } + + @Override + public boolean isSuccessful() { + return successful; + } + + @Override + public String getFailureDescription() { + return failureDescription; + } + + public String getContext() { + return context; + } + + public boolean isExecuted() { + return executed; + } + + @Override + public void verify() { + // DO nothing + } + + } + +} +// CHECKSTYLE:ON diff --git a/src/test/java/org/fuin/utils4j/Utils4JTest.java b/src/test/java/org/fuin/utils4j/Utils4JTest.java index e0e5fdc..85ac80c 100644 --- a/src/test/java/org/fuin/utils4j/Utils4JTest.java +++ b/src/test/java/org/fuin/utils4j/Utils4JTest.java @@ -888,6 +888,34 @@ public final void loadClassFailure() { .hasMessageContaining("Failed to load class"); } + @Test + public final void testSetPrivateField() { + + // PREPARE + final MyTestClass original = new MyTestClass("Test"); + final String name = "Changed"; + + // TEST + Utils4J.setPrivateField(original, "name", name); + + // VERIFY + assertThat(original.getName()).isEqualTo(name); + + } + + private static class MyTestClass { + + private String name; + + public MyTestClass(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + } // CHECKSTYLE:ON From b6787cd0bce3d7efc0b5dbd4e6d789a9a884b087 Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sun, 11 Feb 2024 09:02:28 +0100 Subject: [PATCH 16/22] Moved jandex dependent classes to separate package --- README.md | 24 +- .../{ => jandex}/JandexIndexFileReader.java | 2 +- .../{ => jandex}/JandexIndexFileWriter.java | 2 +- .../utils4j/{ => jandex}/JandexUtils.java | 3 +- .../JandexIndexFileReaderTest.java | 6 +- .../JandexIndexFileWriterTest.java | 5 +- .../utils4j/{ => jandex}/JandexUtilsTest.java | 300 +++++++++--------- src/test/resources/sample.index | Bin 1218 -> 24252 bytes 8 files changed, 175 insertions(+), 167 deletions(-) rename src/main/java/org/fuin/utils4j/{ => jandex}/JandexIndexFileReader.java (99%) rename src/main/java/org/fuin/utils4j/{ => jandex}/JandexIndexFileWriter.java (97%) rename src/main/java/org/fuin/utils4j/{ => jandex}/JandexUtils.java (98%) rename src/test/java/org/fuin/utils4j/{ => jandex}/JandexIndexFileReaderTest.java (93%) rename src/test/java/org/fuin/utils4j/{ => jandex}/JandexIndexFileWriterTest.java (92%) rename src/test/java/org/fuin/utils4j/{ => jandex}/JandexUtilsTest.java (96%) diff --git a/README.md b/README.md index 6e3f086..34a8f0a 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Directly create a URL using a utility method: ```Java URL url = Utils4J.url("classpath:org/fuin/utils4j/test.properties"); ``` -A full example can be found here: [ClasspathURLExample.java](https://github.com/fuinorg/utils4j/blob/master/src/test/java/org/fuin/utils4j/examples/ClasspathURLExample.java) +A full example can be found here: [ClasspathURLExample.java](src/test/java/org/fuin/utils4j/examples/ClasspathURLExample.java) If you register the URL stream handler, all URLs (no matter how they were constructed) will work: ```Java @@ -63,7 +63,7 @@ a=1 b=1/2 c=1/2/3 ``` -A full example can be found here: [VariableResolverExample.java](https://github.com/fuinorg/utils4j/blob/master/src/test/java/org/fuin/utils4j/examples/VariableResolverExample.java) +A full example can be found here: [VariableResolverExample.java](src/test/java/org/fuin/utils4j/examples/VariableResolverExample.java) ### ZIP and UNZIP @@ -74,7 +74,7 @@ final File zipFile = new File(Utils4J.getTempDir(), "myfile1.zip"); Utils4J.zipDir(zipDir, "abc/def", zipFile); Utils4J.unzip(zipFile, Utils4J.getTempDir()); ``` -A full example can be found here: [ZipDirExample.java](https://github.com/fuinorg/utils4j/blob/master/src/test/java/org/fuin/utils4j/examples/ZipDirExample.java) +A full example can be found here: [ZipDirExample.java](src/test/java/org/fuin/utils4j/examples/ZipDirExample.java) ### Tracking changes of a list / map @@ -87,8 +87,8 @@ System.out.println(trackingList.getDeleted()); System.out.println(trackingList.getAdded()); trackingList.revert(); ``` -A list example can be found here: [ChangeTrackingUniqueListExample.java](https://github.com/fuinorg/utils4j/blob/master/src/test/java/org/fuin/utils4j/examples/ChangeTrackingUniqueListExample.java) -A map example can be found here: [ChangeTrackingMapExample.java](https://github.com/fuinorg/utils4j/blob/master/src/test/java/org/fuin/utils4j/examples/ChangeTrackingMapExample.java) +A list example can be found here: [ChangeTrackingUniqueListExample.java](src/test/java/org/fuin/utils4j/examples/ChangeTrackingUniqueListExample.java) +A map example can be found here: [ChangeTrackingMapExample.java](src/test/java/org/fuin/utils4j/examples/ChangeTrackingMapExample.java) ### Easy file locking @@ -101,7 +101,7 @@ try { lock.release(); } ``` -A full example can be found here: [LockFileExample.java](https://github.com/fuinorg/utils4j/blob/master/src/test/java/org/fuin/utils4j/examples/LockFileExample.java) +A full example can be found here: [LockFileExample.java](src/test/java/org/fuin/utils4j/examples/LockFileExample.java) ### Properties file preferences @@ -110,7 +110,7 @@ Shows the use of a directory and properties file based [Preferences API](http:// System.setProperty("java.util.prefs.PreferencesFactory", PropertiesFilePreferencesFactory.class.getName()); Preferences userPrefs = Preferences.userRoot(); ``` -A full example can be found here: [PropertiesFilePreferencesFactoryExample.java](https://github.com/fuinorg/utils4j/blob/master/src/test/java/org/fuin/utils4j/examples/PropertiesFilePreferencesFactoryExample.java) +A full example can be found here: [PropertiesFilePreferencesFactoryExample.java](src/test/java/org/fuin/utils4j/examples/PropertiesFilePreferencesFactoryExample.java) ### JAXB CDATA Stream Writer @@ -163,7 +163,7 @@ System.out.println(copy.getContent()); // ``` -A full example can be found here: [CDataJaxbExample.java](https://github.com/fuinorg/utils4j/blob/master/src/test/java/org/fuin/utils4j/examples/CDataJaxbExample.java) +A full example can be found here: [CDataJaxbExample.java](src/test/java/org/fuin/utils4j/examples/CDataJaxbExample.java) **Caution** - You must explicitly add the xml.bind-api dependency to your POM if you want to use this feature, because it's defined as optional here. @@ -180,7 +180,7 @@ A full example can be found here: [CDataJaxbExample.java](https://github.com/fui > :warning: Deprecated in favour of [Awaitility](https://github.com/awaitility/awaitility) -The [WaitHelper](https://github.com/fuinorg/utils4j/blob/master/src/main/java/org/fuin/utils4j/WaitHelper.java) class supports waiting for some condition. +The [WaitHelper](src/main/java/org/fuin/utils4j/WaitHelper.java) class supports waiting for some condition. Example of waiting for a function to finish without an exception: ```Java @@ -208,7 +208,7 @@ waitHelper.waitUntilResult(() -> { }, Arrays.asList("Peter Parker, Inc")); ``` -A full example can be found here: [WaitHelperExample.java](https://github.com/fuinorg/utils4j/blob/master/src/test/java/org/fuin/utils4j/examples/WaitHelperExample.java) +A full example can be found here: [WaitHelperExample.java](src/test/java/org/fuin/utils4j/examples/WaitHelperExample.java) ### Find all JARs and classes in the classpath @@ -234,7 +234,7 @@ for (final File file : Utils4J.pathsFiles(System.getProperty("sun.boot.class.pat System.out.println(file); } ``` -A full example can be found here: [FindJarsAndClassesInClasspath.java](https://github.com/fuinorg/utils4j/blob/master/src/test/java/org/fuin/utils4j/examples/FindJarsAndClassesInClasspath.java) +A full example can be found here: [FindJarsAndClassesInClasspath.java](src/test/java/org/fuin/utils4j/examples/FindJarsAndClassesInClasspath.java) ### Analyze classes in the classpath with Jandex Easily find matching types from all classes or JAR files in the classpath using [Jandex](https://github.com/wildfly/jandex) @@ -255,7 +255,7 @@ for (File file : knownFiles) { System.out.println(file); } ``` -A test that shows the usage can be found here: [JandexUtilsTest](https://github.com/fuinorg/utils4j/blob/master/src/test/java/org/fuin/utils4j/JandexUtilsTest.java) +A test that shows the usage can be found here: [JandexUtilsTest](src/test/java/org/fuin/utils4j/jandex/JandexUtilsTest.java) **Caution** - You must explicitly add the Jandex dependency to your POM if you want to use this feature, because it's defined as optional here. diff --git a/src/main/java/org/fuin/utils4j/JandexIndexFileReader.java b/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileReader.java similarity index 99% rename from src/main/java/org/fuin/utils4j/JandexIndexFileReader.java rename to src/main/java/org/fuin/utils4j/jandex/JandexIndexFileReader.java index ddce9b1..c8bed2a 100644 --- a/src/main/java/org/fuin/utils4j/JandexIndexFileReader.java +++ b/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileReader.java @@ -1,4 +1,4 @@ -package org.fuin.utils4j; +package org.fuin.utils4j.jandex; import org.jboss.jandex.CompositeIndex; import org.jboss.jandex.IndexReader; diff --git a/src/main/java/org/fuin/utils4j/JandexIndexFileWriter.java b/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileWriter.java similarity index 97% rename from src/main/java/org/fuin/utils4j/JandexIndexFileWriter.java rename to src/main/java/org/fuin/utils4j/jandex/JandexIndexFileWriter.java index 9a3708e..5302843 100644 --- a/src/main/java/org/fuin/utils4j/JandexIndexFileWriter.java +++ b/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileWriter.java @@ -1,4 +1,4 @@ -package org.fuin.utils4j; +package org.fuin.utils4j.jandex; import org.jboss.jandex.*; diff --git a/src/main/java/org/fuin/utils4j/JandexUtils.java b/src/main/java/org/fuin/utils4j/jandex/JandexUtils.java similarity index 98% rename from src/main/java/org/fuin/utils4j/JandexUtils.java rename to src/main/java/org/fuin/utils4j/jandex/JandexUtils.java index 1749729..125ccbf 100644 --- a/src/main/java/org/fuin/utils4j/JandexUtils.java +++ b/src/main/java/org/fuin/utils4j/jandex/JandexUtils.java @@ -15,8 +15,9 @@ * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see http://www.gnu.org/licenses/. */ -package org.fuin.utils4j; +package org.fuin.utils4j.jandex; +import org.fuin.utils4j.Utils4J; import org.jboss.jandex.DotName; import org.jboss.jandex.Index; import org.jboss.jandex.Indexer; diff --git a/src/test/java/org/fuin/utils4j/JandexIndexFileReaderTest.java b/src/test/java/org/fuin/utils4j/jandex/JandexIndexFileReaderTest.java similarity index 93% rename from src/test/java/org/fuin/utils4j/JandexIndexFileReaderTest.java rename to src/test/java/org/fuin/utils4j/jandex/JandexIndexFileReaderTest.java index c418963..0eb4b70 100644 --- a/src/test/java/org/fuin/utils4j/JandexIndexFileReaderTest.java +++ b/src/test/java/org/fuin/utils4j/jandex/JandexIndexFileReaderTest.java @@ -15,10 +15,12 @@ * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see http://www.gnu.org/licenses/. */ -package org.fuin.utils4j; +package org.fuin.utils4j.jandex; -import org.fuin.utils4j.JandexIndexFileReader.Builder; +import org.fuin.utils4j.jandex.JandexIndexFileReader; +import org.fuin.utils4j.jandex.JandexIndexFileReader.Builder; +import org.fuin.utils4j.jandex.JandexUtils; import org.jboss.jandex.IndexView; import org.junit.jupiter.api.Test; diff --git a/src/test/java/org/fuin/utils4j/JandexIndexFileWriterTest.java b/src/test/java/org/fuin/utils4j/jandex/JandexIndexFileWriterTest.java similarity index 92% rename from src/test/java/org/fuin/utils4j/JandexIndexFileWriterTest.java rename to src/test/java/org/fuin/utils4j/jandex/JandexIndexFileWriterTest.java index a8cae24..ebc3322 100644 --- a/src/test/java/org/fuin/utils4j/JandexIndexFileWriterTest.java +++ b/src/test/java/org/fuin/utils4j/jandex/JandexIndexFileWriterTest.java @@ -15,8 +15,11 @@ * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see http://www.gnu.org/licenses/. */ -package org.fuin.utils4j; +package org.fuin.utils4j.jandex; +import org.fuin.utils4j.jandex.JandexIndexFileReader; +import org.fuin.utils4j.jandex.JandexIndexFileWriter; +import org.fuin.utils4j.jandex.JandexUtils; import org.jboss.jandex.Index; import org.jboss.jandex.IndexView; import org.jboss.jandex.Indexer; diff --git a/src/test/java/org/fuin/utils4j/JandexUtilsTest.java b/src/test/java/org/fuin/utils4j/jandex/JandexUtilsTest.java similarity index 96% rename from src/test/java/org/fuin/utils4j/JandexUtilsTest.java rename to src/test/java/org/fuin/utils4j/jandex/JandexUtilsTest.java index 16bcf64..8e05dad 100644 --- a/src/test/java/org/fuin/utils4j/JandexUtilsTest.java +++ b/src/test/java/org/fuin/utils4j/jandex/JandexUtilsTest.java @@ -1,149 +1,151 @@ -/** - * Copyright (C) 2015 Michael Schnell. All rights reserved. - * http://www.fuin.org/ - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 3 of the License, or (at your option) any - * later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library. If not, see http://www.gnu.org/licenses/. - */ -package org.fuin.utils4j; - -import org.jboss.jandex.DotName; -import org.jboss.jandex.Index; -import org.jboss.jandex.Indexer; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -/** - * Tests for {@link JandexUtils}. - */ -// CHECKSTYLE:OFF -public class JandexUtilsTest { - - private static final File TARGET_DIR = new File("target"); - - private static final File CLASSES_DIR = new File(TARGET_DIR, "classes"); - - private static final File TEST_CLASSES_DIR = new File(TARGET_DIR, "test-classes"); - - @Test - public final void testIndexClassFile() { - - // PREPARE - final List knownFiles = new ArrayList(); - final File classFile = new File(CLASSES_DIR, JandexUtils.class.getName().replace('.', '/') + ".class"); - final Indexer indexer = new Indexer(); - - // TEST - assertThat(JandexUtils.indexClassFile(indexer, knownFiles, classFile)).isTrue(); - assertThat(JandexUtils.indexClassFile(indexer, knownFiles, classFile)).isFalse(); - - // VERIFY - final Index index = indexer.complete(); - assertThat(knownFiles).contains(classFile); - assertThat(index.getClassByName(DotName.createSimple(JandexUtils.class.getName()))).isNotNull(); - - } - - @Test - public final void testIndexDirSimple() { - - // TEST - final Index index = JandexUtils.indexDir(CLASSES_DIR); - - // VERIFY - assertThat(index.getClassByName(DotName.createSimple(JandexUtils.class.getName()))).isNotNull(); - assertThat(index.getClassByName(DotName.createSimple(Utils4J.class.getName()))).isNotNull(); - - } - - @Test - public final void testIndexDir() { - - // PREPARE - final File jandexClassFile = new File(CLASSES_DIR, JandexUtils.class.getName().replace('.', '/') + ".class"); - final File utils4JClassFile = new File(CLASSES_DIR, Utils4J.class.getName().replace('.', '/') + ".class"); - final List knownFiles = new ArrayList(); - final File classesDir = new File("target/classes"); - final Indexer indexer = new Indexer(); - - // TEST - JandexUtils.indexDir(indexer, knownFiles, classesDir); - - // VERIFY - final Index index = indexer.complete(); - assertThat(knownFiles).contains(jandexClassFile); - assertThat(knownFiles).contains(utils4JClassFile); - assertThat(index.getClassByName(DotName.createSimple(JandexUtils.class.getName()))).isNotNull(); - assertThat(index.getClassByName(DotName.createSimple(Utils4J.class.getName()))).isNotNull(); - - } - - @Test - public final void testIndexJar() { - - // PREPARE - final File jarFile = new File("src/test/resources/ext4logback-0.2.0.jar"); - final List knownFiles = new ArrayList(); - final Indexer indexer = new Indexer(); - - // TEST - assertThat(JandexUtils.indexJar(indexer, knownFiles, jarFile)).isTrue(); - assertThat(JandexUtils.indexJar(indexer, knownFiles, jarFile)).isFalse(); - - // VERIFY - final Index index = indexer.complete(); - assertThat(knownFiles).contains(jarFile); - assertThat(index.getClassByName(DotName.createSimple("org.fuin.ext4logback.LogbackStandalone"))).isNotNull(); - - } - - @Test - public final void testIndexClasspath() throws IOException { - - // PREPARE - final File jandexClassFile = new File(CLASSES_DIR, JandexUtils.class.getName().replace('.', '/') + ".class") - .getCanonicalFile(); - final List knownFiles = new ArrayList(); - final Indexer indexer = new Indexer(); - - // TEST - JandexUtils.indexClasspath(indexer, knownFiles); - - // VERIFY - final Index index = indexer.complete(); - assertThat(index.getClassByName(DotName.createSimple(JandexUtils.class.getName()))).isNotNull(); - assertThat(knownFiles).contains(jandexClassFile); - - } - - @Test - public final void loadClassOK() { - assertThat(JandexUtils.loadClass(DotName.createSimple(Utils4J.class))).isEqualTo(Utils4J.class); - } - - @Test - public final void loadClassFailure() { - assertThatThrownBy(() -> JandexUtils.loadClass(DotName.createSimple("a.b.c.d.DoesNotExist"))) - .isInstanceOf(RuntimeException.class) - .hasMessageContaining("Failed to load class"); - } - -} -// CHECKSTYLE:ON +/** + * Copyright (C) 2015 Michael Schnell. All rights reserved. + * http://www.fuin.org/ + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) any + * later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see http://www.gnu.org/licenses/. + */ +package org.fuin.utils4j.jandex; + +import org.fuin.utils4j.Utils4J; +import org.fuin.utils4j.jandex.JandexUtils; +import org.jboss.jandex.DotName; +import org.jboss.jandex.Index; +import org.jboss.jandex.Indexer; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** + * Tests for {@link JandexUtils}. + */ +// CHECKSTYLE:OFF +public class JandexUtilsTest { + + private static final File TARGET_DIR = new File("target"); + + private static final File CLASSES_DIR = new File(TARGET_DIR, "classes"); + + private static final File TEST_CLASSES_DIR = new File(TARGET_DIR, "test-classes"); + + @Test + public final void testIndexClassFile() { + + // PREPARE + final List knownFiles = new ArrayList(); + final File classFile = new File(CLASSES_DIR, JandexUtils.class.getName().replace('.', '/') + ".class"); + final Indexer indexer = new Indexer(); + + // TEST + assertThat(JandexUtils.indexClassFile(indexer, knownFiles, classFile)).isTrue(); + assertThat(JandexUtils.indexClassFile(indexer, knownFiles, classFile)).isFalse(); + + // VERIFY + final Index index = indexer.complete(); + assertThat(knownFiles).contains(classFile); + assertThat(index.getClassByName(DotName.createSimple(JandexUtils.class.getName()))).isNotNull(); + + } + + @Test + public final void testIndexDirSimple() { + + // TEST + final Index index = JandexUtils.indexDir(CLASSES_DIR); + + // VERIFY + assertThat(index.getClassByName(DotName.createSimple(JandexUtils.class.getName()))).isNotNull(); + assertThat(index.getClassByName(DotName.createSimple(Utils4J.class.getName()))).isNotNull(); + + } + + @Test + public final void testIndexDir() { + + // PREPARE + final File jandexClassFile = new File(CLASSES_DIR, JandexUtils.class.getName().replace('.', '/') + ".class"); + final File utils4JClassFile = new File(CLASSES_DIR, Utils4J.class.getName().replace('.', '/') + ".class"); + final List knownFiles = new ArrayList(); + final File classesDir = new File("target/classes"); + final Indexer indexer = new Indexer(); + + // TEST + JandexUtils.indexDir(indexer, knownFiles, classesDir); + + // VERIFY + final Index index = indexer.complete(); + assertThat(knownFiles).contains(jandexClassFile); + assertThat(knownFiles).contains(utils4JClassFile); + assertThat(index.getClassByName(DotName.createSimple(JandexUtils.class.getName()))).isNotNull(); + assertThat(index.getClassByName(DotName.createSimple(Utils4J.class.getName()))).isNotNull(); + + } + + @Test + public final void testIndexJar() { + + // PREPARE + final File jarFile = new File("src/test/resources/ext4logback-0.2.0.jar"); + final List knownFiles = new ArrayList(); + final Indexer indexer = new Indexer(); + + // TEST + assertThat(JandexUtils.indexJar(indexer, knownFiles, jarFile)).isTrue(); + assertThat(JandexUtils.indexJar(indexer, knownFiles, jarFile)).isFalse(); + + // VERIFY + final Index index = indexer.complete(); + assertThat(knownFiles).contains(jarFile); + assertThat(index.getClassByName(DotName.createSimple("org.fuin.ext4logback.LogbackStandalone"))).isNotNull(); + + } + + @Test + public final void testIndexClasspath() throws IOException { + + // PREPARE + final File jandexClassFile = new File(CLASSES_DIR, JandexUtils.class.getName().replace('.', '/') + ".class") + .getCanonicalFile(); + final List knownFiles = new ArrayList(); + final Indexer indexer = new Indexer(); + + // TEST + JandexUtils.indexClasspath(indexer, knownFiles); + + // VERIFY + final Index index = indexer.complete(); + assertThat(index.getClassByName(DotName.createSimple(JandexUtils.class.getName()))).isNotNull(); + assertThat(knownFiles).contains(jandexClassFile); + + } + + @Test + public final void loadClassOK() { + assertThat(JandexUtils.loadClass(DotName.createSimple(Utils4J.class))).isEqualTo(Utils4J.class); + } + + @Test + public final void loadClassFailure() { + assertThatThrownBy(() -> JandexUtils.loadClass(DotName.createSimple("a.b.c.d.DoesNotExist"))) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Failed to load class"); + } + +} +// CHECKSTYLE:ON diff --git a/src/test/resources/sample.index b/src/test/resources/sample.index index 7aa843fa74a6859cb1db50a2e7ccf2ed8255c046..5f0dbb6bedf1869f6ca072f4e639d8f0445a5f59 100644 GIT binary patch literal 24252 zcmb_^*IFCfw&tuPl>!ooj4=ib&Iz0|Nf>OBK{zfO3siuNkgy~$IDTW6F3v?i#Cd>z zg1+b{=!fcm%vl22YxiA$YZt08!-)R~Ro?&Wf1hcOIY}cytF^SdnJ;)t<4c5-P&StvFBEKHn3lbgSzL-#yuEBW zTP>ACWiOla%Eo4NJ6p^ZylE^R*)L-0%67I87MS1|q0p{cGQNjxy>j(vA-n6vup!7; zFL=9^*hV2+smzslDZ7Y=$x42Aui#CVcCn9_DH+9hzL>A(vxQgL!oJt?wVbbd>D|5R zQ5y5TV%0g|`>loS?s_gew3n@JSD2K_&<&d>hOya7eyiA|xtuF)?968m!y6!a%gd#L zX~%RA-3WiqmU#h(rBw;%@@1wu{JE?+bg|50d8Jy8GyCHeoaKvK;R-}}wC7oKnRLoK z-19ad*Yx3rw^z-Vik0}x_`=j&dU#j}+btT2(?*vXWZOQq@(=yfdHFhvuuQ9cR? zOcuSbtg5=q94Nxeh4U4~y0cl>uWZLyIl1g!)hkz+z13pbtCR`{UM^Dhc1s7|%3eOU znJ-tW;0J?P?&;!2DF=$9IDg?C&E+fANCjpvafGW-HM<3&IHl^gS8l5FF`3=3KrNVi z0CCSKWtYP&oz>;J&?6S|6DMC;@V>gxvexQe*{fEMmLQvI$9A?dsinP=FK&1l>;VEo zAOQ5WVqKPRWiPt{r5CH-VKsaJh9I{P_5j)TX1Af0ix5AXx@%a%3_Bq^;<5O=8Sjwgy;66DN|ToN0-k{<$5akfV582t zhGT`{O(Ik&Z%pOO$*J`8`089{4JNU+l37mju-VN8Z^NrpvgIRQSgVV5V{VRE`{g`q zZaL6xvoMWhQ^K~Ka5NSP#oaKZ&XbcO9Jd`8H!ZU%lrY*LHt!H?d2D3k#hkKZy}XyG zWDgV;z`*ieB?N_S<_}%P9~-oH=xyv*J*%|-*{);@RkqF(vZ5<5W|!8cXXnx@?&f}R zgRMLSfz3ldd;6?cCkNZ#Zr<3=7jk8hD+n<}6sr*kU{9e#tg>DD3h3B{k%qqI_b|S9Whp&5 zJ3hBIIWxYzwwzv?8=p+irx!A7^W#evh>ft5v6d@rssW%C8EiA{smzF&rZfxKm)Aogw90QOY9XK*o3fm6kT4L2z&7fMxy z5FueWKw!AXH_yo0rXehC=$2!*ZL*?75}J#yGCDpsXh?)r-0wpy&_3k#+BQrSC(0igJa!SUSj@|MDn&~}N} zad)$anKEpYZ3A$20J%@+y+V%hL;FK-0aB<7@ioXP?N`%>Rja0YC*3y7IbK!)-W zLQQTeTg^HfP+&C%JE~^$#R}p;6kG+dD14ArRvF4xRCrNF!~(K%)tsBJZ~#CkV^*M_ zc7@$j-ez{ca1sd|kWj3KKu3P_i1otJl|dv?k4nnlE6L4Ld6xx}Timb0nK?YGC(-mv zIQ!iAoAgu|z{G^O*+91mwdHsfp?e(|=Q6S|eSmFO0o(Z891rF_DHb1viVBBE~Qp*&!y2S9?eG9BX_u>lQ1@N3I?N`g!9fv=@>fQ%QskA5;VHi-Z!$Q_UtHO9300^wJsd5AZ*7B5rHgNO1}l ziYJoIE$!W%(WbVJu4sB`adHL$aeCU!=OPG0#|KoTDipyc;&`27}-d+K*`4#fI zFhUp$Dy9TD%i(1?meZz;Kv9yNj8xI*Oyy!U!kKmQ-tJSBDddwY4WtxzR{-Z@jyy$F>sM5$XXZqAvk; z;ra2*{E%1Xsv=}{+N4Q#2^hfe=4t3^a-Y%tA*naBiL?RIBWO;5glU)yMzH-e0 z+8zUBWOiXCGrlmHUP*ux%q|9jsYi5ncR{s4&se-E>_*z69WANm_GF?J`z!1Vd0&w3 zRKh{FVZn0j%1(aIf!}7g!Xo4tmTAY4A}w)xwDuzX))A&{Sk1dT5Pd^Jf?P72E97_c zRhN~<`Uh@fGL}M!RoKgD;FVQ1%A5PRYk60*M`R2kY zicEsbh#n3(c8@YI@XTI?MLLsE z#;;I>>9B!WUXsJF?Ln`;Bs5RWhs(2ATY!hKI$? zR@_m^U1R>vNf5MdZWLS*Ho$>pHtf&(wh<#L79wRhs|y$i0yaLW4JlrLY-XW#m3-sA zGL(c$aB!MeM#u%kWc82(@hn?ku}M4Y3?w{1b=%r2Rbr4Ql10GO;wI9kfOHEJqdUdY z*CI=zavYDDt^i$KCV&Gjuy-R{U;$G{Mkp#{QHFUSsKn^72Iz5YDhEpQ-BD%GZoxq30HqBvYGuq~u<3dFUUpbkM15;g@> zp>xp)55PUg4f7-ve-X8025D&wp{p)MhkbWBy6Yi7QH6jDe=KtaYI8F{BiJO9gc?)H zIJ$paPKJ0gDniiT&?R83X303aUU|#oE&>vdQZWyKv0#;G;99P-Je-6yPcfAl>rMlz zIE5TGqAjA!{)MVXEy(Ac5@QPfg8eqmgO*{}rQLD0 zA#=$dq3t1BIW7kWMBkbI*0xkfyJ1FR(XN(ccTc>z^HlHYM3e1?!j|Kz!U!pEDu^)k zz6sDKs)IS}rfGErU4xm$`7{G`Tivr4m(mM$$3B%_US3>AF|)ifgS=&S;n`Xyy^>j* z8qbV(i;k|&#yAmeZ%(zeAxtz?RPDQ>OA8CuIBuLB4mmBU7;4M-sjk+czJdNTmN|IQ ze(pgurd}-uL#2vkU_o|3)Dx_u=y2=Kp zGE;WN^L8vm9Ckk~C$9MaPWNJLj6wFosgS~{6MuBna$GIgmWVjoDZ;M8e%LvH(y&8L z*iw298WhIH9~QX;=Z>poxI9Ema0B3}Ao(bGTZj$T2G9h=X~#klk9=DDC+9=xA0Wlx z* zETII=ZmB}p<_H{NNaEp@e@B{;gi0M)U}}WB7vz{h9|#@15IdD)st~PeSMDNkeLH)S z%Z3$70b#fyWE+5@;|w1j!@gC|VA$>5AkV6>I)HobRL296?|!E0J^Z z6NKy|8(}zWKFiqL>ER2HTV0J#>tOUOnoxW2JfzP-i4v`rK!gee0ni5y&5=L29mGO) z6;eBwgIc*Ep9w;4J!Wueuka2C)vV?Kjq6<`3kV8a~R@$1WW(#pn#f*E9guKrEY>_XP^p9y@FiGB>_517GE08qx{} zeV`$ch(&uGfEzbSB27tDEp1&L?Va7dr~CQ`2II}A&YVSe?!eP_#EMoRgG?UzMgooj zhpj70b_gMo%GA+fD-~5YSJ?Y#iil${6md8ml>C~z>}3(2D3wry6-CEi^8%0+O*%yD z%Zi98;GR?20zXpuZJ?NYZaIBE=CQD5$4_ zzsS%xp%HlVX|m;*W}$D5ce)*vv6 zQ-521LnINc+KeC=U{0Oc4kbl&D5sJ2oxC0q(WQwruzdxuO+*M(Bie~@UA|$x(nHat zPbRnr$fPcm7F9`AADCdvC{bsclCoyI5#1`5ow8N~xEl>KXqJ?P)RHB2Sh_g4<>kwff z0}_e97=*S_v_TLp@DRo6$wo14yxI#K#7dw*Vq$-jks%k*A4RtSH9W+h6Gldar%I|Q z6>(IhoJC#D7dK0yJwUU+Hg6qYuT(j|YY?4i(y~+~cd0C#&+Da1MHsJyql{QY|8Nq8 znai+S*p%W$Nm?~xDx!mHK0wRgRuDbWrRWMU>fiXpfDE|NnYw77&lb4l>E!?}Co%$T zz`uEOJ?^0h1=NHTxerA<^Yd@lOY-ekd3epDD)2@4{T!php@^L@_)vtE^lv>EE{|t^ zLiUt_r5LPaIV}Wp;mXsC_+9Ku6uwR1JGVrla-V#Dd+^y(SobVxEiplTlnMicqj! zY$dzNjbQ+7MYJz_Tj|3+lyNFas$*B%F-eWohvrJ9oqYgb@UlZ#cDRAq6C=0DNpqw_04&BMc=L3I*%ej2fTiD-SM-L=$ zTTX;3w>|^&i+BU1clzv&me7!31t0=Z=>C;4a<*l~n+4`7$VWdUJF&|pL^}MHPe7{;!MX6f1 z>m=*^%e?WHVaq!d=KBebsK>8`gz-Wgci2RmDrd_3{QB%fUN)x-91rJ2bo|6H&>B*4 zxFV9v&eUaDsN>>9xGYkJERkwtyB;k0Y2Yl%m5{eL zhQ8xB`l5Lr#cW=Gjl){42zN4DP~{c!C}?{TZv{B!##9E(J!wFOyU5?qsMNezuSi5o zU2Z4*V{g1j)lBigK*qd8NE-{tSGd>6gh1AMxGtIkvM8)ULi!@Fc07Nj*Y| zTGrW~suvy#tAa?^9^`d@O>C{llt#5eQ2Ao;>QC4OR1Ttv3z-wH>ZuJ%JW$|?ZcYS| znLvv=Aw3zYzg!a069^E^$2A-z${mur-*9bp>>;Q#8ibW%;iF9B?E>Qv5rq)1^4?bw zQSm@IS##i&CnQ7j-*H*6x{y@RVv1N*uIrZTcLS}X|sL{fZBm=k> zwMIudEa!ZHN&GhNn{?fzQx*+} zsK=xYn|{Q}G@C6lLezr4;%Bf}+?HnOvqhUxD#stY;bNbhD4H^;7F09Sl+U9Bo~Y;u0-h*}F#PZ)}b_w^H{& zB)zgjA!>GW(MbGiLN+(QPtlz=>gw3(qOl&j+IyytKJ-&;koJczoud~Q=-DNixI%r` zUf-YxqocPdcjx-OvkwLyfjIhP_k6x_N_DQ#&yus%~^!?lulXfrBj@fyQ&YCo7)8H+- zXMVC@hUl}Kd_r%`Hv8KYIVN41q08nEo6dzOBB3)bN+>U5hygf12oKHdRvb}=}UDC4XNiQY) zX7KCW9qK=jDvr|9tpkf5-lK&F=N|Q$H^yKsGG;f0mfe2-omH$P6%uQuB5puMiu9y;tLC=jOgaxgt~?;L%*@bL#- zG{0N2B{bx|p%8sF&)YH;qQ~yD=t7)UsqG{6teY5g%l;6eM=o_nWjsEYDAE-+^q=Mh zx8nFM2N>iycFUct~-S32>YMYyy7bM zImi3-8|SfLs~9jYU`Q*DS2*xe2^)!fIJJeC#?NbvI*qscHm-3Z=rfKb9AITpJsUIc zGF$7IYU9Q!(V>2O1QYlM$A-E)Vcf_0DIEPm$Rv&g4!kDBy_d!mW>4YSFWei%(T4-O zy~eG}IIiG$FT@OfDr!d7VA+5U38v8C3SSpFv#Cjl>$ts&;}wRr3J>S}djS&VUnc1p zp8lh*O86C!<`Aw11j}In#|t5@;Kpg;0;hyvF%1X+BmS1~_zMmstcjlxXP7p{FJlJ_ z7I1eHzeUKmfcvKenFg|4oc!j8YwC0We}_b$F|4k@Bd){){N!+0xOp0?FzrE{4JcaC zxPzH&3o$9g4j8pD?uQT%38s#?LnL0x#>Dk5rZAO7}=K4DXaUV>-CU^9@gS-?6j`tcmx zzUMO`JB7HUZ)_N!@fg-JkCCj}2`urRide$lppudv*xfVf5>y!!;vO!!)9160xA!XfxXJHJojBb~twT zsngv?AG*=z8QbVL?E$O9wxhP~3=TSjcI>PhoSrq#I`(NEeA+yB(L8s_bR5&}!8%DC zDWkGgIz8gS4`)cb)$R87%}ZO({9Jo-KITi+Be}mrZHspblZ+|>$dG& zvmO3(2Os1)IPO^eBaf{oPi^bTm~A{UANQLNVpjj-5hG^WF{9hKYP1?-#slM_F^$~^ z@uGRqnrU^cnK8$lX*FlYtk#)UYiwrBc#dyXt*~Po^TwiO-@k7xo33lTGF}^RjJL)m zBWa|JcgB0;gYnVG8tcX^CO42rw>%@ds33u#LfX68aDZL3R{3C}~dFCbcXYkBkM=nKh`*G);rz)){Jd z%meB)4$SUhv)eSg5z4wR8Pshch=4&lZBU=lY!29F2i`l3+a|O2ca15Hxn1ziI zTihHD564Y|h73Aq=9jGeQVcB6d4piS7Yz8+MHr!NTc^6a5kj#qU9s5m>9VCL8Z}LO z+M*50QGV2fqvWa6qP$GV78y5WTy`6>`<;yedD@WxP*Wylf?@{7xR!KfSVrW4A)D#6 zL(6JVhwR+4X^lSdGBkx8Lv~RF6IxA)XVNgF!7g-^WXJq~QMT+bWXFt2Z)u$_8@LCS z^0Z~pmS@vDwW|4&kszzqyo;xIaL9H;w$rRy_AAeL$bSY68I@-YnYeDq)*(c7-u0Zx zzZcZd$1$w*9&0JCsR(A9!EXB@Wh+%*7Des&1@_CChb#IT86Yf z@_O3_ZQr-FcKZ$K4hLGJHx_K-4b}?tFr@03_5t}9y;Lg5;ORRpJFuCB^?0;NTeMA| zF?!#OD@Flfk}daz(8f^BesTi z0}CNT)TZMwRVfD)zSCmd41-oJbj+i@ONQ*c$fnmxHw@`4hA{rSgghi0Nt&N@RfnOo z3^F_B^d0upoYd)O+P^`z+KLQCbtrH=SR?jj<89SeC0n3@%Kyg&Kf!cpz=pK7n%@Qr zc?Qm12xQfzSM(Z$!!K(4 z@K=QPyop1eW?M=!7yz-fB?ILO^i26MwIm_6cUXWoW=*r4s`L{(xmd8}rUtW5D0;vF zfPIZV#&{u^(FCs_4$v#tr_g{^y{?uj2Ig|aLWi#E{`IHO86aC_8?9^KUC-N!6?iw` z8{+C`|H;Az<}|%7_PmATIfRCSF$)Ts2_-0-Ck!*2I95GFZ2@X-Fvz=c#V8v_9`;u~ zF;~hOxVdR!_NEjjqf7$3+`~b82JNj_;0o}w%s237`AzItVn38Eg|+4W3PB9KJi}qj zKU#_THsxm8FqxfoW%zaH`Uz17a0Z@#(nY9j-jH2C@e36*Sgo2c>^z;r_G17xdV-S& zrds7x2Qo$6|7V&6F+P)tE&q2Cc}5AtSO=K@M``JhesD zKJWkXkC-82PaJFlYf~alsKD;OsrCQ&xFNbjToV+ zmhdMGL(tid4pf0CsV?%s;bDBkL)Yn0crAu-kQ8H$+BuvL>T~}R&gqK2kQe?711x>f z$)~{8yfFQ@@<60fUEWuV*K8p_@m?48NNUF#-TJ&XhI6~4gQCLd5^|59Fy)5-O3)2{ z7Hp;XP|G35_nSd%OkK4KwJ}!6gN*|r3)mOCG2xGxq}Eo{wI(IxTYYWegA!9dlH;P* z&$~@bV7GgMmT?i&^D6%x#l-!6{Gp~+kOd+H0=Uu668%Dab#`x${O>2MF5p?FRKf$lTfD$UAl2u0qkKIL4r>oV!#HBZE57qh zj%wi}u5UAA3!;|7+7=yBGp3~?a)a{)LL-9t$~vCv48jGXyTQKK-wP-knUM0`}}syi!5buHgv)Ou@kr2>3;v z)CuD7OzwgRt1o~sy;)Kjx!)rEeqQF%Wr#>FwF>z}ufu!G2RQ#8&@l~3b+xpl*v{qK zz|KE3kn;`e*mv%-sIN*-JmNhA^D1DNwV>GhM@WWli)QILZ<%6HWrQL(kkSiYr>{FhpuH+$_OBe`cVin+_=BkGfRm>}JOBk8RpkJUKK42{$9N>bQ{5>(#;MnqP z3oQ%k<0#1D?+{OUW2|P1bK>$dOr58w0f2)QhSffo&0X zTV*(J2<%swR131N7XK_k|qd^;MYpENXBCb_azzD#~QOePdb>VpuSc1huvfOhr-Wdk=CXJE^3{DP|M2f zp8-%Bh^mEn{UCw3%!_MK`Xzk(kDci*OOej*6qxH?K@O)irZyI(Q*EjrbOMk}f@f<> z9&ku|gp~rhQVzc1D9fdV0R^xka||pD{{cqH0}k};NRv~5sM=+^vMqY}`7hMO~n>c17M6v`A1KKDNh%-=Y>}X0=0E2o`)ryZ8@e`}@>`zWG6e zJ@|sR4m4SN(BMTrr)EPMePk!=E{KSJMI(iO6*sSsjEu7L$X|Y|s9k66+`I+KB=I}YhvBaZ{|t0zpF5AcwK#`= z;WM(!P1j&lu`tv1Vp=c1OtZru+auzdbO zfUZRhPN-apATc(JcpIW%6(#T*519rk_%2o$q&74(kmPouOD?O}fX)^_vw`jk|4D<< z=$vq9s2#KCzKYsSkjeI}1i?^$5_?a4OEwFC1<&eCcY{+~p&d=g(MW^Rsp5|d3qxU- zYRNHDuz7{9f?mHO&xm0>4SfAbmlWtkslom?-d~>+M}fdF{W&~7K}&@X+JU&Ds1lxL z78f(?!l8-&ava@ zaYi(;X_rOhF9nOA(>}ZHo-vDMP8h57qjdIe) zbB*A2&{UKa#o!XuH4WZ^IQ*HnQ2ce(P5m4(7S~Okt2jDaFXQ|*NayN}8({F=l#tBN zxK7b7ecqS+4-uXsMAnA9hjKk-x>#J44ent!$tL1Fd>`TWd$?jOqn-p8(yQ zj~F1QVaT)y@zt9F+Ey*j7vwGBCk8M|Cp%ZQiG2UA6(Fx@Bjs{TOX(J=SUv6E7d;Ba zIR^Mg0UxoOqKKlY_Dt z=GjA|f;dIg-5m~_T*=YddVa4)XENAEW%H6-0>^oC6LSczR5R%lE=ILPd`?`s6Ng;b z{9Nl2y?7RMpkxH+b%fyiQ+kdfg67a30oJ8_#OPiSVm0QOGRK?0e#2{{*3h-pTCin< z>SHiI3)ckmi< zL@mM~AiH>ZnxF|}7sxnMx*iQEgP}lub@w4|8U!T-Jz+-mFqy&fI#{Aet&KH?UAPyo zU%-EPVQ+DF5vTz5iHUi3u6`lsF+0%bEu7ZHr4n!;<72dRIS2no`hmU#% z=EvvqK3GDTn-W3oim1Wy+1R)%gB;^Dh8>`*yu=m~mffPJWc2(wWHfsRAG#1o%pBJ* zEzG%I3V4pHx9&r#+M~1ea<8GeNe6;yY4kPn$ise|`U=TOMUZB1t%)D3%O_6|1>Q+~ z_$8V+2OFl_=v)GxeydDE@l&_0>pZ<)EUL`E-qrd~z(O6)<3@<{Luyqd%?Vse7Um_Gu^%_+&DXTtUA zaJ`Wg$AwO#xaY_%l)6Kda307FaKk3}XVItqSlg1{G;$1{zRgn9bgPW>*eKQ2@y@#2 z_g4W|JHryMCo*ykG#q!crGYDCPD*sOZo=kg5i*XRFyNV3{3O&$yXV#RMf;4qINPAwq zP}yzmKI%tAF&-wbL4xp91pIo?Cpe}RDThrGqI0l z>Uq0756*^EJEUFc2(j>)1^66atKkun8%+aS=`k09VUH{7-axV^6$ZYD^G6{ba_a%k z=PVVh9&?NrQXFA8+ttYdzG8yJ{6%(Y;eYxoI&(Wb2zxY(^Xt?^O`{MzHv;4U?gZwL z7JeDKpj;t*aD`{8qN20)l1jg92;ARiVjv0PWY6$zJ@cEwKg2(=a|88Co&-mKy{w(})jKMM#=Ur}yUEHJLF66z5lq2L# zkR{F3ec|6rZ3{VOqS4rl8K-$ZJx(2<|CB<%e$UL|t3Y0AJvAWwQy_*n!t0_ZDSS>= zyA7J;FB62lWsaMAhQtNl^H)-E|R3miEoC;UN)!X!;U{%Zg|K^rygPhmE1)&|0l3Vv+We*jWs{C^5=VS*)G>HpDt=74X7<_8xpji&tEX}`&TDqp{l zM$~^Hj~ozSwP@%#R?EA!~sU;9YU zXxzug2EN0?jREnj&WTNU3+US+C^1dH{|7*&{=|@Lic#63m7o}RgPCg~I3|1cuB4g-$t&^&S^g>Np7$TivivR|%W-P= zN8UpK?|8yn<^vyMy^%=f?B$_bzvQapUw$Sp{g6p~CyXJLk$^&{c<0HR&$TJASd;_Q zB2UZ17MXm@gN_CaeuV{s-jC6z5G=15-);QDryD-{w`tiipv+1L_imzm^YZkAVY$%* zxiQu0RvyW{1-0( zClXF!_EY+|-xp*0{cAEU@ion@Y{_3;#`oY@u@K0@FjqQj1D0I4N~>xw!_2T>ZH$OB zS`24?(x;ZT=W-{vNVjOgANMoz;Vb#m@A9W)aoV4e-+95Ex^S%*t=&?%TlD3#%=jy^ zAQSZ32hye~Gh+NyiyBuoe>0xu@AZh__b*`Z77OGzUDX1~4G03$cwk;TQyXYzG8W|| zE!<%;Xm*;q(K&e)Md=}}%ZvWYYxqv-i68f`%4fXdQllH8x;~=>AzMcbLe33AV2}gL z*l(gexgsy~oKHxc(VM_G-S|S~V~FtKym1|J^t=5IEywRCe0<~i9aQyg%E6`$UZ7al zi+Oth|JDS{d!Bz*zT#(V$BWgBpW!(^?qxdFl8 z>x&1s?onqFZ#O%r#cz=xF0IQ!c}N~b<&}P!+~D!}av$TzAfqFE#FJtfnd3e5$?@lW zXOafxEgu0XEt~7w!v%X_$-n1s@&fz(kvL5nFoCMlf(1Cck8Tk=sI-nz<`12ZP zo%#mh+(?^!ZuLto907iR0JVYGWU_`7B26n8*@u7B0Ksi+UG!>aht~FJ60e(QH|1+t zl|TGmzh~;6e?dO?-A;O+pa*mQus`&g9>Tgd{XV}f?i>DHIr0r0e61-SvJFxL%rD_X z%zk{h)N}o(T;@$TndV=0^Bt8N^6C9yAN}aG6wozF3ebZqOUC@AkQQm=#0Z*T1W(9j zE6|1_lPkRJ8|}9S{$+tRc;l87_R4Q3?ITr8%g#DUVc_)T3SjzTx6EFoNAj89PXqFr z<>T{5`9=2h(EbU(&-y?1eok=6z!$tN6DJX) zst4f%Q(;BINlLl+pdvzPd0*yEAq_vkzmEVx(YlJv$MDKfyS%(0r+&dgkp84;kIDUa zMDQAw?a1@^ZtW($buaOPUA!RrYp|*bKRs}RPWy@2L;n>m(+fXJ7yJQvKr#Q^7(T51 zc_9^{A=v#WKA?Fdr!(Vndyr=6seI?(;Qg1e7@FB%u$uGX!l^Frbr1E*v-0(6TKYtt zev}v_2a!8j3Ev~fED-`;S?Y#cA_&EcqzBE%D`nU#?RYE1U`cflx^Rj z8*&Ie3pOEX2Pqx6flb?T%%7C26jsY7v@Q+&Ga&PA3!GN&b^8Nce=hhw6nJq z3>Sr-y;Njvo6cpSS#%W zcaKKLhv$NuTPbZv_p z>#QoeZnX8(1(p{e9enj_4)Mq~ z%exjJsGb->tjoY}v4LMUxrKnRN46#bKFO>4Zl;g!n%sb=_kc9*{V{pxXJepc0`W;p zdG0!cJSuAUYQUdg6jcR&dvG95FXm=igKRsKuve6yLAEuoPJl18C3l@vL3mh}`fE!g za{HyYHqbe1Y@IL7JxzC_mlrcl_oOe^CoqH#>#>NZ;&CvDF#Co5$hr6_co{uN`q@S& z>Ahe>?s-AbJ&4&8{`6PI4)~VvgNM<660%(`;W^u3n{1E&9R0vD_Ka@}5j=`imIB1! z0h0hjAVUs-p${+sIB;760b~dvMgaQ&v_lp2)_jjkpV6D+(i2>Gl1of5#fLIEjsy$RMQDvyMQKhI3P)SrBR9mQCpn8mI6BS40qe@VDsGgu2 zpo&pNsQRb`)kYygz!(B{A#iq*#DE+^XCo3aBxJHQrDdlF%sDbZ@I>5)j`MsPjFIzT zofo%xPM3L{^5T9MQu4ezZ)@EL(S0!+-)%_PBo4N2+V)Qp;^N>_QXEBOdw|()Mn9AK XjnW((tyvNZ4E#8Yn3qbv4G8}NXRHI5 From 5608c18b0bc76afe9594239943dd276a8d7acd5e Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sat, 2 Mar 2024 15:14:32 +0100 Subject: [PATCH 17/22] Added new locking methods --- src/main/java/org/fuin/utils4j/Utils4J.java | 732 ++++++++---------- .../java/org/fuin/utils4j/Utils4JTest.java | 119 ++- 2 files changed, 411 insertions(+), 440 deletions(-) diff --git a/src/main/java/org/fuin/utils4j/Utils4J.java b/src/main/java/org/fuin/utils4j/Utils4J.java index f623105..7ae59e4 100644 --- a/src/main/java/org/fuin/utils4j/Utils4J.java +++ b/src/main/java/org/fuin/utils4j/Utils4J.java @@ -1,5 +1,5 @@ /** - * Copyright (C) 2015 Michael Schnell. All rights reserved. + * Copyright (C) 2015 Michael Schnell. All rights reserved. * http://www.fuin.org/ * * This library is free software; you can redistribute it and/or modify it under @@ -22,7 +22,25 @@ import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; -import java.io.*; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.RandomAccessFile; +import java.io.Reader; +import java.io.Writer; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -36,7 +54,16 @@ import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.Semaphore; +import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Stream; import java.util.zip.ZipEntry; @@ -72,7 +99,7 @@ public final class Utils4J { /** * Used building output as Hex. */ - private static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; /** * Private default constructor. @@ -83,10 +110,8 @@ private Utils4J() { /** * Returns the package path of a class. - * - * @param clasz - * Class to determine the path for - Cannot be null. - * + * + * @param clasz Class to determine the path for - Cannot be null. * @return Package path for the class. */ public static String getPackagePath(final Class clasz) { @@ -96,12 +121,9 @@ public static String getPackagePath(final Class clasz) { /** * Get the path to a resource located in the same package as a given class. - * - * @param clasz - * Class with the same package where the resource is located - Cannot be null. - * @param name - * Filename of the resource - Cannot be null. - * + * + * @param clasz Class with the same package where the resource is located - Cannot be null. + * @param name Filename of the resource - Cannot be null. * @return Resource URL. */ public static URL getResource(final Class clasz, final String name) { @@ -113,9 +135,8 @@ public static URL getResource(final Class clasz, final String name) { /** * Check if the argument is an existing file. If the check fails an IllegalArgumentException is thrown. - * - * @param file - * File to check - Cannot be null. + * + * @param file File to check - Cannot be null. */ public static void checkValidFile(final File file) { checkNotNull("file", file); @@ -129,9 +150,8 @@ public static void checkValidFile(final File file) { /** * Check if the argument is an existing directory. If the check fails an IllegalArgumentException is thrown. - * - * @param dir - * Directory to check - Cannot be null. + * + * @param dir Directory to check - Cannot be null. */ public static void checkValidDir(final File dir) { checkNotNull("dir", dir); @@ -145,10 +165,8 @@ public static void checkValidDir(final File dir) { /** * Create an instance with Class.forName(..) and wrap all exceptions into RuntimeExceptions. The class loader of this class is used. - * - * @param className - * Full qualified class name - Cannot be null. - * + * + * @param className Full qualified class name - Cannot be null. * @return New instance of the class. */ public static Object createInstance(final String className) { @@ -157,12 +175,9 @@ public static Object createInstance(final String className) { /** * Create an instance with Class.forName(..) and wrap all exceptions into RuntimeExceptions. - * - * @param className - * Full qualified class name - Cannot be null. - * @param classLoader - * Dedicated class loader to use - Cannot be NULL. - * + * + * @param className Full qualified class name - Cannot be null. + * @param classLoader Dedicated class loader to use - Cannot be NULL. * @return New instance of the class. */ public static Object createInstance(final String className, final ClassLoader classLoader) { @@ -190,12 +205,9 @@ public static Object createInstance(final String className, final ClassLoader cl /** * Checks if the array or URLs contains the given URL. - * - * @param urls - * Array of URLs - Cannot be null. - * @param url - * URL to find - Cannot be null. - * + * + * @param urls Array of URLs - Cannot be null. + * @param url URL to find - Cannot be null. * @return If the URL is in the array TRUE else FALSE. */ public static boolean containsURL(final URL[] urls, final URL url) { @@ -214,10 +226,8 @@ public static boolean containsURL(final URL[] urls, final URL url) { /** * Creates an MD5 hash from a file. - * - * @param file - * File to create an hash for - Cannot be null. - * + * + * @param file File to create an hash for - Cannot be null. * @return Hash as text. */ public static String createHashMD5(final File file) { @@ -226,12 +236,9 @@ public static String createHashMD5(final File file) { /** * Creates a HEX encoded hash from a file. - * - * @param file - * File to create a hash for - Cannot be null. - * @param algorithm - * Hash algorithm like "MD5" or "SHA" - Cannot be null. - * + * + * @param file File to create a hash for - Cannot be null. + * @param algorithm Hash algorithm like "MD5" or "SHA" - Cannot be null. * @return HEX encoded hash. */ public static String createHash(final File file, final String algorithm) { @@ -248,12 +255,9 @@ public static String createHash(final File file, final String algorithm) { /** * Creates a HEX encoded hash from a stream. - * - * @param inputStream - * Stream to create a hash for - Cannot be null. - * @param algorithm - * Hash algorithm like "MD5" or "SHA" - Cannot be null. - * + * + * @param inputStream Stream to create a hash for - Cannot be null. + * @param algorithm Hash algorithm like "MD5" or "SHA" - Cannot be null. * @return HEX encoded hash. */ public static String createHash(final InputStream inputStream, final String algorithm) { @@ -276,22 +280,14 @@ public static String createHash(final InputStream inputStream, final String algo /** * Creates a cipher for encryption or decryption. - * - * @param algorithm - * PBE algorithm like "PBEWithMD5AndDES" or "PBEWithMD5AndTripleDES". - * @param mode - * Encyrption or decyrption. - * @param password - * Password. - * @param salt - * Salt usable with algorithm. - * @param count - * Iterations. - * + * + * @param algorithm PBE algorithm like "PBEWithMD5AndDES" or "PBEWithMD5AndTripleDES". + * @param mode Encyrption or decyrption. + * @param password Password. + * @param salt Salt usable with algorithm. + * @param count Iterations. * @return Ready initialized cipher. - * - * @throws GeneralSecurityException - * Error creating the cipher. + * @throws GeneralSecurityException Error creating the cipher. */ private static Cipher createCipher(final String algorithm, final int mode, final char[] password, final byte[] salt, final int count) throws GeneralSecurityException { @@ -308,22 +304,16 @@ private static Cipher createCipher(final String algorithm, final int mode, final /** * Encrypts some data based on a password. - * - * @param algorithm - * PBE algorithm like "PBEWithMD5AndDES" or "PBEWithMD5AndTripleDES" - Cannot be null. - * @param data - * Data to encrypt - Cannot be null. - * @param password - * Password - Cannot be null. - * @param salt - * Salt usable with algorithm - Cannot be null. - * @param count - * Iterations. - * + * + * @param algorithm PBE algorithm like "PBEWithMD5AndDES" or "PBEWithMD5AndTripleDES" - Cannot be null. + * @param data Data to encrypt - Cannot be null. + * @param password Password - Cannot be null. + * @param salt Salt usable with algorithm - Cannot be null. + * @param count Iterations. * @return Encrypted data. */ public static byte[] encryptPasswordBased(final String algorithm, final byte[] data, final char[] password, final byte[] salt, - final int count) { + final int count) { checkNotNull("algorithm", algorithm); checkNotNull("data", data); @@ -340,22 +330,16 @@ public static byte[] encryptPasswordBased(final String algorithm, final byte[] d /** * Decrypts some data based on a password. - * - * @param algorithm - * PBE algorithm like "PBEWithMD5AndDES" or "PBEWithMD5AndTripleDES" - Cannot be null. - * @param encryptedData - * Data to decrypt - Cannot be null. - * @param password - * Password - Cannot be null. - * @param salt - * Salt usable with algorithm - Cannot be null. - * @param count - * Iterations. - * + * + * @param algorithm PBE algorithm like "PBEWithMD5AndDES" or "PBEWithMD5AndTripleDES" - Cannot be null. + * @param encryptedData Data to decrypt - Cannot be null. + * @param password Password - Cannot be null. + * @param salt Salt usable with algorithm - Cannot be null. + * @param count Iterations. * @return Encrypted data. */ public static byte[] decryptPasswordBased(final String algorithm, final byte[] encryptedData, final char[] password, final byte[] salt, - final int count) { + final int count) { checkNotNull("algorithm", algorithm); checkNotNull("encryptedData", encryptedData); @@ -372,15 +356,11 @@ public static byte[] decryptPasswordBased(final String algorithm, final byte[] e /** * Creates an URL based on a directory a relative path and a filename. - * - * @param baseUrl - * Directory URL with or without slash ("/") at the end of the string - Cannot be null. - * @param path - * Relative path inside the base URL (with or without slash ("/") at the end of the string) - Can be null or an - * empty string. - * @param filename - * Filename without path - Cannot be null. - * + * + * @param baseUrl Directory URL with or without slash ("/") at the end of the string - Cannot be null. + * @param path Relative path inside the base URL (with or without slash ("/") at the end of the string) - Can be null or an + * empty string. + * @param filename Filename without path - Cannot be null. * @return URL. */ public static URL createUrl(final URL baseUrl, final String path, final String filename) { @@ -410,12 +390,9 @@ public static URL createUrl(final URL baseUrl, final String path, final String f /** * Returns a relative path based on a base directory. If the dir is not inside baseDir an * IllegalArgumentException is thrown. - * - * @param baseDir - * Base directory the path is relative to - Cannot be null. - * @param dir - * Directory inside the base directory - Cannot be null. - * + * + * @param baseDir Base directory the path is relative to - Cannot be null. + * @param dir Directory inside the base directory - Cannot be null. * @return Path of dir relative to baseDir. If both are equal an empty string is returned. */ public static String getRelativePath(final File baseDir, final File dir) { @@ -435,12 +412,9 @@ public static String getRelativePath(final File baseDir, final File dir) { /** * Checks if a given file is inside the given directory. - * - * @param dir - * Base directory - Cannot be null. - * @param file - * File - Cannot be null. - * + * + * @param dir Base directory - Cannot be null. + * @param file File - Cannot be null. * @return If the file is inside the directory TRUE, else FALSE. */ public static boolean fileInsideDirectory(final File dir, final File file) { @@ -455,10 +429,8 @@ public static boolean fileInsideDirectory(final File dir, final File file) { /** * Returns the canonical path for the file without throwing a checked exception. A potential {@link IOException} is converted into a * {@link RuntimeException} - * - * @param file - * File to return the canonical path for or null. - * + * + * @param file File to return the canonical path for or null. * @return Canonical path for the given argument or null if the input was null. */ public static String getCanonicalPath(final File file) { @@ -475,10 +447,8 @@ public static String getCanonicalPath(final File file) { /** * Returns the canonical file for the file without throwing a checked exception. A potential {@link IOException} is converted into a * {@link RuntimeException} - * - * @param file - * File to return the canonical file for or null. - * + * + * @param file File to return the canonical file for or null. * @return Canonical file for the given argument or null if the input was null. */ public static File getCanonicalFile(final File file) { @@ -499,12 +469,9 @@ public static File getCanonicalFile(final File file) { * "a/b/c" => "../../.."
* "my-dir" => ".."
* "my-dir/other/" => "../../".
- * - * @param relativePath - * Relative path to convert - Expected to be a directory and NOT a file - Cannot be NULL. - * @param fileSeparatorChar - * See {@link File#separatorChar}. - * + * + * @param relativePath Relative path to convert - Expected to be a directory and NOT a file - Cannot be NULL. + * @param fileSeparatorChar See {@link File#separatorChar}. * @return Relative path with ".." (dot dot) */ public static String getBackToRootPath(final String relativePath, final char fileSeparatorChar) { @@ -528,11 +495,9 @@ public static String getBackToRootPath(final String relativePath, final char fil /** * Checks if a variable is not null and throws an IllegalNullArgumentException if this rule is violated. - * - * @param name - * Name of the variable to be displayed in an error message. - * @param value - * Value to check for null. + * + * @param name Name of the variable to be displayed in an error message. + * @param value Value to check for null. */ public static void checkNotNull(final String name, final Object value) { if (value == null) { @@ -543,11 +508,9 @@ public static void checkNotNull(final String name, final Object value) { /** * Checks if a variable is not empty and throws an IllegalNullArgumentException if this rule is violated. A * String with spaces is NOT considered empty! - * - * @param name - * Name of the variable to be displayed in an error message. - * @param value - * Value to check for an empty String - Cannot be null. + * + * @param name Name of the variable to be displayed in an error message. + * @param value Value to check for an empty String - Cannot be null. */ public static void checkNotEmpty(final String name, final String value) { if (value.length() == 0) { @@ -557,14 +520,10 @@ public static void checkNotEmpty(final String name, final String value) { /** * Creates a textual representation of the method. - * - * @param returnType - * Return type of the method - Can be null. - * @param methodName - * Name of the method - Cannot be null. - * @param argTypes - * The list of parameters - Can be null. - * + * + * @param returnType Return type of the method - Can be null. + * @param methodName Name of the method - Cannot be null. + * @param argTypes The list of parameters - Can be null. * @return Textual signature of the method. */ private static String getMethodSignature(final String returnType, final String methodName, final Class[] argTypes) { @@ -589,20 +548,13 @@ private static String getMethodSignature(final String returnType, final String m /** * Calls a method with reflection and maps all errors into one exception. - * - * @param obj - * The object the underlying method is invoked from - Cannot be null. - * @param methodName - * Name of the Method - Cannot be null. - * @param argTypes - * The list of parameters - May be null. - * @param args - * Arguments the arguments used for the method call - May be null if "argTypes" is also null. - * + * + * @param obj The object the underlying method is invoked from - Cannot be null. + * @param methodName Name of the Method - Cannot be null. + * @param argTypes The list of parameters - May be null. + * @param args Arguments the arguments used for the method call - May be null if "argTypes" is also null. * @return The result of dispatching the method represented by this object on obj with parameters args. - * - * @throws InvokeMethodFailedException - * Invoking the method failed for some reason. + * @throws InvokeMethodFailedException Invoking the method failed for some reason. */ public static Object invoke(final Object obj, final String methodName, final Class[] argTypes, final Object[] args) throws InvokeMethodFailedException { @@ -613,11 +565,11 @@ public static Object invoke(final Object obj, final String methodName, final Cla final Class[] argTypesIntern; final Object[] argsIntern; if (argTypes == null) { - argTypesIntern = new Class[] {}; + argTypesIntern = new Class[]{}; if (args != null) { throw new IllegalArgumentException("The argument 'argTypes' is null but " + "'args' containes values!"); } - argsIntern = new Object[] {}; + argsIntern = new Object[]{}; } else { argTypesIntern = argTypes; if (args == null) { @@ -664,14 +616,10 @@ private static void checkSameLength(final Class[] argTypes, final Object[] ar /** * Unzips a file into a given directory. WARNING: Only relative path entries are allowed inside the archive! - * - * @param zipFile - * Source ZIP file - Cannot be null and must be a valid ZIP file. - * @param destDir - * Destination directory - Cannot be null and must exist. - * - * @throws IOException - * Error unzipping the file. + * + * @param zipFile Source ZIP file - Cannot be null and must be a valid ZIP file. + * @param destDir Destination directory - Cannot be null and must exist. + * @throws IOException Error unzipping the file. */ public static void unzip(final File zipFile, final File destDir) throws IOException { unzip(zipFile, destDir, null, null); @@ -679,19 +627,13 @@ public static void unzip(final File zipFile, final File destDir) throws IOExcept /** * Unzips a file into a given directory. WARNING: Only relative path entries are allowed inside the archive! - * - * @param zipFile - * Source ZIP file - Cannot be null and must be a valid ZIP file. - * @param destDir - * Destination directory - Cannot be null and must exist. - * @param wrapper - * Callback interface to give the caller the chance to wrap the ZIP input stream into another one. This is useful for example - * to display a progress bar - Can be null if no wrapping is required. - * @param cancelable - * Signals if the unzip should be canceled - Can be null if no cancel option is required. - * - * @throws IOException - * Error unzipping the file. + * + * @param zipFile Source ZIP file - Cannot be null and must be a valid ZIP file. + * @param destDir Destination directory - Cannot be null and must exist. + * @param wrapper Callback interface to give the caller the chance to wrap the ZIP input stream into another one. This is useful for example + * to display a progress bar - Can be null if no wrapping is required. + * @param cancelable Signals if the unzip should be canceled - Can be null if no cancel option is required. + * @throws IOException Error unzipping the file. */ public static void unzip(final File zipFile, final File destDir, final UnzipInputStreamWrapper wrapper, final Cancelable cancelable) throws IOException { @@ -741,7 +683,7 @@ private static void createIfNecessary(final File dir) throws IOException { /** * Returns the user home directory and checks if it is valid and exists. If not a IllegalStateException is thrown. - * + * * @return Directory. */ public static File getUserHomeDir() { @@ -765,7 +707,7 @@ public static File getUserHomeDir() { /** * Returns the temporary directory and checks if it is valid and exists. If not a IllegalStateException is thrown. - * + * * @return Directory. */ public static File getTempDir() { @@ -788,12 +730,9 @@ public static File getTempDir() { /** * Replaces all variables inside a string with values from a map. - * - * @param str - * Text with variables (Format: ${key} ) - May be null or empty. - * @param vars - * Map with key/values (both of type String - May be null. - * + * + * @param str Text with variables (Format: ${key} ) - May be null or empty. + * @param vars Map with key/values (both of type String - May be null. * @return String with replaced variables. Unknown variables will remain unchanged. */ public static String replaceVars(final String str, final Map vars) { @@ -837,9 +776,8 @@ public static String replaceVars(final String str, final Map var * Converts Date into a Windows FILETIME. The Windows FILETIME structure holds a date and time associated with a file. The structure * identifies a 64-bit integer specifying the number of 100-nanosecond intervals which have passed since January 1, 1601. This code is * copied from the org.apache.poi.hpsf.Util class. - * - * @param date - * The date to be converted - Cannot be null. + * + * @param date The date to be converted - Cannot be null. * @return The file time */ public static long dateToFileTime(final Date date) { @@ -852,43 +790,31 @@ public static long dateToFileTime(final Date date) { /** * Creates an URL Link on the Windows Desktop. This is done by creating a file (URL File Format) with an ".url" extension. For a * description see http://www.cyanwerks.com/file-format-url.html . - * - * @param baseUrl - * Base URL for the link - Cannot be null or empty. - * @param url - * Target URL - Cannot be null or empty. - * @param workingDir - * It's the "working folder" that your URL file uses. The working folder is possibly the folder to be set as the current - * folder for the application that would open the file. However Internet Explorer does not seem to be affected by this field - * - Can be null. - * @param showCommand - * Normal=null, Minimized=7, Maximized=3 - * @param iconIndex - * The Icon Index within the icon library specified by IconFile. In an icon library, which can be generally be either a ICO, - * DLL or EXE file, the icons are indexed with numbers. The first icon index starts at 0 - Can be null if the - * file is not indexed. - * @param iconFile - * Specifies the path of the icon library file. Generally the icon library can be an ICO, DLL or EXE file. The default icon - * library used tends to be the URL.DLL library on the system's Windows\System directory - Can be null if no - * icon is required. - * @param hotKey - * The HotKey field specifies what is the shortcut key used to automatically launch the Internet shortcut. The field uses a - * number to specify what hotkey is used. To get the appropriate code simply create a shortcut with MSIE and examine the - * file's content. - * @param linkFilenameWithoutExtension - * Name for the link file (displayed as text) - Cannot be null or empty. - * @param overwrite - * Overwrite an existing ".url" file. - * @param modified - * Timestamp. - * - * @throws IOException - * Error writing the file. + * + * @param baseUrl Base URL for the link - Cannot be null or empty. + * @param url Target URL - Cannot be null or empty. + * @param workingDir It's the "working folder" that your URL file uses. The working folder is possibly the folder to be set as the current + * folder for the application that would open the file. However Internet Explorer does not seem to be affected by this field + * - Can be null. + * @param showCommand Normal=null, Minimized=7, Maximized=3 + * @param iconIndex The Icon Index within the icon library specified by IconFile. In an icon library, which can be generally be either a ICO, + * DLL or EXE file, the icons are indexed with numbers. The first icon index starts at 0 - Can be null if the + * file is not indexed. + * @param iconFile Specifies the path of the icon library file. Generally the icon library can be an ICO, DLL or EXE file. The default icon + * library used tends to be the URL.DLL library on the system's Windows\System directory - Can be null if no + * icon is required. + * @param hotKey The HotKey field specifies what is the shortcut key used to automatically launch the Internet shortcut. The field uses a + * number to specify what hotkey is used. To get the appropriate code simply create a shortcut with MSIE and examine the + * file's content. + * @param linkFilenameWithoutExtension Name for the link file (displayed as text) - Cannot be null or empty. + * @param overwrite Overwrite an existing ".url" file. + * @param modified Timestamp. + * @throws IOException Error writing the file. */ // CHECKSTYLE:OFF Maximum Parameters public static void createWindowsDesktopUrlLink(final String baseUrl, final String url, final File workingDir, final Integer showCommand, - final Integer iconIndex, final File iconFile, final Integer hotKey, final String linkFilenameWithoutExtension, - final boolean overwrite, final Date modified) throws IOException { + final Integer iconIndex, final File iconFile, final Integer hotKey, final String linkFilenameWithoutExtension, + final boolean overwrite, final Date modified) throws IOException { // CHECKSTYLE:ON checkNotNull("baseUrl", baseUrl); @@ -916,37 +842,28 @@ public static void createWindowsDesktopUrlLink(final String baseUrl, final Strin /** * Creates the content of an URL Link file (.url) on the Windows Desktop. For a description see * http://www.cyanwerks.com/file-format-url.html . - * - * @param baseUrl - * Base URL for the link - Cannot be null or empty. - * @param url - * Target URL - Cannot be null or empty. - * @param workingDir - * It's the "working folder" that your URL file uses. The working folder is possibly the folder to be set as the current - * folder for the application that would open the file. However Internet Explorer does not seem to be affected by this field - * - Can be null. - * @param showCommand - * Normal=null, Minimized=7, Maximized=3 - * @param iconIndex - * The Icon Index within the icon library specified by IconFile. In an icon library, which can be generally be either a ICO, - * DLL or EXE file, the icons are indexed with numbers. The first icon index starts at 0 - Can be null if the - * file is not indexed. - * @param iconFile - * Specifies the path of the icon library file. Generally the icon library can be an ICO, DLL or EXE file. The default icon - * library used tends to be the URL.DLL library on the system's Windows\System directory - Can be null if no - * icon is required. - * @param hotKey - * The HotKey field specifies what is the shortcut key used to automatically launch the Internet shortcut. The field uses a - * number to specify what hotkey is used. To get the appropriate code simply create a shortcut with MSIE and examine the - * file's content. - * @param modified - * Timestamp. - * + * + * @param baseUrl Base URL for the link - Cannot be null or empty. + * @param url Target URL - Cannot be null or empty. + * @param workingDir It's the "working folder" that your URL file uses. The working folder is possibly the folder to be set as the current + * folder for the application that would open the file. However Internet Explorer does not seem to be affected by this field + * - Can be null. + * @param showCommand Normal=null, Minimized=7, Maximized=3 + * @param iconIndex The Icon Index within the icon library specified by IconFile. In an icon library, which can be generally be either a ICO, + * DLL or EXE file, the icons are indexed with numbers. The first icon index starts at 0 - Can be null if the + * file is not indexed. + * @param iconFile Specifies the path of the icon library file. Generally the icon library can be an ICO, DLL or EXE file. The default icon + * library used tends to be the URL.DLL library on the system's Windows\System directory - Can be null if no + * icon is required. + * @param hotKey The HotKey field specifies what is the shortcut key used to automatically launch the Internet shortcut. The field uses a + * number to specify what hotkey is used. To get the appropriate code simply create a shortcut with MSIE and examine the + * file's content. + * @param modified Timestamp. * @return INI file text. */ // CHECKSTYLE:OFF public static String createWindowsDesktopUrlLinkContent(final String baseUrl, final String url, final File workingDir, - final Integer showCommand, final Integer iconIndex, final File iconFile, final Integer hotKey, final Date modified) { + final Integer showCommand, final Integer iconIndex, final File iconFile, final Integer hotKey, final Date modified) { // CHECKSTYLE:ON checkNotNull("baseUrl", baseUrl); @@ -983,14 +900,10 @@ public static String createWindowsDesktopUrlLinkContent(final String baseUrl, fi /** * Concatenate a path and a filename taking null and empty string values into account. - * - * @param path - * Path - Can be null or an empty string. - * @param filename - * Filename - Cannot be null. - * @param separator - * Separator for directories - Can be null or an empty string. - * + * + * @param path Path - Can be null or an empty string. + * @param filename Filename - Cannot be null. + * @param separator Separator for directories - Can be null or an empty string. * @return Path and filename divided by the separator. */ public static String concatPathAndFilename(final String path, final String filename, final String separator) { @@ -1017,12 +930,10 @@ public static String concatPathAndFilename(final String path, final String filen /** * Converts an array of bytes into an array of characters representing the hexidecimal values of each byte in order. The returned array * will be double the length of the passed array, as it takes two characters to represent any given byte. - * + *

* Author: Apache Software Foundation See: org.apache.commons.codec.binary.Hex - * - * @param data - * A byte[] to convert to Hex characters - Cannot be null. - * + * + * @param data A byte[] to convert to Hex characters - Cannot be null. * @return A string containing hexidecimal characters */ // CHECKSTYLE:OFF Orginal Apache code @@ -1047,13 +958,11 @@ public static String encodeHex(final byte[] data) { * Converts an array of characters representing hexidecimal values into an array of bytes of those same values. The returned array will * be half the length of the passed array, as it takes two characters to represent any given byte. An exception is thrown if the passed * char array has an odd number of elements. - * - * @param data - * An array of characters containing hexidecimal digits - Cannot be null. - * + * + * @param data An array of characters containing hexidecimal digits - Cannot be null. * @return A byte array containing binary data decoded from the supplied char array. - * - * Author: Apache Software Foundation See: org.apache.commons.codec.binary.Hex + *

+ * Author: Apache Software Foundation See: org.apache.commons.codec.binary.Hex */ // CHECKSTYLE:OFF Orginal Apache code public static byte[] decodeHex(final String data) { @@ -1084,13 +993,10 @@ public static byte[] decodeHex(final String data) { /** * Converts a hexadecimal character to an integer. - * - * @param ch - * A character to convert to an integer digit - * @param index - * The index of the character in the source + * + * @param ch A character to convert to an integer digit + * @param index The index of the character in the source * @return An integer - * * @author Apache Software Foundation * @see org.apache.commons.codec.binary.Hex */ @@ -1104,18 +1010,12 @@ private static int toDigit(final char ch, final int index) { /** * Lock the file. - * - * @param file - * File to lock - Cannot be null. - * @param tryLockMax - * Number of tries to lock before throwing an exception. - * @param tryWaitMillis - * Milliseconds to sleep between retries. - * + * + * @param file File to lock - Cannot be null. + * @param tryLockMax Number of tries to lock before throwing an exception. + * @param tryWaitMillis Milliseconds to sleep between retries. * @return FileLock. - * - * @throws LockingFailedException - * Locking the file failed. + * @throws LockingFailedException Locking the file failed. */ public static FileLock lockRandomAccessFile(final RandomAccessFile file, final int tryLockMax, final long tryWaitMillis) throws LockingFailedException { @@ -1153,16 +1053,11 @@ private static void ignore() { /** * Adds a file to a ZIP output stream. - * - * @param srcFile - * File to add - Cannot be null. - * @param destPath - * Path to use for the file - May be null or empty. - * @param out - * Destination stream - Cannot be null. - * - * @throws IOException - * Error writing to the output stream. + * + * @param srcFile File to add - Cannot be null. + * @param destPath Path to use for the file - May be null or empty. + * @param out Destination stream - Cannot be null. + * @throws IOException Error writing to the output stream. */ private static void zipFile(final File srcFile, final String destPath, final ZipOutputStream out) throws IOException { @@ -1181,12 +1076,9 @@ private static void zipFile(final File srcFile, final String destPath, final Zip /** * List all files for a directory. - * - * @param srcDir - * Directory to list the files for - Cannot be null and must be a valid directory. - * @param filter - * Filter or null for all files. - * + * + * @param srcDir Directory to list the files for - Cannot be null and must be a valid directory. + * @param filter Filter or null for all files. * @return List of child entries of the directory. */ private static File[] listFiles(final File srcDir, final FileFilter filter) { @@ -1203,18 +1095,12 @@ private static File[] listFiles(final File srcDir, final FileFilter filter) { /** * Add a directory to a ZIP output stream. - * - * @param srcDir - * Directory to add - Cannot be null and must be a valid directory. - * @param filter - * Filter or null for all files. - * @param destPath - * Path to use for the ZIP archive - May be null or an empyt string. - * @param out - * Destination stream - Cannot be null. - * - * @throws IOException - * Error writing to the output stream. + * + * @param srcDir Directory to add - Cannot be null and must be a valid directory. + * @param filter Filter or null for all files. + * @param destPath Path to use for the ZIP archive - May be null or an empyt string. + * @param out Destination stream - Cannot be null. + * @throws IOException Error writing to the output stream. */ private static void zipDir(final File srcDir, final FileFilter filter, final String destPath, final ZipOutputStream out) throws IOException { @@ -1233,18 +1119,12 @@ private static void zipDir(final File srcDir, final FileFilter filter, final Str /** * Creates a ZIP file and adds all files in a directory and all it's sub directories to the archive. Only entries are added that comply * to the file filter. - * - * @param srcDir - * Directory to add - Cannot be null and must be a valid directory. - * @param filter - * Filter or null for all files/directories. - * @param destPath - * Path to use for the ZIP archive - May be null or an empyt string. - * @param destFile - * Target ZIP file - Cannot be null. - * - * @throws IOException - * Error writing to the output stream. + * + * @param srcDir Directory to add - Cannot be null and must be a valid directory. + * @param filter Filter or null for all files/directories. + * @param destPath Path to use for the ZIP archive - May be null or an empyt string. + * @param destFile Target ZIP file - Cannot be null. + * @throws IOException Error writing to the output stream. */ public static void zipDir(final File srcDir, final FileFilter filter, final String destPath, final File destFile) throws IOException { @@ -1260,16 +1140,11 @@ public static void zipDir(final File srcDir, final FileFilter filter, final Stri /** * Creates a ZIP file and adds all files in a directory and all it's sub directories to the archive. - * - * @param srcDir - * Directory to add - Cannot be null and must be a valid directory. - * @param destPath - * Path to use for the ZIP archive - May be null or an empyt string. - * @param destFile - * Target ZIP file - Cannot be null. - * - * @throws IOException - * Error writing to the output stream. + * + * @param srcDir Directory to add - Cannot be null and must be a valid directory. + * @param destPath Path to use for the ZIP archive - May be null or an empyt string. + * @param destFile Target ZIP file - Cannot be null. + * @throws IOException Error writing to the output stream. */ public static void zipDir(final File srcDir, final String destPath, final File destFile) throws IOException { @@ -1279,10 +1154,8 @@ public static void zipDir(final File srcDir, final String destPath, final File d /** * Serializes the given object. A null argument returns null. - * - * @param obj - * Object to serialize or null. - * + * + * @param obj Object to serialize or null. * @return Serialized object or null. */ public static byte[] serialize(final Object obj) { @@ -1300,14 +1173,10 @@ public static byte[] serialize(final Object obj) { /** * Deserializes a byte array to an object. A null argument returns null. - * - * @param data - * Byte array to deserialize or null. - * + * + * @param data Byte array to deserialize or null. + * @param Type of returned data. * @return Object created from data or null. - * - * @param - * Type of returned data. */ @SuppressWarnings("unchecked") public static T deserialize(final byte[] data) { @@ -1324,14 +1193,10 @@ public static T deserialize(final byte[] data) { /** * Reads a given URL and returns the content as String. - * - * @param url - * URL to read. - * @param encoding - * Encoding (like 'utf-8'). - * @param bufSize - * Size of the buffer to use. - * + * + * @param url URL to read. + * @param encoding Encoding (like 'utf-8'). + * @param bufSize Size of the buffer to use. * @return File content as String. */ public static String readAsString(final URL url, final String encoding, final int bufSize) { @@ -1350,10 +1215,8 @@ public static String readAsString(final URL url, final String encoding, final in /** * Returns a given string as URL and supports "classpath:" scheme. A null argument returns null. - * - * @param url - * String to convert into an URL or null. - * + * + * @param url String to convert into an URL or null. * @return URL or null */ public static URL url(final String url) { @@ -1372,10 +1235,8 @@ public static URL url(final String url) { /** * Replaces the strings "\r", "\n" and "\t" with "carriage return", "new line" and "tab" character. - * - * @param str - * String to replace or null. - * + * + * @param str String to replace or null. * @return Replaced string or null. */ public static String replaceCrLfTab(final String str) { @@ -1411,9 +1272,8 @@ public static String replaceCrLfTab(final String str) { * Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the * precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors. The * {@link InterruptedException} is wrapped into a {@link RuntimeException}. - * - * @param millis - * The length of time to sleep in milliseconds. + * + * @param millis The length of time to sleep in milliseconds. */ public static void sleep(final long millis) { try { @@ -1425,12 +1285,9 @@ public static void sleep(final long millis) { /** * Verifies if the cause of an exception is of a given type. - * - * @param actualException - * Actual exception that was caused by something else - Cannot be null. - * @param expectedExceptions - * Expected exceptions - May be null if any cause is expected. - * + * + * @param actualException Actual exception that was caused by something else - Cannot be null. + * @param expectedExceptions Expected exceptions - May be null if any cause is expected. * @return TRUE if the actual exception is one of the expected exceptions. */ public static boolean expectedCause(final Exception actualException, final Collection> expectedExceptions) { @@ -1454,16 +1311,13 @@ public static boolean expectedCause(final Exception actualException, final Colle /** * Verifies if an exception is of a given type. - * - * @param actualException - * Actual exception - Cannot be null. - * @param expectedExceptions - * Expected exceptions - May be null if any exception is expected. - * + * + * @param actualException Actual exception - Cannot be null. + * @param expectedExceptions Expected exceptions - May be null if any exception is expected. * @return TRUE if the actual exception is one of the expected exceptions. */ public static boolean expectedException(final Exception actualException, - final Collection> expectedExceptions) { + final Collection> expectedExceptions) { checkNotNull("actualException", actualException); @@ -1484,10 +1338,8 @@ public static boolean expectedException(final Exception actualException, /** * Determines if the file is a file from the Java runtime and exists. - * - * @param file - * File to test. - * + * + * @param file File to test. * @return TRUE if the file is in the 'java.home' directory. */ public static boolean jreFile(final File file) { @@ -1501,10 +1353,8 @@ public static boolean jreFile(final File file) { /** * Determines if the file is a class file. - * - * @param file - * File to test. - * + * + * @param file File to test. * @return TRUE if the file ends with '.class'. */ public static boolean classFile(final File file) { @@ -1513,10 +1363,8 @@ public static boolean classFile(final File file) { /** * Determines if the file is a JAR file. - * - * @param file - * File to test. - * + * + * @param file File to test. * @return TRUE if the file ends with '.jar'. */ public static boolean jarFile(final File file) { @@ -1525,10 +1373,8 @@ public static boolean jarFile(final File file) { /** * Determines if the file is a JAR file not located in the JRE directory. - * - * @param file - * File to test. - * + * + * @param file File to test. * @return TRUE if the file ends with '.jar' and is not located in the 'java.home' directory. */ public static boolean nonJreJarFile(final File file) { @@ -1537,10 +1383,8 @@ public static boolean nonJreJarFile(final File file) { /** * Determines if the file is a JAR file located in the JRE directory. - * - * @param file - * File to test. - * + * + * @param file File to test. * @return TRUE if the file ends with '.jar' and is located in the 'java.home' directory. */ public static boolean jreJarFile(final File file) { @@ -1549,10 +1393,8 @@ public static boolean jreJarFile(final File file) { /** * Returns a list of filtered files from the classpath including content of directories and sub directories. - * - * @param predicate - * Condition that returns files from the classpath. - * + * + * @param predicate Condition that returns files from the classpath. * @return List of files in the classpath (from property "java.class.path"). */ public static List classpathFiles(final Predicate predicate) { @@ -1562,7 +1404,7 @@ public static List classpathFiles(final Predicate predicate) { /** * Returns a list of all files from the classpath. Only returns the files itself and no files in directories. - * + * * @return List of files in the classpath (from property "java.class.path"). */ public static List classpathFiles() { @@ -1577,11 +1419,8 @@ public static List classpathFiles() { /** * Returns a list of files from all given paths. * - * @param paths - * Paths to search (Paths separated by {@link File#pathSeparator}. - * @param predicate - * Condition for files to return. - * + * @param paths Paths to search (Paths separated by {@link File#pathSeparator}. + * @param predicate Condition for files to return. * @return List of files in the given paths. */ public static List pathsFiles(final String paths, final Predicate predicate) { @@ -1610,14 +1449,10 @@ public static interface UnzipInputStreamWrapper { /** * Wraps the input stream into another one. - * - * @param in - * Stream to create a wrapping stream for. - * @param entry - * Zip entry the input stream is reading. - * @param destFile - * Destination file. - * + * + * @param in Stream to create a wrapping stream for. + * @param entry Zip entry the input stream is reading. + * @param destFile Destination file. * @return Wrapped input stream. */ public InputStream wrapInputStream(InputStream in, ZipEntry entry, File destFile); @@ -1628,7 +1463,6 @@ public static interface UnzipInputStreamWrapper { * Loads the class using the current thread's context class loader. * * @param name Name of the class to load. - * * @return Loaded class. */ public static Class loadClass(String name) { @@ -1642,12 +1476,9 @@ public static Class loadClass(String name) { /** * Sets a private field in an object by using reflection. * - * @param obj - * Object with the attribute to set. - * @param name - * Name of the attribute to set. - * @param value - * Value to set for the attribute. + * @param obj Object with the attribute to set. + * @param name Name of the attribute to set. + * @param value Value to set for the attribute. */ public static void setPrivateField(final Object obj, final String name, final Object value) { try { @@ -1659,4 +1490,49 @@ public static void setPrivateField(final Object obj, final String name, final Ob } } + /** + * Tries to acquire a lock and runs the code. If no lock can be acquired, the method + * terminates immediately without executing anything. + * + * @param lock Semaphore to use. Must be a {@literal null} value. + * @param code Code to run. Must be a {@literal null} value. + */ + public static void tryLocked(final Semaphore lock, final Runnable code) { + Objects.requireNonNull(lock, "lock==null"); + Objects.requireNonNull(code, "code==null"); + if (lock.tryAcquire()) { + try { + code.run(); + } finally { + lock.release(); + } + } + } + + /** + * Waits until a lock is available and executes the code after it was acquired. + * + * @param lock Semaphore to use. Must be a {@literal null} value. + * @param code Code to run. Must be a {@literal null} value. + * @param failedToLockListener Gets informed in case it was not possible to get a lock. May be {@literal null}. + */ + public static void runLocked(final Semaphore lock, + final Runnable code, + final Consumer failedToLockListener) { + Objects.requireNonNull(lock, "lock==null"); + Objects.requireNonNull(code, "code==null"); + try { + lock.acquire(); + try { + code.run(); + } finally { + lock.release(); + } + } catch (final InterruptedException ex) { // NOSONAR + if (failedToLockListener != null) { + failedToLockListener.accept(ex); + } + } + } + } diff --git a/src/test/java/org/fuin/utils4j/Utils4JTest.java b/src/test/java/org/fuin/utils4j/Utils4JTest.java index 85ac80c..fbb1714 100644 --- a/src/test/java/org/fuin/utils4j/Utils4JTest.java +++ b/src/test/java/org/fuin/utils4j/Utils4JTest.java @@ -1,5 +1,5 @@ /** - * Copyright (C) 2015 Michael Schnell. All rights reserved. + * Copyright (C) 2015 Michael Schnell. All rights reserved. * http://www.fuin.org/ * * This library is free software; you can redistribute it and/or modify it under @@ -11,7 +11,7 @@ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see http://www.gnu.org/licenses/. */ @@ -29,10 +29,21 @@ import java.net.MalformedURLException; import java.net.URL; import java.nio.channels.FileLock; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.AssertionsKt.fail; /** * Tests for Utils4J. @@ -211,7 +222,7 @@ public final void testCreateInstanceIllegalAccess() { @Test public final void testContainsURL() throws IOException { - final URL[] urls = new URL[] { new URL("http://www.google.com"), new URL("http://www.yahoo.com"), new URL("file:/foobar.txt") }; + final URL[] urls = new URL[]{new URL("http://www.google.com"), new URL("http://www.yahoo.com"), new URL("file:/foobar.txt")}; assertThat(Utils4J.containsURL(urls, new URL("http://www.google.com"))).isTrue(); assertThat(Utils4J.containsURL(urls, new URL("http://www.google.com/"))).isFalse(); assertThat(Utils4J.containsURL(urls, new URL("http://www.abc.com"))).isFalse(); @@ -298,14 +309,14 @@ public final void testCheckNotEmptyFail() { @Test public final void testInvokeOK() throws InvokeMethodFailedException { - assertThat(Utils4J.invoke(new IllegalNullArgumentException("abc"), "getArgument", new Class[] {}, new Object[] {})) + assertThat(Utils4J.invoke(new IllegalNullArgumentException("abc"), "getArgument", new Class[]{}, new Object[]{})) .isEqualTo("abc"); } @Test public final void testInvokeFail() throws InvokeMethodFailedException { assertThatThrownBy(() -> { - Utils4J.invoke(new IllegalNullArgumentException("abc"), "getArgument", new Class[] { String.class }, new Object[] { "" }); + Utils4J.invoke(new IllegalNullArgumentException("abc"), "getArgument", new Class[]{String.class}, new Object[]{""}); }).isInstanceOf(InvokeMethodFailedException.class); } @@ -524,8 +535,8 @@ public final void testEncryptDecryptPasswordBased() { final String str1 = "This is a secret text 1234567890-ÄÖÜäöüß"; final byte[] data1 = str1.getBytes(); final char[] password = "MyVerySecretPw!".toCharArray(); - final byte[] salt = new byte[] { (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c, (byte) 0x7e, (byte) 0xc8, (byte) 0xee, - (byte) 0x99 }; + final byte[] salt = new byte[]{(byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c, (byte) 0x7e, (byte) 0xc8, (byte) 0xee, + (byte) 0x99}; final int count = 100; final byte[] encrypted = Utils4J.encryptPasswordBased(algorithm, data1, password, salt, count); @@ -670,7 +681,7 @@ private static class ExceptionContainer { /** * Create a runnable that locks the file. - * + * * @param file * File to lock. * @param ec @@ -681,11 +692,11 @@ private static class ExceptionContainer { * Milliseconds to sleep between retries. * @param sleepMillis * Number of milliseconds to hold the lock. - * + * * @return New runnable instance. */ private Runnable createLockRunnable(final File file, final ExceptionContainer ec, final int tryLockMax, final long tryWaitMillis, - final long sleepMillis) { + final long sleepMillis) { return new Runnable() { @Override public void run() { @@ -711,7 +722,7 @@ public void run() { /** * Start the two threads and wait until both finished. - * + * * @param thread1 * First thread. * @param thread2 @@ -903,6 +914,90 @@ public final void testSetPrivateField() { } + @Test + public final void testTryLockedOK() { + + // PREPARE + final Semaphore semaphore = new Semaphore(1); + final AtomicBoolean executed = new AtomicBoolean(); + + // TEST + Utils4J.tryLocked(semaphore, () -> executed.set(true)); + + // VERIFY + assertThat(executed.get()).isTrue(); + + } + + + @Test + public final void testTryLockedFails() { + + // PREPARE + final Semaphore semaphore = new Semaphore(1); + final AtomicBoolean executed = new AtomicBoolean(); + + Utils4J.runLocked(semaphore, () -> { + + // TEST + Utils4J.tryLocked(semaphore, () -> executed.set(true)); + + // VERIFY + assertThat(executed.get()).isFalse(); + + }, ex -> fail("First lock is not expected to fail", ex)); + + } + + @Test + public final void testRunLockedOK() { + + // PREPARE + final Semaphore semaphore = new Semaphore(1); + final AtomicBoolean executed = new AtomicBoolean(); + + // TEST + Utils4J.runLocked(semaphore, () -> executed.set(true), ex -> fail("Lock is not expected to fail", ex)); + + // VERIFY + assertThat(executed.get()).isTrue(); + + } + + + @Test + public final void testRunLockedFails() { + + // PREPARE + final List executionOrder = Collections.synchronizedList(new ArrayList<>()); + final Semaphore semaphore = new Semaphore(1); + final AtomicReference firstFailed = new AtomicReference<>(); + final Thread t1 = new Thread(() -> { + Utils4J.runLocked(semaphore, () -> { + executionOrder.add("1A"); + Utils4J.sleep(2000); + executionOrder.add("1B"); + }, firstFailed::set); + }); + t1.start(); + + final AtomicBoolean secondExecuted = new AtomicBoolean(); + final AtomicReference secondFailed = new AtomicReference<>(); + + // TEST + Utils4J.sleep(1000); // Wait until 1st thread started + executionOrder.add("2A"); + Utils4J.runLocked(semaphore, () -> secondExecuted.set(true), secondFailed::set); + executionOrder.add("2B"); + + // VERIFY + assertThat(firstFailed.get()).isNull(); + assertThat(secondFailed.get()).isNull(); + assertThat(secondExecuted.get()).isTrue(); + assertThat(executionOrder).containsExactly("1A", "2A", "1B", "2B"); + + } + private static class MyTestClass { private String name; From bb56b2a92953707217dc76447447662521d40178 Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Tue, 1 Apr 2025 11:21:18 +0200 Subject: [PATCH 18/22] Updated dependencies --- pom.xml | 24 ++++++++++++------- src/main/java/org/fuin/utils4j/Utils4J.java | 4 +++- .../utils4j/jandex/JandexIndexFileReader.java | 4 ++++ .../java/org/fuin/utils4j/jaxb/JaxbUtils.java | 10 ++++++++ .../java/org/fuin/utils4j/Utils4JTest.java | 8 +++++-- 5 files changed, 39 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index 8a05b56..ef239a8 100644 --- a/pom.xml +++ b/pom.xml @@ -40,14 +40,14 @@ io.smallrye jandex - 3.1.6 + 3.2.7 true jakarta.xml.bind jakarta.xml.bind-api - 4.0.1 + 4.0.2 true @@ -56,42 +56,42 @@ org.junit.jupiter junit-jupiter - 5.10.2 + 5.12.1 test org.assertj assertj-core - 3.25.3 + 3.27.3 test nl.jqno.equalsverifier equalsverifier - 3.15.6 + 3.19.2 test org.xmlunit xmlunit-core - 2.9.1 + 2.10.0 test commons-io commons-io - 2.15.1 + 2.18.0 test org.glassfish.jaxb jaxb-runtime - 4.0.4 + 4.0.5 test @@ -111,6 +111,14 @@ maven-source-plugin + + org.apache.maven.plugins + maven-surefire-plugin + + ${argLine} -Duser.language=en -Duser.region=US + + + org.apache.maven.plugins maven-javadoc-plugin diff --git a/src/main/java/org/fuin/utils4j/Utils4J.java b/src/main/java/org/fuin/utils4j/Utils4J.java index 7ae59e4..11be3fe 100644 --- a/src/main/java/org/fuin/utils4j/Utils4J.java +++ b/src/main/java/org/fuin/utils4j/Utils4J.java @@ -1429,13 +1429,15 @@ public static List pathsFiles(final String paths, final Predicate pr final File file = new File(filePathAndName); if (file.isDirectory()) { try (final Stream stream = Files.walk(file.toPath(), Integer.MAX_VALUE)) { - stream.map(f -> f.toFile()).filter(predicate).forEach(files::add); + stream.map(Path::toFile).filter(predicate).forEach(files::add); } catch (final IOException ex) { throw new RuntimeException("Error walking path: " + file, ex); } } else { if (predicate.test(file)) { files.add(file); + } else { + System.err.println("Ignoring file: " + file); } } } diff --git a/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileReader.java b/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileReader.java index c8bed2a..ae3c217 100644 --- a/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileReader.java +++ b/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileReader.java @@ -127,6 +127,8 @@ public Builder addDefaultResource() { /** * Adds one or more resources. * + * @param resources Array with resources to add. + * * @return Builder. */ public Builder addResources(final String...resources) { @@ -136,6 +138,8 @@ public Builder addResources(final String...resources) { /** * Adds one or more resources. * + * @param resources List of resources to add. + * * @return Builder. */ public Builder addResources(final List resources) { diff --git a/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java b/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java index b42763f..270aabd 100644 --- a/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java +++ b/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java @@ -55,6 +55,7 @@ private JaxbUtils() { * Type of the data. * @deprecated Use method {@link #marshal(Marshaller, Object)} together with {@link MarshallerBuilder} instead */ + @Deprecated public static String marshal(final T data, final Class... classesToBeBound) { return marshal(data, null, classesToBeBound); } @@ -75,6 +76,7 @@ public static String marshal(final T data, final Class... classesToBeBoun * Type of the data. * @deprecated Use method {@link #marshal(Marshaller, Object)} together with {@link MarshallerBuilder} instead */ + @Deprecated public static String marshal(final T data, final XmlAdapter[] adapters, final Class... classesToBeBound) { if (data == null) { return null; @@ -101,6 +103,7 @@ public static String marshal(final T data, final XmlAdapter[] adapters * Type of the data. * @deprecated Use method {@link #marshal(Marshaller, Object)} together with {@link MarshallerBuilder} instead */ + @Deprecated public static String marshal(final JAXBContext ctx, final T data) { return marshal(ctx, data, null); } @@ -121,6 +124,7 @@ public static String marshal(final JAXBContext ctx, final T data) { * Type of the data. * @deprecated Use method {@link #marshal(Marshaller, Object)} together with {@link MarshallerBuilder} instead */ + @Deprecated public static String marshal(final JAXBContext ctx, final T data, final XmlAdapter[] adapters) { if (data == null) { return null; @@ -146,6 +150,7 @@ public static String marshal(final JAXBContext ctx, final T data, final XmlA * Type of the data to write. * @deprecated Use method {@link #marshal(Marshaller, Object, Writer)} together with {@link MarshallerBuilder} instead */ + @Deprecated public static void marshal(final JAXBContext ctx, final T data, final XmlAdapter[] adapters, final Writer writer) { if (data == null) { return; @@ -179,6 +184,7 @@ public static void marshal(final JAXBContext ctx, final T data, final XmlAda * Type of the data to write. * @deprecated Use method {@link #marshal(Marshaller, Object, XMLStreamWriter)} together with {@link MarshallerBuilder} instead */ + @Deprecated public static void marshal(final JAXBContext ctx, final T data, final XmlAdapter[] adapters, final XMLStreamWriter writer) { if (data == null) { return; @@ -211,6 +217,7 @@ public static void marshal(final JAXBContext ctx, final T data, final XmlAda * * @deprecated Use method {@link #unmarshal(Unmarshaller, String)} together with {@link UnmarshallerBuilder} instead */ + @Deprecated public static T unmarshal(final String xmlData, final Class... classesToBeBound) { final UnmarshallerBuilder builder = new UnmarshallerBuilder(); if (classesToBeBound != null) { @@ -237,6 +244,7 @@ public static T unmarshal(final String xmlData, final Class... classesToB * * @deprecated Use method {@link #unmarshal(Unmarshaller, String)} together with {@link UnmarshallerBuilder} instead */ + @Deprecated public static T unmarshal(final String xmlData, final XmlAdapter[] adapters, final Class... classesToBeBound) { final UnmarshallerBuilder builder = new UnmarshallerBuilder(); if (classesToBeBound != null) { @@ -264,6 +272,7 @@ public static T unmarshal(final String xmlData, final XmlAdapter[] ada * * @deprecated Use method {@link #unmarshal(Unmarshaller, String)} together with {@link UnmarshallerBuilder} instead */ + @Deprecated public static T unmarshal(final JAXBContext ctx, final String xmlData, final XmlAdapter[] adapters) { final UnmarshallerBuilder builder = new UnmarshallerBuilder().withContext(ctx); if (adapters != null) { @@ -290,6 +299,7 @@ public static T unmarshal(final JAXBContext ctx, final String xmlData, final * * @deprecated Use method {@link #unmarshal(Unmarshaller, Reader)} together with {@link UnmarshallerBuilder} instead */ + @Deprecated public static T unmarshal(final JAXBContext ctx, final Reader reader, final XmlAdapter[] adapters) { final UnmarshallerBuilder builder = new UnmarshallerBuilder().withContext(ctx); if (adapters != null) { diff --git a/src/test/java/org/fuin/utils4j/Utils4JTest.java b/src/test/java/org/fuin/utils4j/Utils4JTest.java index fbb1714..8893331 100644 --- a/src/test/java/org/fuin/utils4j/Utils4JTest.java +++ b/src/test/java/org/fuin/utils4j/Utils4JTest.java @@ -869,10 +869,14 @@ public void testClasspathFilesPredicate() throws IOException { } @Test - public void testPathsFiles() { + public void testPathsFiles() throws IOException { final File javaHomeDir = new File(System.getProperty("java.home")); - final List bootJarFiles = Utils4J.pathsFiles(System.getProperty("sun.boot.library.path"), Utils4J::jreJarFile); + String path = System.getProperty("sun.boot.library.path"); + if (path.endsWith("bin")) { + path = path.substring(0, path.length() - 4) + File.separator + "lib"; + } + final List bootJarFiles = Utils4J.pathsFiles(path, Utils4J::jreJarFile); final File rtJar = new File(javaHomeDir, "lib/jrt-fs.jar"); assertThat(bootJarFiles).contains(rtJar); From fbf5e7dfdb682efbc8fdfd27a4ad8622c4d6e58a Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Tue, 1 Apr 2025 16:25:54 +0200 Subject: [PATCH 19/22] Fixed Sonar issues --- .../org/fuin/utils4j/jandex/JandexIndexFileReader.java | 4 ++-- .../org/fuin/utils4j/jandex/JandexIndexFileWriter.java | 5 ----- src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java | 8 ++++---- .../java/org/fuin/utils4j/jaxb/MarshallerBuilder.java | 2 -- .../org/fuin/utils4j/fileprocessor/FileProcessorTest.java | 1 - .../fuin/utils4j/jandex/JandexIndexFileReaderTest.java | 2 -- .../fuin/utils4j/jandex/JandexIndexFileWriterTest.java | 2 -- .../java/org/fuin/utils4j/jandex/JandexUtilsTest.java | 2 -- .../java/org/fuin/utils4j/jaxb/MarshallerBuilderTest.java | 4 ++-- 9 files changed, 8 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileReader.java b/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileReader.java index ae3c217..7747983 100644 --- a/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileReader.java +++ b/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileReader.java @@ -62,8 +62,8 @@ private IndexView loadFile(final File file) throws IOException { private IndexView loadResources(final String indexFilePathAndName) throws IOException { final Enumeration enu = Thread.currentThread().getContextClassLoader().getResources(indexFilePathAndName); final List indexes = new ArrayList<>(); - final List resources = Collections.list(enu); - for (final URL url : resources) { + final List urlList = Collections.list(enu); + for (final URL url : urlList) { try (final InputStream input = url.openStream()) { indexes.add(new IndexReader(input).read()); } diff --git a/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileWriter.java b/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileWriter.java index 5302843..98c8239 100644 --- a/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileWriter.java +++ b/src/main/java/org/fuin/utils4j/jandex/JandexIndexFileWriter.java @@ -3,11 +3,6 @@ import org.jboss.jandex.*; import java.io.*; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; /** * Helps to write Jandex index files. diff --git a/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java b/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java index 270aabd..9c4653c 100644 --- a/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java +++ b/src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java @@ -223,7 +223,7 @@ public static T unmarshal(final String xmlData, final Class... classesToB if (classesToBeBound != null) { builder.addClassesToBeBound(classesToBeBound); } - builder.withHandler(event -> { return false; }); + builder.withHandler(event -> false); return unmarshal(builder.build(), xmlData); } @@ -251,7 +251,7 @@ public static T unmarshal(final String xmlData, final XmlAdapter[] ada builder.addClassesToBeBound(classesToBeBound); } builder.addAdapters(adapters); - builder.withHandler(event -> { return false; }); + builder.withHandler(event -> false); return unmarshal(builder.build(), xmlData); } @@ -278,7 +278,7 @@ public static T unmarshal(final JAXBContext ctx, final String xmlData, final if (adapters != null) { builder.addAdapters(adapters); } - builder.withHandler(event -> { return false; }); + builder.withHandler(event -> false); return unmarshal(builder.build(), xmlData); } @@ -305,7 +305,7 @@ public static T unmarshal(final JAXBContext ctx, final Reader reader, final if (adapters != null) { builder.addAdapters(adapters); } - builder.withHandler(event -> { return false; }); + builder.withHandler(event -> false); return unmarshal(builder.build(), reader); } diff --git a/src/main/java/org/fuin/utils4j/jaxb/MarshallerBuilder.java b/src/main/java/org/fuin/utils4j/jaxb/MarshallerBuilder.java index 4e0a9fb..00c17c1 100644 --- a/src/main/java/org/fuin/utils4j/jaxb/MarshallerBuilder.java +++ b/src/main/java/org/fuin/utils4j/jaxb/MarshallerBuilder.java @@ -29,8 +29,6 @@ public class MarshallerBuilder { private ValidationEventHandler handler; - private boolean formattedOutput; - private JAXBContext ctx; diff --git a/src/test/java/org/fuin/utils4j/fileprocessor/FileProcessorTest.java b/src/test/java/org/fuin/utils4j/fileprocessor/FileProcessorTest.java index bfdb71a..c0860a8 100644 --- a/src/test/java/org/fuin/utils4j/fileprocessor/FileProcessorTest.java +++ b/src/test/java/org/fuin/utils4j/fileprocessor/FileProcessorTest.java @@ -17,7 +17,6 @@ */ package org.fuin.utils4j.fileprocessor; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import java.io.File; diff --git a/src/test/java/org/fuin/utils4j/jandex/JandexIndexFileReaderTest.java b/src/test/java/org/fuin/utils4j/jandex/JandexIndexFileReaderTest.java index 0eb4b70..489e4e8 100644 --- a/src/test/java/org/fuin/utils4j/jandex/JandexIndexFileReaderTest.java +++ b/src/test/java/org/fuin/utils4j/jandex/JandexIndexFileReaderTest.java @@ -17,10 +17,8 @@ */ package org.fuin.utils4j.jandex; -import org.fuin.utils4j.jandex.JandexIndexFileReader; import org.fuin.utils4j.jandex.JandexIndexFileReader.Builder; -import org.fuin.utils4j.jandex.JandexUtils; import org.jboss.jandex.IndexView; import org.junit.jupiter.api.Test; diff --git a/src/test/java/org/fuin/utils4j/jandex/JandexIndexFileWriterTest.java b/src/test/java/org/fuin/utils4j/jandex/JandexIndexFileWriterTest.java index ebc3322..2efc735 100644 --- a/src/test/java/org/fuin/utils4j/jandex/JandexIndexFileWriterTest.java +++ b/src/test/java/org/fuin/utils4j/jandex/JandexIndexFileWriterTest.java @@ -37,8 +37,6 @@ public class JandexIndexFileWriterTest { private static final File TARGET_DIR = new File("target"); - private static final File CLASSES_DIR = new File(TARGET_DIR, "classes"); - private static final File TEST_CLASSES_DIR = new File(TARGET_DIR, "test-classes"); @Test diff --git a/src/test/java/org/fuin/utils4j/jandex/JandexUtilsTest.java b/src/test/java/org/fuin/utils4j/jandex/JandexUtilsTest.java index 8e05dad..86e5e6e 100644 --- a/src/test/java/org/fuin/utils4j/jandex/JandexUtilsTest.java +++ b/src/test/java/org/fuin/utils4j/jandex/JandexUtilsTest.java @@ -42,8 +42,6 @@ public class JandexUtilsTest { private static final File CLASSES_DIR = new File(TARGET_DIR, "classes"); - private static final File TEST_CLASSES_DIR = new File(TARGET_DIR, "test-classes"); - @Test public final void testIndexClassFile() { diff --git a/src/test/java/org/fuin/utils4j/jaxb/MarshallerBuilderTest.java b/src/test/java/org/fuin/utils4j/jaxb/MarshallerBuilderTest.java index de4adc1..00eba2a 100644 --- a/src/test/java/org/fuin/utils4j/jaxb/MarshallerBuilderTest.java +++ b/src/test/java/org/fuin/utils4j/jaxb/MarshallerBuilderTest.java @@ -19,11 +19,9 @@ import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; -import jakarta.xml.bind.MarshalException; import jakarta.xml.bind.Marshaller; import jakarta.xml.bind.annotation.adapters.XmlAdapter; import org.junit.jupiter.api.Test; -import org.xml.sax.SAXParseException; import org.xmlunit.builder.DiffBuilder; import org.xmlunit.diff.Diff; @@ -201,9 +199,11 @@ public void testWithListener() throws JAXBException { final AtomicBoolean afterCalled = new AtomicBoolean(false); final Marshaller marshaller = new MarshallerBuilder().withContext(ctx).addAdapters(new MyId.Adapter()) .withListener(new Marshaller.Listener() { + @Override public void beforeMarshal(Object source) { beforeCalled.set(true); } + @Override public void afterMarshal(Object source) { afterCalled.set(true); } From ea1cafaf772ccaa879e30208a176825d3cf427b3 Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Wed, 2 Apr 2025 13:46:32 +0200 Subject: [PATCH 20/22] Harmonized versions for Quarkus/SB3 integration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ef239a8..694e31a 100644 --- a/pom.xml +++ b/pom.xml @@ -56,14 +56,14 @@ org.junit.jupiter junit-jupiter - 5.12.1 + 5.10.5 test org.assertj assertj-core - 3.27.3 + 3.26.3 test From 82c03fe858abe77e3e08bb8fd87380a7b7437104 Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Fri, 4 Apr 2025 11:17:13 +0200 Subject: [PATCH 21/22] Added shared sonar config --- .gitignore | 1 + .sonarlint/connectedMode.json | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 .sonarlint/connectedMode.json diff --git a/.gitignore b/.gitignore index 0906061..74a3cc5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ !.gitkeep !.mvn !.github +!.sonarlint !.devcontainer target META-INF diff --git a/.sonarlint/connectedMode.json b/.sonarlint/connectedMode.json new file mode 100644 index 0000000..0291107 --- /dev/null +++ b/.sonarlint/connectedMode.json @@ -0,0 +1,5 @@ +{ + "sonarCloudOrganization": "fuinorg", + "projectKey": "org.fuin:utils4j", + "region": "EU" +} \ No newline at end of file From d45ef33087681dc1790fcbc8d51fb5cd65dc41fe Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Thu, 17 Apr 2025 11:14:34 +0200 Subject: [PATCH 22/22] Added release notes --- README.md | 1 + release-notes.md | 17 +++++++++++++++++ .../org/fuin/utils4j/ChangeTrackingMap.java | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 release-notes.md diff --git a/README.md b/README.md index 34a8f0a..9496c95 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ A small Java library that contains several helpful utility classes. [![Java Development Kit 17](https://img.shields.io/badge/JDK-17-green.svg)](https://openjdk.java.net/projects/jdk/17/) ## Versions +- 0.14.0 = See [release-notes](release-notes.md) - 0.13.x (or later) = **Java 17** - 0.12.0 = **Java 11** with new **jakarta** namespace - 0.11.x = **Java 11** before namespace change from 'javax' to 'jakarta' diff --git a/release-notes.md b/release-notes.md new file mode 100644 index 0000000..d8ed268 --- /dev/null +++ b/release-notes.md @@ -0,0 +1,17 @@ +# Release Notes + +## 0.14.0 + +### General +- Dependency updates +- New [MultipleCommands](src/main/java/org/fuin/utils4j/MultipleCommands.java) class +- New [TestCommand](src/main/java/org/fuin/utils4j/TestCommand.java) class +- New [TestOmitted](src/main/java/org/fuin/utils4j/TestOmitted.java) annotation + +### Jandex +- [JandexUtils](src/main/java/org/fuin/utils4j/jandex/JandexUtils.java) moved to "jandex" subdirectory +- New [JandexIndexFileReader](src/main/java/org/fuin/utils4j/jandex/JandexIndexFileReader.java) and [JandexIndexFileWriter](src/main/java/org/fuin/utils4j/jandex/JandexIndexWriter.java) + +### JAX-B +- [MarshallerBuilder](src/main/java/org/fuin/utils4j/jaxb/MarshallerBuilder.java) +- Several static methods in [JaxbUtils](src/main/java/org/fuin/utils4j/jaxb/JaxbUtils.java) are now deprecated in favour of [MarshallerBuilder](src/main/java/org/fuin/utils4j/jaxb/MarshallerBuilder.java) and [UnmarshallerBuilder](src/main/java/org/fuin/utils4j/jaxb/UnmarshallerBuilder.java) diff --git a/src/main/java/org/fuin/utils4j/ChangeTrackingMap.java b/src/main/java/org/fuin/utils4j/ChangeTrackingMap.java index c4e3b8d..f0713b2 100644 --- a/src/main/java/org/fuin/utils4j/ChangeTrackingMap.java +++ b/src/main/java/org/fuin/utils4j/ChangeTrackingMap.java @@ -65,7 +65,7 @@ public ChangeTrackingMap(final Map map) { * @return If elements have been added or deleted true else false. */ public final boolean isChanged() { - return (added.size() > 0) || (changed.size() > 0) || (removed.size() > 0); + return (!added.isEmpty()) || (changed.size() > 0) || (removed.size() > 0); } /**