Vorhandene Klassen einfach blind eingefügt

Benötigt einige Nacharbeiten, damit es übersetzbar wird.
This commit is contained in:
Konrad Neitzel 2025-04-03 18:58:47 +02:00
parent 77ea70f4e6
commit 8d01fd4935
16 changed files with 1501 additions and 0 deletions

View File

@ -0,0 +1,69 @@
package de.neitzel.core.commandline;
import java.util.Iterator;
/**
* Provides one argument after the other.
*/
public class ArgumentProvider implements Iterator<String> {
/**
* List of Arguments (from command line)
*/
private String[] arguments;
/**
* Current element we work on.
*/
private int current = 0;
/**
* Creates a new instance of ArgumentProvider.
* @param arguments List of Arguments.
*/
public ArgumentProvider(final String[] arguments) {
if (arguments == null) {
this.arguments = new String[] {};
} else {
this.arguments = arguments;
}
}
/**
* Checks if more arguments are available.
* @return True if more arguments are available else false.
*/
public boolean hasNext() {
return current < arguments.length;
}
/**
* Checks if count more arguments are available.
* @param count Number of arguments we want to get.
* @return True if count more arguments are available else false.
*/
public boolean hasNext(final int count) {
return current + count <= arguments.length;
}
/**
* Get the next token.
* @return The next token or null if no more available.
*/
public String next() {
if (!hasNext()) return null;
String result = arguments[current];
current++;
return result;
}
/**
* Get the next token without removing it.
* @return The next token or null if no more available.
*/
public String peek() {
if (!hasNext()) return null;
return arguments[current];
}
}

View File

@ -0,0 +1,75 @@
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;
/**
* A parameter on the command line.
* <br>
* Each parameter has to start with either - or /!
*/
@Slf4j
@Builder
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Parameter {
/**
* Name of the parameter.
*/
private String name;
/**
* Min number of values given.
*/
private int minNumberValues;
/**
* Max number of values given.
*/
private int maxNumberValues;
/**
* Defines if the parameter can be given multiple times.
*/
private boolean multipleEntries;
/**
* Short description of the parameter.
*/
private String shortDescription;
/**
* Long description of the parameter.
*/
private String longDescription;
/**
* Callback wenn der Parameter gefunden wurde.
*/
private Consumer<List<String>> callback;
/**
* Determines if this Element is the parameter for help.
*/
private boolean isHelpCommand;
/**
* Determines if this Parameter is the default parameter.
* <br>
* A default parameter must take at least one additional value.
*/
private boolean isDefaultParameter;
/**
* List of aliases.
*/
@Singular("alias")
private List<String> aliasList;
}

View File

@ -0,0 +1,145 @@
package de.neitzel.core.commandline;
import lombok.extern.slf4j.Slf4j;
import java.util.*;
/**
* A parser of the CommandLine.
* <br>
* Parameter are defined. Each parameter will start with either - or /.
*/
@Slf4j
public class Parser {
/**
* Parameters known by the CommandLineParser.
*/
private Map<String, Parameter> parameters = new HashMap<>();
/**
* The default parameter.
*/
private Parameter defaultParameter = null;
/**
* Adds a parameter to the list of known parameters.
* @param parameter
*/
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 if param is a parameter.
* <br>
* - When the parameter is known as a parameter, then it is true.
* - Everything that starts with a - must be a known parameter -> false
* - Parameter is not known and does not start with a -? -> Default parameter if available.
* @param param Parameter in lower case to check.
* @return true if it is either a known parameter or an argument for the default parameter.
*/
protected boolean isParameter(final String param) {
if (parameters.containsKey(param)) return true;
if (param.startsWith("-")) return false;
return defaultParameter != null;
}
/**
* Parse the given commandline arguments.
* @param args Commandline Arguments to parse.
*/
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()));
}
}
/**
* Get the given optional data of a parameter-
* @param provider Provider of token.
* @param min Minimum number of elements to get.
* @param max Maximum number of elements to get.
* @return List of token of the Parameter.
*/
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;
}
/**
* Callback for help command.
* @param arguments null for general help or name of a command.
*/
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());
}
}
}
}

