A small Java library that contains several helpful utility classes.
- 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
- URL support for "classpath:" scheme
- Variable resolver
- ZIP and UNZIP
- Tracking changes of a list / map
- Easy file locking
- Properties file preferences
- JAXB CDATA Stream Writer
- Wait for code to finish (Deprecated in favour of Awaitility)
- Find all JARs and classes in the classpath
- Analyze classes in the classpath with Jandex
There are two variats you can use.
Directly create a URL using a utility method:
URL url = Utils4J.url("classpath:org/fuin/utils4j/test.properties");
A full example can be found here: ClasspathURLExample.java
If you register the URL stream handler, all URLs (no matter how they were constructed) will work:
Handler.add();
URL url = new URL("classpath:/org/fuin/utils4j/test.properties");
Resolves variable references in a map and prevents on cycles.
a=1
b=${a}/2
c=${b}/3
After calling the resolver a map is returned that has the replaced values:
a=1
b=1/2
c=1/2/3
A full example can be found here: VariableResolverExample.java
Compress and descompress a complete directory and it's subdirectories with a single line of code
final File zipDir = new File(Utils4J.getTempDir(), "mydir");
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
This is a wrapper for lists that keeps track of all changes made to the list. This means adding, replacing or deleting elements is tracked - not the changes to the objects itself. It's also possible to revert (undo) all changes made to the list. A restriction is that no duplicate elements are allowed in the list.
List<String> list = new ArrayList<>();
ChangeTrackingUniqueList<String> trackingList = new ChangeTrackingUniqueList<>(list);
System.out.println(trackingList.isChanged());
System.out.println(trackingList.getDeleted());
System.out.println(trackingList.getAdded());
trackingList.revert();
A list example can be found here: ChangeTrackingUniqueListExample.java A map example can be found here: ChangeTrackingMapExample.java
Allows to synchronize local processes by using a file based lock.
FileLock lock = Utils4J.lockRandomAccessFile(randomAccessFile, tryLockMax, tryWaitMillis);
try {
// Do something...
} finally {
lock.release();
}
A full example can be found here: LockFileExample.java
Shows the use of a directory and properties file based Preferences API implementation. It's basically a replacement for the registry based implementation on Windows.
System.setProperty("java.util.prefs.PreferencesFactory", PropertiesFilePreferencesFactory.class.getName());
Preferences userPrefs = Preferences.userRoot();
A full example can be found here: PropertiesFilePreferencesFactoryExample.java
XML stream writer that does not escape the content of a CDATA section. This is meant to be used with JAXB to serialize a string field to a CDATA section. The field to write as CDATA section is annotated with a CDataXmlAdapter.
Example of class using the adapter:
/**
* Example class with CDATA field.
*/
@XmlRootElement(name = "my-class-with-cdata")
public final class MyClassWithCData {
// Field has the CDataXmlAdapter
@XmlValue
@XmlJavaTypeAdapter(CDataXmlAdapter.class)
private String content;
}
ℹ️ If you just need to unmarshal (XML to Java) a CDATA section, using the above annotation is all you need to do.
// Create writers
final StringWriter writer = new StringWriter();
final XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);
final CDataXmlStreamWriter cdataWriter = new CDataXmlStreamWriter(xmlWriter);
// Create JAXB context with example class
final JAXBContext ctx = JAXBContext.newInstance(MyClassWithCData.class);
final MyClassWithCData testee = new MyClassWithCData("<whatever this=\"is\"/>");
// Convert instance to XML
marshal(ctx, testee, null, cdataWriter);
final String xml = writer.toString();
// Prints out the result
System.out.println(xml);
// <?xml version="1.0" ?><my-class-with-cdata><![CDATA[<whatever this="is"/>]]></my-class-with-cdata>
// Convert it back to object
final MyClassWithCData copy = unmarshal(xml, MyClassWithCData.class);
// Print out cdata content
System.out.println(copy.getContent());
// <whatever this="is"/>
A full example can be found here: 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.
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.1</version>
</dependency>
⚠️ Deprecated in favour of Awaitility
The WaitHelper class supports waiting for some condition.
Example of waiting for a function to finish without an exception:
// Try 5 times and wait 100 millis between tries (wait at max 10 seconds)
final WaitHelper waitHelper = new WaitHelper(1000, 5);
// Example of waiting for a customer to be found
waitHelper.waitUntilNoMoreException(() -> {
// We want to wait some time to see if the CustomerNotFoundException
// disappears and a customer name is finally loaded
loadCustomerName(customerId);
}, Arrays.asList(CustomerNotFoundException.class));
Example of waiting for an expected customer name:
waitHelper.waitUntilResult(() -> {
// We want to wait some time to see if the CustomerNotFoundException
// disappears and a customer name is finally loaded
return loadCustomerName2(customerId);
}, Arrays.asList("Peter Parker, Inc"));
A full example can be found here: WaitHelperExample.java
Easily return a list of all classes or JAR files in the classpath.
// List CLASS files
for (final File file : Utils4J.classpathFiles(Utils4J::classFile)) {
System.out.println(file);
}
// List JAR files that are not located in the JRE directory
for (final File file : Utils4J.classpathFiles(Utils4J::nonJreJarFile)) {
System.out.println(file);
}
// List JAR files that are located in the JRE directory
for (final File file : Utils4J.classpathFiles(Utils4J::jreJarFile)) {
System.out.println(file);
}
// List JAR files that are located in the boot path of the JRE
for (final File file : Utils4J.pathsFiles(System.getProperty("sun.boot.class.path"), Utils4J::jreJarFile)) {
System.out.println(file);
}
A full example can be found here: FindJarsAndClassesInClasspath.java
Easily find matching types from all classes or JAR files in the classpath using Jandex
List<File> knownFiles = new ArrayList<>();
Indexer indexer = new Indexer();
JandexUtils.indexClasspath((URLClassLoader) this.getClass().getClassLoader(), indexer, knownFiles);
Index index = indexer.complete();
Set<ClassInfo> implementors = index.getAllKnownImplementors(DotName.createSimple(List.class.getName()));
// Print all classes that implement the 'List' interface
for (ClassInfo ci : implementors) {
System.out.println(ci.name().toString());
}
// Print all files ("*.jar" and ".class") that were analyzed
for (File file : knownFiles) {
System.out.println(file);
}
A test that shows the usage can be found here: JandexUtilsTest
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.
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jandex</artifactId>
<version>3.1.6</version>
</dependency>
Snapshots can be found on the OSS Sonatype Snapshots Repository.
Add the following to your .m2/settings.xml to enable snapshots in your Maven build:
<repository>
<id>sonatype.oss.snapshots</id>
<name>Sonatype OSS Snapshot Repository</name>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>