Merge pull request #3 from kneitzel/add-existing-stuff
Add existing stuff
This commit is contained in:
commit
f98e476458
23
README.md
23
README.md
@ -1,23 +1,16 @@
|
|||||||
# NeitzelLib Maven Project
|
# NeitzelLib Maven Project
|
||||||
|
|
||||||
Small Library with classes that I found helpfully or interesting.
|
## A Java Utilities Library
|
||||||
|
|
||||||
The idea is not to diretly use anything from this library. It is only meant to provide some code which could be a quick start when required inside a project. So simply copy the classes that you need.
|
This repository is **not** a production-ready library, but rather a loose collection of small helpers, utilities, and ideas that might come in handy for Java developers.
|
||||||
|
|
||||||
## Components
|
The code in this project is intended as a **starting point** or **inspiration** for your own solutions. It is often easier to copy and adapt individual classes as needed instead of using the whole library as a dependency.
|
||||||
|
|
||||||
### core
|
Feel free to explore, copy, modify, and improve whatever you find useful.
|
||||||
|
|
||||||
This is the core library that does not have special dependencies like JavaFX.
|
> ⚠️ Use at your own discretion — no guarantees of stability, backwards compatibility, or completeness.
|
||||||
|
|
||||||
It contains:
|
---
|
||||||
- **inject** Some small, basic Injection Library (Just a quick start)
|
|
||||||
- **sql** Helper classes to work with SQL in Java
|
|
||||||
|
|
||||||
### fx
|
## License
|
||||||
Library that extends JavaFX or helps with it.
|
This is free and unencumbered software released into the public domain. Please see the [License](LICENSE.md) for details.
|
||||||
|
|
||||||
It contains:
|
|
||||||
- **component** Just a quick start where I experiment with the idea to have JavaFX components which means that we have a View to display a specific Model.
|
|
||||||
- **injectfx** Injection inside JavaFX, main idea is to use constructor injection on FXML controller to include required Elements.
|
|
||||||
- **mvvm** The mvvmFX project seems to get no more updates / is no longer maintained. In this area I am simply playing around with some helper classes to make the use of the mvvm pattern easier through generation of ViewModels. **Currently not really useable**
|
|
||||||
@ -0,0 +1,95 @@
|
|||||||
|
package de.neitzel.core.commandline;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ArgumentProvider class is a helper utility for iterating over an array
|
||||||
|
* of command-line arguments. It provides methods to check for available arguments
|
||||||
|
* and retrieve them in sequence.
|
||||||
|
*
|
||||||
|
* This class is designed to work seamlessly with a command-line parser
|
||||||
|
* and handle tokenized inputs efficiently. It implements the Iterator interface
|
||||||
|
* for ease of iteration.
|
||||||
|
*/
|
||||||
|
public class ArgumentProvider implements Iterator<String> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A String array representing the command-line arguments provided to the application.
|
||||||
|
* This array holds each tokenized element of the command-line input for further parsing
|
||||||
|
* and processing by the application logic. It is used within the {@code ArgumentProvider}
|
||||||
|
* class to iterate through and retrieve arguments systematically.
|
||||||
|
*/
|
||||||
|
private String[] arguments;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks the current position within an array of arguments.
|
||||||
|
*
|
||||||
|
* This variable is used to index into the arguments array, enabling
|
||||||
|
* sequential access to command-line tokens. It is incremented as arguments
|
||||||
|
* are processed or retrieved using methods such as {@code next()} or {@code peek()}
|
||||||
|
* in the {@link ArgumentProvider} class.
|
||||||
|
*
|
||||||
|
* Its value starts at 0 and increases until it reaches the length of
|
||||||
|
* the provided arguments array, at which point iteration ends.
|
||||||
|
*/
|
||||||
|
private int current = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of the ArgumentProvider class to iterate over the given array of arguments.
|
||||||
|
* If the provided array is null, it initializes the arguments with an empty array.
|
||||||
|
*
|
||||||
|
* @param arguments The array of command-line arguments to be iterated over.
|
||||||
|
* If null, it defaults to an empty array.
|
||||||
|
*/
|
||||||
|
public ArgumentProvider(final String[] arguments) {
|
||||||
|
if (arguments == null) {
|
||||||
|
this.arguments = new String[] {};
|
||||||
|
} else {
|
||||||
|
this.arguments = arguments;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if there are more arguments available to iterate over.
|
||||||
|
*
|
||||||
|
* @return true if there are additional arguments available; false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean hasNext() {
|
||||||
|
return current < arguments.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the specified number of additional arguments are available in the collection.
|
||||||
|
*
|
||||||
|
* @param count the number of additional arguments to check for availability
|
||||||
|
* @return true if there are at least the specified number of arguments available, otherwise false
|
||||||
|
*/
|
||||||
|
public boolean hasNext(final int count) {
|
||||||
|
return current + count <= arguments.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the next argument in the sequence.
|
||||||
|
* If no more arguments are available, returns {@code null}.
|
||||||
|
*
|
||||||
|
* @return the next argument as a {@code String}, or {@code null} if no further arguments are available
|
||||||
|
*/
|
||||||
|
public String next() {
|
||||||
|
if (!hasNext()) return null;
|
||||||
|
|
||||||
|
String result = arguments[current];
|
||||||
|
current++;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next argument in the sequence without advancing the iterator.
|
||||||
|
* If there are no more arguments available, this method returns null.
|
||||||
|
*
|
||||||
|
* @return the next argument in the sequence or null if no arguments are available
|
||||||
|
*/
|
||||||
|
public String peek() {
|
||||||
|
if (!hasNext()) return null;
|
||||||
|
return arguments[current];
|
||||||
|
}
|
||||||
|
}
|
||||||
192
core/src/main/java/de/neitzel/core/commandline/Parameter.java
Normal file
192
core/src/main/java/de/neitzel/core/commandline/Parameter.java
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
package de.neitzel.core.commandline;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.extern.log4j.Log4j;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `Parameter` class defines a command-line parameter with associated metadata,
|
||||||
|
* such as constraints on the number of values it accepts, descriptions, and aliases.
|
||||||
|
* It also allows specifying callbacks to handle parameter processing.
|
||||||
|
*
|
||||||
|
* This class is intended to be used as part of a command-line parser, enabling
|
||||||
|
* structured handling of arguments provided via the command line.
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Builder
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class Parameter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a command-line parameter definition within the application.
|
||||||
|
*
|
||||||
|
* This class encapsulates the metadata and configuration of a command-line parameter,
|
||||||
|
* including its name, aliases, descriptions, value constraints, and behavior. Instances
|
||||||
|
* of this class are used to define and manage the parameters that the `Parser` class
|
||||||
|
* recognizes and processes.
|
||||||
|
*
|
||||||
|
* A parameter can be configured as a default parameter or as a help command. The default
|
||||||
|
* parameter serves as a catch-all for unmatched command-line inputs, while the help
|
||||||
|
* command provides usage information for users.
|
||||||
|
*/
|
||||||
|
public Parameter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Parameter with the given attributes.
|
||||||
|
*
|
||||||
|
* @param name The name of the parameter.
|
||||||
|
* @param minNumberValues The minimum number of values allowed for this parameter.
|
||||||
|
* @param maxNumberValues The maximum number of values allowed for this parameter.
|
||||||
|
* @param multipleEntries Indicates whether multiple entries are allowed for this parameter.
|
||||||
|
* @param shortDescription A brief description of the parameter.
|
||||||
|
* @param longDescription A detailed description of the parameter.
|
||||||
|
* @param callback A consumer function that processes a list of values associated with this parameter.
|
||||||
|
* @param isHelpCommand Indicates whether this parameter represents a help command.
|
||||||
|
* @param isDefaultParameter Indicates whether this parameter is the default parameter.
|
||||||
|
* @param aliasList A list of aliases for this parameter.
|
||||||
|
*/
|
||||||
|
public Parameter(String name, int minNumberValues, int maxNumberValues, boolean multipleEntries, String shortDescription, String longDescription, Consumer<List<String>> callback, boolean isHelpCommand, boolean isDefaultParameter, List<String> aliasList) {
|
||||||
|
this.name = name;
|
||||||
|
this.minNumberValues = minNumberValues;
|
||||||
|
this.maxNumberValues = maxNumberValues;
|
||||||
|
this.multipleEntries = multipleEntries;
|
||||||
|
this.shortDescription = shortDescription;
|
||||||
|
this.longDescription = longDescription;
|
||||||
|
this.callback = callback;
|
||||||
|
this.isHelpCommand = isHelpCommand;
|
||||||
|
this.isDefaultParameter = isDefaultParameter;
|
||||||
|
this.aliasList = aliasList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `name` variable represents the primary identifier for a parameter.
|
||||||
|
* This string is used to uniquely identify a command-line parameter when parsing
|
||||||
|
* arguments. It serves as the key for registering and retrieving parameters in a
|
||||||
|
* command-line parser.
|
||||||
|
*
|
||||||
|
* The value of `name` is case-insensitive and can be used alongside aliases to
|
||||||
|
* recognize and process parameters provided in the command-line input.
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the minimum number of values required for this parameter.
|
||||||
|
*
|
||||||
|
* This variable enforces a constraint on the number of arguments that must
|
||||||
|
* be provided for the parameter during command-line parsing. If the number of
|
||||||
|
* provided arguments is less than this value, an exception will be thrown during parsing.
|
||||||
|
*
|
||||||
|
* It is primarily used in validation logic within the command-line parser
|
||||||
|
* to ensure the required input is received for proper processing of the parameter.
|
||||||
|
*/
|
||||||
|
private int minNumberValues;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the maximum number of values that the corresponding parameter can accept.
|
||||||
|
*
|
||||||
|
* This field is used to validate and enforce constraints during command-line parsing.
|
||||||
|
* If more values than specified are provided for a parameter, the parser throws an exception
|
||||||
|
* to indicate a violation of this constraint.
|
||||||
|
*
|
||||||
|
* A value of 0 implies that the parameter does not support any values, while a positive
|
||||||
|
* value indicates the exact maximum limit of acceptable values.
|
||||||
|
*/
|
||||||
|
private int maxNumberValues;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the parameter allows multiple entries.
|
||||||
|
*
|
||||||
|
* If set to {@code true}, the parameter can be specified multiple times
|
||||||
|
* on the command-line. This allows the association of multiple values
|
||||||
|
* or options with the same parameter name.
|
||||||
|
*
|
||||||
|
* If set to {@code false}, the parameter can be specified only once
|
||||||
|
* during command-line parsing.
|
||||||
|
*/
|
||||||
|
private boolean multipleEntries;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A concise, human-readable description of the parameter's purpose and functionality.
|
||||||
|
*
|
||||||
|
* This description provides a brief summary to help users understand the
|
||||||
|
* essential role of the parameter within the command-line parser. It is typically
|
||||||
|
* displayed in usage instructions, help messages, or command summaries.
|
||||||
|
*/
|
||||||
|
private String shortDescription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A detailed, extended description of the parameter's purpose and usage.
|
||||||
|
*
|
||||||
|
* This description provides deeper context about what the parameter represents,
|
||||||
|
* how it fits into the overall command-line application, and any nuances
|
||||||
|
* associated with its use. It is displayed when help or additional documentation
|
||||||
|
* for a specific parameter is requested.
|
||||||
|
*/
|
||||||
|
private String longDescription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback function that processes a list of string arguments for a specific parameter.
|
||||||
|
* The callback is invoked during command-line parsing when a parameter is recognized,
|
||||||
|
* passing the associated values of the parameter for further processing.
|
||||||
|
*
|
||||||
|
* The provided {@link Consumer} implementation defines the logic to
|
||||||
|
* handle or validate the values supplied for a command-line parameter. The values
|
||||||
|
* passed are determined based on the parameter's configuration (e.g., minimum and
|
||||||
|
* maximum number of associated values).
|
||||||
|
*
|
||||||
|
* This field is typically set for the `Parameter` class to enable custom handling
|
||||||
|
* of parameter-specific logic, such as invoking a help command or performing
|
||||||
|
* business logic with the values parsed from the command-line arguments.
|
||||||
|
*/
|
||||||
|
private Consumer<List<String>> callback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the parameter is designated as the help command.
|
||||||
|
*
|
||||||
|
* When set to {@code true}, this parameter is treated as the special help command
|
||||||
|
* within the command-line parser. A parameter marked as the help command typically
|
||||||
|
* provides users with information about available options or detailed descriptions
|
||||||
|
* of specific commands when invoked. If this flag is enabled, a custom callback
|
||||||
|
* method for displaying help context is automatically associated with the parameter.
|
||||||
|
*/
|
||||||
|
private boolean isHelpCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the parameter is designated as the default parameter.
|
||||||
|
*
|
||||||
|
* The default parameter is a special type of parameter that can accept arguments
|
||||||
|
* without an explicit prefix or identifier. It is used when a provided command-line
|
||||||
|
* argument does not match any defined parameter and does not start with a special
|
||||||
|
* character (e.g., '-') typically used to denote named parameters.
|
||||||
|
*
|
||||||
|
* If this field is set to {@code true}, the parameter is treated as the default
|
||||||
|
* parameter. Only one parameter can be assigned this role within the parser.
|
||||||
|
* Attempting to assign multiple default parameters or a default parameter without
|
||||||
|
* accepting values (both `minNumberValues` and `maxNumberValues` set to 0) will
|
||||||
|
* result in an exception during configuration.
|
||||||
|
*
|
||||||
|
* This property is utilized during the parsing process to determine whether an
|
||||||
|
* unmatched argument should be handled as a default parameter value, simplifying
|
||||||
|
* the handling of positional arguments or other unnamed input data.
|
||||||
|
*/
|
||||||
|
private boolean isDefaultParameter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of alias names associated with a parameter.
|
||||||
|
*
|
||||||
|
* This variable holds alternative names that can be used
|
||||||
|
* to reference the parameter in command-line input. Each alias
|
||||||
|
* functions as an equivalent to the primary parameter name.
|
||||||
|
* Aliases are case-insensitive when used within the command-line parser.
|
||||||
|
*
|
||||||
|
* The aliases associated with a parameter allow greater flexibility
|
||||||
|
* and user convenience when specifying parameters during command-line execution.
|
||||||
|
*/
|
||||||
|
@Singular("alias")
|
||||||
|
private List<String> aliasList;
|
||||||
|
}
|
||||||
216
core/src/main/java/de/neitzel/core/commandline/Parser.java
Normal file
216
core/src/main/java/de/neitzel/core/commandline/Parser.java
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
package de.neitzel.core.commandline;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Parser class is responsible for parsing and handling command-line arguments.
|
||||||
|
* It allows for the registration of known parameters and provides mechanisms
|
||||||
|
* to validate and process command-line input.
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class Parser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A map to store parameters where the key is a string representing
|
||||||
|
* the parameter name and the value is the corresponding {@link Parameter} object.
|
||||||
|
*
|
||||||
|
* This map serves as a registry for defining, organizing, and accessing
|
||||||
|
* command-line parameters. Each entry holds a parameter's metadata and
|
||||||
|
* its associated configuration to facilitate effective command-line parsing.
|
||||||
|
*
|
||||||
|
* Key considerations:
|
||||||
|
* - The key represents the primary name of the parameter.
|
||||||
|
* - The value, encapsulated as a {@link Parameter} object, includes
|
||||||
|
* details such as descriptions, value constraints, aliases, and processing logic.
|
||||||
|
*/
|
||||||
|
private Map<String, Parameter> parameters = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `defaultParameter` variable represents the default command-line parameter for a parser.
|
||||||
|
*
|
||||||
|
* This parameter is used to capture arguments that do not explicitly match any named parameter
|
||||||
|
* or alias. It acts as a catch-all for unnamed command-line input, often simplifying the handling
|
||||||
|
* of positional arguments or other free-form input provided by the user.
|
||||||
|
*
|
||||||
|
* It is essential to note:
|
||||||
|
* - Only one parameter can be designated as the default parameter in a command-line parser.
|
||||||
|
* - The parameter must allow values to be processed (e.g., its `minNumberValues` or `maxNumberValues`
|
||||||
|
* should not disallow input).
|
||||||
|
* - This parameter is automatically invoked if an input does not match any explicitly named
|
||||||
|
* parameter or alias in the parser configuration.
|
||||||
|
*
|
||||||
|
* When set to `null`, the parser does not handle unmatched arguments, and unrecognized inputs
|
||||||
|
* may result in an error or exception, depending on the parser's implementation.
|
||||||
|
*/
|
||||||
|
private Parameter defaultParameter = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new instance of the `Parser` class.
|
||||||
|
*
|
||||||
|
* The `Parser` class is responsible for parsing and processing
|
||||||
|
* command-line arguments. It interprets input data based on defined
|
||||||
|
* parameters and provides structured access to arguments, enabling
|
||||||
|
* streamlined application configuration and execution.
|
||||||
|
*
|
||||||
|
* This constructor initializes the parser without any predefined
|
||||||
|
* configuration or parameters. Users can define parameters,
|
||||||
|
* add handlers, and parse command-line arguments using available
|
||||||
|
* methods in the class.
|
||||||
|
*/
|
||||||
|
public Parser() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new parameter to the internal parameter map. The method registers the parameter
|
||||||
|
* using its primary name and all specified aliases (case-insensitive). It also sets up
|
||||||
|
* specific behaviors for help and default parameters based on the parameter's configuration.
|
||||||
|
*
|
||||||
|
* @param parameter the Parameter object to be added. It contains the primary name, aliases,
|
||||||
|
* and other metadata such as whether it is a help command or default parameter.
|
||||||
|
* The parameter must fulfill specific constraints if defined as the default
|
||||||
|
* parameter (e.g., accepting values).
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if the parameter is defined as a default parameter and
|
||||||
|
* does not accept values (both minNumberValues and maxNumberValues
|
||||||
|
* are set to 0).
|
||||||
|
*/
|
||||||
|
public void addParameter(final Parameter parameter) {
|
||||||
|
// Add by name
|
||||||
|
parameters.put(parameter.getName().toLowerCase(), parameter);
|
||||||
|
|
||||||
|
// Add for all aliases
|
||||||
|
for (String alias: parameter.getAliasList()) {
|
||||||
|
parameters.put(alias.toLowerCase(), parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set help Callback for help command.
|
||||||
|
if (parameter.isHelpCommand())
|
||||||
|
parameter.setCallback(this::helpCommandCallback);
|
||||||
|
|
||||||
|
if (parameter.isDefaultParameter()) {
|
||||||
|
if (parameter.getMinNumberValues() == 0 && parameter.getMaxNumberValues() == 0)
|
||||||
|
throw new IllegalArgumentException("Default Parameter must accept values!");
|
||||||
|
|
||||||
|
defaultParameter = parameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a given parameter string matches a valid parameter within the defined constraints.
|
||||||
|
*
|
||||||
|
* @param param the parameter string to be checked. This can either be a key defined in the `parameters` map
|
||||||
|
* or a potential default parameter if it does not start with a dash ("-").
|
||||||
|
* @return {@code true} if the parameter is a valid entry in the `parameters` map or matches the default parameter;
|
||||||
|
* {@code false} otherwise, including when the parameter starts with a dash ("-").
|
||||||
|
*/
|
||||||
|
protected boolean isParameter(final String param) {
|
||||||
|
if (parameters.containsKey(param)) return true;
|
||||||
|
if (param.startsWith("-")) return false;
|
||||||
|
return defaultParameter != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses an array of command-line arguments and processes them as defined by the application's parameters.
|
||||||
|
*
|
||||||
|
* The method iteratively checks each argument in the provided array, validates it against
|
||||||
|
* the registered parameters, and invokes the corresponding processing callback if applicable.
|
||||||
|
* Unrecognized parameters or missing required values will result in an {@code IllegalArgumentException}.
|
||||||
|
*
|
||||||
|
* @param args the array of command-line arguments to be parsed and processed. Each element in this
|
||||||
|
* array represents a single input argument provided to the application. The format and
|
||||||
|
* content of the arguments are expected to conform to the application's parameter definitions.
|
||||||
|
*/
|
||||||
|
public void parse(final String[] args) {
|
||||||
|
ArgumentProvider provider = new ArgumentProvider(args);
|
||||||
|
while (provider.hasNext()) {
|
||||||
|
log.debug("Parsing argument: " + provider.peek());
|
||||||
|
|
||||||
|
// Peek to see the next parameter.
|
||||||
|
String next = provider.peek().toLowerCase();
|
||||||
|
if (!isParameter(next)) {
|
||||||
|
log.error("Unknown Parameter: " + next);
|
||||||
|
throw new IllegalArgumentException("Unknown argument: " + next);
|
||||||
|
}
|
||||||
|
|
||||||
|
Parameter parameter = parameters.get(next);
|
||||||
|
if (parameter == null) {
|
||||||
|
parameter = defaultParameter;
|
||||||
|
} else {
|
||||||
|
provider.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!provider.hasNext(parameter.getMinNumberValues())) {
|
||||||
|
String message = "Parameter " + next + " requires " + parameter.getMinNumberValues() + " more elements!";
|
||||||
|
log.error(message);
|
||||||
|
throw new IllegalArgumentException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
parameter.getCallback().accept(getOptions(provider, parameter.getMinNumberValues(), parameter.getMaxNumberValues()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a list of options by consuming arguments from the provided {@link ArgumentProvider}
|
||||||
|
* within the range specified by the minimum and maximum values.
|
||||||
|
*
|
||||||
|
* @param provider The source providing the command-line arguments. This object allows
|
||||||
|
* retrieving and examining argument strings in sequence.
|
||||||
|
* @param min The minimum number of arguments to be retrieved. If fewer arguments
|
||||||
|
* are available, no arguments will be added to the result.
|
||||||
|
* @param max The maximum number of arguments to be retrieved. If `max` is smaller
|
||||||
|
* than `min`, it will be adjusted to match `min`. Only up to `max`
|
||||||
|
* arguments will be added to the result.
|
||||||
|
* @return A list of argument strings, containing up to `max` elements and at least `min`
|
||||||
|
* elements if sufficient arguments are available. The list will not include
|
||||||
|
* arguments already recognized in the `parameters` map.
|
||||||
|
*/
|
||||||
|
private List<String> getOptions(ArgumentProvider provider, int min, int max) {
|
||||||
|
if (max < min) max = min;
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
|
||||||
|
int current = 0;
|
||||||
|
while (current < max && provider.hasNext()) {
|
||||||
|
if (current < min || !parameters.containsKey(provider.peek())) {
|
||||||
|
result.add(provider.next());
|
||||||
|
current++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the help command when invoked in the command-line interface, providing information about available parameters.
|
||||||
|
* If no arguments are provided, it lists all possible parameters and their short descriptions.
|
||||||
|
* If specific arguments are supplied, it provides the detailed description of the corresponding parameter.
|
||||||
|
* In case an unknown parameter is specified, it indicates so to the user.
|
||||||
|
*
|
||||||
|
* @param arguments a list of strings representing the user-provided arguments. If empty or {@code null},
|
||||||
|
* the method lists all available parameters with their short descriptions. If a parameter name
|
||||||
|
* is provided in the list, its detailed information is displayed. If an unrecognized parameter
|
||||||
|
* is provided, a corresponding message is shown.
|
||||||
|
*/
|
||||||
|
public void helpCommandCallback(final List<String> arguments) {
|
||||||
|
if (arguments == null || arguments.size() == 0) {
|
||||||
|
System.out.println("Moegliche Parameter der Applikation:");
|
||||||
|
parameters.values().stream()
|
||||||
|
.distinct()
|
||||||
|
.sorted(Comparator.comparing(Parameter::getName))
|
||||||
|
.forEach(p -> System.out.println(p.getShortDescription() ));
|
||||||
|
} else {
|
||||||
|
Parameter parameter = null;
|
||||||
|
if (parameters.containsKey(arguments.get(0))) parameter = parameters.get(arguments.get(0));
|
||||||
|
if (parameters.containsKey("-" + arguments.get(0))) parameter = parameters.get("-" + arguments.get(0));
|
||||||
|
|
||||||
|
if (parameter == null) {
|
||||||
|
System.out.println("Unbekannter Parameter: " + arguments.get(0));
|
||||||
|
} else {
|
||||||
|
System.out.println(parameter.getLongDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
268
core/src/main/java/de/neitzel/core/config/Configuration.java
Normal file
268
core/src/main/java/de/neitzel/core/config/Configuration.java
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
package de.neitzel.core.config;
|
||||||
|
|
||||||
|
import de.neitzel.core.util.FileUtils;
|
||||||
|
import de.neitzel.core.util.Strings;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a utility class for managing configuration properties in an
|
||||||
|
* application. This class allows loading properties from files, accessing
|
||||||
|
* values with various types including environment variable substitution,
|
||||||
|
* and updating properties.
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class Configuration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link Properties} object that stores a set of key-value pairs.
|
||||||
|
* This variable can be used to manage configuration settings or other
|
||||||
|
* collections of properties within the application.
|
||||||
|
*
|
||||||
|
* It provides methods to load, retrieve, and modify properties
|
||||||
|
* as necessary for the application's requirements.
|
||||||
|
*/
|
||||||
|
private final Properties properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Configuration instance with default properties.
|
||||||
|
* This constructor initializes the Configuration object using an
|
||||||
|
* empty set of {@code Properties}.
|
||||||
|
*/
|
||||||
|
public Configuration() {
|
||||||
|
this(new Properties());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Configuration instance using the provided properties.
|
||||||
|
*
|
||||||
|
* @param properties the Properties object containing configuration key-value pairs
|
||||||
|
*/
|
||||||
|
public Configuration(Properties properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a boolean property value associated with the specified key. If the key does not exist in the properties,
|
||||||
|
* the provided default value is returned. The method also supports interpreting specific string values as true.
|
||||||
|
*
|
||||||
|
* @param key the key used to retrieve the boolean property
|
||||||
|
* @param defaultValue the default value returned if the key is not found in the properties
|
||||||
|
* @return the boolean value associated with the key, or the defaultValue if the key does not exist
|
||||||
|
*/
|
||||||
|
protected boolean getBooleanProperty(final String key, final boolean defaultValue) {
|
||||||
|
if (!properties.containsKey(key)) return defaultValue;
|
||||||
|
return getStringProperty(key, defaultValue ? "ja": "nein").equalsIgnoreCase("ja") || properties.getProperty(key).equalsIgnoreCase("true");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value of the specified property as a trimmed string.
|
||||||
|
* If the property is not found, the default value is returned.
|
||||||
|
*
|
||||||
|
* @param key the key of the property to retrieve
|
||||||
|
* @param defaultValue the default value to return if the property is not found
|
||||||
|
* @return the trimmed string value of the property, or the default value if the property is not found
|
||||||
|
*/
|
||||||
|
protected String getStringProperty(final String key, final String defaultValue) {
|
||||||
|
if (!properties.containsKey(key)) return defaultValue;
|
||||||
|
return properties.getProperty(key).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a string property value associated with the specified key, applies
|
||||||
|
* environment variable expansion on the value, and returns the processed result.
|
||||||
|
*
|
||||||
|
* @param key the key identifying the property to retrieve.
|
||||||
|
* @param defaultValue the default value to use if the property is not found.
|
||||||
|
* @return the processed property value with expanded environment variables, or
|
||||||
|
* the defaultValue if the property is not found.
|
||||||
|
*/
|
||||||
|
protected String getStringPropertyWithEnv(final String key, final String defaultValue) {
|
||||||
|
String result = getStringProperty(key, defaultValue);
|
||||||
|
return Strings.expandEnvironmentVariables(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value of a string property associated with the specified key,
|
||||||
|
* removes any surrounding quotes from the value, and returns the resultant string.
|
||||||
|
*
|
||||||
|
* @param key the key associated with the desired property
|
||||||
|
* @param defaultValue the default value to return if the property is not found or is null
|
||||||
|
* @return the string property without surrounding quotes, or the defaultValue if the property is not found
|
||||||
|
*/
|
||||||
|
protected String getStringPropertyWithoutQuotes(final String key, final String defaultValue) {
|
||||||
|
return Strings.removeQuotes(getStringProperty(key, defaultValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the string value of a configuration property identified by the given key,
|
||||||
|
* removes surrounding quotes if present, and expands any environment variables found
|
||||||
|
* within the string. If the property is not found, a default value is used.
|
||||||
|
*
|
||||||
|
* @param key the key identifying the configuration property
|
||||||
|
* @param defaultValue the default value to use if the property is not found
|
||||||
|
* @return the processed string property with quotes removed and environment variables expanded
|
||||||
|
*/
|
||||||
|
protected String getStringPropertyWithoutQuotesWithEnv(final String key, final String defaultValue) {
|
||||||
|
String result = getStringPropertyWithoutQuotes(key, defaultValue);
|
||||||
|
return Strings.expandEnvironmentVariables(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the integer value for the specified property key. If the key does
|
||||||
|
* not exist in the properties or the value is null/empty, the provided default
|
||||||
|
* value is returned.
|
||||||
|
*
|
||||||
|
* @param key the property key to retrieve the value for
|
||||||
|
* @param defaultValue the default value to return if the key is not present
|
||||||
|
* or the value is null/empty
|
||||||
|
* @return the integer value associated with the key, or the defaultValue if
|
||||||
|
* the key does not exist or its value is null/empty
|
||||||
|
*/
|
||||||
|
protected Integer getIntegerProperty(final String key, final Integer defaultValue) {
|
||||||
|
if (!properties.containsKey(key)) return defaultValue;
|
||||||
|
String value = properties.getProperty(key);
|
||||||
|
return Strings.isNullOrEmpty(value) ? null : Integer.parseInt(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an integer property in the properties object. If the provided value is null,
|
||||||
|
* an empty string will be stored as the property's value.
|
||||||
|
*
|
||||||
|
* @param key the key under which the property will be stored
|
||||||
|
* @param value the integer value to be stored; if null, an empty string will be used
|
||||||
|
*/
|
||||||
|
protected void setIntegerProperty(final String key, final Integer value) {
|
||||||
|
if (value == null) {
|
||||||
|
properties.setProperty(key, "");
|
||||||
|
} else {
|
||||||
|
properties.setProperty(key, ""+value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a LocalDate value from the properties based on the provided key.
|
||||||
|
* If the key does not exist or the value is invalid, a default value is returned.
|
||||||
|
*
|
||||||
|
* @param key the key to look up the property in the properties map
|
||||||
|
* @param defaultValue the default LocalDate value to return if the key is not found
|
||||||
|
* @param formatString the format string to parse the LocalDate value
|
||||||
|
* @return the LocalDate value from the properties if available and valid,
|
||||||
|
* otherwise the defaultValue
|
||||||
|
*/
|
||||||
|
protected LocalDate getLocalDateProperty(final String key, final LocalDate defaultValue, final String formatString) {
|
||||||
|
if (!properties.containsKey(key)) return defaultValue;
|
||||||
|
|
||||||
|
String value = properties.getProperty(key);
|
||||||
|
if (value == null || value.isEmpty()) return null;
|
||||||
|
return LocalDate.parse(value, DateTimeFormatter.ofPattern(formatString));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a property with the given key and a formatted LocalDate value.
|
||||||
|
* If the provided value is null, the property will be set to an empty string.
|
||||||
|
*
|
||||||
|
* @param key the key of the property to set
|
||||||
|
* @param value the LocalDate value to format and set as the property value
|
||||||
|
* @param formatString the pattern string used to format the LocalDate value
|
||||||
|
*/
|
||||||
|
protected void setLocalDateProperty(final String key, final LocalDate value, final String formatString) {
|
||||||
|
if (value == null) {
|
||||||
|
setProperty(key, "");
|
||||||
|
} else {
|
||||||
|
setProperty(key, value.format(DateTimeFormatter.ofPattern(formatString)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a property with the specified key to the given value. If the value is null,
|
||||||
|
* it defaults to an empty string. Logs the operation and updates the property.
|
||||||
|
*
|
||||||
|
* @param key the key of the property to be set
|
||||||
|
* @param value the value to be associated with the specified key; defaults to an empty string if null
|
||||||
|
*/
|
||||||
|
public void setProperty(final String key, final String value) {
|
||||||
|
String newValue = value == null ? "" : value;
|
||||||
|
log.info("Setting a new value for '" + key + "': '" + newValue + "'");
|
||||||
|
properties.setProperty(key, newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the content of the specified file using the provided file name.
|
||||||
|
*
|
||||||
|
* @param fileName the name of the file to be loaded
|
||||||
|
*/
|
||||||
|
public void load(final String fileName) {
|
||||||
|
load(fileName, Charset.defaultCharset().name(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the configuration from a specified file. If the file does not exist in the
|
||||||
|
* specified location, it attempts to find the file alongside the JAR file of the application.
|
||||||
|
* Reads the configuration with the provided encoding and an option to accept UTF-8 encoding.
|
||||||
|
*
|
||||||
|
* @param fileName the name of the configuration file to be loaded
|
||||||
|
* @param encoding the encoding format to be used while reading the configuration file
|
||||||
|
* @param acceptUTF8 a boolean flag indicating whether to accept UTF-8 encoding
|
||||||
|
*/
|
||||||
|
public void load(final String fileName, final String encoding, final boolean acceptUTF8) {
|
||||||
|
log.info("Reading Config: " + fileName + " with encoding: " + encoding + "accepting UTF-8: " + acceptUTF8);
|
||||||
|
File configFile = new File(fileName);
|
||||||
|
|
||||||
|
// Try to get the file next to the jar file if the configFile does not exist.
|
||||||
|
if (!configFile.exists()) {
|
||||||
|
try {
|
||||||
|
String fileAtJar = new File(Configuration.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParent() + "/" + fileName;
|
||||||
|
configFile = new File(fileAtJar);
|
||||||
|
} catch (URISyntaxException ex) {
|
||||||
|
log.error("Unable to get path of jar file / class.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the configuration file if it exists.
|
||||||
|
if (configFile.exists()) {
|
||||||
|
log.info("Reading Configuration file. " + configFile.getAbsolutePath());
|
||||||
|
try (InputStreamReader reader = FileUtils.createUniversalFileReader(configFile, encoding, acceptUTF8)) {
|
||||||
|
log.info("Reading the configuration with encoding: " + reader.getEncoding());
|
||||||
|
properties.load(reader);
|
||||||
|
} catch (FileNotFoundException fnfe) {
|
||||||
|
log.error("Configuration file: " + fileName + " not found!", fnfe);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
log.error("Cannot read config file.", ioe);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.error("Unable to load config file! Last try: " + configFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges the properties from the provided configuration into the current configuration.
|
||||||
|
*
|
||||||
|
* @param config the Configuration object whose properties will be merged into this instance
|
||||||
|
*/
|
||||||
|
public void merge(final Configuration config) {
|
||||||
|
for(Map.Entry<Object, Object> entry: config.properties.entrySet()) {
|
||||||
|
properties.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the specified key-value pair from the properties map if the key exists.
|
||||||
|
*
|
||||||
|
* @param key the key to be removed from the properties map
|
||||||
|
*/
|
||||||
|
public void remove(final String key){
|
||||||
|
if (properties.containsKey(key)) properties.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,103 @@
|
|||||||
|
package de.neitzel.core.io;
|
||||||
|
|
||||||
|
import de.neitzel.core.util.FileUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.IllegalCharsetNameException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ConvertedEncodingFileReader class extends {@link InputStreamReader} to provide functionality
|
||||||
|
* for handling file encoding conversion transparently. If a file is detected to be in UTF-8 encoding,
|
||||||
|
* this class converts it to the specified target encoding using a temporary file, then opens the reader
|
||||||
|
* with the converted encoding. If the file is already in the target encoding, it opens the reader directly.
|
||||||
|
*
|
||||||
|
* This class is useful for applications needing to process text files in specific encodings and ensures
|
||||||
|
* encoding compatibility.
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class ConvertedEncodingFileReader extends InputStreamReader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `checkEncoding` variable specifies the default encoding to be used
|
||||||
|
* when verifying file encodings within the `ConvertedEncodingFileReader` class.
|
||||||
|
* This encoding is primarily used to determine whether a file needs conversion
|
||||||
|
* to the target format or can be read directly in its existing format.
|
||||||
|
* The default value is set to "ISO-8859-15".
|
||||||
|
*
|
||||||
|
* Modifying this variable requires careful consideration, as it affects
|
||||||
|
* the behavior of methods that rely on encoding validation, particularly
|
||||||
|
* in the process of detecting UTF-8 files or converting them during file reading.
|
||||||
|
*/
|
||||||
|
private static String checkEncoding = "ISO-8859-15";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the encoding that will be used to check the file encoding for compatibility.
|
||||||
|
* Throws an exception if the specified encoding is not valid or supported.
|
||||||
|
*
|
||||||
|
* @param encoding the name of the character encoding to set as the check encoding;
|
||||||
|
* it must be a valid and supported Charset.
|
||||||
|
* @throws IllegalCharsetNameException if the specified encoding is not valid or supported.
|
||||||
|
*/
|
||||||
|
private static void setCheckEncoding(final String encoding) {
|
||||||
|
if (Charset.forName(encoding) != null) throw new IllegalCharsetNameException("Encoding " + encoding + " is not supported!");
|
||||||
|
|
||||||
|
checkEncoding = encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a ConvertedEncodingFileReader for a specified file and target encoding format.
|
||||||
|
* The class reads the provided file and ensures that its content is handled in the target encoding.
|
||||||
|
* If the file is not already in the target encoding, it converts the file's encoding
|
||||||
|
* transparently using a temporary file before reading it.
|
||||||
|
*
|
||||||
|
* @param file The file to be read. Must exist and be accessible.
|
||||||
|
* @param targetFormat The target character encoding format to which the file content should be converted.
|
||||||
|
* @throws IOException If the file does not exist, is inaccessible, or an error occurs during the encoding conversion process.
|
||||||
|
*/
|
||||||
|
public ConvertedEncodingFileReader(final File file, final String targetFormat) throws IOException {
|
||||||
|
super(createTargetFormatInputFileStream(file, targetFormat), targetFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a ConvertedEncodingFileReader for reading a file with encoding conversion support.
|
||||||
|
* This constructor takes the file path as a string and ensures the file's encoding is either
|
||||||
|
* converted to the specified target format or read directly if it matches the target format.
|
||||||
|
*
|
||||||
|
* @param filename the path to the file to be read
|
||||||
|
* @param targetFormat the target encoding format to use for reading the file
|
||||||
|
* @throws IOException if an I/O error occurs while accessing or reading the specified file
|
||||||
|
*/
|
||||||
|
public ConvertedEncodingFileReader(final String filename, final String targetFormat) throws IOException {
|
||||||
|
this(new File(filename), targetFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an input file stream for a given file, converting its encoding if necessary.
|
||||||
|
* If the file is not in UTF-8 encoding, a direct {@link FileInputStream} is returned for the file.
|
||||||
|
* If the file is in UTF-8 encoding, it is converted to the specified target format using a temporary file,
|
||||||
|
* and then an input stream for the temporary file is returned.
|
||||||
|
*
|
||||||
|
* @param file the file for which the input stream is to be created
|
||||||
|
* @param targetFormat the desired target encoding format
|
||||||
|
* @return a {@link FileInputStream} for the file or a temporary file with converted encoding
|
||||||
|
* @throws IOException if the file does not exist or an error occurs during file operations
|
||||||
|
*/
|
||||||
|
private static FileInputStream createTargetFormatInputFileStream(final File file, final String targetFormat) throws IOException {
|
||||||
|
if (!file.exists()) {
|
||||||
|
String errorMessage = "File " + file.toString() + " does not exist!";
|
||||||
|
log.error(errorMessage);
|
||||||
|
throw new FileNotFoundException(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FileUtils.isUTF8(file, checkEncoding)) {
|
||||||
|
return new FileInputStream(file);
|
||||||
|
} else {
|
||||||
|
File tempFile = File.createTempFile(file.getName(), "tmp");
|
||||||
|
FileUtils.convertTextFile(file, "UTF-8", tempFile, targetFormat);
|
||||||
|
tempFile.deleteOnExit();
|
||||||
|
return new FileInputStream(tempFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
package de.neitzel.core.io;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ISO8859EncodingFileReader class extends the ConvertedEncodingFileReader to provide
|
||||||
|
* file reading functionality with specific encoding support for ISO-8859-15.
|
||||||
|
* This class ensures that the file content is either read directly in the ISO-8859-15 encoding
|
||||||
|
* or converted transparently to this encoding if needed.
|
||||||
|
*/
|
||||||
|
public class ISO8859EncodingFileReader extends ConvertedEncodingFileReader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the target encoding format used by the ISO8859EncodingFileReader class.
|
||||||
|
* The TARGET_FORMAT is set to "ISO-8859-15", which specifies an encoding standard
|
||||||
|
* that is a variant of ISO-8859-1, adding the Euro symbol and other additional characters.
|
||||||
|
* This constant is used to indicate the desired character encoding for reading file content.
|
||||||
|
*/
|
||||||
|
private static final String TARGET_FORMAT = "ISO-8859-15";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance of ISO8859EncodingFileReader to read the provided file
|
||||||
|
* while ensuring the encoding is set to ISO-8859-15. If the file is not in the
|
||||||
|
* target encoding, this method transparently converts the file content to match
|
||||||
|
* the encoding before reading.
|
||||||
|
*
|
||||||
|
* @param file The file to be read. Must exist and be accessible.
|
||||||
|
* @throws IOException If the file does not exist, is inaccessible, or an error
|
||||||
|
* occurs during the encoding conversion process.
|
||||||
|
*/
|
||||||
|
public ISO8859EncodingFileReader(File file) throws IOException {
|
||||||
|
super(file, TARGET_FORMAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an ISO8859EncodingFileReader for reading a file with encoding conversion
|
||||||
|
* to the ISO-8859-15 format. This constructor accepts the file path as a string.
|
||||||
|
*
|
||||||
|
* @param filename the path to the file to be read
|
||||||
|
* @throws IOException if an I/O error occurs while accessing or reading the specified file
|
||||||
|
*/
|
||||||
|
public ISO8859EncodingFileReader(String filename) throws IOException {
|
||||||
|
super(filename, TARGET_FORMAT);
|
||||||
|
}
|
||||||
|
}
|
||||||
96
core/src/main/java/de/neitzel/core/io/StringEncoder.java
Normal file
96
core/src/main/java/de/neitzel/core/io/StringEncoder.java
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package de.neitzel.core.io;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for encoding and decoding strings.
|
||||||
|
* This class provides methods for transforming strings into encoded representations
|
||||||
|
* and decoding them back to the original representation.
|
||||||
|
*/
|
||||||
|
public class StringEncoder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent instantiation of the utility class.
|
||||||
|
* This utility class is not meant to be instantiated, as it only provides
|
||||||
|
* static utility methods for array-related operations.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always, to indicate that this class
|
||||||
|
* should not be instantiated.
|
||||||
|
*/
|
||||||
|
private StringEncoder() {
|
||||||
|
throw new UnsupportedOperationException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a string containing encoded characters back to its original representation.
|
||||||
|
* Encoded characters are expected to be in the format {@code "&#<code>;<code>"}, where
|
||||||
|
* {@code <code>} is a numeric representation of the character to decode.
|
||||||
|
*
|
||||||
|
* @param data the string to decode; may contain encoded characters or regular text. If null, an empty string is returned.
|
||||||
|
* @return the decoded string with all encoded characters replaced by their original representations.
|
||||||
|
* @throws IllegalArgumentException if the input string has encoding markup
|
||||||
|
* that is improperly formatted or incomplete.
|
||||||
|
*/
|
||||||
|
public static String decodeData(final String data) {
|
||||||
|
if (data == null) return "";
|
||||||
|
|
||||||
|
String remaining = data;
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
while (!remaining.isEmpty()) {
|
||||||
|
int indexAmp = remaining.indexOf("&");
|
||||||
|
if (indexAmp == -1) {
|
||||||
|
result.append(remaining);
|
||||||
|
remaining="";
|
||||||
|
} else {
|
||||||
|
// First get the elements till the &
|
||||||
|
if (indexAmp > 0) {
|
||||||
|
result.append(remaining.substring(0, indexAmp));
|
||||||
|
remaining = remaining.substring(indexAmp);
|
||||||
|
}
|
||||||
|
int endSpecial=remaining.indexOf(";");
|
||||||
|
if (endSpecial == -1) throw new IllegalArgumentException("String couldn't be decoded! (" + data + ")");
|
||||||
|
String special = remaining.substring(0, endSpecial+1);
|
||||||
|
remaining = remaining.substring(endSpecial+1);
|
||||||
|
result.append(decodeCharacter(special));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a character from its numeric character reference representation.
|
||||||
|
* The input string must represent an encoded character in the format {@code "&#<code_point>;"}.
|
||||||
|
*
|
||||||
|
* @param data the string containing the numeric character reference to decode.
|
||||||
|
* It must start with {@code "&#"} and end with {@code ";"}.
|
||||||
|
* @return the decoded character represented by the numeric character reference.
|
||||||
|
* @throws IllegalArgumentException if the input string does not follow the expected format.
|
||||||
|
*/
|
||||||
|
public static char decodeCharacter(final String data) {
|
||||||
|
if (!data.startsWith("&#")) throw new IllegalArgumentException("Data does not start with &# (" + data + ")");
|
||||||
|
if (!data.endsWith(";")) throw new IllegalArgumentException("Data does not end with ; (" + data + ")");
|
||||||
|
return (char)Integer.parseInt(data.substring(2, data.length()-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the provided string by converting characters outside the ASCII range (32-127)
|
||||||
|
* and the ampersand {@code "&"} character into their corresponding numeric character reference
|
||||||
|
* representation (e.g., {@code "&"}).
|
||||||
|
*
|
||||||
|
* @param data the input string to encode; if null, an empty string is returned
|
||||||
|
* @return an encoded string where non-ASCII and ampersand characters
|
||||||
|
* are replaced with numeric character references
|
||||||
|
*/
|
||||||
|
public static String encodeData(final String data) {
|
||||||
|
if (data == null) return "";
|
||||||
|
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for (int index=0; index < data.length(); index++) {
|
||||||
|
char character = data.charAt(index);
|
||||||
|
if (character < 32 || character > 127 || character == 38) {
|
||||||
|
result.append("&#" + (int)character + ";");
|
||||||
|
} else {
|
||||||
|
result.append(character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,6 +10,18 @@ import javax.sound.sampled.SourceDataLine;
|
|||||||
* It allows playing tones based on frequency or predefined tone names.
|
* It allows playing tones based on frequency or predefined tone names.
|
||||||
*/
|
*/
|
||||||
public class ToneGenerator {
|
public class ToneGenerator {
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent instantiation of the utility class.
|
||||||
|
* This utility class is not meant to be instantiated, as it only provides
|
||||||
|
* static utility methods for array-related operations.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always, to indicate that this class
|
||||||
|
* should not be instantiated.
|
||||||
|
*/
|
||||||
|
private ToneGenerator() {
|
||||||
|
throw new UnsupportedOperationException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plays a tone based on a predefined tone name for a specified duration.
|
* Plays a tone based on a predefined tone name for a specified duration.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -13,6 +13,18 @@ import java.util.HashMap;
|
|||||||
* frequency information for specific tones.
|
* frequency information for specific tones.
|
||||||
*/
|
*/
|
||||||
public class ToneTable {
|
public class ToneTable {
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent instantiation of the utility class.
|
||||||
|
* This utility class is not meant to be instantiated, as it only provides
|
||||||
|
* static utility methods for array-related operations.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always, to indicate that this class
|
||||||
|
* should not be instantiated.
|
||||||
|
*/
|
||||||
|
private ToneTable() {
|
||||||
|
throw new UnsupportedOperationException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A static map that associates written tone names with their corresponding frequencies in hertz (Hz).
|
* A static map that associates written tone names with their corresponding frequencies in hertz (Hz).
|
||||||
* The keys represent tone names (e.g., "C4", "D#5"), and the values are their respective frequencies.
|
* The keys represent tone names (e.g., "C4", "D#5"), and the values are their respective frequencies.
|
||||||
|
|||||||
@ -22,7 +22,6 @@ import java.util.stream.StreamSupport;
|
|||||||
* @param <T> The type of the objects returned by the query.
|
* @param <T> The type of the objects returned by the query.
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class Query<T> {
|
public class Query<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,6 +68,15 @@ public class Query<T> {
|
|||||||
*/
|
*/
|
||||||
private String queryText;
|
private String queryText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Query object with the given database connection.
|
||||||
|
*
|
||||||
|
* @param connection The Connection object used to interact with the database.
|
||||||
|
*/
|
||||||
|
public Query(Connection connection) {
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the given SQL query using the provided database connection.
|
* Executes the given SQL query using the provided database connection.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -18,7 +18,6 @@ import java.util.Map;
|
|||||||
* If any additional behaviors or transformations are applied, they are documented
|
* If any additional behaviors or transformations are applied, they are documented
|
||||||
* in the respective overridden method descriptions.
|
* in the respective overridden method descriptions.
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class TrimmingResultSet implements ResultSet {
|
public class TrimmingResultSet implements ResultSet {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,6 +31,15 @@ public class TrimmingResultSet implements ResultSet {
|
|||||||
*/
|
*/
|
||||||
private final ResultSet resultSet;
|
private final ResultSet resultSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new instance of the TrimmingResultSet class, wrapping the provided ResultSet.
|
||||||
|
*
|
||||||
|
* @param resultSet the ResultSet to be wrapped and processed by this TrimmingResultSet instance
|
||||||
|
*/
|
||||||
|
public TrimmingResultSet(ResultSet resultSet) {
|
||||||
|
this.resultSet = resultSet;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the string value from the specified column index of the current row in the ResultSet.
|
* Retrieves the string value from the specified column index of the current row in the ResultSet.
|
||||||
* The value is trimmed to remove leading and trailing whitespace. If the value is null, it returns null.
|
* The value is trimmed to remove leading and trailing whitespace. If the value is null, it returns null.
|
||||||
|
|||||||
78
core/src/main/java/de/neitzel/core/util/ArrayUtils.java
Normal file
78
core/src/main/java/de/neitzel/core/util/ArrayUtils.java
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
package de.neitzel.core.util;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class providing helper methods for working with arrays.
|
||||||
|
*/
|
||||||
|
public class ArrayUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent instantiation of the utility class.
|
||||||
|
* This utility class is not meant to be instantiated, as it only provides
|
||||||
|
* static utility methods for array-related operations.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always, to indicate that this class
|
||||||
|
* should not be instantiated.
|
||||||
|
*/
|
||||||
|
private ArrayUtils() {
|
||||||
|
throw new UnsupportedOperationException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given character array contains the specified character.
|
||||||
|
*
|
||||||
|
* @param array the character array to be searched
|
||||||
|
* @param ch the character to search for in the array
|
||||||
|
* @return true if the character is found in the array, false otherwise
|
||||||
|
*/
|
||||||
|
public static boolean contains(char[] array, char ch) {
|
||||||
|
for(int index=0; index < array.length; index++) {
|
||||||
|
if (array[index] == ch) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the specified integer array contains the given integer value.
|
||||||
|
*
|
||||||
|
* @param array the array of integers to search
|
||||||
|
* @param ch the integer value to search for in the array
|
||||||
|
* @return true if the array contains the specified integer value, false otherwise
|
||||||
|
*/
|
||||||
|
public static boolean contains(int[] array, int ch) {
|
||||||
|
for(int index=0; index < array.length; index++) {
|
||||||
|
if (array[index] == ch) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the specified long array contains the given long value.
|
||||||
|
*
|
||||||
|
* @param array the array of long values to search
|
||||||
|
* @param ch the long value to search for in the array
|
||||||
|
* @return true if the array contains the specified long value, false otherwise
|
||||||
|
*/
|
||||||
|
public static boolean contains(long[] array, long ch) {
|
||||||
|
for(int index=0; index < array.length; index++) {
|
||||||
|
if (array[index] == ch) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the specified array contains the given element.
|
||||||
|
*
|
||||||
|
* @param array the array to be searched
|
||||||
|
* @param ch the element to search for in the array
|
||||||
|
* @param <T> the type of the elements in the array
|
||||||
|
* @return true if the element is found in the array, false otherwise
|
||||||
|
*/
|
||||||
|
public static <T> boolean contains(T[] array, T ch) {
|
||||||
|
for(int index=0; index < array.length; index++) {
|
||||||
|
if (Objects.equals(array[index], ch)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
79
core/src/main/java/de/neitzel/core/util/EnumUtil.java
Normal file
79
core/src/main/java/de/neitzel/core/util/EnumUtil.java
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package de.neitzel.core.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for working with Enum types, providing methods to parse and generate
|
||||||
|
* patterns for Enum flags.
|
||||||
|
*/
|
||||||
|
public class EnumUtil {
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent instantiation of the utility class.
|
||||||
|
* This utility class is not meant to be instantiated, as it only provides
|
||||||
|
* static utility methods for array-related operations.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always, to indicate that this class
|
||||||
|
* should not be instantiated.
|
||||||
|
*/
|
||||||
|
private EnumUtil() {
|
||||||
|
throw new UnsupportedOperationException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a regular expression pattern that matches all possible case-insensitive representations
|
||||||
|
* of the enum constants within the specified Enum class. The pattern also includes optional delimiters
|
||||||
|
* such as commas, spaces, and empty values, enabling the matching of lists or sequences of flag values.
|
||||||
|
*
|
||||||
|
* @param <T> The type of the Enum.
|
||||||
|
* @param clazz The Enum class for which the regular expression is to be generated.
|
||||||
|
* @return A String containing the regular expression pattern for matching the Enum's flag values.
|
||||||
|
*/
|
||||||
|
public static <T extends Enum<T>> String getFlagRegEx(Class<T> clazz) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
result.append("(|,|\\s");
|
||||||
|
|
||||||
|
for (T flag: clazz.getEnumConstants()) {
|
||||||
|
result.append("|");
|
||||||
|
for(char ch: flag.toString().toUpperCase().toCharArray()) {
|
||||||
|
if (Character.isAlphabetic(ch)) {
|
||||||
|
result.append("[");
|
||||||
|
result.append(ch);
|
||||||
|
result.append(Character.toLowerCase(ch));
|
||||||
|
result.append("]");
|
||||||
|
} else {
|
||||||
|
result.append(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.append(")*");
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a delimited string containing Enum constant names into a list of Enum constants.
|
||||||
|
*
|
||||||
|
* This method takes an Enum class and a string of flags, splits the string by commas
|
||||||
|
* or whitespace, and converts each substring into an Enum constant of the given class.
|
||||||
|
* The flag names are case-insensitive and will be converted to uppercase before matching
|
||||||
|
* to the Enum constants.
|
||||||
|
*
|
||||||
|
* @param <T> The type of the Enum.
|
||||||
|
* @param clazz The Enum class to which the flags should be parsed.
|
||||||
|
* @param flags A string containing the delimited list of flag names to parse.
|
||||||
|
* Individual names can be separated by commas or whitespace.
|
||||||
|
* @return A list of Enum constants parsed from the input string. If the input string
|
||||||
|
* is null or empty, an empty list is returned.
|
||||||
|
* @throws IllegalArgumentException if any of the flag names do not match the constants in the given Enum class.
|
||||||
|
* @throws NullPointerException if the clazz parameter is null.
|
||||||
|
*/
|
||||||
|
public static <T extends Enum<T>> List<T> parseFlags(final Class<T> clazz, final String flags) {
|
||||||
|
List<T> result = new ArrayList<>();
|
||||||
|
if (flags != null) {
|
||||||
|
for (String flag: flags.split("[,\\s]")) {
|
||||||
|
if (!flag.isEmpty()) result.add(T.valueOf(clazz, flag.toUpperCase()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
298
core/src/main/java/de/neitzel/core/util/FileUtils.java
Normal file
298
core/src/main/java/de/neitzel/core/util/FileUtils.java
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
package de.neitzel.core.util;
|
||||||
|
|
||||||
|
import lombok.extern.log4j.Log4j;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for handling file operations, such as encoding checks, content reading/writing,
|
||||||
|
* path manipulations, and file conversions.
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class FileUtils {
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent instantiation of the utility class.
|
||||||
|
* This utility class is not meant to be instantiated, as it only provides
|
||||||
|
* static utility methods for array-related operations.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always, to indicate that this class
|
||||||
|
* should not be instantiated.
|
||||||
|
*/
|
||||||
|
private FileUtils() {
|
||||||
|
throw new UnsupportedOperationException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a standardized timestamp format for debugging purposes, specifically used for naming
|
||||||
|
* or identifying files with precise timestamps. The format is "yyyy-MM-dd_HH_mm_ss_SSS", which
|
||||||
|
* includes:
|
||||||
|
* - Year in four digits (yyyy)
|
||||||
|
* - Month in two digits (MM)
|
||||||
|
* - Day of the month in two digits (dd)
|
||||||
|
* - Hour in 24-hour format with two digits (HH)
|
||||||
|
* - Minutes in two digits (mm)
|
||||||
|
* - Seconds in two digits (ss)
|
||||||
|
* - Milliseconds in three digits (SSS)
|
||||||
|
*
|
||||||
|
* This ensures timestamps are sortable and easily identifiable.
|
||||||
|
*/
|
||||||
|
public static final SimpleDateFormat DEBUG_FILE_TIMESTAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss_SSS");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default encoding used for string checks and validations in the application.
|
||||||
|
*
|
||||||
|
* This constant represents the `ISO-8859-15` encoding, which is a standardized
|
||||||
|
* character set encoding, commonly used in contexts where backward compatibility
|
||||||
|
* with `ISO-8859-1` is required, but with support for certain additional characters,
|
||||||
|
* such as the euro currency symbol (€).
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_CHECK_ENCODING = "ISO-8859-15";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the default buffer size used for data processing operations.
|
||||||
|
*
|
||||||
|
* This constant represents the size of the buffer in bytes, set to 1024,
|
||||||
|
* and is typically utilized in input/output operations to optimize performance
|
||||||
|
* by reducing the number of read/write calls.
|
||||||
|
*/
|
||||||
|
public static final int BUFFER_SIZE = 1024;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the given file is encoded in UTF-8.
|
||||||
|
*
|
||||||
|
* @param file The file to be checked for UTF-8 encoding.
|
||||||
|
* @param checkEncoding The character encoding to use while checking the file content.
|
||||||
|
* @return true if the file is determined to be encoded in UTF-8; false otherwise.
|
||||||
|
* @throws IOException If an I/O error occurs while reading the file.
|
||||||
|
*/
|
||||||
|
public static boolean isUTF8(final File file, final String checkEncoding) throws IOException {
|
||||||
|
|
||||||
|
if (hasUTF8BOM(file)) return true;
|
||||||
|
|
||||||
|
int BUFFER_SIZE = 1024;
|
||||||
|
char[] buffer = new char[BUFFER_SIZE];
|
||||||
|
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(file), checkEncoding)) {
|
||||||
|
|
||||||
|
while (reader.read(buffer, 0, BUFFER_SIZE) > 0) {
|
||||||
|
|
||||||
|
if (
|
||||||
|
(ArrayUtils.contains(buffer, (char) 0x00C2)) // Part of UTF-8 Characters 0xC2 0xZZ
|
||||||
|
|| (ArrayUtils.contains(buffer, (char) 0x00C3))) { // Part of UTF-8 Characters 0xC3 0xZZ
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (IOException ex) {
|
||||||
|
log.error("Exception while reading file.", ex);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the provided file starts with a UTF-8 Byte Order Mark (BOM).
|
||||||
|
*
|
||||||
|
* This method reads the first character of the file using a reader that assumes
|
||||||
|
* UTF-8 encoding and checks if it matches the Unicode Byte Order Mark (U+FEFF).
|
||||||
|
*
|
||||||
|
* @param file The file to check for a UTF-8 BOM. Must not be null.
|
||||||
|
* @return true if the file starts with a UTF-8 BOM, false otherwise.
|
||||||
|
* @throws IOException If an input or output exception occurs while reading the file.
|
||||||
|
*/
|
||||||
|
public static boolean hasUTF8BOM(final File file) throws IOException {
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
|
||||||
|
return reader.read() == 0xFEFF;
|
||||||
|
} catch (IOException ex) {
|
||||||
|
log.error("Exception while reading file.", ex);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the content of the given file is encoded in UTF-8.
|
||||||
|
*
|
||||||
|
* @param file The file to check for UTF-8 encoding. Must not be null.
|
||||||
|
* @return true if the file content is in UTF-8 encoding; false otherwise.
|
||||||
|
* @throws IOException If an I/O error occurs while reading the file.
|
||||||
|
*/
|
||||||
|
public static boolean isUTF8(final File file) throws IOException {
|
||||||
|
return isUTF8(file, DEFAULT_CHECK_ENCODING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the content of a text file from one character encoding format to another.
|
||||||
|
*
|
||||||
|
* This method reads the input text file using the specified source encoding and writes
|
||||||
|
* the content to the output text file in the specified target encoding.
|
||||||
|
*
|
||||||
|
* @param inFile The input text file to be converted. Must not be null.
|
||||||
|
* @param sourceFormat The character encoding of the input file. Must not be null or empty.
|
||||||
|
* @param outFile The output text file to write the converted content to. Must not be null.
|
||||||
|
* @param targetFormat The character encoding to be used for the output file. Must not be null or empty.
|
||||||
|
* @throws IOException If an I/O error occurs during reading or writing.
|
||||||
|
*/
|
||||||
|
public static void convertTextFile(final File inFile, final String sourceFormat, final File outFile, final String targetFormat) throws IOException {
|
||||||
|
char[] buffer = new char[BUFFER_SIZE];
|
||||||
|
|
||||||
|
int charsRead, startIndex;
|
||||||
|
boolean first = true;
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(inFile), sourceFormat);
|
||||||
|
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(outFile), targetFormat)) {
|
||||||
|
|
||||||
|
while ((charsRead = reader.read(buffer, 0, BUFFER_SIZE)) > 0) {
|
||||||
|
startIndex = 0;
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
// Check UTF-8 BOM
|
||||||
|
if (buffer[0] == 0xFEFF) {
|
||||||
|
log.info("BOM found!");
|
||||||
|
startIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.write(buffer, startIndex, charsRead - startIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException ex) {
|
||||||
|
log.error("Exception when converting Textfile.", ex);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a universal file reader for the specified file name.
|
||||||
|
* This method initializes and returns an InputStreamReader to read
|
||||||
|
* the content of the given file.
|
||||||
|
*
|
||||||
|
* @param filename The name or path of the file to be read.
|
||||||
|
* @return An InputStreamReader for reading the specified file.
|
||||||
|
* @throws IOException If an I/O error occurs while creating the file reader.
|
||||||
|
*/
|
||||||
|
public static InputStreamReader createUniversalFileReader(final String filename) throws IOException {
|
||||||
|
return createUniversalFileReader(new File(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a universal file reader for the specified file and format.
|
||||||
|
* The method resolves the file using its name and the expected format,
|
||||||
|
* returning an InputStreamReader for reading the file contents.
|
||||||
|
*
|
||||||
|
* @param filename the name of the file to be read.
|
||||||
|
* @param expectedFormat the format expected for the file content.
|
||||||
|
* @return an InputStreamReader for the specified file and format.
|
||||||
|
* @throws IOException if an I/O error occurs while opening or reading the file.
|
||||||
|
*/
|
||||||
|
public static InputStreamReader createUniversalFileReader(final String filename, final String expectedFormat) throws IOException {
|
||||||
|
return createUniversalFileReader(new File(filename), expectedFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a universal file reader for the specified file using the default encoding and configuration.
|
||||||
|
*
|
||||||
|
* @param file The file to be read. Must not be null.
|
||||||
|
* @return An InputStreamReader configured to read the specified file.
|
||||||
|
* @throws IOException If an I/O error occurs while creating the reader.
|
||||||
|
*/
|
||||||
|
public static InputStreamReader createUniversalFileReader(final File file) throws IOException {
|
||||||
|
return createUniversalFileReader(file, DEFAULT_CHECK_ENCODING, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a universal file reader for the specified file with an expected format.
|
||||||
|
* This method wraps the given file in an InputStreamReader for consistent character stream manipulation.
|
||||||
|
*
|
||||||
|
* @param file The file to be read. Must not be null.
|
||||||
|
* @param expectedFormat The expected format of the file (e.g., encoding). Must not be null.
|
||||||
|
* @return An InputStreamReader for the specified file, allowing the caller to read the file
|
||||||
|
* with the desired format applied.
|
||||||
|
* @throws IOException If an I/O error occurs during the creation of the reader.
|
||||||
|
*/
|
||||||
|
public static InputStreamReader createUniversalFileReader(final File file, final String expectedFormat) throws IOException {
|
||||||
|
return createUniversalFileReader(file, expectedFormat, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an InputStreamReader for reading a file, considering the specified encoding format
|
||||||
|
* and whether UTF-8 should be accepted. Handles potential BOM for UTF-8 encoded files.
|
||||||
|
*
|
||||||
|
* @param file The file to be read.
|
||||||
|
* @param expectedFormat The expected encoding format of the file.
|
||||||
|
* @param acceptUTF8 Indicates whether UTF-8 encoding should be accepted if detected.
|
||||||
|
* @return An InputStreamReader for the specified file and encoding.
|
||||||
|
* @throws IOException If there is an error accessing the file or reading its content.
|
||||||
|
*/
|
||||||
|
public static InputStreamReader createUniversalFileReader(final File file, final String expectedFormat, final boolean acceptUTF8) throws IOException {
|
||||||
|
String encoding = acceptUTF8 && isUTF8(file, expectedFormat)
|
||||||
|
? "UTF-8"
|
||||||
|
: expectedFormat;
|
||||||
|
|
||||||
|
boolean skipBOM = encoding.equals("UTF-8") && hasUTF8BOM(file);
|
||||||
|
|
||||||
|
InputStreamReader result = new InputStreamReader(new FileInputStream(file), encoding);
|
||||||
|
if (skipBOM) {
|
||||||
|
int BOM = result.read();
|
||||||
|
if (BOM != 0xFEFF) log.error ("Skipping BOM but value not 0xFEFF!");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the parent directory of the given file or directory path.
|
||||||
|
*
|
||||||
|
* If the given path does not have a parent directory, it defaults to returning the
|
||||||
|
* current directory represented by ".".
|
||||||
|
*
|
||||||
|
* @param filename The file or directory path for which the parent directory is to be retrieved.
|
||||||
|
* @return The parent directory of the given path, or "." if no parent directory exists.
|
||||||
|
*/
|
||||||
|
public static String getParentDirectory(final String filename) {
|
||||||
|
File file = new File(filename);
|
||||||
|
return file.getParent() != null ? file.getParent() : ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the name of a file from the given file path.
|
||||||
|
*
|
||||||
|
* @param filename The full path or name of the file. Must not be null.
|
||||||
|
* @return The name of the file without any directory path.
|
||||||
|
*/
|
||||||
|
public static String getFilename(final String filename) {
|
||||||
|
File file = new File(filename);
|
||||||
|
return file.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the content of a file and returns it as a string, joining all lines with the system line separator.
|
||||||
|
*
|
||||||
|
* @param filename The name of the file to be read.
|
||||||
|
* @return A string containing the content of the file with all lines joined by the system line separator.
|
||||||
|
* @throws IOException If an I/O error occurs while reading the file.
|
||||||
|
*/
|
||||||
|
public static String readFileContent(final String filename) throws IOException {
|
||||||
|
try (BufferedReader reader = new BufferedReader(createUniversalFileReader(filename))) {
|
||||||
|
return reader.lines().collect(Collectors.joining(System.lineSeparator()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the given content to the specified file path. If the file already exists, it will be overwritten.
|
||||||
|
*
|
||||||
|
* @param path The path of the file to write to. Must not be null and must be writable.
|
||||||
|
* @param content The content to be written to the file. Must not be null.
|
||||||
|
* @throws IOException If an I/O error occurs during writing to the file.
|
||||||
|
*/
|
||||||
|
public static void writeFile(final Path path, final String content) throws IOException {
|
||||||
|
try (BufferedWriter writer = new BufferedWriter(new FileWriter(path.toFile()))) {
|
||||||
|
writer.write(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
package de.neitzel.core.util;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The RegionalizationMessage class provides functionality to retrieve
|
||||||
|
* localized messages from a resource bundle and format messages with parameters.
|
||||||
|
* It supports multiple constructors for initializing with specific locales if needed.
|
||||||
|
*/
|
||||||
|
public class RegionalizationMessage {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `res` variable holds a `ResourceBundle` instance,
|
||||||
|
* which is used to retrieve locale-specific objects and messages.
|
||||||
|
* It facilitates the process of internationalization by loading resources
|
||||||
|
* such as text and messages from specified bundles based on the provided locale.
|
||||||
|
*
|
||||||
|
* This variable is initialized in constructors of the `RegionalizationMessage` class
|
||||||
|
* and is used internally by various methods to fetch localized messages.
|
||||||
|
*/
|
||||||
|
private ResourceBundle res;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new RegionalizationMessage instance using the specified resource bundle source.
|
||||||
|
* This constructor initializes the resource bundle with the given source name.
|
||||||
|
*
|
||||||
|
* @param source The base name of the resource bundle to load.
|
||||||
|
* This is typically a fully qualified class name or package name for the resource.
|
||||||
|
*/
|
||||||
|
public RegionalizationMessage(final String source) {
|
||||||
|
res = ResourceBundle.getBundle(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a RegionalizationMessage object to retrieve localized messages
|
||||||
|
* from a specified resource bundle using the given source and locale.
|
||||||
|
*
|
||||||
|
* @param source The base name of the resource bundle, a fully qualified class name.
|
||||||
|
* @param locale The Locale object specifying the desired language and region for localization.
|
||||||
|
*/
|
||||||
|
public RegionalizationMessage(final String source, final Locale locale) {
|
||||||
|
res = ResourceBundle.getBundle(source, locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the localized message corresponding to the specified key from the resource bundle.
|
||||||
|
* If the key does not exist in the resource bundle, this method returns null.
|
||||||
|
*
|
||||||
|
* @param key The key for which the localized message needs to be retrieved.
|
||||||
|
* @return The localized message as a String if the key exists in the resource bundle;
|
||||||
|
* otherwise, null.
|
||||||
|
*/
|
||||||
|
public String getMessage(final String key) {
|
||||||
|
if (!res.containsKey(key)) return null;
|
||||||
|
return res.getString(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a localized message for the given key from the resource bundle.
|
||||||
|
* If the key is not found, the specified default message is returned.
|
||||||
|
*
|
||||||
|
* @param key The key to look up in the resource bundle.
|
||||||
|
* @param defaultMessage The default message to return if the key is not found.
|
||||||
|
* @return The localized message corresponding to the key, or the default message
|
||||||
|
* if the key does not exist in the resource bundle.
|
||||||
|
*/
|
||||||
|
public String getMessage(final String key, final String defaultMessage) {
|
||||||
|
if (res.containsKey(key))
|
||||||
|
return res.getString(key);
|
||||||
|
|
||||||
|
return defaultMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a localized and formatted message from a resource bundle based on a key.
|
||||||
|
* If the key is not found in the resource bundle, a default message is used.
|
||||||
|
* The message supports parameter substitution using the supplied arguments.
|
||||||
|
*
|
||||||
|
* @param key The key used to retrieve the localized message from the resource bundle.
|
||||||
|
* @param defaultMessage The default message to be used if the key is not found in the resource bundle.
|
||||||
|
* @param params The parameters to substitute into the message placeholders.
|
||||||
|
* @return A formatted string containing the localized message with substituted parameters.
|
||||||
|
*/
|
||||||
|
public String getFormattedMessage(final String key, final String defaultMessage, final Object... params) {
|
||||||
|
MessageFormat format = new MessageFormat(getMessage(key, defaultMessage));
|
||||||
|
return format.format(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
157
core/src/main/java/de/neitzel/core/util/Strings.java
Normal file
157
core/src/main/java/de/neitzel/core/util/Strings.java
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
package de.neitzel.core.util;
|
||||||
|
|
||||||
|
import lombok.NonNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class providing common string manipulation methods.
|
||||||
|
*/
|
||||||
|
public class Strings {
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent instantiation of the utility class.
|
||||||
|
* This utility class is not meant to be instantiated, as it only provides
|
||||||
|
* static utility methods for array-related operations.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always, to indicate that this class
|
||||||
|
* should not be instantiated.
|
||||||
|
*/
|
||||||
|
private Strings() {
|
||||||
|
throw new UnsupportedOperationException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A map that holds the system's environment variables. The keys represent
|
||||||
|
* environment variable names, and the values represent their corresponding
|
||||||
|
* values. It is initialized with the current system environment variables using
|
||||||
|
* {@link System#getenv()}.
|
||||||
|
*
|
||||||
|
* This variable provides access to the underlying system environment, which can
|
||||||
|
* be used for various purposes such as configuration, path resolution, or
|
||||||
|
* dynamic value substitution.
|
||||||
|
*
|
||||||
|
* Note: Modifications to this map will not affect the system environment, as it
|
||||||
|
* is a copy of the environment at the time of initialization.
|
||||||
|
*/
|
||||||
|
private static Map<String, String> environmentVariables = System.getenv();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expands environment variable placeholders within the provided text.
|
||||||
|
* Placeholders in the format ${VARIABLE_NAME} are replaced with their
|
||||||
|
* corresponding values from the environment variables.
|
||||||
|
*
|
||||||
|
* @param text The input string containing environment variable placeholders.
|
||||||
|
* If null, the method returns null.
|
||||||
|
* @return A string with the placeholders replaced by their corresponding
|
||||||
|
* environment variable values. If no placeholders are found,
|
||||||
|
* the original string is returned.
|
||||||
|
*/
|
||||||
|
public static String expandEnvironmentVariables(String text) {
|
||||||
|
if (text == null) return null;
|
||||||
|
for (Map.Entry<String, String> entry : environmentVariables.entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
String value = entry.getValue().replace('\\', '/');
|
||||||
|
text = text.replaceAll("\\$\\{" + key + "\\}", value);
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a given string is either null or empty.
|
||||||
|
*
|
||||||
|
* @param string the string to be checked for nullity or emptiness.
|
||||||
|
* @return true if the string is null or has a length of 0; false otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean isNullOrEmpty(final String string) {
|
||||||
|
return (string == null || string.length()==0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes surrounding double quotes from the input string if they are present.
|
||||||
|
* Trims leading and trailing whitespaces from the input before processing.
|
||||||
|
*
|
||||||
|
* @param value The input string that might contain surrounding double quotes.
|
||||||
|
* The input cannot be null, and leading/trailing whitespaces will be ignored.
|
||||||
|
* @return A string with leading and trailing double quotes removed if present.
|
||||||
|
* Returns the original string if no surrounding double quotes are detected.
|
||||||
|
*/
|
||||||
|
public static String removeQuotes(final String value) {
|
||||||
|
String trimmedValue = value.trim();
|
||||||
|
if (trimmedValue.length() > 1 && trimmedValue.startsWith("\"") && trimmedValue.endsWith("\""))
|
||||||
|
return trimmedValue.substring(1, trimmedValue.length()-1);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces illegal characters in a given string with a specified replacement string.
|
||||||
|
* Optionally, consecutive illegal characters can be combined into a single replacement.
|
||||||
|
*
|
||||||
|
* @param value The input string in which illegal characters are to be replaced.
|
||||||
|
* @param illegalCharacters A string specifying the set of illegal characters to be matched.
|
||||||
|
* @param replacement The string to replace each illegal character or group of characters.
|
||||||
|
* @param combine A boolean flag indicating whether consecutive illegal characters should be replaced
|
||||||
|
* with a single replacement string. If true, groups of illegal characters are combined.
|
||||||
|
* @return A new string with the illegal characters replaced by the provided replacement string.
|
||||||
|
*/
|
||||||
|
public static String replaceIllegalCharacters(final String value, final String illegalCharacters, final String replacement, final boolean combine) {
|
||||||
|
String replacementRegex = "[" + illegalCharacters + "]" + (combine ? "+" : "");
|
||||||
|
return value.replaceAll(replacementRegex, replacement);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces characters in the input string that are not in the allowed characters set
|
||||||
|
* with a specified replacement string. Optionally combines consecutive non-allowed
|
||||||
|
* characters into a single replacement.
|
||||||
|
*
|
||||||
|
* @param value The input string to be processed.
|
||||||
|
* @param allowedCharacters A string containing the set of characters that are allowed.
|
||||||
|
* Any character not in this set will be replaced.
|
||||||
|
* @param replacement The string to replace non-allowed characters with.
|
||||||
|
* @param combine If true, consecutive non-allowed characters will be replaced with
|
||||||
|
* a single instance of the replacement string.
|
||||||
|
* @return A new string with non-allowed characters replaced according to the specified rules.
|
||||||
|
*/
|
||||||
|
public static String replaceNonAllowedCharacters(final String value, final String allowedCharacters, final String replacement, final boolean combine) {
|
||||||
|
String replacementRegex = "[^" + allowedCharacters + "]" + (combine ? "+" : "");
|
||||||
|
return value.replaceAll(replacementRegex, replacement);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increments a string value by modifying its last character, or leading characters if necessary.
|
||||||
|
* The increment follows these rules:
|
||||||
|
* - If the last character is a digit '9', it wraps to 'A'.
|
||||||
|
* - If the last character is 'Z', the preceding part of the string is recursively incremented, and '0' is appended.
|
||||||
|
* - If the string is empty, it returns "1".
|
||||||
|
* - For all other characters, increments the last character by one.
|
||||||
|
*
|
||||||
|
* @param element The string whose value is to be incremented. Must not be null.
|
||||||
|
* @return The incremented string value. If the input string is empty, returns "1".
|
||||||
|
*/
|
||||||
|
public static String increment(@NonNull final String element) {
|
||||||
|
if (element.isEmpty()) return "1";
|
||||||
|
|
||||||
|
String firstPart = element.substring(0, element.length()-1);
|
||||||
|
char lastChar = element.charAt(element.length()-1);
|
||||||
|
if (lastChar == '9') return firstPart + 'A';
|
||||||
|
if (lastChar == 'Z') return increment(firstPart) + '0';
|
||||||
|
return firstPart + (char)(lastChar+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trims the input string to a specified maximum length, if necessary.
|
||||||
|
* If the input string's length is less than or equal to the specified max length,
|
||||||
|
* the string is returned unchanged. If the input string's length exceeds the max
|
||||||
|
* length, it is truncated to that length.
|
||||||
|
*
|
||||||
|
* @param original The original input string to be processed. If null, the method returns null.
|
||||||
|
* @param maxLength The maximum number of characters allowed in the resulting string.
|
||||||
|
* @return The original string if its length is less than or equal to maxLength,
|
||||||
|
* otherwise a truncated version of the string up to maxLength characters.
|
||||||
|
*/
|
||||||
|
public static String limitCharNumber(final String original, final int maxLength) {
|
||||||
|
if (original == null || original.length() <= maxLength) return original;
|
||||||
|
|
||||||
|
return original.substring(0, maxLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
239
core/src/main/java/de/neitzel/core/util/XmlUtils.java
Normal file
239
core/src/main/java/de/neitzel/core/util/XmlUtils.java
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
package de.neitzel.core.util;
|
||||||
|
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.extern.log4j.Log4j;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.transform.*;
|
||||||
|
import javax.xml.transform.dom.DOMSource;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for handling common XML operations such as creating XML elements,
|
||||||
|
* formatting XML strings, and validating XML content.
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class XmlUtils {
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent instantiation of the utility class.
|
||||||
|
* This utility class is not meant to be instantiated, as it only provides
|
||||||
|
* static utility methods for array-related operations.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always, to indicate that this class
|
||||||
|
* should not be instantiated.
|
||||||
|
*/
|
||||||
|
private XmlUtils() {
|
||||||
|
throw new UnsupportedOperationException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link DateTimeFormatter} instance used for formatting or parsing dates in the "yyyy-MM-dd" pattern.
|
||||||
|
*
|
||||||
|
* This formatter adheres to the XML date format standard (ISO-8601). It can be used
|
||||||
|
* to ensure consistent date representations in XML or other similar text-based formats.
|
||||||
|
*
|
||||||
|
* Thread-safe and immutable, this formatter can be shared across multiple threads.
|
||||||
|
*/
|
||||||
|
public static final DateTimeFormatter XML_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new element in the provided XML document with the specified name.
|
||||||
|
*
|
||||||
|
* @param doc The XML document in which the new element is to be created. Must not be null.
|
||||||
|
* @param name The name of the element to be created. Must not be null or empty.
|
||||||
|
* @return The newly created element with the given name. Never returns null.
|
||||||
|
*/
|
||||||
|
public static Element createElement(final Document doc, final String name) {
|
||||||
|
log.debug("Creating a new element " + name);
|
||||||
|
return doc.createElement(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new XML element with the specified name and value, appends the value
|
||||||
|
* as a text node to the element, and returns the resulting element.
|
||||||
|
*
|
||||||
|
* @param doc the XML document to which the element belongs. Must not be null.
|
||||||
|
* @param name the name of the element to create. Must not be null.
|
||||||
|
* @param value the text value to be set as the content of the created element.
|
||||||
|
* If null, an empty string will be used as the content.
|
||||||
|
* @return the newly created XML element containing the specified value as a text node.
|
||||||
|
*/
|
||||||
|
public static Element createElement(final Document doc, final String name, final String value) {
|
||||||
|
log.debug("Creating a new element " + name + " with value: " + value);
|
||||||
|
Element element = doc.createElement(name);
|
||||||
|
|
||||||
|
Node content = doc.createTextNode(value != null ? value : "");
|
||||||
|
element.appendChild(content);
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an XML element with the specified name and value, formatted as a date string.
|
||||||
|
* The date value is converted to an XML-compatible string format using a predefined formatter.
|
||||||
|
*
|
||||||
|
* @param doc the XML document to which the element belongs; must not be null
|
||||||
|
* @param name the name of the element to be created; must not be null or empty
|
||||||
|
* @param value the date value to be assigned to the created element; must not be null
|
||||||
|
* @return the created XML element containing the specified name and formatted date value
|
||||||
|
*/
|
||||||
|
public static Element createElement(final Document doc, final String name, final Date value) {
|
||||||
|
return createElement(doc, name, XML_DATE_FORMATTER.format(value.toInstant()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an XML element with the specified name and optional value.
|
||||||
|
*
|
||||||
|
* @param doc The Document object to which the element will belong. Must not be null.
|
||||||
|
* @param name The name of the element to be created. Must not be null or empty.
|
||||||
|
* @param value The optional value to be set as the text content of the element. If null,
|
||||||
|
* the element will have an empty text content.
|
||||||
|
* @return The newly created Element object with the specified name and value.
|
||||||
|
*/
|
||||||
|
public static Element createElement(final Document doc, final String name, final Integer value) {
|
||||||
|
log.debug("Creating a new element " + name + " with value: " + value);
|
||||||
|
Element element = doc.createElement(name);
|
||||||
|
|
||||||
|
Node content = doc.createTextNode(value != null ? ""+value : "");
|
||||||
|
element.appendChild(content);
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new element with the specified name, appends it to the provided parent element,
|
||||||
|
* and returns the newly created element.
|
||||||
|
*
|
||||||
|
* @param doc The Document to which the new element belongs. Must not be null.
|
||||||
|
* @param name The name of the new element to be created. Must not be null or empty.
|
||||||
|
* @param parent The parent element to which the new element will be appended. Must not be null.
|
||||||
|
* @return The newly created and appended Element object.
|
||||||
|
*/
|
||||||
|
public static Element createAndInsertElement(final Document doc, final String name, @NonNull final Element parent) {
|
||||||
|
log.debug("Creating a new element " + name + " and adding it to a parent.");
|
||||||
|
Element element = createElement(doc, name);
|
||||||
|
parent.appendChild(element);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new XML element with a specified name and value, adds it to the specified parent element,
|
||||||
|
* and returns the created element.
|
||||||
|
*
|
||||||
|
* @param doc The XML document to which the new element belongs. Must not be null.
|
||||||
|
* @param name The name of the element to create. Must not be null.
|
||||||
|
* @param value The value to be set for the created element. Can be null if no value is required.
|
||||||
|
* @param parent The parent element to which the new element will be appended. Must not be null.
|
||||||
|
* @return The newly created and inserted element.
|
||||||
|
*/
|
||||||
|
public static Element createAndInsertElement(final Document doc, final String name, final String value, @NonNull final Element parent) {
|
||||||
|
log.debug("Creating a new element " + name + " with value: " + value + " and adding it to a parent.");
|
||||||
|
Element element = createElement(doc, name, value);
|
||||||
|
parent.appendChild(element);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a given XML string by applying proper indentation to enhance readability.
|
||||||
|
* The method uses a transformer to process the XML input, applying indentation
|
||||||
|
* with a four-space configuration. In case of an error, the original XML string
|
||||||
|
* is returned without any modifications.
|
||||||
|
*
|
||||||
|
* @param xmlStream The raw XML string to be formatted. Cannot be null.
|
||||||
|
* @return The formatted XML string with proper indentation. If an exception occurs
|
||||||
|
* during formatting, the original XML string is returned.
|
||||||
|
*/
|
||||||
|
public static String format(final String xmlStream) {
|
||||||
|
log.debug("formatXML");
|
||||||
|
|
||||||
|
try {
|
||||||
|
Source xmlInput = new StreamSource(new StringReader(xmlStream));
|
||||||
|
StringWriter stringWriter = new StringWriter();
|
||||||
|
StreamResult xmlOutput = new StreamResult(stringWriter);
|
||||||
|
|
||||||
|
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||||
|
transformerFactory.setAttribute("indent-number", "4");
|
||||||
|
|
||||||
|
Transformer transformer = transformerFactory.newTransformer();
|
||||||
|
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||||
|
transformer.transform(xmlInput, xmlOutput);
|
||||||
|
|
||||||
|
return xmlOutput.getWriter().toString();
|
||||||
|
}
|
||||||
|
catch(TransformerException e) {
|
||||||
|
log.error("Error in XML: " + e.getMessage() + "\n"+xmlStream, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return xmlStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a given XML Document into a human-readable string representation.
|
||||||
|
* The method applies indentation and specific output properties to the XML content.
|
||||||
|
* If an exception occurs during the transformation process, it logs the error
|
||||||
|
* and returns null.
|
||||||
|
*
|
||||||
|
* @param doc The XML Document to be formatted. Must not be null.
|
||||||
|
* @return A formatted string representation of the XML document, or null if an error occurs during processing.
|
||||||
|
*/
|
||||||
|
public static String format(final Document doc) {
|
||||||
|
try {
|
||||||
|
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||||
|
transformerFactory.setAttribute("indent-number", "4");
|
||||||
|
Transformer transformer = transformerFactory.newTransformer();
|
||||||
|
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||||
|
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
|
||||||
|
transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
|
||||||
|
StringWriter stringWriter = new StringWriter();
|
||||||
|
|
||||||
|
Source source = new DOMSource(doc);
|
||||||
|
Result result = new StreamResult(stringWriter);
|
||||||
|
transformer.transform(source, result);
|
||||||
|
|
||||||
|
String xmlString = stringWriter.toString();
|
||||||
|
log.info("MO Request: " + xmlString);
|
||||||
|
return xmlString;
|
||||||
|
}
|
||||||
|
catch(TransformerException e) {
|
||||||
|
log.error("Error in XML Transformation: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates whether a given XML string is well-formed.
|
||||||
|
* This method attempts to parse the input XML string and checks
|
||||||
|
* if it can successfully create a valid DOM object from it.
|
||||||
|
*
|
||||||
|
* @param xml The XML string to be validated. Must not be null.
|
||||||
|
* If null or invalid, the method will return false.
|
||||||
|
* @return true if the XML string is well-formed and can be successfully parsed;
|
||||||
|
* false otherwise, such as in the case of invalid content or parsing errors.
|
||||||
|
*/
|
||||||
|
public static boolean checkXml(final String xml) {
|
||||||
|
try {
|
||||||
|
InputStream stream = new ByteArrayInputStream(xml.getBytes());
|
||||||
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||||
|
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||||
|
Document document = docBuilder.parse(stream);
|
||||||
|
return document != null;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.warn("Exception when validating xml.", ex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -43,160 +43,4 @@
|
|||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<profiles>
|
|
||||||
|
|
||||||
<!-- Profile that adds JLink and JPackage runs.
|
|
||||||
|
|
||||||
Add -Pimage or -Dimage to use this profile.
|
|
||||||
-->
|
|
||||||
<profile>
|
|
||||||
<id>image</id>
|
|
||||||
<activation>
|
|
||||||
<property>
|
|
||||||
<name>image</name>
|
|
||||||
</property>
|
|
||||||
</activation>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<!-- Copy dependencies -->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<version>${maven.dependency.plugin}</version>
|
|
||||||
<executions>
|
|
||||||
<!-- erstmal Abhängigkeiten für den Class-Path kopieren -->
|
|
||||||
<execution>
|
|
||||||
<id>copy-dependencies</id>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy-dependencies</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.directory}/modules</outputDirectory>
|
|
||||||
<includeScope>runtime</includeScope>
|
|
||||||
<overWriteReleases>false</overWriteReleases>
|
|
||||||
<overWriteSnapshots>false</overWriteSnapshots>
|
|
||||||
<overWriteIfNewer>true</overWriteIfNewer>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
|
|
||||||
<!-- dazu noch das Projekt-JAR -->
|
|
||||||
<execution>
|
|
||||||
<id>copy</id>
|
|
||||||
<phase>install</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.directory}/modules</outputDirectory>
|
|
||||||
<artifactItems>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>${project.artifactId}</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<type>${project.packaging}</type>
|
|
||||||
<destFileName>${project.build.finalName}.jar</destFileName>
|
|
||||||
</artifactItem>
|
|
||||||
</artifactItems>
|
|
||||||
<overWriteIfNewer>true</overWriteIfNewer>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<plugin>
|
|
||||||
<groupId>com.github.akman</groupId>
|
|
||||||
<artifactId>jpackage-maven-plugin</artifactId>
|
|
||||||
<version>${jpackage.maven.plugin}</version>
|
|
||||||
<configuration>
|
|
||||||
<name>${appName}</name>
|
|
||||||
<type>IMAGE</type>
|
|
||||||
<modulepath>
|
|
||||||
<dependencysets>
|
|
||||||
<dependencyset>
|
|
||||||
<includenames>
|
|
||||||
<includename>javafx\..*</includename>
|
|
||||||
</includenames>
|
|
||||||
</dependencyset>
|
|
||||||
</dependencysets>
|
|
||||||
</modulepath>
|
|
||||||
<addmodules>
|
|
||||||
<addmodule>javafx.controls</addmodule>
|
|
||||||
<addmodule>javafx.graphics</addmodule>
|
|
||||||
<addmodule>javafx.fxml</addmodule>
|
|
||||||
<addmodule>javafx.web</addmodule>
|
|
||||||
</addmodules>
|
|
||||||
<mainclass>${main.class}</mainclass>
|
|
||||||
<input>${project.build.directory}/modules</input>
|
|
||||||
<mainjar>${jar.filename}.jar</mainjar>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>install</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>jpackage</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
|
|
||||||
<!-- Profile to build a fat jar
|
|
||||||
|
|
||||||
Add -Pfatjar or -Dfatjar to use this profile.
|
|
||||||
-->
|
|
||||||
<profile>
|
|
||||||
<id>fatjar</id>
|
|
||||||
<activation>
|
|
||||||
<property>
|
|
||||||
<name>fatjar</name>
|
|
||||||
</property>
|
|
||||||
</activation>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
|
||||||
<version>${maven.shade.plugin}</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>shade</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
|
||||||
<shadedClassifierName>full</shadedClassifierName>
|
|
||||||
<transformers>
|
|
||||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
|
||||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
|
||||||
<manifestEntries>
|
|
||||||
<Main-Class>${main.class}</Main-Class>
|
|
||||||
<Build-Version>1.0</Build-Version>
|
|
||||||
</manifestEntries>
|
|
||||||
</transformer>
|
|
||||||
</transformers>
|
|
||||||
<filters>
|
|
||||||
<filter>
|
|
||||||
<artifact>*:*</artifact>
|
|
||||||
<excludes>
|
|
||||||
<exclude>META-INF/MANIFEST.MF</exclude>
|
|
||||||
<exclude>**/module-info.class</exclude>
|
|
||||||
<exclude>META-INF/*.SF</exclude>
|
|
||||||
<exclude>META-INF/*.DSA</exclude>
|
|
||||||
<exclude>META-INF/*.RSA</exclude>
|
|
||||||
</excludes>
|
|
||||||
</filter>
|
|
||||||
</filters>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
54
log4j/pom.xml
Normal file
54
log4j/pom.xml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>de.neitzel.lib</groupId>
|
||||||
|
<artifactId>neitzellib</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>log4j</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<!-- Application Properties -->
|
||||||
|
<link.name>${project.artifactId}</link.name>
|
||||||
|
<launcher>${project.artifactId}</launcher>
|
||||||
|
<appName>${project.artifactId}</appName>
|
||||||
|
<jar.filename>${project.artifactId}-${project.version}</jar.filename>
|
||||||
|
|
||||||
|
<!-- Dependency Versions -->
|
||||||
|
<log4j.version>1.2.17</log4j.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>log4j</groupId>
|
||||||
|
<artifactId>log4j</artifactId>
|
||||||
|
<version>${log4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>log4j</groupId>
|
||||||
|
<artifactId>apache-log4j-extras</artifactId>
|
||||||
|
<version>${log4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>${jar.filename}</finalName>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.github.spotbugs</groupId>
|
||||||
|
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-pmd-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
88
log4j/src/main/java/de/neitzel/log4j/Log4jUtils.java
Normal file
88
log4j/src/main/java/de/neitzel/log4j/Log4jUtils.java
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package de.neitzel.log4j;
|
||||||
|
|
||||||
|
import org.apache.log4j.PropertyConfigurator;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for managing Log4j configurations. Provides methods to set up
|
||||||
|
* Log4j configurations from default files, resources, or command line arguments.
|
||||||
|
*/
|
||||||
|
public class Log4jUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default path to the Log4j configuration file.
|
||||||
|
* This variable is used to specify the local file path for the Log4j configuration
|
||||||
|
* when no custom configuration is provided.
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_LOG4J_LOGFILE = "./log4j.properties";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default resource path to the Log4j configuration file included in the classpath.
|
||||||
|
* This path is used as a fallback when no other Log4j configuration is explicitly set.
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_LOG4J_RESOURCE = "/log4j.default.properties";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the system property "log4j.configuration" is set.
|
||||||
|
*
|
||||||
|
* @return true if the "log4j.configuration" property is defined, false otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean isLog4jConfigFileSet() {
|
||||||
|
return System.getProperty("log4j.configuration") != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures Log4j using default configuration settings.
|
||||||
|
* This method leverages a default configuration file path and a default resource path
|
||||||
|
* to set up Log4j logging if a configuration file is not already specified via
|
||||||
|
* a system property. If a valid configuration file or resource is found, it will be applied.
|
||||||
|
*
|
||||||
|
* Delegates to the overloaded {@code setLog4jConfiguration(String log4jConfigFile, String defaultResource)}
|
||||||
|
* method using predefined defaults.
|
||||||
|
*/
|
||||||
|
public static void setLog4jConfiguration() {
|
||||||
|
setLog4jConfiguration(DEFAULT_LOG4J_LOGFILE, DEFAULT_LOG4J_RESOURCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the absolute path to the specified Log4j configuration file located
|
||||||
|
* in the same directory as the JAR file of the application.
|
||||||
|
*
|
||||||
|
* @param log4jConfigFile The name of the Log4j configuration file.
|
||||||
|
* @return The absolute path to the specified Log4j configuration file if the
|
||||||
|
* path is successfully constructed; otherwise, returns null in case of an error.
|
||||||
|
*/
|
||||||
|
public static String getLog4jLogfileAtJar(final String log4jConfigFile) {
|
||||||
|
try {
|
||||||
|
return new File(Log4jUtils.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParent() + "/" + log4jConfigFile;
|
||||||
|
} catch (URISyntaxException ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the Log4j configuration using the specified configuration file or a default resource
|
||||||
|
* if the configuration file is not found. If a Log4j configuration is already set, the method
|
||||||
|
* does nothing.
|
||||||
|
*
|
||||||
|
* @param log4jConfigFile the path to the Log4j configuration file to be used.
|
||||||
|
* @param defaultResource the fallback resource to be used as the configuration if the file
|
||||||
|
* is not found or accessible.
|
||||||
|
*/
|
||||||
|
public static void setLog4jConfiguration(final String log4jConfigFile, final String defaultResource) {
|
||||||
|
if (isLog4jConfigFileSet()) return;
|
||||||
|
|
||||||
|
String fileAtJar = getLog4jLogfileAtJar(log4jConfigFile);
|
||||||
|
|
||||||
|
if (new File(log4jConfigFile).exists()) {
|
||||||
|
PropertyConfigurator.configure(log4jConfigFile);
|
||||||
|
} else if (fileAtJar != null && new File(fileAtJar).exists()) {
|
||||||
|
System.out.println("Nutze Log4J Konfiguration bei jar File: " + fileAtJar);
|
||||||
|
PropertyConfigurator.configure(fileAtJar);
|
||||||
|
}else {
|
||||||
|
PropertyConfigurator.configure(Log4jUtils.class.getResource(defaultResource));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
pom.xml
17
pom.xml
@ -15,6 +15,7 @@
|
|||||||
<module>encryption</module>
|
<module>encryption</module>
|
||||||
<module>fx</module>
|
<module>fx</module>
|
||||||
<module>net</module>
|
<module>net</module>
|
||||||
|
<module>log4j</module>
|
||||||
<module>fx-example</module>
|
<module>fx-example</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
@ -24,10 +25,10 @@
|
|||||||
|
|
||||||
<!-- Dependency versions -->
|
<!-- Dependency versions -->
|
||||||
<javafx.version>21.0.3</javafx.version>
|
<javafx.version>21.0.3</javafx.version>
|
||||||
<jetbrains.annotations.version>24.1.0</jetbrains.annotations.version>
|
<jetbrains.annotations.version>26.0.2</jetbrains.annotations.version>
|
||||||
<junit.version>5.10.2</junit.version>
|
<junit.version>5.12.1</junit.version>
|
||||||
<lombok.version>1.18.32</lombok.version>
|
<lombok.version>1.18.38</lombok.version>
|
||||||
<mockito.version>5.12.0</mockito.version>
|
<mockito.version>5.16.1</mockito.version>
|
||||||
<reflections.version>0.10.2</reflections.version>
|
<reflections.version>0.10.2</reflections.version>
|
||||||
<slf4j.version>2.0.17</slf4j.version>
|
<slf4j.version>2.0.17</slf4j.version>
|
||||||
|
|
||||||
@ -99,6 +100,7 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- Lombok -->
|
<!-- Lombok -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -143,6 +145,13 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Logging implementation -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Dependency used for @NotNull / @Nullable -->
|
<!-- Dependency used for @NotNull / @Nullable -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jetbrains</groupId>
|
<groupId>org.jetbrains</groupId>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user