View File

@ -0,0 +1,221 @@
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;
/**
* Base class for a simple configuration.
*/
@Slf4j
public class Configuration {
/**
* Properties with configuration data.
*/
private Properties properties = new Properties();
/**
* Gets a boolean property
* @param defaultValue Default value to return if key is not present.
* @param key Key of the property to get.
* @return The value of the property if it exists or the default value.
*/
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");
}
/**
* Gets a String property
* @param key Key of the property to query.
* @param defaultValue Default value to return if property not available.
* @return The property if it exists, else the default value.
*/
protected String getStringProperty(final String key, final String defaultValue) {
if (!properties.containsKey(key)) return defaultValue;
return properties.getProperty(key).trim();
}
/**
* Gets a String property with all environment variables replaced
* <p>
* Environment variable can be included with ${variable name}.
* </p>
* @param key Key of the property to query.
* @param defaultValue Default value to return if property not available.
* @return The property if it exists, else the default value.
*/
protected String getStringPropertyWithEnv(final String key, final String defaultValue) {
String result = getStringProperty(key, defaultValue);
return Strings.expandEnvironmentVariables(result);
}
/**
* Gets a String property without quotes.
* <p>
* If the value is put in quotes, then the quote signs are replaced.
* </p>
* @param key Key of the property to query.
* @param defaultValue Default value to return if property not available.
* @return The property if it exists, else the default value (without leading/ending quote signs).
*/
protected String getStringPropertyWithoutQuotes(final String key, final String defaultValue) {
return Strings.removeQuotes(getStringProperty(key, defaultValue));
}
/**
* Gets a String property without quotes.
* <p>
* If the value is put in quotes, then the quote signs are replaced.
* </p>
* @param key Key of the property to query.
* @param defaultValue Default value to return if property not available.
* @return The property if it exists, else the default value (without leading/ending quote signs).
*/
protected String getStringPropertyWithoutQuotesWithEnv(final String key, final String defaultValue) {
String result = getStringPropertyWithoutQuotes(key, defaultValue);
return Strings.expandEnvironmentVariables(result);
}
/**
* Gets an Integer property.
* <br>
* Supports null as value.
* @param defaultValue Default value to return if key is not present.
* @param key Key of the property to get.
* @return The value of the property if it exists or the default value.
*/
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.
* @param key Key of the property to set.
* @param value Value to set.
*/
protected void setIntegerProperty(final String key, final Integer value) {
if (value == null) {
properties.setProperty(key, "");
} else {
properties.setProperty(key, ""+value);
}
}
/**
* Gets the property as LocalDate.
* <br>
* An null value or an empty String is given as null.
* @param key Key of the property.
* @param defaultValue default Value.
* @param formatString Format String to use.
* @return The LocalDate stored the property or the default value if property unknown or couldn't be parsed.
*/
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 the LocalDate using the provided format String.
* <br>
* Null is allowed and is stored as empty string.
* @param key Key of the property to set.
* @param value Value to set.
* @param formatString Format string to use.
*/
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 to a new value.
* @param key Key of property to set.
* @param value New value of property.
*/
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 configuration of the file.
*/
public void load(final String fileName) {
load(fileName, Charset.defaultCharset().name(), true);
}
/**
* Loads the configuration of the file.
*/
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());
}
}
/**
* Insert the configuration settings of the given config.
* @param config Configuration to merge 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 a key from the configuration.
* @param key
*/
public void remove(final String key){
if (properties.containsKey(key)) properties.remove(key);
}
}

View File

