# Java Utility Package (Open Source)

### A user-friendly library for building small- to medium-scale back-end applications.

Provides classes for logging, PBKDF2 hashing, JDBC access, SMTP and HTTP communication, FIFO/LIFO queues, threading, file operations, and various utilities.

<a href="/pages/5yMCoJf1sbTuuBdO7Axl" class="button primary">Free Download</a>

{% hint style="success" %}
*Follow the development at Mastodon* [*#JavaUtil*](https://swiss.social/tags/javautil)*.*

*If you have any questions or feedback, feel free to contact me at* [*andy.brunner@k43.ch*](mailto:andy.brunner@k43.ch)
{% endhint %}

### Features

* [**Advanced Logging Capabilities**](/examples/logging)\
  Simplify logging with an easy-to-use framework based on the standard Java Logger. Includes enhanced logging handlers (JDBC and SMTP) and versatile logging formatters (Tabular Text, CSV, XML, JSON, and YAML).
* [**Password Vault**](/examples/password-vault)\
  Securely hash, store, and verify passwords using PBKDF2 with the PBKDF2WithHmacSHA512 algorithm.
* [**Database Integration**](/examples/jdbc-database)\
  Seamlessly access any JDBC-compliant database and retrieve data in multiple formats, including JSON, YAML, CSV, XML, tabular, or raw Java objects.
* [**Email Functionality**](/examples/smtp-mailer)\
  Create and send MIME multipart SMTP messages with support for text, HTML content, and file attachments.
* [**HTTP / Socket Support**](/examples/http-socket-server)\
  Create raw TCP/IP socket applications or HTTP server applications (for web or REST services).
* [**FIFO / LIFO Queues**](/examples/fifo-lifo-queue)\
  Simple to use, thread-safe and named queues with first-in-first-out and last-in-first-out modes.
* [**Command Argument Parser**](/examples/command-argument-parser)\
  A simple command line argument parser to define, parse and retrieve command options and arguments.
* [**Thread Management**](/examples/java-thread)\
  Leverage a convenient class for starting and terminating Java threads with ease.
* [**File Operations**](/examples/file-tools)\
  Read and write files in various formats, including byte streams, character streams, Java Properties, and JSON data.
* [**Utility Methods**](/examples/utility-class)\
  Access a large collection of static utility functions for common programming tasks.
* [**GraalVM Support**](https://java-util.k43.ch/examples/tips-faq#graalvm-native-image-support)\
  The generation of native executable code with GraalVM is supported by including the necessary reflection definitions in the distributed JAR file.

### Logging Example

<details>

<summary>Code / Debug Output</summary>

```java
try {
   int result = 10 / 0;
   } catch (Exception e) {
      KLog.error("Unexpected error occured", e);
   }
}
```

```
2025-09-03T16:48:28.946 D main[1]:ch.k43.util.KLog:<clinit>:199                        ===== Application started 2025-09-03T16:48:28.904 =====
2025-09-03T16:48:28.947 D main[1]:ch.k43.util.KLog:<clinit>:200                        Java Utility Package (Open Source/Freeware) Version 2025.09.02
2025-09-03T16:48:28.947 D main[1]:ch.k43.util.KLog:<clinit>:201                        Homepage java-util.k43.ch - Please send any feedback to andy.brunner@k43.ch
2025-09-03T16:48:28.947 D main[1]:ch.k43.util.KLog:<clinit>:204                        KLog properties read from file KLog.properties
2025-09-03T16:48:28.969 D main[1]:ch.k43.util.KLog:<clinit>:220                        Network host abmacbookpro (10.0.0.104)
2025-09-03T16:48:28.969 D main[1]:ch.k43.util.KLog:<clinit>:224                        OS platform Mac OS X Version 26.0/aarch64
2025-09-03T16:48:28.972 D main[1]:ch.k43.util.KLog:<clinit>:229                        OS disk space total 3.63 TiB, free 2.28 TiB, usable 2.28 TiB
2025-09-03T16:48:28.973 D main[1]:ch.k43.util.KLog:<clinit>:235                        Java version 23 (Java HotSpot(TM) 64-Bit Server VM - Oracle Corporation)
2025-09-03T16:48:28.973 D main[1]:ch.k43.util.KLog:<clinit>:240                        Java directory /Library/Java/JavaVirtualMachines/graalvm-jdk-23.0.1+11.1/Contents/Home
2025-09-03T16:48:28.973 D main[1]:ch.k43.util.KLog:<clinit>:245                        Java CPUs 10, de/CH, UTF-8, UTC +02:00 (Europe/Zurich)
2025-09-03T16:48:28.973 D main[1]:ch.k43.util.KLog:<clinit>:255                        Java heap maximum 16.00 GiB, current 1.01 GiB, used 9.94 MiB, free 1022.06 MiB
2025-09-03T16:48:28.973 D main[1]:ch.k43.util.KLog:<clinit>:262                        Java classpath ../bin/:../lib/angus-mail-2.0.3.jar:../lib/jakarta.mail-api-2.1.3.jar:../lib/org.json.20230618.jar:../lib/h2-2.2.224.jar:../lib/jakarta.activation-api-2.1.3.jar:../lib/angus-activation-2.0.2.jar
2025-09-03T16:48:28.974 D main[1]:ch.k43.util.KLog:<clinit>:266                        Current user andybrunner, language de, home directory /Users/andybrunner/
2025-09-03T16:48:28.974 D main[1]:ch.k43.util.KLog:<clinit>:272                        Current directory /Users/andybrunner/Documents/Eclipse-Workspace/Java-Utility-Package/src/
2025-09-03T16:48:28.974 D main[1]:ch.k43.util.KLog:<clinit>:276                        Temporary directory /var/folders/9s/tbyqn_vn7bs9rf3f1rc2jpxw0000gn/T/
2025-09-03T16:48:28.974 D main[1]:ch.k43.util.K:getLocalData:1598                      Local data for thread main created
2025-09-03T16:48:28.974 D main[1]:ch.k43.util.K:saveError:2535                         Error message saved: Unexpected error occured
2025-09-03T16:48:28.974 E main[1]:Test:main:13                                         ===> Unexpected error occured
2025-09-03T16:48:28.975 E main[1]:Test:main:13                                         ===> Java Exception: java.lang.ArithmeticException: / by zero
2025-09-03T16:48:28.975 E main[1]:Test:main:13                                         ===> Stack Trace[1]: Test.main(Test.java:11)
```

</details>

### HTTP Example

<details>

<summary>Code / Output</summary>

```java
import ch.k43.util.KHTTPClient;
import ch.k43.util.KLog;

public class HTTPGet {

   public static void main(String[] args) {

      KHTTPClient http = new KHTTPClient();

      if (!http.get("https://reqbin.com/echo/get/json")) {
         KLog.error("Error: {}", http.getLastError());
      } else {
         System.out.println(http.getResponseDataAsString());
      }
   }
}
```

```
{"success":"true"}
```

</details>

### JDBC Example

<details>

<summary>Code / Output</summary>

```java
import ch.k43.util.KDB;
import ch.k43.util.KLog;

public class Database {
	
   public static void main(String[] args) {

      try (KDB db = new KDB(KDB.JDBC_H2, "jdbc:h2:mem:mydb", "", "")) {

         KLog.abort(!db.isConnected(), "Error: {}", db.getErrorMessage());
		
         db.exec("CREATE TABLE addresses (sequence INT AUTO_INCREMENT, lastname VARCHAR(20), firstname VARCHAR(20))");
		   
         db.prepare("INSERT INTO addresses (lastname, firstname) VALUES (?, ?)");
         db.execPrepare("Smith", "Joe");
         db.execPrepare("Miller", "Bob");
         db.execPrepare("Johnson", "Evelyn");
         db.exec("SELECT * FROM addresses");

         System.out.println(db.getDataAsJSON());
      }
   }
}
```

```json
{
  "ADDRESSES": [
    {
      "SEQUENCE": 1,
      "LASTNAME": "Smith",
      "FIRSTNAME": "Joe"
    },
    {
      "SEQUENCE": 2,
      "LASTNAME": "Miller",
      "FIRSTNAME": "Bob"
    },
    {
      "SEQUENCE": 3,
      "LASTNAME": "Johnson",
      "FIRSTNAME": "Evelyn"
    }
  ]
}
```

</details>

### Prerequisites

* [Java SE 1.8](https://adoptium.net) (Java 8) or higher

The Java Utility Package does not require additional libraries with the exception of these classes:

| Class                        | Library                                                                                 |
| ---------------------------- | --------------------------------------------------------------------------------------- |
| KDB                          | [JDBC Driver](https://java-util.k43.ch/examples/jdbc-database#prerequisites)            |
| KSMTPMailer, KLogSMTPHandler | [Java Mail API/Jakarta EE](https://java-util.k43.ch/examples/smtp-mailer#prerequisites) |
| KFile                        | [org.json.JSONObject](https://mvnrepository.com/artifact/org.json/json)                 |

### Installation / Usage

* [Download](/downloads/package-ch-k43-util) the latest Java JAR file
* Add *import ch.k43.util.\** statement in your Java code
* Make sure that the file ch.k43.util.jar can be found at compile time and in the classpath at runtime

### Test Installation

You may test the package by running the HelloWorld program, which is part of the distribution jar.

```
% java -jar ch.k43.util.jar
Java Utility Package (Freeware) Version 2025.02.19
Note: To enable logging, place a valid KLog.properties file in the current directory
JVM version 23 running on Mac OS X Version 15.3.1/aarch64
```

{% hint style="info" %}
See the section [Tips / FAQ](https://java-util.k43.ch/examples/tips-faq#graalvm-native-image-support) on how to create a native binary executable with GraalVM.
{% endhint %}

### Motivation for this library

In my professional life as an administrator and developer, I have benefited many times from countless freeware and open source products. It is therefore natural for me to also contribute to this community (see my other [freeware projects](https://k43.ch/freeware-tools/)).

This collection of Java classes was created in the course of various projects and will be further developed (see [Design Goals](https://java-util.k43.ch/examples/tips-faq#design-goals)). I hope that this tool will also serve you well.

### Freeware / Open Source / Unlicensed

This software is [freeware](https://en.wikipedia.org/wiki/Freeware), [open source](https://en.wikipedia.org/wiki/Open_source) and [unlicensed](https://unlicense.org). It was created with love and passion in the beautiful country of 🇨🇭 Switzerland. This software shall be used for Good not Evil. As far as I know, no animal was harmed in the making of this software 😊


# Logging

Add precise timing and exact code location to your logging data.

### KLog Class Overview

* **Built on Standard Java Logging**\
  Utilizes the built-in java.util.logging framework, part of Java SE. No additional external libraries, such as Apache Log4j, are required.
* **High Performance**\
  Capable of logging over 10,000 lines per second on a MacBook Pro when using the FileHandler and KLogLineFormatter.
* **Simplified Logging**\
  Streamlines logging with straightforward methods for debug, error, and info messages.
* **Static Methods**\
  All methods are static, eliminating the need for instantiation.
* **Flexible Handlers and Formatters**\
  Includes handlers and formatters for generating log output in various formats: tabular text, CSV, XML, JSON, and YAML. Supports sending logs to JDBC-compliant databases or routing error logs to any SMTP server.
* **Enhanced Log Details**\
  Provides precise timestamps and exact code locations in formatted log outputs.
* **Configuration and Runtime Adjustments**\
  Logging is enabled via the *KLog.properties* configuration file, which must be located in the current directory or set thru the startup parameter *KLogPropertyFile*. Logging levels can dynamically be adjusted and log entries may be filtered at runtime.

{% hint style="info" %}
The Java utility package uses KLog internally to assist with problem determination. Setting the log level to *FINEST* in the *KLog.properties* file enables detailed debugging mode, providing comprehensive insights during code execution.
{% endhint %}

### Logging Handlers

In addition to the standard logging handlers for console and file output, KLog provides the additional classes:

* **KLogJDBCHandler**: Write each log entry to any JDBC compliant database
* **KLogSMTPHandler**: Send error log entries (FATAL logging level) to any SMTP server

### Logging Formatters

The log information (timestamp, logging level, code location and message) can be formatted with the additional formatter classes:

* **KLogCSVFormatter**: Format each log entry as a one-line CSV string
* **KLogJSONFormatter**: Format each log entry as a multi-line JSON string
* **KLogLineFormatter**: Format each log entry as a one-line tabular string
* **KLogXMLFormatter**: Format each log entry as a multi-line XML string
* **KLogYAMLFormatter**: Format each log entry as a multi-line YAML string

### Sample Properties Files

The logging properties file enables and configures the logging framework used by all `KLog` methods. Simply download, edit and and place it in the current directory of your application.

{% file src="/files/OY3Oy56cHOWd632JXnp2" %}
Recommended minimal logging (errors only)
{% endfile %}

{% file src="/files/HjQM7XYniq8tl4Pbooe6" %}
Full logging functionality
{% endfile %}

### Special Properties

<details>

<summary>Startup System Properties</summary>

| Command Line Option | Default                         | Purpose                                                     |
| ------------------- | ------------------------------- | ----------------------------------------------------------- |
| -DKLogPropertyFile  | "KLog.properties"               | Path and file name of KLog properties file                  |
| -DKLogLevel         | Set by the KLog properties file | Override KLog level to Info, Error,  Debug or Off           |
| -DKLogInclude       | Set by the KLog properties file | Limit log entries to specified RegEx match, e.g. “password“ |
| -DKLogExclude       | Set by the KLog properties file | Exclude log entries matching RegEx, e.g. “started\|ended“   |

Examples

```bash
% java -DKLogInclude=“Started|Ended“ YourApp
```

<pre class="language-bash"><code class="lang-bash"><strong>% java -DKLogPropertyFile=/etc/KLog.properties -DKLogLevel=Debug YourApp
</strong></code></pre>

{% hint style="warning" %}
Please note that all command line options are case sensitive.
{% endhint %}

</details>

<details>

<summary>Common KLog Properties</summary>

| Property Key             | Value                     | Notes                                                      |
| ------------------------ | ------------------------- | ---------------------------------------------------------- |
| ch.k43.util.KLog.level   | FINEST, INFO, SEVERE, OFF | Corresponds to KLog logging levels Debug, Info, Error, Off |
| ch.k43.util.KLog.exclude | RegEx Pattern             | Exclude matching log entries, e.g. “password“              |
| ch.k43.util.KLog.include | RexEx Pattern             | Include only matching log entries, e.g. “started\|ended“   |

</details>

<details>

<summary>KLog.properties for KLogJDBCHandler</summary>

| Property Key                              | Value                | Notes                                       |
| ----------------------------------------- | -------------------- | ------------------------------------------- |
| ch.k43.util.KLogJDBCHandler.jdbc.driver   | JDBC Driver Class    | Java class name, e.g. org.h2.Driver         |
| ch.k43.util.KLogJDBCHandler.jdbc.url      | Connection URL       | e.g. jdbc:h2:mem:mydb                       |
| ch.k43.util.KLogJDBCHandler.jdbc.username | Connection user name | e.g. johnsmith                              |
| ch.k43.util.KLogJDBCHandler.jdbc.password | Connection password  | e.g. Pa$$w0rd                               |
| ch.k43.util.KLogJDBCHandler.tablename     | Database table name  | Table name to be used, e.g. KLOGDATA        |
| ch.k43.util.KLogJDBCHandler.retensiondays | Number               | Number of days to keep log entries, e.g. 14 |
| ch.k43.util.KLogJDBCHandler.debug         | true, false          | Send debug data to standard output (stdout) |

</details>

<details>

<summary>KLog.properties for KLogSMTPHandler</summary>

| Property Key                              | Value                                   | Notes                                       |
| ----------------------------------------- | --------------------------------------- | ------------------------------------------- |
| ch.k43.util.KLogSMTPHandler.mail.from     | Sender Address                          | e.g. <johnsmith@acme.com>                   |
| ch.k43.util.KLogSMTPHandler.mail.to       | Recipient Address                       | e.g. <fred@hotmail.com>                     |
| h.k43.util.KLogSMTPHandler.mail.subject   | Email subject                           | e.g. "Application Error"                    |
| ch.k43.util.KLogSMTPHandler.smtp.hostname | SMTP hostname                           | e.g. mail.acme.com                          |
| ch.k43.util.KLogSMTPHandler.smtp.hostport | SMTP port number                        | e.g. 25                                     |
| ch.k43.util.KLogSMTPHandler.smtp.username | SMTP authentication user name (or none) | e.g. <johnsmith@acme.com>                   |
| ch.k43.util.KLogSMTPHandler.smtp.password | SMTP authentication password (or none)  | e.g. Pa$$w0rd                               |
| ch.k43.util.KLogSMTPHandler.smtp.tls      | true, false                             | Use TLS or Non-TLS connection               |
| ch.k43.util.KLogSMTPHandler.threshold     | Number                                  | Maximum number of email sent per minute     |
| ch.k43.util.KLogSMTPHandler.debug         | true, false                             | Send debug data to standard output (stdout) |

</details>

<details>

<summary>KLog.properties for KLogCSVFormatter</summary>

| Property Key                             | Value       | Notes                              |
| ---------------------------------------- | ----------- | ---------------------------------- |
| ch.k43.util.KLogCSVFormatter.writeheader | true, false | Add header lines with column names |

</details>

### Examples

<details>

<summary>Code and Output</summary>

<pre class="language-java"><code class="lang-java"><strong>KLog.info("Program started");
</strong>		
int rc = -1;
KLog.error(rc != 0, "Return code is {}", rc);
	
KLog.debug("Just a debug message");
		
Exception e = new Exception("Program error");
KLog.error(e);
		
KLog.info("Program ended");
</code></pre>

```
2024-08-29T15:49:27.867 D main[1]:ch.k43.util.KLog:open:462                            ===== Application started 2024-08-29T15:49:27.850 =====
2024-08-29T15:49:27.867 D main[1]:ch.k43.util.KLog:open:464                            Java Utility Package (Freeware) ch.k43.util Version 2024.08.29
2024-08-29T15:49:27.868 D main[1]:ch.k43.util.KLog:open:467                            Homepage java-util.k43.ch - Please send any feedback to andy.brunner@k43.ch
2024-08-29T15:49:27.889 D main[1]:ch.k43.util.KLog:open:469                            Host ab-macbook-pro (10.0.0.105)
2024-08-29T15:49:27.889 D main[1]:ch.k43.util.KLog:open:470                            OS platform Mac OS X (Version 14.6.1/aarch64)
2024-08-29T15:49:27.889 D main[1]:ch.k43.util.KLog:open:471                            Java version 17 (OpenJDK 64-Bit Server VM - Eclipse Adoptium)
2024-08-29T15:49:27.891 D main[1]:ch.k43.util.KLog:open:475                            Java heap maximum 16.00 GB, current 1.00 GB, used 4.80 MB, free 1019.20 MB
2024-08-29T15:49:27.891 D main[1]:ch.k43.util.KLog:open:479                            Java locale de/CH, local time UTC +02:00
2024-08-29T15:49:27.891 D main[1]:ch.k43.util.KLog:open:482                            Java classpath ../bin/:../lib/org.json.20230618.jar:../lib/jakarta-mail-1.6.7.jar
2024-08-29T15:49:27.891 I main[1]:Test:main:10                                         Program started
2024-08-29T15:49:27.892 E main[1]:Test:main:13                                         ===> Return code is -1
2024-08-29T15:49:27.892 D main[1]:Test:main:15                                         Just a debug message
2024-08-29T15:49:27.892 E main[1]:Test:main:18                                         ===> java.lang.Exception: Program error
2024-08-29T15:49:27.892 E main[1]:Test:main:18                                         ===> Stack[1]: Test.main(Test.java:17)
2024-08-29T15:49:27.892 I main[1]:Test:main:20                                         Program ended
```

</details>

<details>

<summary>Log Exception</summary>

```java
try {
   ...
} catch (Exception e) {
   KLog.error(e);
}
```

</details>

<details>

<summary>Log and Throw RuntimeException</summary>

```java
try {
  ...
} catch (Exception e) {
  KLog.abort(e.toString());
}
```

</details>

<details>

<summary>Log and Throw IllegalArgumentException</summary>

```java
public divide(double arg1, double arg2) {
  // Check arguments
  KLog.argException(arg2 == 0.0, "Divisor 0 not allowed");
  ...
}
```

</details>


# Utility Class

Dozens of handy functions.

### K Class Overview

* **Static Methods**\
  All methods are static, eliminating the need for object instantiation.
* **Encoding and Decoding**\
  Supports encoding and decoding for multiple formats, including URL, Base64, CSV, JSON, XML, and YAML.
* **AES-256 Encryption/Decryption**\
  Provides robust encryption and decryption using the AES/CBC/PKCS5Padding algorithm. The provided secure key is hashed with SHA-256 to create a 256-bit key. Use K.getRandomBytes(16) to generate the required initialization vector.
* **Data Compression**\
  Enables ZLIB and GZIP compression and decompression for efficient data handling.
* **Hash Generation**\
  Supports generating cryptographic hashes using MD5, SHA-2, or SHA-3 algorithms.
* **DNS Querying**\
  Allows querying of any DNS record type (e.g., MX, A). MX records are returned in priority order for convenience.
* **Thread Management**\
  Includes functionality to introduce delays in thread execution.
* **Environment Information**\
  Retrieves detailed environment data, such as JVM version, IP address, hostname, and more.

### Example Delay Thread

```java
// Wait 1/4 second
K.waitMilliseconds(250);

// Wait 5 minutes
K.waitMinutes(5);
```

### Example Encode/Decode

```java
// Encode Base-64 string
String httpAuth = K.encodeBase64(userName + ':' + password);

// Encode URL
String urlEncoded = K.encodeURL("https://example.com?q=1&p=done");
```

### Example Query DNS Server

```java
// Get DNS SOA record
String[] soaRRs = K.queryDNS("SOA", "google.com");

// Get DNS MX record(s)
String[] mxRRs = K.queryDNS("MX", "yahoo.com");
```

### Example AES-256

```java
String secretKey = "This is the secret key";
		
// Create a simple text file
KFile.writeFile("This is a simple text file", "AES-Text.txt");
		
// Generate and save random AES-256 initialization vector
KFile.writeFile(K.getRandomBytes(16), "AES.iv");
		
// AES-256 Encrypt
byte[] clearText  = KFile.readByteFile("AES-Text.txt");
byte[] initVector = KFile.readByteFile("AES.iv");
byte[] cipherText = K.encryptAES256(clearText, secretKey.getBytes(), initVector);
KFile.writeFile(cipherText, "AES-Text.encrypted");
		
// AES-256 Decrypt
cipherText = KFile.readByteFile("AES-Text.encrypted");
initVector = KFile.readByteFile("AES.iv");
clearText  = K.decryptAES256(cipherText, secretKey.getBytes(), initVector);
		
System.out.println(new String(clearText));
```


# Password Vault

Securely hash, store and verify passwords.

### KPasswordVault Class Overview

* **Security Parameters**\
  Uses PBKDF2 with the PBKDF2WithHmacSHA512 algorithm, a key length of 512 bits, a securely generated 32-byte salt, and an optional pepper value.
* **Hash Iteration Count**\
  If no iteration count is specified, a random value between 500,000 and 1,000,000 is used.
* **Password Verification**\
  Provides a method to validate a plaintext password by comparing it against the stored hash.

### Example

```java
public static final String SET_PASSWORD   = "SecretPassword";
public static final String TEST_PASSWORD  = "WrongPassword";
	
public static void main(String[] args) {

   KPasswordVault vault = new KPasswordVault(SET_PASSWORD.toCharArray());

   System.out.println("Hashed Password:       " + K.toHex(vault.getPasswordHash()));
   System.out.println("Used Salt:             " + K.toHex(vault.getSalt()));
   System.out.println("Used Iteration Count:  " + vault.getIterations());
   System.out.println("Hashing Elapsed Time:  " + vault.getHashTimeMs() + " ms");

   System.out.println("Validate 1st Password: " + vault.isPasswordValid(SET_PASSWORD.toCharArray()));
   System.out.println("Validate 2st Password: " + vault.isPasswordValid(TEST_PASSWORD.toCharArray()));
}
```

### Output

```
Hashed Password:       83457DACC30439A16AE5F91AE13DA176935ABEC8F7834B236A950B41A8CEE0AED8BA042DDDF5ACAB183FC0BB882E1513790DE40AA0D7FB7C8A491D8E2371CE0D
Used Salt:             52FAE4F708290D168D3DBF3D924CDAA79AD53632B897F05D3A2EE655C83B44E0
Used Iteration Count:  895434
Hashing Elapsed Time:  433 ms
Validate 1st Password: true
Validate 2st Password: false
```


# HTTP / Socket Server

Create transaction server in minutes.

### KHTTPServerThread / KSocketThread Class Overview

* **Socket and HTTP**\
  Supports raw TCP/IP socket applications or HTTP server applications (for web or REST services).
* **TLS and Non-TLS Client Connection Support**\
  Enables both secure (TLS) and non-secure client connections to server applications, providing flexibility for various networking scenarios.
* **Thread Management**\
  Loads, starts, and manages user classes to dynamically handle socket or HTTP clients.
* **Client and Basic Authentication**\
  Allows server applications to differentiate between authenticated and non-authenticated clients. Use the getAuthenticatedClient() method to verify a valid client name..
* **Flexible Data Read/Write Methods**\
  Includes efficient methods for reading and writing data in various formats, such as byte\[], char\[], String, and line-based input.

<details>

<summary>HTTP Server Example: Simple Webserver</summary>

```java
try (KSocketServer httpServer = new KSocketServer(8080, KHTTPServerThreadSample.class)) {

   if (!httpServer.isActive()) {
      System.out.println("The HTTP server could not be started: " + httpServer.getLastError());
      System.exit(1);
   }
			
   System.out.println("HTTP server ready on port 8080 - Will terminate after 3 minutes");
   K.waitMinutes(3);
   System.out.println("HTTP server terminating");
}
```

```java
public class KHTTPServerThreadSample extends KHTTPServerThread {

   public KHTTPServerThreadSample(Socket argSocket) {
      super(argSocket);
   }
	
   @Override
   public void get(String argURL) {
      sendFile(argURL);
   }
}
```

</details>

<details>

<summary>Socket Server Example: Echo Server</summary>

```java
// Start echo server on port 8080
try (KServerSocket server = New KServerSocket(8080, KSocketServerThreadSample.class)) {
   KLog.abort(!server.isActive(), "Unable to start server: " + server.getLastError());

   // Let client connect (e.g. "nc localhost 8080" or "telnet localhost 8080")
   K.waitMinutes(5);
}
```

```java
public class KSocketServerThreadSample extends KSocketServerThread {

   public KSocketServerThreadSample(Socket argSocket) {
      super(argSocket);
   }

   public void run() {
      KLog.info("Upper-Case-Echo-Server started");
      
      String newLine    = K.getLineSeparator();
      String clientData = null;
      
      write((!isSecuredConnection() ? "Non-" : "") + "TLS Upper-Case-Echo-Server ready" + newLine);
      
      while ((clientData = readLine()) != null) {
         write(clientData.toUpperCase() + newLine);
      }
      close();
      
      KLog.info("Upper-Case-Echo-Server terminated");
   }
}
```

</details>

### Architecture Overview

<figure><img src="/files/YiinF7fwSw2xrKE4dkWq" alt=""><figcaption></figcaption></figure>


# HTTP Client

Get data from server the easy way.

### KHTTPClient Class Overview

* **Comprehensive HTTP Method Support**\
  Fully supports all major HTTP methods, including GET, POST, PUT, PATCH, HEAD, OPTIONS, and DELETE.
* **Automatic Header Management**\
  Automatically adds essential request headers, such as Date, User-Agent, Host, and Content-Length, ensuring seamless communication with HTTP servers.

{% hint style="info" %}
For servers requiring OAuth 2.0 authentication, leverage the [Simple OAuth 2.0 Framework for Authentication](https://sofa.k43.ch) (Freeware) to obtain access tokens efficiently and securely.
{% endhint %}

### Example GET Request

```javascript
KHTTPClient http = new KHTTPClient();

if (!http.get("https://reqbin.com/echo/get/json")) {
   KLog.error("Error: {}", http.getLastError());
} else {
   System.out.println(http.getResponseDataAsString());
}
```

### Example POST Request with Basic Authentication

```java
Properties props = new Properties();
props.put("Authorization", "Basic " + K.encodeBase64(userName + ':' + password);

KHTTPClient http = new KHTTPClient();

if (!http.post("https://example.com:4443", props, "HTTP body data")) {
   KLog.abort("HTTP POST failed - " + http.getLastError());
}
```


# Socket Client

Low-level access to any server socket

### KSocketClient Class Overview

* **TLS and Non-TLS Connection Support**\
  Enables secure and non-secure connections to server applications, providing flexibility for various use cases.
* **Client Authentication**\
  Supports client authentication using Java KeyStore (JKS) files for enhanced security during communication.
* **Versatile Read/Write Methods**\
  Provides efficient methods for reading and writing data in multiple formats, including byte\[], char\[], String, and line-based input.

### Example

```java
try (KSocketClient tlsSocket = new KSocketClient("example.com", 4443)) {
   KLog.abort(!tlsSocket.isConnected(), "Connect failed - " + tlsSocket.getLastError());

   while ((String hostLine = tlsSocket.readLine()) != null) {
      System.out.println(hostLine + K.getLineSeparator());
   }
}
```


# JDBC Database

Simple SQL CRUD operations for any database.

### KDB Class Overview

* **Dynamic and Precompiled SQL Support**\
  Offers flexibility to execute both dynamic and precompiled SQL statements, catering to a wide range of database interaction needs.
* **Versatile Data Retrieval**\
  Retrieve query results in multiple formats:\
  \- Java Format: Rows as ArrayList and columns as Java objects.\
  \- Serialized Formats: JSON, YAML, XML, CSV, or as a tabular string for enhanced compatibility and readability.

### Prerequisites

The *KDB* database class works with any compliant JDBC drivers. Some popular download sources are listed here. Just place the JAR file in a directory pointed to by the classpath and specify the JDBC class name in the KDB constructor.

* [MVN Repository JDBC Drivers](https://mvnrepository.com/open-source/jdbc-drivers)
* [SoapUI JDBC Driver List](https://www.soapui.org/docs/jdbc/reference/jdbc-drivers/)
* [BenchResources.Net JDBC driver](https://www.benchresources.net/jdbc-driver-list-and-url-for-all-databases/)

### Example H2 Database

<pre class="language-java"><code class="lang-java">import ch.k43.util.KDB;
import ch.k43.util.KLog;

public class Database {
	
   public static void main(String[] args) {

      try (KDB db = new KDB(KDB.JDBC_H2, "jdbc:h2:mem:mydb", "", "")) {

         KLog.abort(!db.isConnected(), "Error: {}", db.getErrorMessage());
	
         db.exec("CREATE TABLE addresses (sequence INT AUTO_INCREMENT, lastname VARCHAR(20), firstname VARCHAR(20))");
		   
         db.prepare("INSERT INTO addresses (lastname, firstname) VALUES (?, ?)");
         db.execPrepare("Smith", "Joe");
         db.execPrepare("Miller", "Bob");
         db.execPrepare("Johnson", "Evelyn");
         db.exec("SELECT * FROM addresses");

         System.out.println(db.getDataAsJSON());
<strong>      }
</strong>   }
}
</code></pre>

<details>

<summary>Output</summary>

```json
{
  "ADDRESSES": [
    {
      "SEQUENCE": 1,
      "LASTNAME": "Smith",
      "FIRSTNAME": "Joe"
    },
    {
      "SEQUENCE": 2,
      "LASTNAME": "Miller",
      "FIRSTNAME": "Bob"
    },
    {
      "SEQUENCE": 3,
      "LASTNAME": "Johnson",
      "FIRSTNAME": "Evelyn"
    }
  ]
}
```

</details>


# SMTP Mailer

Create and send multipart MIME messages.

### KSMTPMailer Class Overview

* **MIME Multipart Message Creation**\
  Easily create MIME multipart messages with support for text, HTML content, and file attachments.
* **Secure and Non-Secure Connections**\
  Supports STARTTLS/TLS (default) for secure communication and non-secured connections when required.
* **Authentication Options**\
  Compatible with both OAuth 2.0 and basic authentication for flexible access to SMTP servers.
* **Automatic MX Record Lookup**\
  If the SMTP host is not specified, automatically queries DNS for the highest-priority MX record.
* **Enhanced Mail Header**\
  Automatically includes the `X-Mailer` header to identify the sending application.

{% hint style="info" %}
For servers requiring OAuth 2.0 authentication, leverage the [Simple OAuth 2.0 Framework for Authentication](https://sofa.k43.ch) (Freeware) to obtain access tokens efficiently and securely.
{% endhint %}

### Prerequisites

The *KSMTPMailer* class requires the following Jakarta/Angus Mail jar files:

* angus-activation-2.0.x.jar
* angus-mail-2.0.x.jar
* jakarta.activation-api-2.1.x.jar
* jakarta.mail-api-2.1.x.jar

If you do not already have these jar files, you may download them here. Just place the files in a directory pointed to by the JVM class path.

{% file src="/files/fJ2oMhbk2hVb9kL8clRN" %}

### Example

```java
KSMTPMailer mailer = new KSMTPMailer();

mailer.setFrom("john.doe@acme.com");
mailer.setTo("bob.smith@hotmail.com");
mailer.setSubject("Subject");
mailer.addHTML("<h1>Your requested files</h1>");
mailer.addText("Body Text");
mailer.addFile("test1.txt");
mailer.addFile("test2.txt");
mailer.addText("Regards, John");
mailer.send();
```


# FIFO/LIFO Queue

Support easy to use, named and thread-safe queues.

### KQueue Class Overview

* Support LIFO (last-in-first-out) and FIFO (first-in-first-out) queue types
* Queues may be explicitly named to be accessible by other threads
* Blocking and non-blocking get() methods

### Example

```java
try (KQueue queue = new KQueue(KQueue.LIFO)) {

   queue.put("A");
   queue.put("B");
   queue.put("C");

   while (!queue.isEmpty()) {
      System.out.println(queue.get());
   }
}
```

### Output

```
C
B
A
```


# Command Argument Parser

Define and parse command line arguments

### KCmdArgParser Class Overview

* Define allowed options and arguments
* Parsing of the command line arguments
* Methods to query and retrieve options and arguments

### Example

```java
import ch.k43.util.KCmdArgParser;

public class CmdParser {
	
   public static void main(String[] args) {

      // Parser syntax: -a and -l optional, one parameter required
      final String ARG_SYNTAX = "?-l:?-a:!.";			
		
      // Initialize command line parser with argument syntax
      KCmdArgParser argParser = new KCmdArgParser(ARG_SYNTAX);
		
      // Parse command line arguments
      if (!argParser.parse(args)) {
         System.out.println("Syntax error: " + argParser.getLastError());
         System.exit(1);
      }
		
      System.out.println("Option -l: " + argParser.hasOption("-l"));
      System.out.println("Option -a: " + argParser.hasOption("-a"));
      System.out.println("Parameter: " + argParser.getArgument());
   }
}
```

### Output

```
% CmdParser -l file.txt
Option -l: true
Option -a: false
Parameter: file.txt

% CmdParser -x file.txt
Syntax error: Command line option not supported: -x
```


# Java Thread

Make difficult Java thread creation and cleanup a thing of the past.

### KThread Class Overview

The `KThread` class provides a simple and convenient framework for managing Java threads, focusing on controlled startup, termination, and cleanup processes. It is designed to streamline thread lifecycle management while ensuring resource cleanup before termination.

#### Key Features

* **Thread Termination Signaling**\
  Any thread can invoke the kStop() method to signal a KThread instance to terminate. This method optionally supports interrupting the thread using Thread.interrupt().
* **Termination Check**\
  The kMustTerminate() method allows threads to check if a termination signal has been issued, enabling responsive and graceful shutdowns during execution.
* **Automatic Resource Cleanup**\
  Before the thread terminates, the kCleanup()  method is automatically invoked to handle any necessary resource cleanup tasks. This ensures proper release of resources and avoids potential memory leaks.

#### Usage Scenario

* **Controlled Thread Management**\
  Ideal for applications requiring predictable and safe thread lifecycle control.
* **Resource-Intensive Tasks**\
  Ensures that resources are properly released even in the event of thread termination.

### Example Main Thread

```java
KThread kThread = new TestThread("Hello World");
KLog.info("Thread created and started");

K.waitSeconds(5);

kThread.kStop();
KLog.debug("Thread stopped");
```

### Example Thread

```java
public class TestThread extends KThread {

   private String gStartArgument = null;
	
   public TestThread(String argString) {
      gStartArgument = argString;
   }

   public void kStart() {
      KLog.info("Thread has started with argument " + gStartArgument);
		
      while (!kMustTerminate()) {
         KLog.info("Thread still running ...");
         K.waitSeconds(1);
      }
      KLog.info("Thread has terminated");
   }
	
   public synchronized void kCleanup() {
      KLog.info("Thread cleanup called");
   }
}
```

<details>

<summary>Info Log</summary>

```
2024-09-05T14:42:52.629 I main[1]:Test:main:9                                          Start
2024-09-05T14:42:52.629 I main[1]:Test:thread:20                                       Thread created and started
2024-09-05T14:42:52.630 I T-0[15]:TestThread:kStart:15                                 Thread has started with argument Hello World
2024-09-05T14:42:52.630 I T-0[15]:TestThread:kStart:18                                 Thread still running ...
2024-09-05T14:42:53.636 I T-0[15]:TestThread:kStart:18                                 Thread still running ...
2024-09-05T14:42:54.641 I T-0[15]:TestThread:kStart:18                                 Thread still running ...
2024-09-05T14:42:55.646 I T-0[15]:TestThread:kStart:18                                 Thread still running ...
2024-09-05T14:42:56.654 I T-0[15]:TestThread:kStart:18                                 Thread still running ...
2024-09-05T14:42:57.637 E T-0[15]:ch.k43.util.K:waitThread:1484                        ===> java.lang.InterruptedException: sleep interrupted
2024-09-05T14:42:57.638 I T-0[15]:TestThread:kStart:22                                 Thread has terminated
2024-09-05T14:42:57.639 I T-0[15]:TestThread:kCleanup:27                               Thread cleanup called
```

</details>


# File Tools

Simple file manipulation

### KFile Class Overview

The KFile class provides a versatile set of methods for managing file operations, supporting a wide range of use cases including reading, writing, renaming, and deleting files. Its straightforward API ensures efficient handling of various file formats and operations.

### Key Features

* **Read and Write File Content**\
  **-** Binary Files: Supports reading and writing entire binary files for seamless handling of non-text data.\
  \- Character Files: Enables reading and writing text-based files with full encoding support.\
  \- Java Properties: Simplifies interaction with .properties files, allowing easy serialization and deserialization of key-value pairs.\
  \- JSON Objects: Facilitates reading and writing JSON data to and from files using JSONObject.
* **File Renaming and Deletion**\
  \- Rename Files: Provides a method to rename files, ensuring atomic operations where supported by the underlying filesystem.\
  \- Delete Files: Allows safe and efficient file deletion with error handling for cases like missing or locked files.
* **Additional File Operations**\
  Includes various helper methods for other file-related tasks.

### Use Cases

* **Data Serialization**\
  Manage binary, textual, and structured data formats like JSON or properties files.
* **File Maintenance**\
  Perform common file management tasks such as renaming and deletion.
* **Utility for Applications**\
  Ideal for applications requiring flexible and reliable file handling capabilities.
* **Read/Write**\
  Read and write entire entire file content (binary, character, Java Properties or JSONObject data)

### Prerequisites

* [org.json.JSONObject](https://mvnrepository.com/artifact/org.json/json)

### Example Delete File

```java
KFile.delete("temp.txt);
```

### Example Read JSON File

```java
JSONObject jsonData = KFile.readJSONFile("text.json");

if (jsonData == null) {
   KLog.abort("Unable to read JSON file");
}
```

### Example Create JSON File

```java
JSONObject jsonObject = new JSONObject();
jsonObject.put("lastName", "Smith");
jsonObject.put("firstName", "John");
jsonObject.put("gender", "male");
KFile.writeFile(jsonObject, "test.json");
```

### Example Copy Binary File

```java
byte[] fileBuffer = KFile.readByteFile("inputFile");

if (!K.isEmpty(fileBuffer) {
   KFile.writeBytes(fileBuffer, "outputfile");
}
```


# Timer

Basic timer class

### KTimer Class Overview

* Simple timer with up to nanosecond precision

### Example

```java
KTimer timer = new KTimer();
K.waitSeconds(1);
KLog.info("Waited {} ms", timer.getElapsedMilliseconds());
```


# Tips / FAQ

### Design Goals

1. **Ease of use**: The classes and methods must be flexible and simple to use.
2. **No UI calls**: Do everything without user interface to allow this library to be used for background tasks or server processes.
3. **Fast**: Write the code as performant as possible.
4. **Favor memory usage over I/O:** In today's world, memory is no longer a limiting factor. Therefore, many operations can be done in memory where (temporary) files were used in the past (e.g. KDB creates a data structure from SQL SELECT, KFile operations are mostly in memory).
5. **Use extensive logging**: The KLog.debug() and KLog.error() functions are used throughout the code to help debugging your code. Also use the toString() methods found in each class to show the internal field values of the objects during development.
6. **Platform independence**: Write everything platform independent.
7. **Minimize prerequisites**: Adhere to standard Java SE libraries, maintain compatibility with Java 8 and later, and limit the use of external JAR files to essential cases only (e.g., KSMTPMailer, JDBC drivers).

***

### GraalVM Native Image Support

The Java Utility Package supports the creation of [GraalVM](https://www.graalvm.org) native executables by including the necessary Java reflection definitions within the JAR file.

**Prerequisites**

* macOS: [Xcode](https://apps.apple.com/ch/app/xcode/id497799835?mt=12)
* Windows: [Visual Studio Build Tools 2022](https://visualstudio.microsoft.com/) or later
* [GraalVM](https://www.graalvm.org/latest/getting-started/)

**Compile / Create Executable / Sign / Run (macOS)**

```bash
% javac YourApplication.java
% native-image -cp ch.k43.util.jar:. YourApplication
% codesign --sign "Your Code Signature (XXXXXXXXXX)" YourApplication
% ./YourApplication
```

**Example: GetCurrentVersion (macOS/arm64 executable)**

{% file src="/files/TU3nB7B7aHqOPk0J5Em8" %}

***

### JShell

For a quick test of any ch.k43.util function, utilize the interactive JShell command included in the JDK. Ensure the ch.k43.util JAR file is either located in the current directory or accessible via the directory specified in the class-path argument.

{% code lineNumbers="true" fullWidth="false" %}

```sh
% jshell --class-path "./*"
jshell> import ch.k43.util.*;

jshell> K.queryDNS("MX","yahoo.com");
$2 ==> String[3] { "mta5.am0.yahoodns.net", "mta6.am0.yahoodns.net", "mta7.am0.yahoodns.net" }

jshell> K.getUniqueID();
$3 ==> "36973229-FB14-4D95-9AA7-EEBFA2CC84FD"

jshell> K.getTimeISO8601();
$4 ==> "2025-02-22T08:30:34.145"

jshell> K.isInteger("12.3");
$5 ==> false

jshell> KHTTPClient http = new KHTTPClient();
http ==> KHTTPClient [gHTTPResponseHeaders=null, gHTTPResp ... ode=-1, gHTTPTimeOutSec=5]

jshell> http.get("https://reqbin.com/echo/get/json")
$7 ==> true

jshell> System.out.println(http.getResponseDataAsString());
{"success":"true"}

jshell> /exit
```

{% endcode %}

{% hint style="info" %}
See the [Java Shell User Guide](https://docs.oracle.com/en/java/javase/21/jshell/introduction-jshell.html) on how to use *JShell*
{% endhint %}

***

### Java Stores

There are two keystore files used in Java:

* **Key Store**: These files contain certificates to proof authentication with a private key. Certificates can be server certificates (e.g. [www.acme.com](http://www.acme.com)), intermediate certificates or client certificates (e.g. <john.doe@acme.com>).
* **Trust Store**: These files contain public certificates of trusted identities. Certificates are trusted root certificates (e.g. Verisign, Microsoft, etc.), intermediates certificates or trusted server and client certificates. A default file (usually named cacerts with the default password changeit) is shipped with the JVM.

**Create Self Signed Certificate**

```sh
% openssl req -x509 -newkey rsa:2048 -sha256 -keyout key.pem -out cert.pem -days 365 -nodes
```

**Convert PEM certificate to P12**

```sh
% openssl pkcs12 -export -in certificate.pem -out certificate.p12 
```

**Create JKS file from P12 certificate**

```sh
% keytool -importkeystore -srckeystore certificate.p12 -srcstoretype pkcs12 -destkeystore keyfile.jks
```

**Add Client Certificate to JKS file**

```sh
% keytool -import -trustcacerts -file clientcert.pem -keypass clientCertPass -storepass keyfilePass -keystore keyfile.jks
```

**Display Content of JKS file**

```sh
% keytool -list -v -keystore keyfile.jks
```

**Simple TLS Server**

```bash
% openssl s_server -key key.pem -cert cert.pem -accept 443
```

**TLS Connection Test**

```bash
% openssl s_client -connect hostname:443
```


# Download Package

<details>

<summary>Planned for next version</summary>

* **KQueue**: Removed *setMode()* and *getMode*() to avoid concurrency problems
* Some minor code and documentation changes

</details>

## Current Version 2025.09.15

{% file src="/files/k0xyLJA2GGd8LerQ5JSl" %}

* **KQueue:** New class to support named LIFO/LIFO queues
* **K**: added *writeConsole()*, fixed formatting bug in *getTimeISO8601(Calendar)*, added more object types in *isEmpty()*
* Some minor code and documentation changes

#### Version 2025.09.02

{% file src="/files/qSVRojom0muVByKRrCs8" %}

* **KCmdArgParser:** new class to parse and retrieve command line arguments
* **K**: Added *isValidHostName(), readConsole(), isMinimumVersion(),* internal optimization in timer methods
* Some minor code and documentation changes

#### Version 2025.06.05

{% file src="/files/jU730kB4xlQe7LvaQPDR" %}

* **K**: Added *concat(), clear(), hexToBytes()*
* **KTimer**: Added *getElapsedNanoseconds()*
* Some minor code and documentation changes

#### Version 2025.05.17

{% file src="/files/Ug8lYTsADrGZ55tQa07N" %}

* **KPasswordVault:** New class to securely hash, store and verify passwords
* **KSMTPMailer**: Added *setLocalFQDNHostName()*
* Updated Sample Code
* Some minor code and documentation changes

#### Version 2025.04.26

{% file src="/files/8moaxaErGr3lUuz6Z2qT" %}

* **K**: Added *repeat(), truncateMiddle(), compressGZIP(), decompressGZIP()*
* Some minor code and documentation changes

#### Version 2025.04.13

{% file src="/files/iIwFbuAHGelAMWBnIblP" %}

* **KHTTPServerThread**: new Class to support HTTP server applications (for web or REST services)
* **K**: Added *getHTTPStatusText()* to return text for a given HTTP status code
* Updated Sample Code
* Some minor code and documentation changes

***

#### Version 2025.03.30

{% file src="/files/Izqezs2J5MN4BrZTjAtj" %}

* **K**: Enhance *toPEM()* to format certificate chain of public keys and add option to describe objects in comments
* Added sample GraalVM macOS native image executable "GetCurrentVersion" in [Tips / FAQ](/examples/tips-faq)
* Some minor code and documentation changes

***

#### Version 2025.03.20

{% file src="/files/mUgm8Cwvpl7VpHjgWvMN" %}

* **K**: Added *loadKeyStore()*, *toPEM()*, *generateRSAKeyPair()*, *encodeHTML()* and *decodeHTML()*
* Updated sample code
* Some minor code and documentation changes

#### Version 2025.03.02

{% file src="/files/wTRdv1YsBd7rgiALq947" %}

* **K:** Added *INSTANCE\_UUID* to identify running application instance
* **KLog**: Added options in *KLog.properties* and application startup parameters (*KLogInclude and KLogExclude)* to include or exclude data from logging
* Some minor code and documentation changes

#### Version 2025.02.26

{% file src="/files/HwuLQC4vX4oXrjhHoTeb" %}

* Publish Java code on GitHub as open source
* **K**: Added *getCurrentVersionNumber()*
* Some minor code and documentation changes

#### Version 2025.02.19

{% file src="/files/MTONX9tXiw6osIODjNGL" %}

* **K**: Added *getPasswordHash*()
* Added HelloWorld example to test installation with *java -jar ch.k43.util.jar*
* Some minor code and documentation changes

#### Version 2025.02.13

{% file src="/files/JZvxcl7EcdINBVXItaY8" %}

* **KTimer**: Added *reset()*
* **K:** Added *saveError()*
* **K**: Added multiple static fields that describe the environment
* Updated [sample code](/downloads/sample-code)
* Some minor code and documentation changes

#### Version 2025.01.27

{% file src="/files/DOHK4XqGwHFNyZsXWL38" %}

* **KHTTPClient**: Added *setTimeOutSec()*
* **KLog**: Added command line parameter *KLogPropertyFile* to override name and location of KLog.properties file
* **KLog**: Added command line parameter *KLogLevel* to override logging level (*INFO*, *ERROR*, *DEBUG* or *OFF*)
* Changed locale of generated JavaDoc output to en\_US
* Some minor code and documentation changes

#### Version 2025.01.22

{% file src="/files/54sMJXjixIt7WWE2iB3m" %}

* **K**: Added *replaceParams()*
* **KHTTPClient**: Treat HTTP return code 200-299 as successful
* **KLog**: Added parameterized logging to all methods, e.g.\
  \&#xNAN;*KLog.error("API call failed - Return code {}", returnCode)*
* Internal code optimization and documentation changes

#### Version 2025.01.19

{% file src="/files/RwlzHgjD1nhqNmltcaH0" %}

* Support for GraalVM native-image compilation (see Tips / FAQ)
* Check if JVM is Java 8 (version 1.8) or higher
* K: Added isNewVersionAvailable()
* Some minor code changes
* Major rewrite of the website content

#### Version 2024.12.08

{% file src="/files/E2MYzZFZsF2BBwY4z2tZ" %}

* **KLog**: Save the last 10 errors even if logging is not active (retrievable with *K.getLastError*() and *K.getLastErrors*()
* **K**: Changed *formatBytes*() to show e.g. MiB instead of MB (IEC standard)
* **K**: Added *getPrivateKey*(), *getPublicKey*() and *getCertificate*()
* Sample code updated
* Some minor code and documentation changes

#### Version 2024.10.26

{% file src="/files/v5OrrUXKZhjrJlgiERiz" %}

* **KDB**: Added option *argTimeOutSec* to exec()
* **KDB**: Added *prepare*() and *execPrepare*() to support SQL precompilation and prevent SQL injection attacks
* Some minor code and documentation changes

#### Version 2024.09.15

{% file src="/files/df3NS7fpSEuz5Qai60IC" %}

* **KLog**: Fix small bug when debug log is active in YAML code

#### Version 2024.09.14

{% file src="/files/E14W8GrzJok7ao7nsgGd" %}

* **KLog**: Added formatter class to write logging as YAML output
* **KDB**: Added *getDataAsYAML*() to output result set as YAML string
* **K**: Added *encodeYAML*() and *decodeYAML*()
* Some minor code and documentation changes

#### Version 2024.09.12

{% file src="/files/akD1ANY1PJ5hbVqEbOvh" %}

* **K**: Added option to *isNumber*() to check for allowed numeric range
* **KLog**: Show CPU count and OS disk size in debug log
* Some minor code and documentation changes

#### Version 2024.09.06

{% file src="/files/g7SC65LEysZx5psZkdaK" %}

* **KThread**: New class for easy Java thread creation and termination
* **K**: Removed *argForce* argument from *stopThread*() as newer Java versions removed the depreciated *Thread.stop*() method

#### Version 2024.09.02

{% file src="/files/onFwCw2nbWJppHRj1pwy" %}

{% hint style="info" %}
**Upgrade Notice**: Make sure you are using the new Jakarta/Angus mail jar files for the *KSMTPMailer* and *KLogSMTPHandler* classes
{% endhint %}

* **KSMTPMailer:** Migrated from JavaMail (javax.mail) to Eclipse Jakarta/Angus mail.
* **KDB**: Added option in *getDataAsTable*() to optionally print column headers
* Some minor code and documentation changes

#### Version 2024.08.29

{% file src="/files/OiqJra6qsnPWKzXrFVQg" %}

* **K**: Added *isInteger*() and *stopThread*()
* **KLogSMTPHandler**: Added logging handler to send error log entries (FATAL log level) to any SMTP server
* Some minor code and documentation changes

#### Version 2024.08.24

{% file src="/files/UdGpchs8evqQA9O59JPy" %}

* **K**: Remove SHA-1 algorithm from *generateHash()*
* **K**: Added *serialize*() and *deserialize*()
* **KDB**: Added maxRows argument to *exec()* call
* Added *toString*() to all classes to write out object data
* Updated [sample code](/downloads/sample-code)
* Some minor code and documentation changes

#### Version 2024.08.12

{% file src="/files/hqOYeCCe1QEPwzwTWQ2D" %}

* Added [architecture overview diagramm](/examples/http-socket-server) for *KSocketServer*
* **K**: added *round()*, *compressZLIB()* and *decompressZLIB()*
* Some minor code and documentation changes

#### Version 2024.07.07

{% file src="/files/BlRwSEggG8y7ZnWZhIz4" %}

* Implemented Java AutoCloseable in **KDB**, **KSocketClient**, **KSocketServer**, **KSocketServerListener** and **KSocketServerThread**&#x20;
* **K**: Added *isNumber()*
* **K**: Added option to *encodeJSON()* to return null, boolean and number values without quotes
* Some minor code and documentation changes

#### Version 2024.06.27

{% file src="/files/arc9nTA281edi2jTjLie" %}

{% hint style="info" %}
**Upgrade Notice**: The *K.getJVMMemStats()* now returns number of bytes (not KB).
{% endhint %}

* **K**: Added *formatBytes()*, updated *getJVMMemStats()* to return number of bytes
* **KDB**: Added *setAutoCommit()* and *getElapsedTime()*
* Some minor code and documentation changes

#### Version 2024.06.22

{% file src="/files/BQnSmPUasgRUXVL11nM5" %}

* **KLog**: New formatter classes to write logging as CSV or XML output
* **KLog**: Adds UUID field to JSON, CSV, XML and JDBC output
* New KLog.properties sample file uploaded
* Some minor code and documentation changes

#### Version 2024.06.20

{% file src="/files/lX375fXiDI9bZVkwisbn" %}

* **K:** Added encode and decode methods for XML
* **KLogJDBCHandler**: Added logging handler to output data to any JDBC compliant database
* **KLog**: Added *getLevel()* and *setLevel()*
* **KDB**: Added *getDataAsXML()*, *commit()* and *rollback()*
* **KSMTPMailer**: Added *setUnsubscribe()*
* New KLog.properties sample file uploaded
* Some minor code and documentation changes

#### Version 2024.06.15

{% file src="/files/xx061fW6RNL3qvJkOVFh" %}

* **KDB**: New class to support JDBC compliant databases with various output formats (JSON, CSV, table or Java objects)
* **KSMTPMailer**: Added *setSubject(string, charset)* for non-UTF-8 subjects
* **KSMTPMailer**: Added *setOAuth2Authentication()* to support OAuth 2.0 authentication
* **K**: Added encode and decode methods for JSON and CSV
* Some minor code and documentation changes

#### Version 2024.06.10

{% file src="/files/w7NbHL2vkVwGgMFwdJOK" %}

{% hint style="info" %}
**Upgrade Notice:** Don't forget to rename Log.properties to *KLog.properties* if you are using the KLog framework.
{% endhint %}

* **KLog**: Log.properties file renamed to *KLog.properties* for consistency with the KLog class
* **K**: Added *runGC()* and *getJVMMemStats()*
* **KSMTPMailer**: Added *addText(string, charset)* for non-UTF-8 text parts
* Include downloads of Jakarta Mail and Jakarta Activation on this website
* Some minor code and document changes

#### Version 2024.06.06

{% file src="/files/dVvSPCudPPVSjwo8Qkci" %}

* **KLog**: Added *setLevelXxx()*, *isLevelXxx()* and *resetLevel()* to set or query the configured logging level during runtime
* **KSMTPMailer**: Added *getMessageSize()* to get size of MIME message after delivery
* **KSMTPMailer**: Include Jakarta Mail debug log in KLog logging output
* **KSMTPMailer**: Removed *X-TLS-Connection* header as there is no guarantee that it is enforced by the SMTP server
* **KTimer**: Added *getStartTime()* and *toString()* to return start time as Calendar object or in ISO-8601 format
* **KSocketServerThread**: Added *writeLine()*
* **K**: Added *getRandomInt()*, *getUTCOffsetMin()* and *getUTCOffsetAsString()*

#### Version 2024.05.24

{% file src="/files/eR0dFmmUI8r6So3fCoGi" %}

* **K**: Added *toHex()* to format byte array or string to a hexadecimal string
* **K**: Added *getUniqueID()* to return unique id (UUID)
* **K**: Added *getCurrentDir()* to return current directory
* **K**: Changed *generateHash()* to support SHA3-256, SHA3-384 ad SHA3-512
* **K**: Added getStartTime() to return date and time of application startup
* **KHTTPClient**: Added *put()*, *patch(),* options() and *delete()* methods&#x20;
* **KSMTPMailer**: Added check for hostname (TLS only)
* Added some [sample code](/downloads/sample-code) to this website
* Some minor code and document changes

#### Version 2024.05.20

{% file src="/files/LVnJuiR7ETKnuZMoJHVn" %}

* **K**: Added *isEmpty()* to test string or array for emptiness
* **KSMTPMailer**: Include platform in *X-Mailer* header
* **KSMTPMailer**: Added header *X-TLS-Connnection: true/false*
* Some code cleanup and documentation changes

#### Version 2024.05.17

{% file src="/files/NuG0uRn2yP6ik7Gt9wD7" %}

* **KSMTPMailer:** New class to compose and send multipart SMTP email with text, HTML and file attachments
* **KSocketServerThread:** Added getAuthenthicatedClientCN() to return  common name of the full distinguished name
* **KSocketClient:** Added getAuthenticatedClient() and  getAuthenticatedClientCN()
* **KFile**: Added readPropertiesFile() and writePropertiesFile()
* **KLog:** Added argException() to throw IllegalArgumentException if expression evaluates true
* **K:** Added dnsQuery() to return records for all query types (MX, A, etc)
* Some minor code and documentation changes

#### Version 2024.05.06

{% file src="/files/IAoHOU0Ox5opC9czOYSF" %}

* First public version


# Sample Code

Here you find some sample code to show the use of the Java Utility Package ch.k43.util. If you have any question, do not hesitate to ask the [author](mailto:andy.brunner@k43.ch).

{% file src="/files/SnyctiDXHLCuwZLHlz5x" %}


