7.2. Common Standard¶
Common Standard is meant for “non Quarkus” usage (does not implied Quarkus libraries), while Common Utils is meant for “Quarkus” context, relying on Common Standard too.
7.2.1. GuidLike and relative Guid¶
Prefer to use GUID instead of UUID since UUID are not able to be allocated without collision between several independent instances.
One proposed implementation is the GuidLike. It uses by default the MAC Address and the PID of the Java process, plus a tenant, the time and an internal counter.
// Create Guid simply
String guid = new GuidLike().getId();
String guid = GuidLike.getGuid(); // Equivalent
Those Guid could be used in particular when any unique Id is needed, for instance in database model.
For simple Uuid (not Guid), there is also the LongUuid implementation (uniqueness cannot be ensure across several JVM, neither several regions).
LongUuid uuid = new LongUuid();
// If hexa form is needed
String hexa = uuid.getId();
// If long form is needed
long id = uuid.getLong();
// or quicker
long id2 = LongUuid.getLongUuid();
7.2.2. BaseXx¶
This is simple encapsulation of other libraries to simplify usage:
final String encoded64 = BaseXx.getBase64("FBTest64P".getBytes());
final byte[] bytes64 = BaseXx.getFromBase64(encoded64);
final String encoded32 = BaseXx.getBase32("FBTest32".getBytes());
final byte[] bytes32 = BaseXx.getFromBase32(encoded32);
final String encoded16 = BaseXx.getBase16("FBTest16".getBytes());
final byte[] bytes16 = BaseXx.getFromBase16(encoded16);
7.2.3. Various X InputStream¶
ChunkInputStream : From one InputStream, cut into sub-InputStream with a fix length (useful for multipart support for Object Storage for InputStream greater than 5 GB)
MultipleActionsInputStream: Can compute one Digest from an InputStream, while reading it, and compress or decompress using ZSTD algorithm
FakeInputStream: Only usable in test, create a fake InputStream for a given length with no memory impact (except one buffer) (allows to create 2 TB InputStream for instance). This one is placed in ccs-test-stream module since test only related.
TeeInputStream: Used to consume twice (or more) one InputStream. Note that the overall speed will be the slowest consumer speed. If one consumer is closing its own InputStream, it will not affect the others.
int nbTee = x;
try (FakeInputStream fakeInputStream = new FakeInputStream(INPUTSTREAM_SIZE, (byte) 'a');
TeeInputStream teeInputStream = new TeeInputStream(fakeInputStream, nbTee)) {
InputStream is;
final Future<Integer>[] total = new Future[nbTee];
final ExecutorService executor = Executors.newFixedThreadPool(nbTee);
for (int i = 0; i < nbTee; i++) {
is = teeInputStream.getInputStream(i);
final ThreadReader threadReader = new ThreadReader(i, is, size);
total[i] = executor.submit(threadReader);
}
executor.shutdown();
while (!executor.awaitTermination(10000, TimeUnit.MILLISECONDS)) {
// Empty
}
for (int i = 0; i < nbTee; i++) {
assertEquals(INPUTSTREAM_SIZE, (int) total[i].get());
}
// If one wants to know if any of the underlying threads raised an exception on their own InputStream
teeInputStream.throwLastException();
// teeInputStream.close() implicit since in Try resource
} catch (final InterruptedException | ExecutionException | IOException e) {
LOGGER.error(e);
fail("Should not raised an exception: " + e.getMessage());
}
7.2.3.1. ZstdCompressInputStream and ZstdDecompressInputStream¶
ZSTD (Zstandard) is a modern and efficient compression (both in time, memory and compression).
Those InputStreams allows to compress or decompress on the flY.
General usages should be that those compression / decompression
final ZstdCompressInputStream zstdCompressInputStream = new ZstdCompressInputStream(inputStream);
// Here TrafficShaping is applied once compression is done, and before decompression, as if there were a
// trafficShaping between sending InputStream and receiving InputStream (wire handling)
final var trafficShapingInputStream = new TrafficShapingInputStream(zstdCompressInputStream, trafficShaping);
// Supposedly here: wire transfer
final ZstdDecompressInputStream zstdDecompressInputStream =
new ZstdDecompressInputStream(trafficShapingInputStream);
int read;
while ((read = zstdDecompressInputStream.read(bytes, 0, bytes.length)) >= 0) {
// Do something with the decompressed InpuStream
}
zstdCompressInputStream.close();
zstdDecompressInputStream.close();
7.2.4. ParametersChecker¶
Can be used for String (testing also emptiness) and for general Object. For null String only, use the special method.
It allows also some general sanity check to prevent wrong data in entry (such as
CDATA or ENTITY in xml, SCRIPTS in Javascript, ;
in sql parameters…).
2 special methods checkSanityBucketName(name)
and checkSanityObjectName(name)
are intended to ensure
correctness of such names when using Object Storage.
This could be later on extended to use external library specialized in sanity check (such as the Owasp library).
I also includes a special function to fix Instant to milliseconds, instead of 1000 nanoseconds, since most of the database cannot handle more than millisecond.
7.2.5. Various Random¶
It could be useful (and in particular for Guid) to get random values in an efficient way or in a secure way (a bit less efficient but still efficient).
RandomUtil helps to get efficient Random values
SystemRandomSecure helps to get efficient and secure Random values.
7.2.6. Singleton¶
Utility class to get standard Singleton (empty and unmodifiable object), such as:
Empty byte array
Empty List
Empty Set
Empty Map
Empty InputStream
Empty OutputStream (moved to ccs-test-stream module since test only related)
7.2.7. SysErrLogger¶
In some rare case, we cannot have a Logger due to the fact the initialization is not done.
In some other case, for quality code reasons, while we do not need to log anything in a catched exception, it is useful to set a log (but we do not want an output).
This is where the SysErrLogger comes.
try {
something raising an exception
} catch (final Exception ignore) {
// This exception shall be ignored
SysErrLogger.FAKE_LOGGER.ignoreLog(ignore);
}
// Output to SysErr without Logger
SysErrLogger.FAKE_LOGGER.syserr(NOT_EMPTY, new Exception("Fake exception"));
// Output to SysOut without Logger
SysErrLogger.FAKE_LOGGER.sysout(NOT_EMPTY);
7.2.8. System Properties and Quarkus Configuration¶
We need sometimes to get configuration (Quarkus) or System Properties statically and not through injection.
SystemPropertyUtil.get(KEY, defaultValue);
SystemPropertyUtil.getAndSet(KEY, defaultValue);
SystemPropertyUtil.set(KEY, defaultValue);
// Quarkus Configuration
SystemPropertyUtil.getBooleanConfig(KEY)
SystemPropertyUtil.getStringConfig(KEY);
SystemPropertyUtil.getLongConfig(KEY);
SystemPropertyUtil.getBooleanConfig(KEY);