@ -0,0 +1,76 @@
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;
/**
* FileReader that converts an UTF-8 file to ISO-8859-15 if required.
* <p>
* This FileReader checks, if the file to be read is an UTF-8 file.
* If an UTF-8 encoding is found, a temporary file will be created with the content
* of the original File - just encoded in the new format.
* </p>
* <p>
* This Reader is mainly tested ith ISO-8859-15 and UTF-8. Other formats are not really supported.
* </p>
*/
@Slf4j
public class ConvertedEncodingFileReader extends InputStreamReader {
private static String checkEncoding = "ISO-8859-15";
private static void setCheckEncoding(final String encoding) {
if (Charset.forName(encoding) != null) throw new IllegalCharsetNameException("Encoding " + encoding + " is not supported!");
checkEncoding = encoding;
}
/**
* Creates a new ConvertedEncodingFileReader from a given File.
* @param file File to convert if required and open reader.
* @param targetFormat Target Format to use.
* @throws IOException
*/
public ConvertedEncodingFileReader(final File file, final String targetFormat) throws IOException {
super(createTargetFormatInputFileStream(file, targetFormat), targetFormat);
}
/**
* Creates a new ISO8859ConvertedFileReader from a given File.
* @param filename File to convert if required and open reader.
* @throws IOException
*/
public ConvertedEncodingFileReader(final String filename, final String targetFormat) throws IOException {
this(new File(filename), targetFormat);
}
/**
* Creates an ISO8859-15 encoded InputFileStream on an file.
* <p>
* If the file is UTF-8 encoded, then it is converted to a temp file and the temp file will be opened.
* </p>
* @param file
* @return The InputFileStream on the original file or the converted file in case of an UTF-8 file.
* @throws IOException
*/
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);
}
}
}

View File

@ -0,0 +1,17 @@
package de.neitzel.core.io;
import java.io.File;
import java.io.IOException;
public class ISO8859EncodingFileReader extends ConvertedEncodingFileReader {
private static final String TARGET_FORMAT = "ISO-8859-15";
public ISO8859EncodingFileReader(File file) throws IOException {
super(file, TARGET_FORMAT);
}
public ISO8859EncodingFileReader(String filename) throws IOException {
super(filename, TARGET_FORMAT);
}
}

View File

@ -0,0 +1,75 @@
package de.neitzel.core.io;
/**
* An encoder for Strings.
* <p>
* All characters with unicode number less than 32 or greater than 127 or 38 (Ampersend)
* will be encoded with &#number; with number as the decimal unicode number.
*/
public class StringEncoder {
/**
* Decodes the encoded String.
* @param data Encoded string.
* @return Decoded String.
*/
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();
}
/**
* Decode a single character.
* @param data String in the form &#xxx; with xxx a decimal number.
* @return The decoded character.
*/
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));
}
/**
* Encode data to a better String representation.
* <p>
* All Characters between from ascii 32 to 127 (except 38 / &)
* are replaced with a &#code; where code is the number of the character.
* @param data String that should be encoded.
* @return Encoded String.
*/
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();
}
}

View File

@ -0,0 +1,20 @@
package de.neitzel.core.util;
/**
* Utility Class with static methods about arrays.
*/
public class ArrayUtils {
/**
* Checks if a given char is inside an array of chars.
* @param array Array of chars to seach in.
* @param ch Character to search.
* @return true if character was found, else false.
*/
public static boolean contains(char[] array, char ch) {
for(int index=0; index < array.length; index++) {
if (array[index] == ch) return true;
}
return false;
}
}

View File

@ -0,0 +1,49 @@
package de.neitzel.core.util;
import java.util.ArrayList;
import java.util.List;
/**
* Enumeration Utilities
*/
public class EnumUtil {
/**
* Creates a regular expression to match a comma separated list of Flags.
* @return Regular expression to match flags.
*/
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();
}
/**
* Parse a list of comma separated flags into a List of RequestFlags.
* @param flags String with comma separated flags.
* @return List of RequestFlags.
*/
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;
}
}

View File

@ -0,0 +1,246 @@
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 Methods regarding files.
*/
@Slf4j
public class FileUtils {
/**
* Date/Time format to add to request files.
*/
public static final SimpleDateFormat DEBUG_FILE_TIMESTAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss_SSS");
/**
* Default encoding used to check the File
*/
public static final String DEFAULT_CHECK_ENCODING = "ISO-8859-15";
/**
* Default Buffer size.
*/
public static final int BUFFER_SIZE = 1024;
/**
* Checks if a File is UTF-8 encoded.
* <p>
* This method checks a file for
* - first 3 bytes for UTF-8 BOM (0xEF 0xBB 0xBF)
* - Existence of 0xC2 / 0xC3 character.
* </p>
* @param file File to check.
* @param checkEncoding Encoding to use for the check, e.g. ISO-8859-15.
* @return true if an UTF-8 file is found, else false.
* @throws IOException IOException is thrown if the file could not be read.
*/
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 File has a UTF-8 BOM.
* <p>
* This method checks a file for
* - first 3 bytes for UTF-8 BOM (0xEF 0xBB 0xBF)
* - Existence of 0xC2 / 0xC3 character.
* </p>
* @param file File to check.
* @return true if an UTF-8 BOM Header was found.
* @throws IOException IOException is thrown if the file could not be read.
*/
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;
}
}
/**
* Checks if a File is UTF-8 encoded.
* <p>
* This method checks a file for
* - first 3 bytes for UTF-8 BOM (0xEF 0xBB 0xBF)
* - Existence of 0xC2 / 0xC3 character.
* </p>
* @param file File to check.
* @return true if an UTF-8 file is found, else false.
* @throws IOException IOException is thrown if the file could not be read.
*/
public static boolean isUTF8(final File file) throws IOException {
return isUTF8(file, DEFAULT_CHECK_ENCODING);
}
/**
* Converts the given Textfile inFile to the outFile using the given encodings.
* @param inFile File to read as UTF-8.
* @param sourceFormat Format of the source file.
* @param outFile File to write with ISO-8859-15 format.
* @param targetFormat Format of the target file.
* @throws IOException Thrown when files couldn't be read / written.
*/
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 new InputStreamReader with the given format or UTF-8 if an UTF-8 file was recognized.
* @param filename Name of file to read.
* @return An InputStreamReader
*/
public static InputStreamReader createUniversalFileReader(final String filename) throws IOException {
return createUniversalFileReader(new File(filename));
}
/**
* Creates a new InputStreamReader with the given format or UTF-8 if an UTF-8 file was recognized.
* @param filename Name of file to read.
* @param expectedFormat Expected format e.g. ISO-8859-15
* @return An InputStreamReader
*/
public static InputStreamReader createUniversalFileReader(final String filename, final String expectedFormat) throws IOException {
return createUniversalFileReader(new File(filename), expectedFormat);
}
/**
* Creates a new InputStreamReader with the given format or UTF-8 if an UTF-8 file was recognized.
* @param file File to read.
* @return An InputStreamReader
*/
public static InputStreamReader createUniversalFileReader(final File file) throws IOException {
return createUniversalFileReader(file, DEFAULT_CHECK_ENCODING, true);
}
/**
* Creates a new InputStreamReader with the given format or UTF-8 if an UTF-8 file was recognized.
* @param file File to read.
* @param expectedFormat Expected format e.g. ISO-8859-15
* @return An InputStreamReader
*/
public static InputStreamReader createUniversalFileReader(final File file, final String expectedFormat) throws IOException {
return createUniversalFileReader(file, expectedFormat, true);
}
/**
* Creates a new InputStreamReader with the given format or UTF-8 if an UTF-8 file was recognized.
* @param file File to read.
* @param expectedFormat Expected format e.g. ISO-8859-15
* @return An InputStreamReader
*/
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;
}
/**
* Gets the parent directory of a file name.
* @param filename Name of file.
* @return Parent folder.
*/
public static String getParentDirectory(final String filename) {
File file = new File(filename);
return file.getParent() != null ? file.getParent() : ".";
}
/**
* Gets the core name of the file without path.
* @param filename Filename with path.
* @return Filename without path.
*/
public static String getFilename(final String filename) {
File file = new File(filename);
return file.getName();
}
/**
* Reads the content of a file (With the correct encoding!).
* @param filename Name of file to read.
* @return Content of the file or null in case of an error.
* @throws IOException Throes an IOException if the file cannot be read.
*/
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 content given to a file.
* @param path Path of the file to write.
* @param content Content to write.
* @throws IOException Thrown if the file could not be written.
*/
public static void writeFile(final Path path, final String content) throws IOException {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(path.toFile()))) {
writer.write(content);
}
}
}

View File

@ -0,0 +1,65 @@
package de.neitzel.core.util;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
public class RegionalizationMessage {
/**
* Resource Bundle to use for operations.
*/
private ResourceBundle res;
/**
* Creates a new instance of RegionalizationMessage.
* @param source Source of messages.
*/
public RegionalizationMessage(final String source) {
res = ResourceBundle.getBundle(source);
}
/**
* Creates a new instance of RegionalizationMessage.
* @param source Source of messages.
* @param locale Locale to use.
*/
public RegionalizationMessage(final String source, final Locale locale) {
res = ResourceBundle.getBundle(source, locale);
}
/**
* Gets the Message behind a key.
* @param key Key to look up.
* @return Message or null.
*/
public String getMessage(final String key) {
if (!res.containsKey(key)) return null;
return res.getString(key);
}
/**
* Gets the Message behind a key.
* @param key Key to look up.
* @param defaultMessage Default message to use if message is not available.
* @return Message from resource or default Message.
*/
public String getMessage(final String key, final String defaultMessage) {
if (res.containsKey(key))
return res.getString(key);
return defaultMessage;
}
/**
* Gets a formatted message.
* @param key key to look up message.
* @param defaultMessage Default message to use if message couldn't be loaded.
* @param params parameter to format the message.
* @return Formatted message.
*/
public String getFormattedMessage(final String key, final String defaultMessage, final Object... params) {
MessageFormat format = new MessageFormat(getMessage(key, defaultMessage));
return format.format(params);
}
}

View File

@ -0,0 +1,109 @@
package de.neitzel.core.util;
import lombok.NonNull;
import java.util.Map;
/**
* Utility Methods for Strings
*/
public class Strings {
/**
* Environment variables of the system.
*/
private static Map<String, String> environmentVariables = System.getenv();
/**
* Expands environment Variables inside a string.
* <p>
* The environment variables should be given as ${variable}.
* </p>
* <p>
* Backslash inside variable values are replaced with slashes to avoid that they are seen as escape character.
* This makes the use for paths on windows possible but reduces the use with non paths in which you need a backslash.
* </p>
* @param text Test in which environment variables should be expanded.
* @return String with all environment variables expanded.
*/
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 if the given String is null or empty.
* @param string String to check.
* @return true if given String is null or empty.
*/
public static boolean isNullOrEmpty(final String string) {
return (string == null || string.length()==0);
}
/**
* Removes a leading / ending quote if there.
* @param value String to remove the quotes.
* @return Parameter string if it does not start / end with a quote, else string without leading/ending quote.
*/
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;
}
/**
* Filters a given String and removes all illegal characters.
* @param value String value to filter all illegal characters from.
* @param illegalCharacters String with all Illegal Characters to filter out.
* @param replacement String to replace illegal characters with.
* @param combine Should multiple illegal characters that are together be replaced with one replacement string only?
* @return A new string where all illegal characters are replaced with the 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);
}
/**
* Filters a given String and removes all illegal characters.
* <p>
* All characters, that are not inside allowedCharacters, are illegal characters.
* </p>
* @param value String value to filter all illegal characters from.
* @param allowedCharacters String with all allowed Characters to filter out.
* @param replacement String to replace illegal characters with.
* @param combine Should multiple illegal characters that are together be replaced with one replacement string only?
* @return A new string where all illegal characters are replaced with the replacement string.
*/
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);
}
/**
* Gets the next Element which follows to the current element.
* @param element to get the precessor.
* @return The next element after this one.
*/
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);
}
public static String limitCharNumber(final String original, final int maxLength) {
if (original == null || original.length() <= maxLength) return original;
return original.substring(0, maxLength);
}
}

View File

@ -0,0 +1,203 @@
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;
/**
* Converter with helper functions to format XML.
*/
@Slf4j
public class XmlUtils {
/**
* DateTimeFormatter instance to format a date for XML use (xs:date type).
*/
public static final DateTimeFormatter XML_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
/**
* Creates a new XML element to be used inside a document.
*
* @param doc XML Document to use.
* @param name Name of the Element.
* @return Created Element.
*/
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 text value to be used inside a document.
*
* @param doc XML Document to use.
* @param name Name of the Element.
* @param value Value of the Text Node.
* @return Created Element.
*/
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 a new XML element with date value to be used inside a document.
*
* @param doc XML Document to use.
* @param name Name of the Element.
* @param value Date to insert into node.
* @return Created Element.
*/
public static Element createElement(final Document doc, final String name, final Date value) {
return createElement(doc, name, XML_DATE_FORMATTER.format(value.toInstant()));
}
/**
* Creates a new XML element with integer value to be used inside a document.
*
* @param doc XML Document to use.
* @param name Name of the Element.
* @param value Value of the Integer Node.
* @return Created Element.
*/
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 XML element to be used inside a document and adds it to the parent.
*
* @param doc XML Document to use.
* @param name Name of the Element.
* @param parent Parent for the Element.
* @return Created Element.
*/
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 text value And adds it to the parent.
*
* @param name Name of the Element.
* @param value Value of the Text Node.
* @param parent Parent for the Element.
* @return Created 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 the XML from a given String with XML content.
*
* @param xmlStream String with XML content.
* @return Formated XML content or original content in case of an error.
*/
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 the XML from a given XML Document.
*
* @param doc XML Document to format.
* @return Formated XML content.
*/
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;
}
/**
* Checks if the given xml string is valid XML
* @param xml XML String.
* @return true if xml is valid.
*/
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;
}
}
}

54
log4j/pom.xml Normal file
View 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>

View File

@ -0,0 +1,75 @@
package de.neitzel.log4j;
import org.apache.log4j.PropertyConfigurator;
import java.io.File;
import java.net.URISyntaxException;
/**
* Adds Utility Methods for log4j.
*/
public class Log4jUtils {
/**
* Default Logfile that should be read.
* Must be a relative path that is checked from the current directory and also from the location of the jar file.
*/
public static final String DEFAULT_LOG4J_LOGFILE = "./log4j.properties";
/**
* Resource to use when no file is found.
*/
public static final String DEFAULT_LOG4J_RESOURCE = "/log4j.default.properties";
/**
* Checks if a log4j config file was set on command line with -Dlog4j.configuration
* @return true if log4j.configuration was set.
*/
public static boolean isLog4jConfigFileSet() {
return System.getProperty("log4j.configuration") != null;
}
/**
* Uses the default configurations if no config file was set.
*/
public static void setLog4jConfiguration() {
setLog4jConfiguration(DEFAULT_LOG4J_LOGFILE, DEFAULT_LOG4J_RESOURCE);
}
/**
* Gets the file with path relative to the jar file.
* @param log4jConfigFile log4j config file.
* @return Path if possible or null.
*/
public static String getLog4jLogfileAtJar(final String log4jConfigFile) {
try {
return new File(Log4jUtils.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParent() + "/" + log4jConfigFile;
} catch (URISyntaxException ex) {
return null;
}
}
/**
* Uses the default configurations if no config file was set.
* <p>
* A log4j configuration can be set using -Dlog4j.configuration. If no configuration was set,
* we look for the log4jConfigFile. If it does not exist, we read the defaultResource.
* </p>
* @param log4jConfigFile Default file to look for.
* @param defaultResource Resource path to use if config file wasn't found.
*/
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));
}
}
}

View File

@ -15,6 +15,7 @@
<module>encryption</module>
<module>fx</module>
<module>net</module>
<module>log4j</module>
<module>fx-example</module>
</modules>
@ -99,6 +100,7 @@
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Lombok -->
<dependency>