* Please do not add new Charset references to this class, unless those character encodings are
* part of the set required to be supported by all Java platform implementations! Any Charsets
* initialized here may cause unexpected delays when this class is loaded. See the Charset
@@ -32,37 +32,38 @@ import java.nio.charset.Charset;
*
*/
public final class Charsets {
- private Charsets() {}
+ private Charsets() {
+ }
- /**
- * US-ASCII: seven-bit ASCII, the Basic Latin block of the Unicode character set (ISO646-US).
- */
- public static final Charset US_ASCII = java.nio.charset.StandardCharsets.US_ASCII;
+ /**
+ * US-ASCII: seven-bit ASCII, the Basic Latin block of the Unicode character set (ISO646-US).
+ */
+ public static final Charset US_ASCII = java.nio.charset.StandardCharsets.US_ASCII;
- /**
- * ISO-8859-1: ISO Latin Alphabet Number 1 (ISO-LATIN-1).
- */
- public static final Charset ISO_8859_1 = java.nio.charset.StandardCharsets.ISO_8859_1;
+ /**
+ * ISO-8859-1: ISO Latin Alphabet Number 1 (ISO-LATIN-1).
+ */
+ public static final Charset ISO_8859_1 = java.nio.charset.StandardCharsets.ISO_8859_1;
- /**
- * UTF-8: eight-bit UCS Transformation Format.
- */
- public static final Charset UTF_8 = java.nio.charset.StandardCharsets.UTF_8;
+ /**
+ * UTF-8: eight-bit UCS Transformation Format.
+ */
+ public static final Charset UTF_8 = java.nio.charset.StandardCharsets.UTF_8;
- /**
- * UTF-16BE: sixteen-bit UCS Transformation Format, big-endian byte order.
- */
- public static final Charset UTF_16BE = java.nio.charset.StandardCharsets.UTF_16BE;
+ /**
+ * UTF-16BE: sixteen-bit UCS Transformation Format, big-endian byte order.
+ */
+ public static final Charset UTF_16BE = java.nio.charset.StandardCharsets.UTF_16BE;
- /**
- * UTF-16LE: sixteen-bit UCS Transformation Format, little-endian byte order.
- */
- public static final Charset UTF_16LE = java.nio.charset.StandardCharsets.UTF_16LE;
+ /**
+ * UTF-16LE: sixteen-bit UCS Transformation Format, little-endian byte order.
+ */
+ public static final Charset UTF_16LE = java.nio.charset.StandardCharsets.UTF_16LE;
- /**
- * UTF-16: sixteen-bit UCS Transformation Format, byte order identified by an optional byte-order
- * mark.
- */
- public static final Charset UTF_16 = java.nio.charset.StandardCharsets.UTF_16;
+ /**
+ * UTF-16: sixteen-bit UCS Transformation Format, byte order identified by an optional byte-order
+ * mark.
+ */
+ public static final Charset UTF_16 = java.nio.charset.StandardCharsets.UTF_16;
}
\ No newline at end of file
diff --git a/src/main/java/net/locusworks/common/annotations/MapValue.java b/src/main/java/net/locusworks/common/annotations/MapValue.java
index b1845e7..48b03ef 100644
--- a/src/main/java/net/locusworks/common/annotations/MapValue.java
+++ b/src/main/java/net/locusworks/common/annotations/MapValue.java
@@ -10,15 +10,16 @@ import java.lang.annotation.Target;
* This is at the field level and will map the
* filed name as the key and the field value as the value
* in the map
+ *
* @author Isaac Parenteau
*
*/
-@Target({ElementType.FIELD, ElementType.TYPE})
+@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MapValue {
- String value() default "";
+ String value() default "";
- boolean ignore() default false;
+ boolean ignore() default false;
}
diff --git a/src/main/java/net/locusworks/common/configuration/ConfigurationCallback.java b/src/main/java/net/locusworks/common/configuration/ConfigurationCallback.java
index cc4a75c..a21fce5 100644
--- a/src/main/java/net/locusworks/common/configuration/ConfigurationCallback.java
+++ b/src/main/java/net/locusworks/common/configuration/ConfigurationCallback.java
@@ -2,5 +2,5 @@ package net.locusworks.common.configuration;
@FunctionalInterface
public interface ConfigurationCallback {
- void results(String msg);
+ void results(String msg);
}
diff --git a/src/main/java/net/locusworks/common/configuration/ConfigurationManager.java b/src/main/java/net/locusworks/common/configuration/ConfigurationManager.java
index 24c5d7e..213a42e 100644
--- a/src/main/java/net/locusworks/common/configuration/ConfigurationManager.java
+++ b/src/main/java/net/locusworks/common/configuration/ConfigurationManager.java
@@ -19,132 +19,136 @@ import net.locusworks.common.utils.Utils;
public class ConfigurationManager {
- private Properties configuration;
- private Properties defaults = null;
- private Path conf = null;
-
- protected AES aes;
-
- private ConfigurationCallback callback;
-
- protected void init(String baseDir, String propertiesFile, ConfigurationCallback callback) throws IOException {
- init(baseDir, propertiesFile, this.getClass().getName().getBytes(Charsets.UTF_8), callback);
- }
-
- protected void init(String baseDir, String propertiesFile, byte[] aesKey, ConfigurationCallback callback) throws IOException {
- aes = aesKey.length > 0 ? AES.createInstance(aesKey) : AES.createInstance();
- this.callback = callback;
- try {
- defaults = PropertiesManager.loadConfiguration(this.getClass(), propertiesFile);
- } catch (IOException ex) {
- throw ex;
- }
- // create patchrepoConf File object
- conf = Paths.get(baseDir).resolve(propertiesFile);
-
- loadConfiguration();
- }
-
- private void loadConfiguration() {
- // load the active config file
- // ignore read error, we can continue with an empty configuration map
- // and all default items will be added below and the file created
-
- callbackMessage("Loading config file: " + conf);
- try {
- configuration = PropertiesManager.loadConfiguration(conf);
- } catch (Exception e) {
- callbackMessage("Config file: " + conf + " will be created from template");
- configuration = new Properties();
+ private Properties configuration;
+ private Properties defaults = null;
+ private Path conf = null;
+
+ protected AES aes;
+
+ private ConfigurationCallback callback;
+
+ protected void init(String baseDir, String propertiesFile, ConfigurationCallback callback) throws IOException {
+ init(baseDir, propertiesFile, this.getClass().getName().getBytes(Charsets.UTF_8), callback);
}
- Map results = PropertiesManager.addConfiguration(configuration, defaults);
- boolean changed = !results.isEmpty();
- if (!results.isEmpty()) {
- StringBuilder sb = new StringBuilder("Added new configuration items:\n");
- for (Entry entry : results.entrySet()) {
- sb.append(String.format("%s=%s\n", entry.getKey(), entry.getValue()));
- }
- callbackMessage(sb.toString());
- }
-
- results = PropertiesManager.removeConfiguration(configuration, defaults);
- changed |= !results.isEmpty();
- if (!results.isEmpty()) {
- StringBuilder sb = new StringBuilder("Added new configuration items:\n");
- for (Entry entry : results.entrySet()) {
- sb.append(String.format("%s=%s\n", entry.getKey(), entry.getValue()));
- }
- callbackMessage(sb.toString());
- }
-
- if (changed) {
- PropertiesManager.saveConfiguration(configuration, conf, "Patch Repository properties file");
- }
- }
-
- /**
- * Save the configuration values to file
- * @param confs Configuration property values to save
- * @throws Exception general exception
- */
- public void saveToConf(Properties confs) throws Exception {
- PropertiesManager.saveConfiguration(confs, conf, conf.getFileName().toString());
- callbackMessage("Saved config file: " + conf + ", " + confs.size() + " entries");
- loadConfiguration();
- }
-
- public String getPropertyValue(String key) {
- return getPropertyValue(key, null);
- }
- public String getPropertyValue(String key, String defaultValue) {
- return configuration.containsKey(key) ? configuration.getProperty(key) : defaultValue;
- }
-
- public Properties getConfiguration() {
- return configuration;
- }
-
- public void saveConfiguration(PersistableRequest request, Set fieldsToSave, Set excryptedFields) throws Exception {
- if (fieldsToSave == null || fieldsToSave.isEmpty()) {
- throw ApplicationException.generic("No fields to save were defined");
- }
- if (excryptedFields == null) {
- excryptedFields = new HashSet<>();
- }
- try {
- Properties props = new Properties();
-
- //copy what is current in the configuration settings into the new properties file
- configuration.entrySet().forEach(item -> props.setProperty(String.valueOf(item.getKey()), String.valueOf(item.getValue())));
- boolean changed = false;
- for (Field f : request.getClass().getDeclaredFields()) {
- f.setAccessible(true);
- String fieldName = f.getName();
- String fieldValue = String.valueOf(f.get(request));
+ protected void init(String baseDir, String propertiesFile, byte[] aesKey, ConfigurationCallback callback) throws IOException {
+ aes = aesKey.length > 0 ? AES.createInstance(aesKey) : AES.createInstance();
+ this.callback = callback;
+ try {
+ defaults = PropertiesManager.loadConfiguration(this.getClass(), propertiesFile);
+ } catch (IOException ex) {
+ throw ex;
+ }
+ // create patchrepoConf File object
+ conf = Paths.get(baseDir).resolve(propertiesFile);
- //Ensures we are only saving values that are already configured
- if (!fieldsToSave.contains(fieldName)) continue;
-
- //Check to see if the old value changed
- String oldValue = props.getProperty(fieldName);
- if (Utils.isNotValid(oldValue, fieldValue) || oldValue.equals(fieldValue)) { continue; }
-
- changed = true;
-
- fieldValue = excryptedFields.contains(fieldName) ? aes.encrypt(fieldValue) : fieldValue;
-
- props.setProperty(fieldName, fieldValue);
- }
- if (changed) {
- saveToConf(props);
- }
- } catch (Exception ex) {
- throw ApplicationException.actionNotPermitted(ex.getMessage());
+ loadConfiguration();
+ }
+
+ private void loadConfiguration() {
+ // load the active config file
+ // ignore read error, we can continue with an empty configuration map
+ // and all default items will be added below and the file created
+
+ callbackMessage("Loading config file: " + conf);
+ try {
+ configuration = PropertiesManager.loadConfiguration(conf);
+ } catch (Exception e) {
+ callbackMessage("Config file: " + conf + " will be created from template");
+ configuration = new Properties();
+ }
+
+ Map results = PropertiesManager.addConfiguration(configuration, defaults);
+ boolean changed = !results.isEmpty();
+ if (!results.isEmpty()) {
+ StringBuilder sb = new StringBuilder("Added new configuration items:\n");
+ for (Entry entry : results.entrySet()) {
+ sb.append(String.format("%s=%s\n", entry.getKey(), entry.getValue()));
+ }
+ callbackMessage(sb.toString());
+ }
+
+ results = PropertiesManager.removeConfiguration(configuration, defaults);
+ changed |= !results.isEmpty();
+ if (!results.isEmpty()) {
+ StringBuilder sb = new StringBuilder("Added new configuration items:\n");
+ for (Entry entry : results.entrySet()) {
+ sb.append(String.format("%s=%s\n", entry.getKey(), entry.getValue()));
+ }
+ callbackMessage(sb.toString());
+ }
+
+ if (changed) {
+ PropertiesManager.saveConfiguration(configuration, conf, "Patch Repository properties file");
+ }
+ }
+
+ /**
+ * Save the configuration values to file
+ *
+ * @param confs Configuration property values to save
+ * @throws Exception general exception
+ */
+ public void saveToConf(Properties confs) throws Exception {
+ PropertiesManager.saveConfiguration(confs, conf, conf.getFileName().toString());
+ callbackMessage("Saved config file: " + conf + ", " + confs.size() + " entries");
+ loadConfiguration();
+ }
+
+ public String getPropertyValue(String key) {
+ return getPropertyValue(key, null);
+ }
+
+ public String getPropertyValue(String key, String defaultValue) {
+ return configuration.containsKey(key) ? configuration.getProperty(key) : defaultValue;
+ }
+
+ public Properties getConfiguration() {
+ return configuration;
+ }
+
+ public void saveConfiguration(PersistableRequest request, Set fieldsToSave, Set excryptedFields) throws Exception {
+ if (fieldsToSave == null || fieldsToSave.isEmpty()) {
+ throw ApplicationException.generic("No fields to save were defined");
+ }
+ if (excryptedFields == null) {
+ excryptedFields = new HashSet<>();
+ }
+ try {
+ Properties props = new Properties();
+
+ //copy what is current in the configuration settings into the new properties file
+ configuration.entrySet().forEach(item -> props.setProperty(String.valueOf(item.getKey()), String.valueOf(item.getValue())));
+ boolean changed = false;
+ for (Field f : request.getClass().getDeclaredFields()) {
+ f.setAccessible(true);
+ String fieldName = f.getName();
+ String fieldValue = String.valueOf(f.get(request));
+
+ //Ensures we are only saving values that are already configured
+ if (!fieldsToSave.contains(fieldName)) continue;
+
+ //Check to see if the old value changed
+ String oldValue = props.getProperty(fieldName);
+ if (Utils.isNotValid(oldValue, fieldValue) || oldValue.equals(fieldValue)) {
+ continue;
+ }
+
+ changed = true;
+
+ fieldValue = excryptedFields.contains(fieldName) ? aes.encrypt(fieldValue) : fieldValue;
+
+ props.setProperty(fieldName, fieldValue);
+ }
+ if (changed) {
+ saveToConf(props);
+ }
+ } catch (Exception ex) {
+ throw ApplicationException.actionNotPermitted(ex.getMessage());
+ }
+ }
+
+ private void callbackMessage(String msg) {
+ if (callback != null) callback.results(msg);
}
- }
-
- private void callbackMessage(String msg) {
- if (callback != null) callback.results(msg);
- }
}
diff --git a/src/main/java/net/locusworks/common/configuration/PropertiesManager.java b/src/main/java/net/locusworks/common/configuration/PropertiesManager.java
index c99a16d..de4143b 100644
--- a/src/main/java/net/locusworks/common/configuration/PropertiesManager.java
+++ b/src/main/java/net/locusworks/common/configuration/PropertiesManager.java
@@ -15,139 +15,147 @@ import java.util.Properties;
import java.util.stream.Collectors;
import net.locusworks.common.immutables.Pair;
+import net.locusworks.common.immutables.Unit;
+
/**
* Properties manager class to help load and read properties
+ *
* @author Isaac Parenteau
- * @version 1.0.0
- * @date 02/15/2018
+ * @version 2.0.0
+ * @date 09/17/2023
*/
public class PropertiesManager {
- /**
- * Load a configuration from resource
- * @param clazz class loader
- * @param src source of the file
- * @return properties
- * @throws IOException Exception thrown the file can't be read
- */
- public static Properties loadConfiguration(Class> clazz, String src) throws IOException {
- InputStream is = clazz.getResourceAsStream(src);
- if (is == null) {
- is = clazz.getClassLoader().getResourceAsStream(src);
- }
- if (is == null) {
- return null;
- }
- BufferedReader br = new BufferedReader(new InputStreamReader(is, UTF_8));
- return loadConfiguration(br);
- }
-
- /**
- * Load configuration from a file. This method has been deprecated and may be removed in
- * future released. Please use java.nio.Path
- * @param file File to load
- * @return properties
- * @throws IOException Exception thrown the file can't be read
- */
- @Deprecated
- public static Properties loadConfiguration(File file) throws IOException {
- return loadConfiguration(file.toPath());
- }
-
- /**
- * Load configuration from a file.
- * @param path the path to the file
- * @return properties
- * @throws IOException Exception thrown the file can't be read
- */
- public static Properties loadConfiguration(Path path) throws IOException {
- if (Files.notExists(path)) {
- return new Properties();
+ /**
+ * Load a configuration from a resource
+ *
+ * @param clazz class loader
+ * @param src source of the file
+ * @return properties
+ * @throws IOException Exception thrown the file can't be read
+ */
+ public static Properties loadConfiguration(Class> clazz, String src) throws IOException {
+ InputStream is = clazz.getResourceAsStream(src);
+ if (is == null) {
+ is = clazz.getClassLoader().getResourceAsStream(src);
+ }
+ if (is == null) {
+ return null;
+ }
+ BufferedReader br = new BufferedReader(new InputStreamReader(is, UTF_8));
+ return loadConfiguration(br);
}
- try(BufferedReader br = Files.newBufferedReader(path)) {
- return loadConfiguration(br);
+ /**
+ * Load configuration from a file. This method has been deprecated and may be removed in
+ * future released. Please use java.nio.Path
+ *
+ * @param file File to load
+ * @return properties
+ * @throws IOException Exception thrown the file can't be read
+ */
+ @Deprecated
+ public static Properties loadConfiguration(File file) throws IOException {
+ return loadConfiguration(file.toPath());
}
- }
- /**
- * Load configuration from a buffered reader
- * @param reader Buffered reader to read the properties values from
- * @return properties
- * @throws IOException Exception thrown the file can't be read
- */
- public static Properties loadConfiguration(BufferedReader reader) throws IOException {
- Properties config = new Properties();
- config.load(reader);
- return config;
- }
+ /**
+ * Load configuration from a file.
+ *
+ * @param path the path to the file
+ * @return properties
+ * @throws IOException Exception thrown the file can't be read
+ */
+ public static Properties loadConfiguration(Path path) throws IOException {
+ if (Files.notExists(path)) {
+ return new Properties();
+ }
- /**
- * Add configurations from one properties file to another
- * @param to Properties file to copy values to
- * @param from Properties file to copy values from
- * @return a map containing the results of the values added
- */
- public static Map addConfiguration(Properties to, Properties from) {
- Map results = from.entrySet()
- .stream()
- .filter(entry -> !to.containsKey(entry.getKey()))
- .map(entry -> {
- String key = entry.getKey().toString();
- String value = entry.getValue().toString();
- to.put(key, value);
- return new Pair(key, value);
- })
- .collect(Collectors.toMap(key -> key.getValue1(), value -> value.getValue2()));
-
- return results;
- }
-
- /**
- * Removes configuration values that are not present in the comparedTo
- * @param from Properties file to remove values from
- * @param comparedTo Properties file to compare to
- * @return a map containing the results of the values removed
- */
- public static Map removeConfiguration(Properties from, Properties comparedTo) {
- Map results = from.keySet()
- .stream()
- .filter(key -> !comparedTo.containsKey(key)) //only get the items that are not in the comparedTo properties
- .map(key -> new Pair(String.valueOf(key), String.valueOf(from.get(key))))
- .collect(Collectors.toList()) //Create a list of paired items (key value) of the items that were filtered
- .stream()
- .map(pair -> { //remove those pairs from the from properties
- from.remove(pair.getValue1());
- return pair;
- })
- .collect(Collectors.toMap(key -> key.getValue1(), value -> value.getValue2())); //create a map of what was removed
-
- return results;
- }
-
- /**
- *
Save the properties file to disk.
- *
This method has been depecreated and could be removed in future release. Please use java.nio.Path
- * @param props Properties file to save
- * @param fileToSave File to save to
- * @param comment Any comments to add
- */
- @Deprecated
- public static void saveConfiguration(Properties props, File fileToSave, String comment) {
- saveConfiguration(props, fileToSave.toPath(), comment);
-
- }
-
- /**
- *
Save the properties file to disk.
- * @param props Properties file to save
- * @param fileToSave File to save to
- * @param comment Any comments to add
- */
- public static void saveConfiguration(Properties props, Path fileToSave, String comment) {
- try(OutputStream fos = Files.newOutputStream(fileToSave)) {
- props.store(fos, comment == null ? "" : comment);
- } catch (IOException ex) {
- throw new RuntimeException(ex.getMessage(), ex);
+ try (BufferedReader br = Files.newBufferedReader(path)) {
+ return loadConfiguration(br);
+ }
+ }
+
+ /**
+ * Load configuration from a buffered reader
+ *
+ * @param reader Buffered reader to read the properties values from
+ * @return properties
+ * @throws IOException Exception thrown the file can't be read
+ */
+ public static Properties loadConfiguration(BufferedReader reader) throws IOException {
+ Properties config = new Properties();
+ config.load(reader);
+ return config;
+ }
+
+ /**
+ * Add configurations from one properties file to another
+ *
+ * @param to Properties file to copy values to
+ * @param from Properties file to copy values from
+ * @return a map containing the results of the values added
+ */
+ public static Map addConfiguration(Properties to, Properties from) {
+
+ return from.entrySet()
+ .stream()
+ .filter(entry -> !to.containsKey(entry.getKey()))
+ .map(entry -> {
+ String key = entry.getKey().toString();
+ String value = entry.getValue().toString();
+ to.put(key, value);
+ return new Pair(key, value);
+ })
+ .collect(Collectors.toMap(Unit::getValue1, Pair::getValue2));
+ }
+
+ /**
+ * Removes configuration values that are not present in the comparedTo
+ *
+ * @param from Properties file to remove values from
+ * @param comparedTo Properties file to compare to
+ * @return a map containing the results of the values removed
+ */
+ public static Map removeConfiguration(Properties from, Properties comparedTo) {
+
+ return from.keySet()
+ .stream()
+ .filter(key -> !comparedTo.containsKey(key)) //only get the items that are not in the comparedTo properties
+ .map(key -> new Pair(String.valueOf(key), String.valueOf(from.get(key))))
+ .toList() //Create a list of paired items (key value) of the items that were filtered
+ .stream()
+ .peek(pair -> { //remove those pairs from the from properties
+ from.remove(pair.getValue1());
+ })
+ .collect(Collectors.toMap(Unit::getValue1, Pair::getValue2));
+ }
+
+ /**
+ *
Save the properties file to disk.
+ *
This method has been depecreated and could be removed in future release. Please use java.nio.Path
+ *
+ * @param props Properties file to save
+ * @param fileToSave File to save to
+ * @param comment Any comments to add
+ */
+ @Deprecated
+ public static void saveConfiguration(Properties props, File fileToSave, String comment) {
+ saveConfiguration(props, fileToSave.toPath(), comment);
+
+ }
+
+ /**
+ *
Save the properties file to disk.
+ *
+ * @param props Properties file to save
+ * @param fileToSave File to save to
+ * @param comment Any comments to add
+ */
+ public static void saveConfiguration(Properties props, Path fileToSave, String comment) {
+ try (OutputStream fos = Files.newOutputStream(fileToSave)) {
+ props.store(fos, comment == null ? "" : comment);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex.getMessage(), ex);
+ }
}
- }
}
diff --git a/src/main/java/net/locusworks/common/crypto/AES.java b/src/main/java/net/locusworks/common/crypto/AES.java
index 9c67983..91ef029 100644
--- a/src/main/java/net/locusworks/common/crypto/AES.java
+++ b/src/main/java/net/locusworks/common/crypto/AES.java
@@ -7,23 +7,22 @@ import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
+import java.security.*;
import java.util.Base64;
import net.locusworks.common.utils.RandomString;
import net.locusworks.common.utils.Utils;
+
import static net.locusworks.common.Charsets.UTF_8;
/**
* AES encryption/decryption class
- * This class will encrypt/decrypt data. The encryption key is never known.
- * Instead it is is generated by the provided seed. As long as the seed stays the same
+ * This class will encrypt/decrypt data. The encryption key is never known.
+ * Instead, it is generated by the provided seed. As long as the seed stays the same
* the key will remain the same and the encryption/decryption will work. This
* provides and added security.
+ *
* @author Isaac Parenteau
* @version 1.0.0
* @date 02/15/2018
@@ -31,132 +30,133 @@ import static net.locusworks.common.Charsets.UTF_8;
*/
public class AES {
- private static final String ENCRYPTION_TYPE = "AES";
- private static final String ENCRYPTION_ALGORITH = "AES/CBC/PKCS5Padding";
- private static final String PROVIDER = "SunJCE";
- private static final String ALGORITHM = "SHA1PRNG";
+ private static final String ENCRYPTION_TYPE = "AES";
+ private static final String ENCRYPTION_ALGORITHM = "AES/CBC/PKCS5Padding";
+ private static final String PROVIDER = "SunJCE";
+ private static final String ALGORITHM = "SHA1PRNG";
- private Cipher cipher;
+ private Cipher cipher;
- private SecretKeySpec secretKeySpec;
+ private SecretKeySpec secretKeySpec;
- private IvParameterSpec ivParamSpec;
+ private IvParameterSpec ivParamSpec;
- private String seed;
+ private String seed;
- private void initSecureKey(String seed) {
- try {
- SecureRandom sr = getSecureRandom(seed);
- KeyGenerator generator = KeyGenerator.getInstance(ENCRYPTION_TYPE);
- generator.init(128, sr);
- init(generator.generateKey().getEncoded(), sr);
- } catch (Exception ex) {
- System.err.println(ex);
- throw new IllegalArgumentException("Unable to initalize encryption:", ex);
+ private RandomString randomizer;
+
+ private void initSecureKey(String seed) {
+ try {
+ SecureRandom sr = getSecureRandom(seed);
+ KeyGenerator generator = KeyGenerator.getInstance(ENCRYPTION_TYPE);
+ generator.init(128, sr);
+
+ randomizer = RandomString.newInstance(sr);
+ init(generator.generateKey().getEncoded());
+ } catch (Exception ex) {
+ throw new IllegalArgumentException("Unable to initialize encryption:", ex);
+ }
}
- }
- /**
- * Initializes the secure random object to be the same across all platforms
- * with regard to provider and algorithm used
- * @param seed Seed to initialize SecureRandom with
- * @return SecureRandom object
- * @throws NoSuchAlgorithmException thrown when algorithm can't be used
- * @throws NoSuchProviderException thrown when the provider cant be found
- */
- private static SecureRandom getSecureRandom(String seed) throws NoSuchAlgorithmException {
- SecureRandom sr = SecureRandom.getInstance(ALGORITHM);
- sr.setSeed(seed.getBytes(UTF_8));
- return sr;
- }
+ /**
+ * Initializes the secure random object to be the same across all platforms
+ * with regard to provider and algorithm used
+ *
+ * @param seed Seed to initialize SecureRandom with
+ * @return SecureRandom object
+ * @throws NoSuchAlgorithmException thrown when algorithm can't be used
+ */
+ private static SecureRandom getSecureRandom(String seed) throws NoSuchAlgorithmException {
+ SecureRandom sr = SecureRandom.getInstance(ALGORITHM);
+ sr.setSeed(seed.getBytes(UTF_8));
+ return sr;
+ }
- /**
- * Initialize the aes engine
- * @param key secret key to use
- * @param sr
- */
- private void init(final byte[] key, SecureRandom sr) {
- try {
- this.cipher = Cipher.getInstance(ENCRYPTION_ALGORITH, PROVIDER);
- this.secretKeySpec = new SecretKeySpec(key, ENCRYPTION_TYPE);
- this.ivParamSpec = new IvParameterSpec(RandomString.getBytes(16, sr));
- } catch (Exception ex) {
- System.err.println(ex);
- throw new IllegalArgumentException("Unable to initalize encryption:", ex);
+ /**
+ * Initialize the aes engine
+ *
+ * @param key secret key to use
+ */
+ private void init(final byte[] key) {
+ try {
+ this.cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM, PROVIDER);
+ this.secretKeySpec = new SecretKeySpec(key, ENCRYPTION_TYPE);
+ this.ivParamSpec = new IvParameterSpec(randomizer.getBytes(16));
+ } catch (Exception ex) {
+ throw new IllegalArgumentException("Unable to initialize encryption:", ex);
+ }
}
- }
- /***
- * Encrypt a text string
- * @param plainText String to encrypt
- * @return encrypted string
- */
- public String encrypt(String plainText) {
- if (Utils.isEmptyString(plainText)) {
- plainText = "";
+ /***
+ * Encrypt a text string
+ * @param plainText String to encrypt
+ * @return encrypted string
+ */
+ public String encrypt(String plainText) {
+ if (Utils.isEmptyString(plainText)) {
+ plainText = "";
+ }
+ try {
+ cipher.init(Cipher.ENCRYPT_MODE, this.secretKeySpec, this.ivParamSpec);
+ byte[] cypherText = cipher.doFinal(plainText.getBytes(UTF_8));
+ return new String(Base64.getEncoder().encode(cypherText), UTF_8);
+ } catch (Exception ex) {
+ throw new IllegalArgumentException(ex.getMessage(), ex);
+ }
}
- try {
- cipher.init(Cipher.ENCRYPT_MODE, this.secretKeySpec, this.ivParamSpec);
- byte[] cypherText = cipher.doFinal(plainText.getBytes(UTF_8));
- return new String(Base64.getEncoder().encode(cypherText), UTF_8);
- } catch (Exception ex) {
- throw new IllegalArgumentException(ex.getMessage(), ex);
- }
- }
- /***
- * Decrypt an encrypted string
- * @param cipherString encrypted string to decrypt
- * @return unecrypted string
- */
- public String decrypt(String cipherString) {
- if (Utils.isEmptyString(cipherString)) {
- return "";
- }
- byte[] cipherText = Base64.getDecoder().decode(cipherString.getBytes(UTF_8));
- try {
- cipher.init(Cipher.DECRYPT_MODE, this.secretKeySpec, this.ivParamSpec);
- return new String(cipher.doFinal(cipherText), UTF_8);
- } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {
- throw new IllegalArgumentException(e.getMessage(), e);
+ /***
+ * Decrypt an encrypted string
+ * @param cipherString encrypted string to decrypt
+ * @return unecrypted string
+ */
+ public String decrypt(String cipherString) {
+ if (Utils.isEmptyString(cipherString)) {
+ return "";
+ }
+ byte[] cipherText = Base64.getDecoder().decode(cipherString.getBytes(UTF_8));
+ try {
+ cipher.init(Cipher.DECRYPT_MODE, this.secretKeySpec, this.ivParamSpec);
+ return new String(cipher.doFinal(cipherText), UTF_8);
+ } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException |
+ InvalidAlgorithmParameterException e) {
+ throw new IllegalArgumentException(e.getMessage(), e);
+ }
}
- }
-
- public AES setSeed(String seed) {
- if (this.seed == null || !this.seed.equals(seed)) {
- initSecureKey(seed);
- }
- this.seed = seed;
- return this;
- }
-
- public final String getSeed() {
- return this.seed;
- }
- public static AES createInstance() {
- return createInstance(RandomString.getString(16));
- }
-
- public static AES createInstance(byte[] byteSeed) {
- String seed = new String(byteSeed, UTF_8);
- return createInstance(seed);
- }
-
- public static AES createInstance(String seed) {
- AES aes = new AES();
- aes.setSeed(seed);
- return aes;
- }
-
- public static void main(String[] args) throws NoSuchAlgorithmException {
- if (args == null || !(args.length > 0)) {
- throw new IllegalArgumentException("No args provided. Need password as argument");
+ public AES withSeed(String seed) {
+ if (this.seed == null || !this.seed.equals(seed)) {
+ initSecureKey(seed);
+ }
+ this.seed = seed;
+ return this;
}
- if (args.length % 2 == 0) {
- System.out.println(AES.createInstance(String.valueOf(args[1])).decrypt(String.valueOf(args[0])));
- } else {
- System.out.println(AES.createInstance().encrypt(String.valueOf(args[0])));
+
+ public final String getSeed() {
+ return this.seed;
+ }
+
+ public static AES createInstance() {
+ return createInstance(RandomString.getInstance().getString(16));
+ }
+
+ public static AES createInstance(byte[] byteSeed) {
+ String seed = new String(byteSeed, UTF_8);
+ return createInstance(seed);
+ }
+
+ public static AES createInstance(String seed) {
+ return new AES().withSeed(seed);
+ }
+
+ public static void main(String[] args) throws NoSuchAlgorithmException {
+ if (args == null || !(args.length > 0)) {
+ throw new IllegalArgumentException("No args provided. Need password as argument");
+ }
+ if (args.length % 2 == 0) {
+ System.out.println(AES.createInstance(String.valueOf(args[1])).decrypt(String.valueOf(args[0])));
+ } else {
+ System.out.println(AES.createInstance().encrypt(String.valueOf(args[0])));
+ }
}
- }
}
diff --git a/src/main/java/net/locusworks/common/crypto/AESKey.java b/src/main/java/net/locusworks/common/crypto/AESKey.java
index b64d6b8..c0a8ef0 100644
--- a/src/main/java/net/locusworks/common/crypto/AESKey.java
+++ b/src/main/java/net/locusworks/common/crypto/AESKey.java
@@ -1,30 +1,32 @@
package net.locusworks.common.crypto;
+import java.io.Serial;
import java.security.PrivateKey;
import net.locusworks.common.Charsets;
public class AESKey implements PrivateKey {
-
- private static final long serialVersionUID = -8452357427706386362L;
- private String seed;
-
- public AESKey(String seed) {
- this.seed = seed;
- }
- @Override
- public String getAlgorithm() {
- return "aes";
- }
+ @Serial
+ private static final long serialVersionUID = -8452357427706386362L;
+ private final String seed;
- @Override
- public String getFormat() {
- return "aes-seed";
- }
+ public AESKey(String seed) {
+ this.seed = seed;
+ }
- @Override
- public byte[] getEncoded() {
- return this.seed.getBytes(Charsets.UTF_8);
- }
+ @Override
+ public String getAlgorithm() {
+ return "aes";
+ }
+
+ @Override
+ public String getFormat() {
+ return "aes-seed";
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ return this.seed.getBytes(Charsets.UTF_8);
+ }
}
diff --git a/src/main/java/net/locusworks/common/crypto/AESKeySpec.java b/src/main/java/net/locusworks/common/crypto/AESKeySpec.java
index a29c54f..3df5ea9 100644
--- a/src/main/java/net/locusworks/common/crypto/AESKeySpec.java
+++ b/src/main/java/net/locusworks/common/crypto/AESKeySpec.java
@@ -15,31 +15,31 @@ import static net.locusworks.common.utils.Utils.get;
import static net.locusworks.common.utils.Utils.size;
public class AESKeySpec extends EncodedKeySpec {
-
- private static final String AES_MARKER = "aes-seed";
- public AESKeySpec(byte[] encodedKey) {
- super(encodedKey);
- }
-
- public AESKey generateKey() throws InvalidKeySpecException {
- try {
- byte[] data = this.getEncoded();
- InputStream stream = new ByteArrayInputStream(data);
- Iterable parts = Arrays.asList(IOUtils.toString(stream, Charsets.UTF_8).split(" "));
-
- checkArguments(size(parts) == 2 && AES_MARKER.equals(get(parts, 0)), "Bad format, should be: aes-seed AAB3...");
- stream = new ByteArrayInputStream(Base64.getDecoder().decode(String.valueOf(get(parts, 1))));
- String marker = IOUtils.toString(stream, Charsets.UTF_8);
- return new AESKey(marker);
- } catch (Exception ex) {
- throw new InvalidKeySpecException(ex);
+ private static final String AES_MARKER = "aes-seed";
+
+ public AESKeySpec(byte[] encodedKey) {
+ super(encodedKey);
}
- }
- @Override
- public String getFormat() {
- return "aes";
- }
+ public AESKey generateKey() throws InvalidKeySpecException {
+ try {
+ byte[] data = this.getEncoded();
+ InputStream stream = new ByteArrayInputStream(data);
+ Iterable parts = Arrays.asList(IOUtils.toString(stream, Charsets.UTF_8).split(" "));
+
+ checkArguments(size(parts) == 2 && AES_MARKER.equals(get(parts, 0)), "Bad format, should be: aes-seed AAB3...");
+ stream = new ByteArrayInputStream(Base64.getDecoder().decode(String.valueOf(get(parts, 1))));
+ String marker = IOUtils.toString(stream, Charsets.UTF_8);
+ return new AESKey(marker);
+ } catch (Exception ex) {
+ throw new InvalidKeySpecException(ex);
+ }
+ }
+
+ @Override
+ public String getFormat() {
+ return "aes";
+ }
}
diff --git a/src/main/java/net/locusworks/common/crypto/EncryptionKeyFactory.java b/src/main/java/net/locusworks/common/crypto/EncryptionKeyFactory.java
index e21d4f7..c2737f3 100644
--- a/src/main/java/net/locusworks/common/crypto/EncryptionKeyFactory.java
+++ b/src/main/java/net/locusworks/common/crypto/EncryptionKeyFactory.java
@@ -14,25 +14,25 @@ import sun.security.jca.GetInstance.Instance;
public class EncryptionKeyFactory extends KeyFactory {
- protected EncryptionKeyFactory(KeyFactorySpi keyFacSpi, Provider provider, String algorithm) {
- super(keyFacSpi, provider, algorithm);
- }
-
- public PrivateKey generatePrivateKey(KeySpec keySpec) throws InvalidKeySpecException {
- if (keySpec instanceof AESKeySpec) {
- return ((AESKeySpec)keySpec).generateKey();
+ protected EncryptionKeyFactory(KeyFactorySpi keyFacSpi, Provider provider, String algorithm) {
+ super(keyFacSpi, provider, algorithm);
+ }
+
+ public PrivateKey generatePrivateKey(KeySpec keySpec) throws InvalidKeySpecException {
+ if (keySpec instanceof AESKeySpec) {
+ return ((AESKeySpec) keySpec).generateKey();
+ }
+ return super.generatePrivate(keySpec);
+ }
+
+ public PublicKey generatePublicKey(KeySpec keySpec) throws InvalidKeySpecException {
+ keySpec = keySpec instanceof SSHEncodedKeySpec ? ((SSHEncodedKeySpec) keySpec).convertToRSAPubKeySpec() : keySpec;
+ return super.generatePublic(keySpec);
+ }
+
+ public static EncryptionKeyFactory getInstance(String algorithm) throws NoSuchAlgorithmException {
+ Instance instance = GetInstance.getInstance("KeyFactory", KeyFactorySpi.class, algorithm);
+ return new EncryptionKeyFactory((KeyFactorySpi) instance.impl, instance.provider, algorithm);
}
- return super.generatePrivate(keySpec);
- }
-
- public PublicKey generatePublicKey(KeySpec keySpec) throws InvalidKeySpecException {
- keySpec = keySpec instanceof SSHEncodedKeySpec ? ((SSHEncodedKeySpec)keySpec).convertToRSAPubKeySpec() : keySpec;
- return super.generatePublic(keySpec);
- }
-
- public static EncryptionKeyFactory getInstance(String algorithm) throws NoSuchAlgorithmException {
- Instance instance = GetInstance.getInstance("KeyFactory", KeyFactorySpi.class, algorithm);
- return new EncryptionKeyFactory((KeyFactorySpi)instance.impl, instance.provider, algorithm);
- }
}
diff --git a/src/main/java/net/locusworks/common/crypto/HashSalt.java b/src/main/java/net/locusworks/common/crypto/HashSalt.java
index 1c84004..ca7ec9c 100644
--- a/src/main/java/net/locusworks/common/crypto/HashSalt.java
+++ b/src/main/java/net/locusworks/common/crypto/HashSalt.java
@@ -9,181 +9,178 @@ import javax.crypto.spec.PBEKeySpec;
/**
* The type Hash salt.
+ *
* @author Isaac Parenteau
* @version 1.0.0
* @date 02/15/2018
*/
public class HashSalt {
- /**
- * The constant PBKDF2_ALGORITHM.
- */
- private static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA256";
+ /**
+ * The constant PBKDF2_ALGORITHM.
+ */
+ private static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA256";
- /**
- * The constant SALT_BYTE_SIZE.
- */
- private static final int SALT_BYTE_SIZE = 24;
+ /**
+ * The constant SALT_BYTE_SIZE.
+ */
+ private static final int SALT_BYTE_SIZE = 24;
- /**
- * The constant HASH_BYTE_SIZE.
- */
- private static final int HASH_BYTE_SIZE = 24;
+ /**
+ * The constant HASH_BYTE_SIZE.
+ */
+ private static final int HASH_BYTE_SIZE = 24;
- /**
- * The constant PBKDF2_ITERATIONS.
- */
- private static final int PBKDF2_ITERATIONS = 1000;
+ /**
+ * The constant PBKDF2_ITERATIONS.
+ */
+ private static final int PBKDF2_ITERATIONS = 1000;
- /**
- * The constant ITERATION_INDEX.
- */
- private static final int ITERATION_INDEX = 0;
- /**
- * The constant SALT_INDEX.
- */
- private static final int SALT_INDEX = 1;
- /**
- * The constant PBKDF2_INDEX.
- */
- private static final int PBKDF2_INDEX = 2;
+ /**
+ * The constant ITERATION_INDEX.
+ */
+ private static final int ITERATION_INDEX = 0;
+ /**
+ * The constant SALT_INDEX.
+ */
+ private static final int SALT_INDEX = 1;
+ /**
+ * The constant PBKDF2_INDEX.
+ */
+ private static final int PBKDF2_INDEX = 2;
- /**
- * Returns a salted PBKDF2 hash of the password.
- *
- * @param password the password to hash
- *
- * @return a salted PBKDF2 hash of the password
- * @throws NoSuchAlgorithmException the no such algorithm exception
- * @throws InvalidKeySpecException the invalid key spec exception
- */
- public static String createHash(String password) throws NoSuchAlgorithmException, InvalidKeySpecException {
- return createHash(password.toCharArray());
- }
-
- /**
- * Returns a salted PBKDF2 hash of the password.
- *
- * @param password the password to hash
- *
- * @return a salted PBKDF2 hash of the password
- * @throws NoSuchAlgorithmException the no such algorithm exception
- * @throws InvalidKeySpecException the invalid key spec exception
- */
- public static String createHash(char[] password) throws NoSuchAlgorithmException, InvalidKeySpecException {
- // Generate a random salt
- SecureRandom random = new SecureRandom();
- byte[] salt = new byte[SALT_BYTE_SIZE];
- random.nextBytes(salt);
-
- // Hash the password
- byte[] hash = pbkdf2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE);
- // format iterations:salt:hash
- return PBKDF2_ITERATIONS + ":" + toHex(salt) + ":" + toHex(hash);
- }
-
- /**
- * Validates a password using a hash.
- *
- * @param password the password to check
- * @param correctHash the hash of the valid password
- *
- * @return true if the password is correct, false if not
- * @throws NoSuchAlgorithmException the no such algorithm exception
- * @throws InvalidKeySpecException the invalid key spec exception
- */
- public static boolean validatePassword(String password, String correctHash) throws NoSuchAlgorithmException, InvalidKeySpecException {
- return validatePassword(password.toCharArray(), correctHash);
- }
-
- /**
- * Validates a password using a hash.
- *
- * @param password the password to check
- * @param correctHash the hash of the valid password
- *
- * @return true if the password is correct, false if not
- * @throws NoSuchAlgorithmException the no such algorithm exception
- * @throws InvalidKeySpecException the invalid key spec exception
- */
- public static boolean validatePassword(char[] password, String correctHash) throws NoSuchAlgorithmException, InvalidKeySpecException {
- // Decode the hash into its parameters
- String[] params = correctHash.split(":");
- int iterations = Integer.parseInt(params[ITERATION_INDEX]);
- byte[] salt = fromHex(params[SALT_INDEX]);
- byte[] hash = fromHex(params[PBKDF2_INDEX]);
- // Compute the hash of the provided password, using the same salt,
- // iteration count, and hash length
- byte[] testHash = pbkdf2(password, salt, iterations, hash.length);
- // Compare the hashes in constant time. The password is correct if
- // both hashes match.
- return slowEquals(hash, testHash);
- }
-
- /**
- * Compares two byte arrays in length-constant time. This comparison method
- * is used so that password hashes cannot be extracted from an on-line
- * system using a timing attack and then attacked off-line.
- *
- * @param a the first byte array
- * @param b the second byte array
- * @return true if both byte arrays are the same, false if not
- */
- private static boolean slowEquals(byte[] a, byte[] b) {
- int diff = a.length ^ b.length;
- for(int i = 0; i < a.length && i < b.length; i++)
- diff |= a[i] ^ b[i];
- return diff == 0;
- }
-
- /**
- * Computes the PBKDF2 hash of a password.
- *
- * @param password the password to hash.
- * @param salt the salt
- * @param iterations the iteration count (slowness factor)
- * @param bytes the length of the hash to compute in bytes
- * @return the PBDKF2 hash of the password
- */
- private static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int bytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
- PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, bytes * 8);
- SecretKeyFactory skf = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);
- return skf.generateSecret(spec).getEncoded();
- }
-
- /**
- * Converts a string of hexadecimal characters into a byte array.
- *
- * @param hex the hex string
- * @return the hex string decoded into a byte array
- */
- private static byte[] fromHex(String hex) {
- byte[] binary = new byte[hex.length() / 2];
- for(int i = 0; i < binary.length; i++) {
- binary[i] = (byte)Integer.parseInt(hex.substring(2*i, 2*i+2), 16);
+ /**
+ * Returns a salted PBKDF2 hash of the password.
+ *
+ * @param password the password to hash
+ * @return a salted PBKDF2 hash of the password
+ * @throws NoSuchAlgorithmException the no such algorithm exception
+ * @throws InvalidKeySpecException the invalid key spec exception
+ */
+ public static String createHash(String password) throws NoSuchAlgorithmException, InvalidKeySpecException {
+ return createHash(password.toCharArray());
}
- return binary;
- }
- /**
- * Converts a byte array into a hexadecimal string.
- *
- * @param array the byte array to convert
- * @return a length*2 character string encoding the byte array
- */
- private static String toHex(byte[] array) {
- BigInteger bi = new BigInteger(1, array);
- String hex = bi.toString(16);
- int paddingLength = (array.length * 2) - hex.length();
- if(paddingLength > 0)
- return String.format("%0" + paddingLength + "d", 0) + hex;
- else
- return hex;
- }
+ /**
+ * Returns a salted PBKDF2 hash of the password.
+ *
+ * @param password the password to hash
+ * @return a salted PBKDF2 hash of the password
+ * @throws NoSuchAlgorithmException the no such algorithm exception
+ * @throws InvalidKeySpecException the invalid key spec exception
+ */
+ public static String createHash(char[] password) throws NoSuchAlgorithmException, InvalidKeySpecException {
+ // Generate a random salt
+ SecureRandom random = new SecureRandom();
+ byte[] salt = new byte[SALT_BYTE_SIZE];
+ random.nextBytes(salt);
- public static void main (String[] args) throws Exception {
- if (args == null || !(args.length > 0)) {
- throw new IllegalArgumentException("No args provided. Need password as argument");
+ // Hash the password
+ byte[] hash = pbkdf2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE);
+ // format iterations:salt:hash
+ return PBKDF2_ITERATIONS + ":" + toHex(salt) + ":" + toHex(hash);
+ }
+
+ /**
+ * Validates a password using a hash.
+ *
+ * @param password the password to check
+ * @param correctHash the hash of the valid password
+ * @return true if the password is correct, false if not
+ * @throws NoSuchAlgorithmException the no such algorithm exception
+ * @throws InvalidKeySpecException the invalid key spec exception
+ */
+ public static boolean validatePassword(String password, String correctHash) throws NoSuchAlgorithmException, InvalidKeySpecException {
+ return validatePassword(password.toCharArray(), correctHash);
+ }
+
+ /**
+ * Validates a password using a hash.
+ *
+ * @param password the password to check
+ * @param correctHash the hash of the valid password
+ * @return true if the password is correct, false if not
+ * @throws NoSuchAlgorithmException the no such algorithm exception
+ * @throws InvalidKeySpecException the invalid key spec exception
+ */
+ public static boolean validatePassword(char[] password, String correctHash) throws NoSuchAlgorithmException, InvalidKeySpecException {
+ // Decode the hash into its parameters
+ String[] params = correctHash.split(":");
+ int iterations = Integer.parseInt(params[ITERATION_INDEX]);
+ byte[] salt = fromHex(params[SALT_INDEX]);
+ byte[] hash = fromHex(params[PBKDF2_INDEX]);
+ // Compute the hash of the provided password, using the same salt,
+ // iteration count, and hash length
+ byte[] testHash = pbkdf2(password, salt, iterations, hash.length);
+ // Compare the hashes in constant time. The password is correct if
+ // both hashes match.
+ return slowEquals(hash, testHash);
+ }
+
+ /**
+ * Compares two byte arrays in length-constant time. This comparison method
+ * is used so that password hashes cannot be extracted from an on-line
+ * system using a timing attack and then attacked off-line.
+ *
+ * @param a the first byte array
+ * @param b the second byte array
+ * @return true if both byte arrays are the same, false if not
+ */
+ private static boolean slowEquals(byte[] a, byte[] b) {
+ int diff = a.length ^ b.length;
+ for (int i = 0; i < a.length && i < b.length; i++)
+ diff |= a[i] ^ b[i];
+ return diff == 0;
+ }
+
+ /**
+ * Computes the PBKDF2 hash of a password.
+ *
+ * @param password the password to hash.
+ * @param salt the salt
+ * @param iterations the iteration count (slowness factor)
+ * @param bytes the length of the hash to compute in bytes
+ * @return the PBDKF2 hash of the password
+ */
+ private static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int bytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
+ PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, bytes * 8);
+ SecretKeyFactory skf = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);
+ return skf.generateSecret(spec).getEncoded();
+ }
+
+ /**
+ * Converts a string of hexadecimal characters into a byte array.
+ *
+ * @param hex the hex string
+ * @return the hex string decoded into a byte array
+ */
+ private static byte[] fromHex(String hex) {
+ byte[] binary = new byte[hex.length() / 2];
+ for (int i = 0; i < binary.length; i++) {
+ binary[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
+ }
+ return binary;
+ }
+
+ /**
+ * Converts a byte array into a hexadecimal string.
+ *
+ * @param array the byte array to convert
+ * @return a length*2 character string encoding the byte array
+ */
+ private static String toHex(byte[] array) {
+ BigInteger bi = new BigInteger(1, array);
+ String hex = bi.toString(16);
+ int paddingLength = (array.length * 2) - hex.length();
+ if (paddingLength > 0)
+ return String.format("%0" + paddingLength + "d", 0) + hex;
+ else
+ return hex;
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (args == null || !(args.length > 0)) {
+ throw new IllegalArgumentException("No args provided. Need password as argument");
+ }
+ System.out.println(HashSalt.createHash(String.valueOf(args[0])));
}
- System.out.println(HashSalt.createHash(String.valueOf(args[0])));
- }
}
\ No newline at end of file
diff --git a/src/main/java/net/locusworks/common/crypto/KeyFile.java b/src/main/java/net/locusworks/common/crypto/KeyFile.java
index 9b71ce3..bad712b 100644
--- a/src/main/java/net/locusworks/common/crypto/KeyFile.java
+++ b/src/main/java/net/locusworks/common/crypto/KeyFile.java
@@ -27,187 +27,195 @@ import static net.locusworks.common.utils.Splitter.fixedLengthSplit;
import static java.lang.String.join;
public class KeyFile implements AutoCloseable {
-
- public enum EncryptionType {
- RSA,
- AES,
- SSH
- }
-
- private Key key;
- private String description;
- private Writer writer;
- private EncryptionType encryptionType;
-
- public KeyFile(Key key) {
- this(key, null);
- }
-
- public KeyFile(Key key, String description) {
- this(key, description, EncryptionType.valueOf(key.getAlgorithm().toUpperCase()));
- }
-
- public KeyFile(Key key, String description, EncryptionType encryptionType) {
- this.key = key;
- this.description = description;
- this.encryptionType = encryptionType;
- }
-
- private KeyFile() {}
-
- private void loadFromFile(String fileName) {
- if (Utils.isEmptyString(fileName)) return;
-
- this.key = null;
- try {
- File keyFile = new File(fileName);
- if (!keyFile.exists()) {
- throw new IllegalArgumentException(String.format("Unable to find file with name %s. Please check path", fileName));
- }
-
- String contentStr = IOUtils.toString(new FileInputStream(keyFile), Charsets.UTF_8);
-
- boolean rsaFormat = !contentStr.startsWith("ssh-rsa") && !contentStr.startsWith("aes-seed");
- if (rsaFormat) {
- contentStr = contentStr.replace("-----.*", "");
- }
-
- contentStr = contentStr.replace("\\r?\\n", "");
-
- byte[] content = rsaFormat ? Base64.getDecoder().decode(contentStr): contentStr.getBytes(Charsets.UTF_8);
-
- EncryptionKeyFactory kf = EncryptionKeyFactory.getInstance("RSA");
-
- List keySpecs = Utils.toList(
- new KeySpecHelper(new AESKeySpec(content), true, EncryptionType.AES),
- new KeySpecHelper(new SSHEncodedKeySpec(content), false, EncryptionType.SSH),
- new KeySpecHelper(new PKCS8EncodedKeySpec(content), true, EncryptionType.RSA),
- new KeySpecHelper(new X509EncodedKeySpec(content), false, EncryptionType.RSA)
- );
-
- for (KeySpecHelper ksh : keySpecs) {
- try {
- this.key = ksh.isPrivate() ? kf.generatePrivateKey(ksh.getKeySpec()) : kf.generatePublicKey(ksh.getKeySpec());
- this.encryptionType = ksh.getEncryptionType();
- break;
- } catch (NullPointerException | InvalidKeySpecException ikse) { continue; }
- }
-
- throw new InvalidKeySpecException(String.format("Unable to determine if file %s is a private or public key. Not type of PKCS8, X509, SSH or AES spec", fileName));
- } catch (Exception ex) {
- throw new RuntimeException(ex);
+
+ public enum EncryptionType {
+ RSA,
+ AES,
+ SSH
}
- }
-
- public void write(String fileName) {
- try {
- String data;
- switch(this.encryptionType) {
- case AES:
- data = String.format("%s %s", this.key.getFormat(), Base64.getEncoder().encodeToString(this.key.getEncoded()));
- IOUtils.writeStringToFile(fileName, data);
- break;
- case SSH:
- try (DataOutputStreamHelper dosh = new DataOutputStreamHelper()) {
- getSSHPubKeyBytes(this.key)
- .forEach(handleExceptionWrapper(item ->{
- dosh.writeInt(item.length);
- dosh.write(item);
- }));
- data = String.format("ssh-rsa", dosh.base64Encoded(), this.description);
- IOUtils.writeStringToFile(fileName, data);
- }
- break;
- default:
- writePem(fileName);
- }
- } catch (Exception ex) {
- throw new IllegalArgumentException(ex);
- }
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public String getDescription() {
- if (Utils.isEmptyString(this.description)) {
- return this.key instanceof PrivateKey ? "PRIVATE KEY" : "PUBLIC KEY";
- }
- return this.description;
- }
-
- public Key getKey() {
- return this.key;
- }
-
- @Override
- public void close() {
- try {
- if (this.writer != null) {
- this.writer.flush();
- this.writer.close();
- this.writer = null;
- }
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
- public static KeyFile read(String fileName) {
- try (KeyFile kf = new KeyFile()) {
- kf.loadFromFile(fileName);
- return kf;
- }
- }
-
- private void writePem(String fileName) {
- try {
- String desc = getDescription();
- this.writer = new OutputStreamWriter(new FileOutputStream(fileName), Charsets.UTF_8);
- this.writer.write(String.format("-----BEGIN RSA %s-----", desc));
-
- String encoded = Base64.getEncoder().encodeToString(this.key.getEncoded());
- String out = join("\n", fixedLengthSplit(60).split(encoded));
-
- this.writer.write(out);
- this.writer.write(String.format("-----END RSA %s-----", desc));
- } catch (IOException ex) {
- throw new RuntimeException(ex);
- }
- }
-
- private List getSSHPubKeyBytes(Key key) {
- RSAPublicKey rpk = (RSAPublicKey)key;
- return Arrays.asList("ssh-rsa".getBytes(Charsets.UTF_8),
- rpk.getPublicExponent().toByteArray(),
- rpk.getModulus().toByteArray()
- );
- }
-
- private static class KeySpecHelper {
- private KeySpec keySpec;
- private boolean isPrivate;
+
+ private Key key;
+ private String description;
+ private Writer writer;
private EncryptionType encryptionType;
-
- public KeySpecHelper(KeySpec keySpec, boolean isPrivate, EncryptionType encryptionType) {
- super();
- this.keySpec = keySpec;
- this.isPrivate = isPrivate;
- this.encryptionType = encryptionType;
+
+ public KeyFile(Key key) {
+ this(key, null);
}
- public synchronized final KeySpec getKeySpec() {
- return keySpec;
+ public KeyFile(Key key, String description) {
+ this(key, description, EncryptionType.valueOf(key.getAlgorithm().toUpperCase()));
}
- public synchronized final boolean isPrivate() {
- return isPrivate;
+ public KeyFile(Key key, String description, EncryptionType encryptionType) {
+ this.key = key;
+ this.description = description;
+ this.encryptionType = encryptionType;
}
- public synchronized final EncryptionType getEncryptionType() {
- return encryptionType;
+ private KeyFile() {
+ }
+
+ private void loadFromFile(String fileName) {
+ if (Utils.isEmptyString(fileName)) return;
+
+ this.key = null;
+ try {
+ File keyFile = new File(fileName);
+ if (!keyFile.exists()) {
+ throw new IllegalArgumentException(String.format("Unable to find file with name %s. Please check path", fileName));
+ }
+
+ String contentStr;
+ try (FileInputStream input = new FileInputStream(keyFile)) {
+ contentStr = IOUtils.toString(input, Charsets.UTF_8);
+ }
+
+ boolean rsaFormat = !contentStr.startsWith("ssh-rsa") && !contentStr.startsWith("aes-seed");
+ if (rsaFormat) {
+ contentStr = contentStr.replaceAll("-----[^-]+-----", "");
+ contentStr = contentStr.replaceAll("\\s", "");
+ } else {
+ contentStr = contentStr.trim();
+ }
+
+ byte[] content = rsaFormat ? Base64.getDecoder().decode(contentStr) : contentStr.getBytes(Charsets.UTF_8);
+
+ EncryptionKeyFactory kf = EncryptionKeyFactory.getInstance("RSA");
+
+ List keySpecs = Utils.toList(
+ new KeySpecHelper(new AESKeySpec(content), true, EncryptionType.AES),
+ new KeySpecHelper(new SSHEncodedKeySpec(content), false, EncryptionType.SSH),
+ new KeySpecHelper(new PKCS8EncodedKeySpec(content), true, EncryptionType.RSA),
+ new KeySpecHelper(new X509EncodedKeySpec(content), false, EncryptionType.RSA)
+ );
+
+ for (KeySpecHelper ksh : keySpecs) {
+ try {
+ this.key = ksh.isPrivate() ? kf.generatePrivateKey(ksh.getKeySpec()) : kf.generatePublicKey(ksh.getKeySpec());
+ this.encryptionType = ksh.getEncryptionType();
+ break;
+ } catch (NullPointerException | InvalidKeySpecException ikse) {
+ continue;
+ }
+ }
+ if (this.key == null) {
+ throw new InvalidKeySpecException(String.format("Unable to determine if file %s is a private or public key. Not type of PKCS8, X509, SSH or AES spec", fileName));
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public void write(String fileName) {
+ try {
+ String data;
+ switch (this.encryptionType) {
+ case AES:
+ data = String.format("%s %s", this.key.getFormat(), Base64.getEncoder().encodeToString(this.key.getEncoded()));
+ IOUtils.writeStringToFile(fileName, data);
+ break;
+ case SSH:
+ try (DataOutputStreamHelper dosh = new DataOutputStreamHelper()) {
+ getSSHPubKeyBytes(this.key)
+ .forEach(handleExceptionWrapper(item -> {
+ dosh.writeInt(item.length);
+ dosh.write(item);
+ }));
+ data = String.format("ssh-rsa %s %s", dosh.base64Encoded(), this.description);
+ IOUtils.writeStringToFile(fileName, data);
+ }
+ break;
+ default:
+ writePem(fileName);
+ }
+ } catch (Exception ex) {
+ throw new IllegalArgumentException(ex);
+ }
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ if (Utils.isEmptyString(this.description)) {
+ return this.key instanceof PrivateKey ? "PRIVATE KEY" : "PUBLIC KEY";
+ }
+ return this.description;
+ }
+
+ public Key getKey() {
+ return this.key;
+ }
+
+ @Override
+ public void close() {
+ try {
+ if (this.writer != null) {
+ this.writer.flush();
+ this.writer.close();
+ this.writer = null;
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public static KeyFile read(String fileName) {
+ try (KeyFile kf = new KeyFile()) {
+ kf.loadFromFile(fileName);
+ return kf;
+ }
+ }
+
+ private void writePem(String fileName) {
+ try {
+ String desc = getDescription();
+ this.writer = new OutputStreamWriter(new FileOutputStream(fileName), Charsets.UTF_8);
+ this.writer.write(String.format("-----BEGIN RSA %s-----", desc));
+
+ String encoded = Base64.getEncoder().encodeToString(this.key.getEncoded());
+ String out = join("\n", fixedLengthSplit(60).split(encoded));
+
+ this.writer.write(out);
+ this.writer.write(String.format("-----END RSA %s-----", desc));
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private List getSSHPubKeyBytes(Key key) {
+ RSAPublicKey rpk = (RSAPublicKey) key;
+ return Arrays.asList("ssh-rsa".getBytes(Charsets.UTF_8),
+ rpk.getPublicExponent().toByteArray(),
+ rpk.getModulus().toByteArray()
+ );
+ }
+
+ private static class KeySpecHelper {
+ private final KeySpec keySpec;
+ private final boolean isPrivate;
+ private final EncryptionType encryptionType;
+
+ public KeySpecHelper(KeySpec keySpec, boolean isPrivate, EncryptionType encryptionType) {
+ super();
+ this.keySpec = keySpec;
+ this.isPrivate = isPrivate;
+ this.encryptionType = encryptionType;
+ }
+
+ public synchronized final KeySpec getKeySpec() {
+ return keySpec;
+ }
+
+ public synchronized final boolean isPrivate() {
+ return isPrivate;
+ }
+
+ public synchronized final EncryptionType getEncryptionType() {
+ return encryptionType;
+ }
}
- }
}
diff --git a/src/main/java/net/locusworks/common/crypto/RSA.java b/src/main/java/net/locusworks/common/crypto/RSA.java
index 3ba85aa..8ff6ee6 100644
--- a/src/main/java/net/locusworks/common/crypto/RSA.java
+++ b/src/main/java/net/locusworks/common/crypto/RSA.java
@@ -21,136 +21,136 @@ import net.locusworks.common.crypto.KeyFile.EncryptionType;
import net.locusworks.common.io.IOUtils;
public class RSA {
-
- private static final String ENCRYPTION_TYPE = "RSA";
- private static final String ENCRYPTION_ALGORITHM = "RSA/ECB/PKCS10PADDING";
- private static final String PROVIDER = "SunJCE";
- private static final String RANDOM_ALGORITHM = "SHA1PRNG";
-
- private static final int PADDING_LENGTH = 11;
- private static final int DEFAULT_KEY_LENGTH = 2048;
-
- public static KeyPair generateKeyPair() {
- return generateKeyPair(DEFAULT_KEY_LENGTH);
- }
-
- public static KeyPair generateKeyPair(int keyLength) {
- try {
- KeyPairGenerator kpg = KeyPairGenerator.getInstance(ENCRYPTION_TYPE);
- SecureRandom sr = SecureRandom.getInstance(RANDOM_ALGORITHM);
- kpg.initialize(keyLength, sr);
- return kpg.genKeyPair();
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
- public static KeyPair loadPrivateKey(String privateKeyFileName) {
- return loadKeyPair(null, privateKeyFileName);
- }
-
- public static KeyPair loadPublicKey(String publicKeyFileName) {
- return loadKeyPair(publicKeyFileName, null);
- }
-
- public static KeyPair loadKeyPair(String publicKey, String privateKey) {
- KeyFile pubKey = KeyFile.read(publicKey);
- KeyFile prvKey = KeyFile.read(privateKey);
- return new KeyPair((PublicKey)pubKey.getKey(), (PrivateKey)prvKey.getKey());
- }
-
- public static boolean generateAndWriteSSHKeys() {
- KeyPair kp = generateKeyPair();
- return writePrivateKey(kp) && writePublicKey(kp, true);
- }
-
- public static boolean generateAndWriteKeyPair() {
- return generateAndWriteKeyPair(DEFAULT_KEY_LENGTH);
- }
-
- public static boolean generateAndWriteKeyPair(String keyPairName) {
- return generateAndWriteKeyPair(keyPairName, DEFAULT_KEY_LENGTH);
- }
-
- public static boolean generateAndWriteKeyPair(int keyLength) {
- return generateAndWriteKeyPair("id_rsa", keyLength);
- }
-
- public static boolean generateAndWriteKeyPair(String keyPairName, int keyLength) {
- KeyPair kp = generateKeyPair(keyLength);
- return writePrivateKey(kp, keyPairName, "PRIVATE KEY") && writePublicKey(kp, keyPairName + ".pub", "PUBLIC KEY");
- }
-
- public static boolean writePrivateKey(KeyPair kp) {
- return writePrivateKey(kp, "id_rsa", "PRIVATE KEY");
- }
-
- public static boolean writePrivateKey(KeyPair kp, String fileName, String description) {
- return writePemFile(kp.getPrivate(), fileName, description);
- }
-
- public static boolean writePublicKey(KeyPair kp) {
- return writePublicKey(kp, false);
- }
-
- public static boolean writePublicKey(KeyPair kp, boolean sshFormat) {
- return writePublicKey(kp, "id_rsa.pub", "PUBLIC KEY", sshFormat);
- }
-
- public static boolean writePublicKey(KeyPair kp, String fileName, String description) {
- return writePemFile(kp.getPublic(), fileName, description, false);
- }
-
- public static boolean writePublicKey(KeyPair kp, String fileName, String description, boolean sshFormat) {
- return writePemFile(kp.getPublic(), fileName, description, sshFormat);
- }
-
- public static int calculateRequiredKeyLength(String message) {
- return (message.getBytes(Charsets.UTF_8).length + PADDING_LENGTH) * 8;
- }
-
- public static String encrypt(Key key, String message) {
- try {
- calculateKeyLength(key, message);
- Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM, PROVIDER);
- cipher.init(Cipher.ENCRYPT_MODE, key);
- CipherInputStream cis = new CipherInputStream(new ByteArrayInputStream(message.getBytes(Charsets.UTF_8)), cipher);
- byte[] encrypted = IOUtils.toByteArray(cis);
- return Base64.getEncoder().encodeToString(encrypted);
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
- public static String decrypt(Key key, String message) {
- try {
- Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM, PROVIDER);
- cipher.init(Cipher.DECRYPT_MODE, key);
- byte[] decoded = Base64.getDecoder().decode(message);
- byte[] plainTextArray = cipher.doFinal(decoded);
- return new String(plainTextArray, Charsets.UTF_8);
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
- private static boolean writePemFile(Key key, String fileName, String description) {
- return writePemFile(key, fileName, description, false);
- }
-
- private static boolean writePemFile(Key key, String fileName, String description, boolean sshFormat) {
- try(KeyFile kf = sshFormat ? new KeyFile(key, description, EncryptionType.SSH) : new KeyFile(key, description)) {
- kf.write(fileName);
+ private static final String ENCRYPTION_TYPE = "RSA";
+ private static final String ENCRYPTION_ALGORITHM = "RSA/ECB/PKCS1PADDING";
+ private static final String PROVIDER = "SunJCE";
+ private static final String RANDOM_ALGORITHM = "SHA1PRNG";
+
+ private static final int PADDING_LENGTH = 11;
+ private static final int DEFAULT_KEY_LENGTH = 2048;
+
+ public static KeyPair generateKeyPair() {
+ return generateKeyPair(DEFAULT_KEY_LENGTH);
}
- return Files.exists(Paths.get(fileName));
- }
-
- private static void calculateKeyLength(Key key, String message) throws IllegalBlockSizeException {
- int keyLength = ((RSAKey)key).getModulus().bitLength();
- int requiredKeyLength = calculateRequiredKeyLength(message);
- if (keyLength < requiredKeyLength) {
- throw new IllegalBlockSizeException(String.format("RSA key size of %d is not large enough to encrypt message of length %d. "
- + "Increase key size to a minimum of %d and re-encrypt with new key", keyLength, message.length(), requiredKeyLength));
+
+ public static KeyPair generateKeyPair(int keyLength) {
+ try {
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance(ENCRYPTION_TYPE);
+ SecureRandom sr = SecureRandom.getInstance(RANDOM_ALGORITHM);
+ kpg.initialize(keyLength, sr);
+ return kpg.genKeyPair();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public static KeyPair loadPrivateKey(String privateKeyFileName) {
+ return loadKeyPair(null, privateKeyFileName);
+ }
+
+ public static KeyPair loadPublicKey(String publicKeyFileName) {
+ return loadKeyPair(publicKeyFileName, null);
+ }
+
+ public static KeyPair loadKeyPair(String publicKey, String privateKey) {
+ KeyFile pubKey = KeyFile.read(publicKey);
+ KeyFile prvKey = KeyFile.read(privateKey);
+ return new KeyPair((PublicKey) pubKey.getKey(), (PrivateKey) prvKey.getKey());
+ }
+
+ public static boolean generateAndWriteSSHKeys() {
+ KeyPair kp = generateKeyPair();
+ return writePrivateKey(kp) && writePublicKey(kp, true);
+ }
+
+ public static boolean generateAndWriteKeyPair() {
+ return generateAndWriteKeyPair(DEFAULT_KEY_LENGTH);
+ }
+
+ public static boolean generateAndWriteKeyPair(String keyPairName) {
+ return generateAndWriteKeyPair(keyPairName, DEFAULT_KEY_LENGTH);
+ }
+
+ public static boolean generateAndWriteKeyPair(int keyLength) {
+ return generateAndWriteKeyPair("id_rsa", keyLength);
+ }
+
+ public static boolean generateAndWriteKeyPair(String keyPairName, int keyLength) {
+ KeyPair kp = generateKeyPair(keyLength);
+ return writePrivateKey(kp, keyPairName, "PRIVATE KEY") && writePublicKey(kp, keyPairName + ".pub", "PUBLIC KEY");
+ }
+
+ public static boolean writePrivateKey(KeyPair kp) {
+ return writePrivateKey(kp, "id_rsa", "PRIVATE KEY");
+ }
+
+ public static boolean writePrivateKey(KeyPair kp, String fileName, String description) {
+ return writePemFile(kp.getPrivate(), fileName, description);
+ }
+
+ public static boolean writePublicKey(KeyPair kp) {
+ return writePublicKey(kp, false);
+ }
+
+ public static boolean writePublicKey(KeyPair kp, boolean sshFormat) {
+ return writePublicKey(kp, "id_rsa.pub", "PUBLIC KEY", sshFormat);
+ }
+
+ public static boolean writePublicKey(KeyPair kp, String fileName, String description) {
+ return writePemFile(kp.getPublic(), fileName, description, false);
+ }
+
+ public static boolean writePublicKey(KeyPair kp, String fileName, String description, boolean sshFormat) {
+ return writePemFile(kp.getPublic(), fileName, description, sshFormat);
+ }
+
+ public static int calculateRequiredKeyLength(String message) {
+ return (message.getBytes(Charsets.UTF_8).length + PADDING_LENGTH) * 8;
+ }
+
+ public static String encrypt(Key key, String message) {
+ try {
+ calculateKeyLength(key, message);
+ Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM, PROVIDER);
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+ CipherInputStream cis = new CipherInputStream(new ByteArrayInputStream(message.getBytes(Charsets.UTF_8)), cipher);
+ byte[] encrypted = IOUtils.toByteArray(cis);
+ return Base64.getEncoder().encodeToString(encrypted);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public static String decrypt(Key key, String message) {
+ try {
+ Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM, PROVIDER);
+ cipher.init(Cipher.DECRYPT_MODE, key);
+ byte[] decoded = Base64.getDecoder().decode(message);
+ byte[] plainTextArray = cipher.doFinal(decoded);
+ return new String(plainTextArray, Charsets.UTF_8);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private static boolean writePemFile(Key key, String fileName, String description) {
+ return writePemFile(key, fileName, description, false);
+ }
+
+ private static boolean writePemFile(Key key, String fileName, String description, boolean sshFormat) {
+ try (KeyFile kf = sshFormat ? new KeyFile(key, description, EncryptionType.SSH) : new KeyFile(key, description)) {
+ kf.write(fileName);
+ }
+ return Files.exists(Paths.get(fileName));
+ }
+
+ private static void calculateKeyLength(Key key, String message) throws IllegalBlockSizeException {
+ int keyLength = ((RSAKey) key).getModulus().bitLength();
+ int requiredKeyLength = calculateRequiredKeyLength(message);
+ if (keyLength < requiredKeyLength) {
+ throw new IllegalBlockSizeException(String.format("RSA key size of %d is not large enough to encrypt message of length %d. "
+ + "Increase key size to a minimum of %d and re-encrypt with new key", keyLength, message.length(), requiredKeyLength));
+ }
}
- }
}
diff --git a/src/main/java/net/locusworks/common/crypto/SSHEncodedKeySpec.java b/src/main/java/net/locusworks/common/crypto/SSHEncodedKeySpec.java
index 0572364..8da2a4d 100644
--- a/src/main/java/net/locusworks/common/crypto/SSHEncodedKeySpec.java
+++ b/src/main/java/net/locusworks/common/crypto/SSHEncodedKeySpec.java
@@ -18,48 +18,47 @@ import static net.locusworks.common.utils.Utils.get;
import static net.locusworks.common.utils.Utils.size;
public class SSHEncodedKeySpec extends EncodedKeySpec {
-
- private static final String SSH_MARKER = "ssh-rsa";
- public SSHEncodedKeySpec(byte[] encodedKey) {
- super(encodedKey);
- }
-
- public RSAPublicKeySpec convertToRSAPubKeySpec() throws InvalidKeySpecException {
- try {
- byte[] data = this.getEncoded();
- InputStream stream = new ByteArrayInputStream(data);
- Iterable parts = Arrays.asList(IOUtils.toString(stream, Charsets.UTF_8).split(" "));
-
- checkArguments(size(parts) >= 2 && SSH_MARKER.equals(get(parts, 0)), "Bad format, should be: ssh-rsa AAB3...");
- stream = new ByteArrayInputStream(Base64.getDecoder().decode(String.valueOf(get(parts, 1))));
- String marker = new String(readLengthFirst(stream));
- checkArguments(SSH_MARKER.equals(marker), "Looking for marker %s but received %s", SSH_MARKER, marker);
- BigInteger publicExponent = new BigInteger(readLengthFirst(stream));
- BigInteger modulus = new BigInteger(readLengthFirst(stream));
- RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, publicExponent);
- return keySpec;
- } catch (Exception ex) {
- throw new InvalidKeySpecException(ex);
- }
- }
+ private static final String SSH_MARKER = "ssh-rsa";
- @Override
- public String getFormat() {
- return null;
- }
-
- private static byte[] readLengthFirst(InputStream in) throws IOException {
- int[] bytes = new int[] {in.read(), in.read(), in.read(), in.read()};
- int length = 0;
- int shift = 24;
- for (int i = 0; i < bytes.length; i++) {
- length += bytes[i] << shift;
- shift -= 8;
+ public SSHEncodedKeySpec(byte[] encodedKey) {
+ super(encodedKey);
+ }
+
+ public RSAPublicKeySpec convertToRSAPubKeySpec() throws InvalidKeySpecException {
+ try {
+ byte[] data = this.getEncoded();
+ InputStream stream = new ByteArrayInputStream(data);
+ Iterable parts = Arrays.asList(IOUtils.toString(stream, Charsets.UTF_8).split(" "));
+
+ checkArguments(size(parts) >= 2 && SSH_MARKER.equals(get(parts, 0)), "Bad format, should be: ssh-rsa AAB3...");
+ stream = new ByteArrayInputStream(Base64.getDecoder().decode(String.valueOf(get(parts, 1))));
+ String marker = new String(readLengthFirst(stream));
+ checkArguments(SSH_MARKER.equals(marker), "Looking for marker %s but received %s", SSH_MARKER, marker);
+ BigInteger publicExponent = new BigInteger(readLengthFirst(stream));
+ BigInteger modulus = new BigInteger(readLengthFirst(stream));
+ return new RSAPublicKeySpec(modulus, publicExponent);
+ } catch (Exception ex) {
+ throw new InvalidKeySpecException(ex);
+ }
+ }
+
+ @Override
+ public String getFormat() {
+ return null;
+ }
+
+ private static byte[] readLengthFirst(InputStream in) throws IOException {
+ int[] bytes = new int[]{in.read(), in.read(), in.read(), in.read()};
+ int length = 0;
+ int shift = 24;
+ for (int aByte : bytes) {
+ length += aByte << shift;
+ shift -= 8;
+ }
+ byte[] val = new byte[length];
+ in.read(val);
+ return val;
}
- byte[] val = new byte[length];
- in.read(val);
- return val;
- }
}
diff --git a/src/main/java/net/locusworks/common/exceptions/ApplicationException.java b/src/main/java/net/locusworks/common/exceptions/ApplicationException.java
index 0ade43a..9b0f813 100644
--- a/src/main/java/net/locusworks/common/exceptions/ApplicationException.java
+++ b/src/main/java/net/locusworks/common/exceptions/ApplicationException.java
@@ -1,108 +1,111 @@
package net.locusworks.common.exceptions;
+import java.io.Serial;
+
/***
* Custom exception class for the patch repository
* @author Isaac Parenteau
*
*/
public class ApplicationException extends Exception {
- private final Integer code;
- boolean success = false;
- private static final long serialVersionUID = 1L;
-
- public static ApplicationException egregiousServer() {
- return new ApplicationException(9001, "Something went wrong. Please see logs for details");
- }
+ private final Integer code;
+ boolean success = false;
+ @Serial
+ private static final long serialVersionUID = 1L;
- public static ApplicationException invalidCreds() {
- return new ApplicationException(9001, "Invalid credentials provided");
- }
+ public static ApplicationException egregiousServer() {
+ return new ApplicationException(9001, "Something went wrong. Please see logs for details");
+ }
- public static ApplicationException notLoggedIn() {
- return new ApplicationException(9002, "Not logged in");
- }
+ public static ApplicationException invalidCreds() {
+ return new ApplicationException(9001, "Invalid credentials provided");
+ }
- public static ApplicationException invalidEmailAddress() {
- return new ApplicationException(9005, "Invalid email address");
- }
+ public static ApplicationException notLoggedIn() {
+ return new ApplicationException(9002, "Not logged in");
+ }
- public static ApplicationException actionNotPermitted() {
- return new ApplicationException(9007, "Action not permitted");
- }
-
- public static ApplicationException actionNotPermitted(String message) {
- return new ApplicationException(9007, "Action not permitted: " + message);
- }
+ public static ApplicationException invalidEmailAddress() {
+ return new ApplicationException(9005, "Invalid email address");
+ }
- public static ApplicationException passwordsNotEqual() {
- return new ApplicationException(9008, "Passwords do not match");
- }
-
- public static ApplicationException unAuthorized() {
- return new ApplicationException(9009, "unauthorized");
- }
-
- public static ApplicationException duplicateEntry(String message) {
- return new ApplicationException(9100, message);
- }
-
- public static ApplicationException duplicateEntry(String messageFmt, Object... args) {
- return new ApplicationException(9100, String.format(messageFmt, args));
- }
-
- public static ApplicationException noEntryExists(String message) {
- return new ApplicationException(9101, message);
- }
-
- public static ApplicationException noEntryExists(String messageFmt, Object... items) {
- return new ApplicationException(9101, String.format(messageFmt, items));
- }
-
- public static ApplicationException constraintViolation(String message) {
- return new ApplicationException(9102, message);
- }
-
- public static ApplicationException constraintViolation(String messageFmt, Object... items) {
- return new ApplicationException(9102, String.format(messageFmt, items));
- }
-
- public static ApplicationException illegalArgument(String message) {
- return new ApplicationException(9103, message);
- }
-
- public static ApplicationException generic(String message) {
- return new ApplicationException(9999, message);
- }
-
- public static ApplicationException fromException(Throwable e) {
- return new ApplicationException(9999, e);
- }
-
- public ApplicationException(int code, Throwable e) {
- this(code, e.getMessage(), e);
- }
+ public static ApplicationException actionNotPermitted() {
+ return new ApplicationException(9007, "Action not permitted");
+ }
- public ApplicationException(int code, String message) {
- super(message);
- this.code = code;
- }
-
- public ApplicationException(int code, String message, Throwable e) {
- super(message, e);
- this.code = code;
- }
+ public static ApplicationException actionNotPermitted(String message) {
+ return new ApplicationException(9007, "Action not permitted: " + message);
+ }
- public boolean getSuccess() {
- return success;
- }
+ public static ApplicationException passwordsNotEqual() {
+ return new ApplicationException(9008, "Passwords do not match");
+ }
- public Integer getCode() {
- return code;
- }
+ public static ApplicationException unAuthorized() {
+ return new ApplicationException(9009, "unauthorized");
+ }
- @Override
- public String getMessage() {
- return super.getMessage();
- }
+ public static ApplicationException duplicateEntry(String message) {
+ return new ApplicationException(9100, message);
+ }
+
+ public static ApplicationException duplicateEntry(String messageFmt, Object... args) {
+ return new ApplicationException(9100, String.format(messageFmt, args));
+ }
+
+ public static ApplicationException noEntryExists(String message) {
+ return new ApplicationException(9101, message);
+ }
+
+ public static ApplicationException noEntryExists(String messageFmt, Object... items) {
+ return new ApplicationException(9101, String.format(messageFmt, items));
+ }
+
+ public static ApplicationException constraintViolation(String message) {
+ return new ApplicationException(9102, message);
+ }
+
+ public static ApplicationException constraintViolation(String messageFmt, Object... items) {
+ return new ApplicationException(9102, String.format(messageFmt, items));
+ }
+
+ public static ApplicationException illegalArgument(String message) {
+ return new ApplicationException(9103, message);
+ }
+
+ public static ApplicationException generic(String message) {
+ return new ApplicationException(9999, message);
+ }
+
+ public static ApplicationException fromException(Throwable e) {
+ return new ApplicationException(9999, e);
+ }
+
+ public ApplicationException(int code, Throwable e) {
+ this(code, e.getMessage(), e);
+ }
+
+ public ApplicationException(int code, String message) {
+ super(message);
+ this.code = code;
+ }
+
+ public ApplicationException(int code, String message, Throwable e) {
+ super(message, e);
+ this.code = code;
+ }
+
+ public boolean getSuccess() {
+ return success;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ @Override
+ public String getMessage() {
+ return super.getMessage();
+ }
}
diff --git a/src/main/java/net/locusworks/common/immutables/Pair.java b/src/main/java/net/locusworks/common/immutables/Pair.java
index 36149c3..33b62cc 100644
--- a/src/main/java/net/locusworks/common/immutables/Pair.java
+++ b/src/main/java/net/locusworks/common/immutables/Pair.java
@@ -1,55 +1,64 @@
package net.locusworks.common.immutables;
+import java.util.Objects;
+
/**
* Class that holds two immutable objects as a pair
- * @author Isaac Parenteau
- * @version 1.0.0
+ *
* @param class type of object 1
* @param class type of object 2
+ * @author Isaac Parenteau
+ * @version 1.0.0
*/
public class Pair extends Unit {
-
- private V2 value2;
-
- /**
- * Constructor with no values
- */
- public Pair() {
- super();
- }
-
- /**
- * Constructor
- * @param value1 Object 1
- * @param value2 Object 2
- */
- public Pair(V1 value1, V2 value2) {
- super(value1);
- this.value2 = value2;
- }
-
- /**
- * Set value2
- * @param value2 value to set it
- */
- public void setValue2(V2 value2) {
- this.value2 = value2;
- }
-
- /**
- * Get value2
- * @return value2
- */
- public V2 getValue2() {
- return this.value2;
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof Pair)) return false;
-
- Pair, ?> otherPair = (Pair, ?>)other;
-
- return super.equals(otherPair) && this.getValue2().equals(otherPair.getValue2());
- }
-}
\ No newline at end of file
+
+ private V2 value2;
+
+ /**
+ * Constructor with no values
+ */
+ public Pair() {
+ super();
+ }
+
+ /**
+ * Constructor
+ *
+ * @param value1 Object 1
+ * @param value2 Object 2
+ */
+ public Pair(V1 value1, V2 value2) {
+ super(value1);
+ this.value2 = value2;
+ }
+
+ /**
+ * Set value2
+ *
+ * @param value2 value to set it
+ */
+ public void setValue2(V2 value2) {
+ if (Objects.nonNull(this.value2)) {
+ throw new IllegalArgumentException("Value2 already set. Cannot change");
+ }
+ this.value2 = value2;
+ }
+
+ /**
+ * Get value2
+ *
+ * @return value2
+ */
+ public V2 getValue2() {
+ return this.value2;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null) return false;
+ if (!(other instanceof Pair, ?> pair)) return false;
+
+ return this.getValue2().equals(pair.getValue2()) &&
+ this.getValue1().equals(pair.getValue1());
+ }
+}
diff --git a/src/main/java/net/locusworks/common/immutables/Triplet.java b/src/main/java/net/locusworks/common/immutables/Triplet.java
index 5ff5c83..3abd5df 100644
--- a/src/main/java/net/locusworks/common/immutables/Triplet.java
+++ b/src/main/java/net/locusworks/common/immutables/Triplet.java
@@ -1,57 +1,67 @@
package net.locusworks.common.immutables;
+import java.util.Objects;
+
/**
* Class that holds three immutable objects as triplets
- * @author Isaac Parenteau
- * @version 1.0.0
+ *
* @param class type of object 1
* @param class type of object 2
* @param class type of object 3
+ * @author Isaac Parenteau
+ * @version 1.0.0
*/
public class Triplet extends Pair {
-
- private V3 value3;
-
- /**
- * default constructor with no values
- */
- public Triplet() {
- super();
- }
-
- /**
- * Constructor
- * @param value1 Object 1
- * @param value2 Object 2
- * @param value3 Object 3
- */
- public Triplet(V1 value1, V2 value2, V3 value3) {
- super(value1, value2);
- this.value3 = value3;
- }
-
- /**
- * Set value 3
- * @param value3 value 3
- */
- public void setValue3(V3 value3) {
- this.value3 = value3;
- }
-
- /**
- * Get value 3
- * @return value 3
- */
- public V3 getValue3() {
- return value3;
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof Triplet)) return false;
-
- Triplet, ?, ?> otherTriplet = (Triplet, ?, ?>)other;
-
- return super.equals(otherTriplet) && this.getValue3().equals(otherTriplet.getValue3());
- }
-}
\ No newline at end of file
+
+ private V3 value3;
+
+ /**
+ * default constructor with no values
+ */
+ public Triplet() {
+ super();
+ }
+
+ /**
+ * Constructor
+ *
+ * @param value1 Object 1
+ * @param value2 Object 2
+ * @param value3 Object 3
+ */
+ public Triplet(V1 value1, V2 value2, V3 value3) {
+ super(value1, value2);
+ this.value3 = value3;
+ }
+
+ /**
+ * Set value 3
+ *
+ * @param value3 value 3
+ */
+ public void setValue3(V3 value3) {
+ if (Objects.nonNull(this.value3)) {
+ throw new IllegalArgumentException("Value3 already set. Cannot change");
+ }
+ this.value3 = value3;
+ }
+
+ /**
+ * Get value 3
+ *
+ * @return value 3
+ */
+ public V3 getValue3() {
+ return value3;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null) return false;
+ if (!(other instanceof Triplet, ?, ?> triplet)) return false;
+
+ return this.getValue3().equals(triplet.getValue3()) &&
+ this.getValue2().equals(triplet.getValue2()) &&
+ this.getValue1().equals(triplet.getValue1());
+ }
+}
diff --git a/src/main/java/net/locusworks/common/immutables/Unit.java b/src/main/java/net/locusworks/common/immutables/Unit.java
index b0a0971..90d667b 100644
--- a/src/main/java/net/locusworks/common/immutables/Unit.java
+++ b/src/main/java/net/locusworks/common/immutables/Unit.java
@@ -1,50 +1,58 @@
package net.locusworks.common.immutables;
+import java.util.Objects;
+
/**
* Class that holds three immutable objects as triplets
- * @author Isaac Parenteau
- * @version 1.0.0
+ *
* @param class type of object 1
+ * @author Isaac Parenteau
+ * @version 1.0.0
*/
public class Unit {
-
- private V1 value1;
-
- /**
- * Default constructor with no values
- */
- public Unit() {}
-
- /**
- * Constuctor
- * @param value1 value 1
- */
- public Unit(V1 value1) {
- this.value1 = value1;
- }
-
- /**
- * Set value 1
- * @param value1 value 1
- */
- public void setValue1(V1 value1) {
- this.value1 = value1;
- }
-
- /**
- * Get value 1
- * @return value1
- */
- public V1 getValue1() {
- return value1;
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof Unit)) return false;
-
- Unit> otherUnit = (Unit>)other;
-
- return this.getValue1().equals(otherUnit.getValue1());
- }
-}
\ No newline at end of file
+
+ private V1 value1;
+
+ /**
+ * Default constructor with no values
+ */
+ public Unit() {
+ }
+
+ /**
+ * Constructor
+ *
+ * @param value1 value 1
+ */
+ public Unit(V1 value1) {
+ this.value1 = value1;
+ }
+
+ /**
+ * Set value 1
+ *
+ * @param value1 value 1
+ */
+ public void setValue1(V1 value1) {
+ if (Objects.nonNull(this.value1)) {
+ throw new IllegalArgumentException("Value1 already set. Cannot change");
+ }
+ this.value1 = value1;
+ }
+
+ /**
+ * Get value 1
+ *
+ * @return value1
+ */
+ public V1 getValue1() {
+ return value1;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null) return false;
+ if (!(other instanceof Unit>)) return false;
+ return this.getValue1().equals(((Unit>) other).getValue1());
+ }
+}
diff --git a/src/main/java/net/locusworks/common/interfaces/AutoCloseableIterator.java b/src/main/java/net/locusworks/common/interfaces/AutoCloseableIterator.java
index d494fcb..af6d1d5 100644
--- a/src/main/java/net/locusworks/common/interfaces/AutoCloseableIterator.java
+++ b/src/main/java/net/locusworks/common/interfaces/AutoCloseableIterator.java
@@ -3,8 +3,8 @@ package net.locusworks.common.interfaces;
import java.util.Iterator;
public interface AutoCloseableIterator extends Iterator, AutoCloseable {
-
- @Override
- public void close();
+
+ @Override
+ void close();
}
diff --git a/src/main/java/net/locusworks/common/interfaces/ThrowingConsumer.java b/src/main/java/net/locusworks/common/interfaces/ThrowingConsumer.java
index cde492e..85964fa 100644
--- a/src/main/java/net/locusworks/common/interfaces/ThrowingConsumer.java
+++ b/src/main/java/net/locusworks/common/interfaces/ThrowingConsumer.java
@@ -2,5 +2,5 @@ package net.locusworks.common.interfaces;
@FunctionalInterface
public interface ThrowingConsumer {
- void accept(T t) throws E;
+ void accept(T t) throws E;
}
diff --git a/src/main/java/net/locusworks/common/io/IOUtils.java b/src/main/java/net/locusworks/common/io/IOUtils.java
index 7ce89f1..bbebcf4 100644
--- a/src/main/java/net/locusworks/common/io/IOUtils.java
+++ b/src/main/java/net/locusworks/common/io/IOUtils.java
@@ -38,321 +38,322 @@ import net.locusworks.common.Charsets;
public class IOUtils {
- private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
- public static final int EOF = -1;
+ private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+ public static final int EOF = -1;
- /**
- * Gets the contents of an InputStream as a list of Strings,
- * one entry per line, using the specified character encoding.
- *
- * This method buffers the input internally, so there is no need to use a
- * BufferedInputStream.
- *
- * @param input the InputStream to read from, not null
- * @param encoding the encoding to use, null means platform default
- * @return the list of Strings, never null
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- */
- public static List readLines(final InputStream stream, final Charset charset) throws IOException {
- final InputStreamReader reader = new InputStreamReader(stream, charset);
- return readLines(reader);
- }
-
- /**
- * Gets the contents of a Reader as a list of Strings,
- * one entry per line.
- *
- * This method buffers the input internally, so there is no need to use a
- * BufferedReader.
- *
- * @param input the Reader to read from, not null
- * @return the list of Strings, never null
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- */
- public static List readLines(final Reader input) throws IOException {
- final BufferedReader reader = toBufferedReader(input);
- final List list = new ArrayList<>();
- for(String line = reader.readLine(); line != null; line = reader.readLine()) {
- list.add(line);
+ /**
+ * Gets the contents of an InputStream as a list of Strings,
+ * one entry per line, using the specified character encoding.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedInputStream.
+ *
+ * @param stream the InputStream to read from, not null
+ * @param charset the encoding to use, null means platform default
+ * @return the list of Strings, never null
+ * @throws NullPointerException if the input is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static List readLines(final InputStream stream, final Charset charset) throws IOException {
+ final InputStreamReader reader = new InputStreamReader(stream, charset);
+ return readLines(reader);
}
- return list;
- }
- /**
- * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given
- * reader.
- *
- * @param reader the reader to wrap or return (not null)
- * @return the given reader or a new {@link BufferedReader} for the given reader
- * @throws NullPointerException if the input parameter is null
- * @see #buffer(Reader)
- */
- public static BufferedReader toBufferedReader(final Reader reader) {
- return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader);
- }
-
- /**
- * Gets the contents of an InputStream as a byte[].
- *
- * This method buffers the input internally, so there is no need to use a
- * BufferedInputStream.
- *
- * @param input the InputStream to read from
- * @return the requested byte array
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- */
- public static byte[] toByteArray(final InputStream input) throws IOException {
- try (final ByteArrayOutputStream output = new ByteArrayOutputStream()) {
- copy(input, output);
- return output.toByteArray();
+ /**
+ * Gets the contents of a Reader as a list of Strings,
+ * one entry per line.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedReader.
+ *
+ * @param input the Reader to read from, not null
+ * @return the list of Strings, never null
+ * @throws NullPointerException if the input is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static List readLines(final Reader input) throws IOException {
+ final BufferedReader reader = toBufferedReader(input);
+ final List list = new ArrayList<>();
+ for (String line = reader.readLine(); line != null; line = reader.readLine()) {
+ list.add(line);
+ }
+ return list;
}
- }
- /**
- * Copies bytes from an InputStream to an
- * OutputStream.
- *
- * This method buffers the input internally, so there is no need to use a
- * BufferedInputStream.
- *
- * Large streams (over 2GB) will return a bytes copied value of
- * -1 after the copy has completed since the correct
- * number of bytes cannot be returned as an int. For large streams
- * use the copyLarge(InputStream, OutputStream) method.
- *
- * @param input the InputStream to read from
- * @param output the OutputStream to write to
- * @return the number of bytes copied, or -1 if > Integer.MAX_VALUE
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- */
- public static int copy(final InputStream input, final OutputStream output) throws IOException {
- final long count = copyLarge(input, output);
- if (count > Integer.MAX_VALUE) {
- return -1;
+ /**
+ * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given
+ * reader.
+ *
+ * @param reader the reader to wrap or return (not null)
+ * @return the given reader or a new {@link BufferedReader} for the given reader
+ * @throws NullPointerException if the input parameter is null
+ * @see #buffer(Reader)
+ */
+ public static BufferedReader toBufferedReader(final Reader reader) {
+ return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader);
}
- return (int) count;
- }
- /**
- * Copies bytes from an InputStream to an OutputStream using an internal buffer of the
- * given size.
- *
- * This method buffers the input internally, so there is no need to use a BufferedInputStream.
- *
- *
- * @param input the InputStream to read from
- * @param output the OutputStream to write to
- * @param bufferSize the bufferSize used to copy from the input to the output
- * @return the number of bytes copied
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- */
- public static long copy(final InputStream input, final OutputStream output, final int bufferSize)
- throws IOException {
- return copyLarge(input, output, new byte[bufferSize]);
- }
- /**
- * Copies bytes from an InputStream to chars on a
- * Writer using the specified character encoding.
- *
- * This method buffers the input internally, so there is no need to use a
- * BufferedInputStream.
- *
- * This method uses {@link InputStreamReader}.
- *
- * @param input the InputStream to read from
- * @param output the Writer to write to
- * @param inputEncoding the encoding to use for the input stream, null means platform default
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- */
- public static void copy(final InputStream input, final Writer output, final Charset inputEncoding)
- throws IOException {
- final InputStreamReader in = new InputStreamReader(input, inputEncoding.toString());
- copy(in, output);
- }
-
- /**
- * Copies chars from a Reader to a Writer.
- *
- * This method buffers the input internally, so there is no need to use a
- * BufferedReader.
- *
- * Large streams (over 2GB) will return a chars copied value of
- * -1 after the copy has completed since the correct
- * number of chars cannot be returned as an int. For large streams
- * use the copyLarge(Reader, Writer) method.
- *
- * @param input the Reader to read from
- * @param output the Writer to write to
- * @return the number of characters copied, or -1 if > Integer.MAX_VALUE
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- */
- public static int copy(final Reader input, final Writer output) throws IOException {
- final long count = copyLarge(input, output);
- if (count > Integer.MAX_VALUE) {
- return -1;
+ /**
+ * Gets the contents of an InputStream as a byte[].
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedInputStream.
+ *
+ * @param input the InputStream to read from
+ * @return the requested byte array
+ * @throws NullPointerException if the input is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static byte[] toByteArray(final InputStream input) throws IOException {
+ try (final ByteArrayOutputStream output = new ByteArrayOutputStream()) {
+ copy(input, output);
+ return output.toByteArray();
+ }
}
- return (int) count;
- }
- /**
- * Copies chars from a large (over 2GB) Reader to a Writer.
- *
- * This method buffers the input internally, so there is no need to use a
- * BufferedReader.
- *
- * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
- *
- * @param input the Reader to read from
- * @param output the Writer to write to
- * @return the number of characters copied
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- */
- public static long copyLarge(final Reader input, final Writer output) throws IOException {
- return copyLarge(input, output, new char[DEFAULT_BUFFER_SIZE]);
- }
-
- /**
- * Copies bytes from a large (over 2GB) InputStream to an
- * OutputStream.
- *
- * This method buffers the input internally, so there is no need to use a
- * BufferedInputStream.
- *
- * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
- *
- * @param input the InputStream to read from
- * @param output the OutputStream to write to
- * @return the number of bytes copied
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- */
- public static long copyLarge(final InputStream input, final OutputStream output)
- throws IOException {
- return copy(input, output, DEFAULT_BUFFER_SIZE);
- }
-
- /**
- * Copies bytes from a large (over 2GB) InputStream to an
- * OutputStream.
- *
- * This method uses the provided buffer, so there is no need to use a
- * BufferedInputStream.
- *
- *
- * @param input the InputStream to read from
- * @param output the OutputStream to write to
- * @param buffer the buffer to use for the copy
- * @return the number of bytes copied
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- */
- public static long copyLarge(final InputStream input, final OutputStream output, final byte[] buffer)
- throws IOException {
- long count = 0;
- int n;
- while (EOF != (n = input.read(buffer))) {
- output.write(buffer, 0, n);
- count += n;
+ /**
+ * Copies bytes from an InputStream to an
+ * OutputStream.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedInputStream.
+ *
+ * Large streams (over 2GB) will return a bytes copied value of
+ * -1 after the copy has completed since the correct
+ * number of bytes cannot be returned as an int. For large streams
+ * use the copyLarge(InputStream, OutputStream) method.
+ *
+ * @param input the InputStream to read from
+ * @param output the OutputStream to write to
+ * @return the number of bytes copied, or -1 if > Integer.MAX_VALUE
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static int copy(final InputStream input, final OutputStream output) throws IOException {
+ final long count = copyLarge(input, output);
+ if (count > Integer.MAX_VALUE) {
+ return -1;
+ }
+ return (int) count;
}
- return count;
- }
- /**
- * Copies chars from a large (over 2GB) Reader to a Writer.
- *
- * This method uses the provided buffer, so there is no need to use a
- * BufferedReader.
- *
- *
- * @param input the Reader to read from
- * @param output the Writer to write to
- * @param buffer the buffer to be used for the copy
- * @return the number of characters copied
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
- */
- public static long copyLarge(final Reader input, final Writer output, final char[] buffer) throws IOException {
- long count = 0;
- int n;
- while (EOF != (n = input.read(buffer))) {
- output.write(buffer, 0, n);
- count += n;
+ /**
+ * Copies bytes from an InputStream to an OutputStream using an internal buffer of the
+ * given size.
+ *
+ * This method buffers the input internally, so there is no need to use a BufferedInputStream.
+ *
+ *
+ * @param input the InputStream to read from
+ * @param output the OutputStream to write to
+ * @param bufferSize the bufferSize used to copy from the input to the output
+ * @return the number of bytes copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static long copy(final InputStream input, final OutputStream output, final int bufferSize)
+ throws IOException {
+ return copyLarge(input, output, new byte[bufferSize]);
}
- return count;
- }
- /**
- * Gets the contents of an InputStream as a String
- * using the specified character encoding.
- *
- * This method buffers the input internally, so there is no need to use a
- * BufferedInputStream.
- *
- *
- * @param input the InputStream to read from
- * @param encoding the encoding to use, null means platform default
- * @return the requested String
- * @throws NullPointerException if the input is null
- * @throws IOException if an I/O error occurs
- */
- public static String toString(final InputStream input, final Charset encoding) throws IOException {
- try (final StringWriter sw = new StringWriter()) {
- copy(input, sw, encoding);
- return sw.toString();
+ /**
+ * Copies bytes from an InputStream to chars on a
+ * Writer using the specified character encoding.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedInputStream.
+ *
+ * This method uses {@link InputStreamReader}.
+ *
+ * @param input the InputStream to read from
+ * @param output the Writer to write to
+ * @param inputEncoding the encoding to use for the input stream, null means platform default
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static void copy(final InputStream input, final Writer output, final Charset inputEncoding)
+ throws IOException {
+ final InputStreamReader in = new InputStreamReader(input, inputEncoding);
+ copy(in, output);
}
- }
- public static void writeStringToFile(String fileName, String data) throws IOException {
- writeStringToFile(Paths.get(fileName), data, Charsets.UTF_8);
- }
-
-
- public static void writeStringToFile(String fileName, String data, Charset charset) throws IOException {
- writeStringToFile(Paths.get(fileName), data, charset);
- }
-
- public static void writeStringToFile(Path file, String data) throws IOException {
- writeStringToFile(file, data, Charsets.UTF_8);
- }
-
- @Deprecated
- public static void writeStringToFile(File file, String data, Charset charset) throws IOException {
- writeStringToFile(file.toPath(), data, charset);
- }
-
- public static void writeStringToFile(Path file, String data, Charset charset) throws IOException {
- try(Writer writer = Files.newBufferedWriter(file, charset)) {
- writer.write(data);
- writer.flush();
+ /**
+ * Copies chars from a Reader to a Writer.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedReader.
+ *
+ * Large streams (over 2GB) will return a chars copied value of
+ * -1 after the copy has completed since the correct
+ * number of chars cannot be returned as an int. For large streams
+ * use the copyLarge(Reader, Writer) method.
+ *
+ * @param input the Reader to read from
+ * @param output the Writer to write to
+ * @return the number of characters copied, or -1 if > Integer.MAX_VALUE
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static int copy(final Reader input, final Writer output) throws IOException {
+ final long count = copyLarge(input, output);
+ if (count > Integer.MAX_VALUE) {
+ return -1;
+ }
+ return (int) count;
}
- }
- public static void deleteFile(String fileName) {
- deleteFile(Paths.get(fileName));
- }
-
- @Deprecated
- public static void deleteFile(File file) {
- deleteFile(file.toPath());
- }
-
- public static void deleteFile(Path file) {
- try {
- Files.deleteIfExists(file);
- } catch (IOException ex) {
- throw new IllegalArgumentException(ex);
+ /**
+ * Copies chars from a large (over 2GB) Reader to a Writer.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedReader.
+ *
+ * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
+ *
+ * @param input the Reader to read from
+ * @param output the Writer to write to
+ * @return the number of characters copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static long copyLarge(final Reader input, final Writer output) throws IOException {
+ return copyLarge(input, output, new char[DEFAULT_BUFFER_SIZE]);
}
- }
- public static void deleteFiles(String... fileNames) {
- Arrays.asList(fileNames).forEach(file -> deleteFile(file));
- }
+ /**
+ * Copies bytes from a large (over 2GB) InputStream to an
+ * OutputStream.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedInputStream.
+ *
+ * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
+ *
+ * @param input the InputStream to read from
+ * @param output the OutputStream to write to
+ * @return the number of bytes copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static long copyLarge(final InputStream input, final OutputStream output)
+ throws IOException {
+ return copy(input, output, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * Copies bytes from a large (over 2GB) InputStream to an
+ * OutputStream.
+ *
+ * This method uses the provided buffer, so there is no need to use a
+ * BufferedInputStream.
+ *
+ *
+ * @param input the InputStream to read from
+ * @param output the OutputStream to write to
+ * @param buffer the buffer to use for the copy
+ * @return the number of bytes copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static long copyLarge(final InputStream input, final OutputStream output, final byte[] buffer)
+ throws IOException {
+ long count = 0;
+ int n;
+ while (EOF != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ count += n;
+ }
+ return count;
+ }
+
+ /**
+ * Copies chars from a large (over 2GB) Reader to a Writer.
+ *
+ * This method uses the provided buffer, so there is no need to use a
+ * BufferedReader.
+ *
+ *
+ * @param input the Reader to read from
+ * @param output the Writer to write to
+ * @param buffer the buffer to be used for the copy
+ * @return the number of characters copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static long copyLarge(final Reader input, final Writer output, final char[] buffer) throws IOException {
+ long count = 0;
+ int n;
+ while (EOF != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ count += n;
+ }
+ return count;
+ }
+
+ /**
+ * Gets the contents of an InputStream as a String
+ * using the specified character encoding.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedInputStream.
+ *
+ *
+ * @param input the InputStream to read from
+ * @param encoding the encoding to use, null means platform default
+ * @return the requested String
+ * @throws NullPointerException if the input is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static String toString(final InputStream input, final Charset encoding) throws IOException {
+ try (final StringWriter sw = new StringWriter()) {
+ copy(input, sw, encoding);
+ return sw.toString();
+ }
+ }
+
+ public static void writeStringToFile(String fileName, String data) throws IOException {
+ writeStringToFile(Paths.get(fileName), data, Charsets.UTF_8);
+ }
+
+
+ public static void writeStringToFile(String fileName, String data, Charset charset) throws IOException {
+ writeStringToFile(Paths.get(fileName), data, charset);
+ }
+
+ public static void writeStringToFile(Path file, String data) throws IOException {
+ writeStringToFile(file, data, Charsets.UTF_8);
+ }
+
+ @Deprecated
+ public static void writeStringToFile(File file, String data, Charset charset) throws IOException {
+ writeStringToFile(file.toPath(), data, charset);
+ }
+
+ public static void writeStringToFile(Path file, String data, Charset charset) throws IOException {
+ try (Writer writer = Files.newBufferedWriter(file, charset)) {
+ writer.write(data);
+ writer.flush();
+ }
+ }
+
+ public static void deleteFile(String fileName) {
+ deleteFile(Paths.get(fileName));
+ }
+
+ @Deprecated
+ public static void deleteFile(File file) {
+ deleteFile(file.toPath());
+ }
+
+ public static void deleteFile(Path file) {
+ try {
+ Files.deleteIfExists(file);
+ } catch (IOException ex) {
+ throw new IllegalArgumentException(ex);
+ }
+ }
+
+ public static void deleteFiles(String... fileNames) {
+ Arrays.asList(fileNames).forEach(file -> deleteFile(file));
+ }
}
diff --git a/src/main/java/net/locusworks/common/migration/BaseMigrationManager.java b/src/main/java/net/locusworks/common/migration/BaseMigrationManager.java
index 8f96110..c9c5b2f 100644
--- a/src/main/java/net/locusworks/common/migration/BaseMigrationManager.java
+++ b/src/main/java/net/locusworks/common/migration/BaseMigrationManager.java
@@ -4,9 +4,9 @@ import java.util.ArrayList;
import java.util.List;
public abstract class BaseMigrationManager {
-
- protected List migrations = new ArrayList<>();
-
- public abstract void migrate() throws Exception;
+
+ protected List migrations = new ArrayList<>();
+
+ public abstract void migrate() throws Exception;
}
diff --git a/src/main/java/net/locusworks/common/migration/MigrationCallback.java b/src/main/java/net/locusworks/common/migration/MigrationCallback.java
index fc47e2f..0d7f157 100644
--- a/src/main/java/net/locusworks/common/migration/MigrationCallback.java
+++ b/src/main/java/net/locusworks/common/migration/MigrationCallback.java
@@ -2,5 +2,5 @@ package net.locusworks.common.migration;
@FunctionalInterface
public interface MigrationCallback {
- void results(String msg);
+ void results(String msg);
}
diff --git a/src/main/java/net/locusworks/common/migration/MigrationItem.java b/src/main/java/net/locusworks/common/migration/MigrationItem.java
index ad3280a..ac881b5 100644
--- a/src/main/java/net/locusworks/common/migration/MigrationItem.java
+++ b/src/main/java/net/locusworks/common/migration/MigrationItem.java
@@ -7,68 +7,68 @@ import org.flywaydb.core.api.MigrationInfo;
import org.flywaydb.core.internal.info.MigrationInfoDumper;
public class MigrationItem {
-
- protected Flyway flyway = null;
- protected MigrationInfo[] pendingMigrations;
- protected MigrationInfo[] allMigrations;
- private MigrationCallback callback;
-
- public MigrationItem(Flyway flyway, MigrationCallback callback) {
- this.allMigrations = flyway.info().all();
- this.pendingMigrations = flyway.info().pending();
- this.flyway=flyway;
- this.callback = callback;
- }
- public MigrationItem(Flyway flyway) {
- this(flyway, null);
- }
+ protected Flyway flyway = null;
+ protected MigrationInfo[] pendingMigrations;
+ protected MigrationInfo[] allMigrations;
+ private final MigrationCallback callback;
- public String[] getSchemas() {
- return flyway.getConfiguration().getSchemas();
- }
-
- public int qtyPending() {
- return pendingMigrations.length;
- }
-
- public void repair() {
- // no harm in calling migrate even if none pending, log will contain
- // assurance that the migrations were verified
- try {
- String schemas = Arrays.toString(getSchemas()).replace("[", "").replace("]", "");
-
- String status = String.format("Repair status for %s:%n%s", schemas, getAllMigrationsLog());
-
- callback(status);
-
- flyway.repair();
- } catch (Exception e) {
- String message = String.format("%nDatabase migration error:%n %s %nPortal webapp cannot continue.", e.getMessage());
- throw new RuntimeException(message, e);
+ public MigrationItem(Flyway flyway, MigrationCallback callback) {
+ this.allMigrations = flyway.info().all();
+ this.pendingMigrations = flyway.info().pending();
+ this.flyway = flyway;
+ this.callback = callback;
}
- }
- public void migrate() {
- // no harm in calling migrate even if none pending, log will contain
- // assurance that the migrations were verified
- try {
- String schemas = Arrays.toString(getSchemas()).replace("[", "").replace("]", "");
- String status = String.format("Repair status for %s:%n%s", schemas, getAllMigrationsLog());
- callback(status);
- flyway.migrate();
- } catch (Exception e) {
- String message = String.format("%nDatabase migration error:%n %s %nPortal webapp cannot continue.", e.getMessage());
- throw new RuntimeException(message, e);
+ public MigrationItem(Flyway flyway) {
+ this(flyway, null);
+ }
+
+ public String[] getSchemas() {
+ return flyway.getConfiguration().getSchemas();
+ }
+
+ public int qtyPending() {
+ return pendingMigrations.length;
+ }
+
+ public void repair() {
+ // no harm in calling migrate even if none pending, log will contain
+ // assurance that the migrations were verified
+ try {
+ String schemas = Arrays.toString(getSchemas()).replace("[", "").replace("]", "");
+
+ String status = String.format("Repair status for %s:%n%s", schemas, getAllMigrationsLog());
+
+ callback(status);
+
+ flyway.repair();
+ } catch (Exception e) {
+ String message = String.format("%nDatabase migration error:%n %s %nPortal webapp cannot continue.", e.getMessage());
+ throw new RuntimeException(message, e);
+ }
+ }
+
+ public void migrate() {
+ // no harm in calling migrate even if none pending, log will contain
+ // assurance that the migrations were verified
+ try {
+ String schemas = Arrays.toString(getSchemas()).replace("[", "").replace("]", "");
+ String status = String.format("Repair status for %s:%n%s", schemas, getAllMigrationsLog());
+ callback(status);
+ flyway.migrate();
+ } catch (Exception e) {
+ String message = String.format("%nDatabase migration error:%n %s %nPortal webapp cannot continue.", e.getMessage());
+ throw new RuntimeException(message, e);
+ }
+ }
+
+ public String getAllMigrationsLog() {
+ return MigrationInfoDumper.dumpToAsciiTable(allMigrations);
+ }
+
+ private void callback(String msg) {
+ if (this.callback != null) this.callback.results(msg);
}
- }
- public String getAllMigrationsLog() {
- return MigrationInfoDumper.dumpToAsciiTable(allMigrations);
- }
-
- private void callback(String msg) {
- if (this.callback != null) this.callback.results(msg);
- }
-
}
diff --git a/src/main/java/net/locusworks/common/net/HttpClientHelper.java b/src/main/java/net/locusworks/common/net/HttpClientHelper.java
index 56039bf..04922ef 100644
--- a/src/main/java/net/locusworks/common/net/HttpClientHelper.java
+++ b/src/main/java/net/locusworks/common/net/HttpClientHelper.java
@@ -1,95 +1,79 @@
package net.locusworks.common.net;
-import java.security.SecureRandom;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.http.util.EntityUtils;
-
-import net.locusworks.common.net.certmanagers.TrustAllCertsManager;
-import net.locusworks.common.net.hostverifiers.AllHostValidVerifyer;
+import net.locusworks.common.net.ssl.SSLManager;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
public class HttpClientHelper {
- public enum HttpSchema {
- HTTP,
- HTTPS;
+ public enum HttpSchema {
+ HTTP,
+ HTTPS;
- public static HttpSchema findEnum(String value) {
- for (HttpSchema schema : values()) {
- if (value.equalsIgnoreCase(schema.toString())) {
- return schema;
+ public static HttpSchema findEnum(String value) {
+ for (HttpSchema schema : values()) {
+ if (value.equalsIgnoreCase(schema.toString())) {
+ return schema;
+ }
+ }
+ return null;
}
- }
- return null;
}
- }
-
- private static final String[] TLS = new String[] {"TLSv1", "TLSv1.1", "TLSv1.2"};
- private HttpClient client;
- private String baseUrl;
-
- /**
- * Constructor to handle http connection
- * @param protocol protocol to use (http or https)
- * @param host the host url
- * @param port the host port
- * @throws Exception exception
- */
- public HttpClientHelper(String protocol, String host, String port) throws Exception {
- HttpSchema schema = HttpSchema.findEnum(protocol);
- if (schema == null) {
- throw new Exception("Unable to find http schema of " + protocol);
+ private static final String[] TLS = new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"};
+
+ private final HttpClient client;
+ private final String baseUrl;
+
+ /**
+ * Constructor to handle http connection
+ *
+ * @param protocol protocol to use (http or https)
+ * @param host the host url
+ * @param port the host port
+ * @throws Exception exception
+ */
+ public HttpClientHelper(String protocol, String host, String port) throws Exception {
+ HttpSchema schema = HttpSchema.findEnum(protocol);
+ if (schema == null) {
+ throw new Exception("Unable to find http schema of " + protocol);
+ }
+ this.baseUrl = String.format("%s://%s:%s", schema.toString().toLowerCase(), host, port);
+ this.client = createClient(schema);
}
- this.baseUrl = String.format("%s://%s:%s", schema.toString().toLowerCase(), host, port);
- this.client = createClient(schema);
- }
-
- private HttpClient createClient(HttpSchema schema) throws Exception {
- HttpClientBuilder builder = HttpClientBuilder.create();
-
- if (schema == HttpSchema.HTTP) {
- return builder.build();
+
+ private HttpClient createClient(HttpSchema schema) throws Exception {
+ HttpClientBuilder builder = HttpClientBuilder.create();
+
+ if (schema == HttpSchema.HTTP) {
+ return builder.build();
+ }
+
+ return SSLManager.getTrustAllTLSClient();
}
-
- TrustManager[] trustAllCerts = new TrustManager[] { new TrustAllCertsManager() };
- //Setup the ssl instance using tls
- SSLContext sslContext = SSLContext.getInstance("TLS");
- sslContext.init(null, trustAllCerts, new SecureRandom());
-
- SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, TLS, null, new AllHostValidVerifyer());
-
- builder = builder.setSSLSocketFactory(sslsf);
-
- return builder.build();
- }
-
- /**
- * Get the http GET response code
- * @param endpoint endpoint to get the response from
- * @return responseCode
- * @throws Exception general exception
- */
- public Integer getGetResponseCode(String endpoint) throws Exception {
- String url = this.baseUrl + endpoint;
-
- HttpResponse response = this.client.execute(new HttpGet(url));
-
- HttpEntity entity = response.getEntity();
-
- Integer responseCode = response.getStatusLine().getStatusCode();
-
- EntityUtils.consume(entity);
-
- return responseCode;
- };
-
+
+ /**
+ * Get the http GET response code
+ *
+ * @param endpoint endpoint to get the response from
+ * @return responseCode
+ * @throws Exception general exception
+ */
+ public Integer getResponseCode(String endpoint) throws Exception {
+ String url = this.baseUrl + endpoint;
+
+ return this.client.execute(new HttpGet(url), response -> {
+ HttpEntity entity = response.getEntity();
+ int responseCode = response.getCode();
+ EntityUtils.consume(entity);
+ return responseCode;
+ });
+ }
+
+ ;
+
}
diff --git a/src/main/java/net/locusworks/common/net/certmanagers/TrustAllCertsManager.java b/src/main/java/net/locusworks/common/net/certmanagers/TrustAllCertsManager.java
index d27e2f1..7ef740a 100644
--- a/src/main/java/net/locusworks/common/net/certmanagers/TrustAllCertsManager.java
+++ b/src/main/java/net/locusworks/common/net/certmanagers/TrustAllCertsManager.java
@@ -8,17 +8,21 @@ import javax.net.ssl.X509TrustManager;
public class TrustAllCertsManager implements X509TrustManager {
- @Override
- public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { }
+ @Override
+ public void checkClientTrusted(X509Certificate[] arg0, String arg1) {
+ }
- @Override
- public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { }
+ @Override
+ public void checkServerTrusted(X509Certificate[] arg0, String arg1) {
+ }
- @Override
- public X509Certificate[] getAcceptedIssuers() { return null; }
-
- public static TrustManager[] trustAllCerts() {
- return new TrustManager[] { new TrustAllCertsManager() };
- }
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ public static TrustManager[] trustAllCerts() {
+ return new TrustManager[]{new TrustAllCertsManager()};
+ }
}
diff --git a/src/main/java/net/locusworks/common/net/hostverifiers/AllHostValidVerifier.java b/src/main/java/net/locusworks/common/net/hostverifiers/AllHostValidVerifier.java
new file mode 100644
index 0000000..f098cba
--- /dev/null
+++ b/src/main/java/net/locusworks/common/net/hostverifiers/AllHostValidVerifier.java
@@ -0,0 +1,13 @@
+package net.locusworks.common.net.hostverifiers;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSession;
+
+public class AllHostValidVerifier implements HostnameVerifier {
+
+ @Override
+ public boolean verify(String arg0, SSLSession arg1) {
+ return true;
+ }
+
+}
diff --git a/src/main/java/net/locusworks/common/net/hostverifiers/AllHostValidVerifyer.java b/src/main/java/net/locusworks/common/net/hostverifiers/AllHostValidVerifyer.java
deleted file mode 100644
index c385876..0000000
--- a/src/main/java/net/locusworks/common/net/hostverifiers/AllHostValidVerifyer.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package net.locusworks.common.net.hostverifiers;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLSession;
-
-public class AllHostValidVerifyer implements HostnameVerifier {
-
- @Override
- public boolean verify(String arg0, SSLSession arg1) { return true; }
-
-}
diff --git a/src/main/java/net/locusworks/common/net/ssl/SSLManager.java b/src/main/java/net/locusworks/common/net/ssl/SSLManager.java
index 1309b0b..a2e332b 100644
--- a/src/main/java/net/locusworks/common/net/ssl/SSLManager.java
+++ b/src/main/java/net/locusworks/common/net/ssl/SSLManager.java
@@ -7,24 +7,35 @@ import java.security.SecureRandom;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
-import org.apache.http.client.HttpClient;
-import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.apache.http.impl.client.HttpClientBuilder;
import net.locusworks.common.net.certmanagers.TrustAllCertsManager;
-import net.locusworks.common.net.hostverifiers.AllHostValidVerifyer;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
+import org.apache.hc.client5.http.io.HttpClientConnectionManager;
+import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
+import org.apache.hc.client5.http.ssl.TlsSocketStrategy;
public class SSLManager {
- public static final String[] TLS = new String[] {"TLSv1", "TLSv1.1", "TLSv1.2"};
+ public static final String[] TLS = new String[] {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"};
public static HttpClient getTrustAllTLSClient() throws NoSuchAlgorithmException, KeyManagementException {
- SSLContext context = SSLContext.getInstance("TLS");
- context.init(null, new TrustManager[] { new TrustAllCertsManager() }, new SecureRandom());
-
- SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(context, TLS, null, new AllHostValidVerifyer());
-
- return HttpClientBuilder.create().setSSLSocketFactory(sslsf).build();
+ TrustManager[] trustAllCerts = new TrustManager[]{new TrustAllCertsManager()};
+ //Setup the ssl instance using tls
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, trustAllCerts, new SecureRandom());
+ TlsSocketStrategy tlsStrategy = new DefaultClientTlsStrategy(sslContext);
+
+ HttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
+ .setTlsSocketStrategy(tlsStrategy)
+ .build();
+
+ return HttpClients.custom()
+ .setConnectionManager(connectionManager)
+ .build();
}
+ private SSLManager() { }
+
}
diff --git a/src/main/java/net/locusworks/common/objectmapper/ObjectMapperError.java b/src/main/java/net/locusworks/common/objectmapper/ObjectMapperError.java
index 1f90f29..973725e 100644
--- a/src/main/java/net/locusworks/common/objectmapper/ObjectMapperError.java
+++ b/src/main/java/net/locusworks/common/objectmapper/ObjectMapperError.java
@@ -2,11 +2,12 @@ package net.locusworks.common.objectmapper;
/**
* Error handler for the object mapper class
+ *
* @author Isaac Parenteau
* @version 1.0.0
* @date 02/15/2018
*
*/
public interface ObjectMapperError {
- void getError(Throwable e);
+ void getError(Throwable e);
}
diff --git a/src/main/java/net/locusworks/common/objectmapper/ObjectMapperHelper.java b/src/main/java/net/locusworks/common/objectmapper/ObjectMapperHelper.java
index 9ce2050..92fe176 100644
--- a/src/main/java/net/locusworks/common/objectmapper/ObjectMapperHelper.java
+++ b/src/main/java/net/locusworks/common/objectmapper/ObjectMapperHelper.java
@@ -12,137 +12,146 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
/**
- * Object mapper to map to convert objects to json string or
+ * Object mapper to map to convert objects to json string or
* json string back to object
+ *
* @author Isaac Parenteau
* @version 1.0.0
* @date 02/15/2018
*/
public class ObjectMapperHelper {
-
- private static ObjectMapper mapper;
- static {
- mapper = new ObjectMapper();
- mapper.setSerializationInclusion(Include.NON_NULL);
- mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
- }
-
- /**
- * Write an object out to json
- * @param object Object to convert to json
- * @return return a string representation of the object converted to json
- */
- public static ObjectMapperResults writeValue(Object object) {
- String results = "";
- try {
- results = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
- } catch (Exception ex) {
- try {
- GsonBuilder gsonBuilder = new GsonBuilder();
- gsonBuilder.setPrettyPrinting();
- Gson gson = gsonBuilder.create();
- results = gson.toJson(object);
- } catch (Exception e) {
- new ObjectMapperResults<>(e);
- }
- }
- return new ObjectMapperResults<>(results);
- }
-
- /**
- * Convert binary data to an object
- * @param src Binary data to convert
- * @param clazz Class to convert the data to
- * @param The expected class of the value
- * @return the object populated with the data in the json string
- */
- public static ObjectMapperResults readValue(byte[] src, Class clazz) {
- try {
- return new ObjectMapperResults(mapper.readValue(src, clazz));
- } catch (Exception ex) {
- return new ObjectMapperResults(ex);
- }
- }
-
- /**
- * Convert a json string to an object
- * @param src Json String
- * @param clazz Class to convert the json string to
- * @param The expected class of the value
- * @return the object populated with the data in the json string
- */
- public static ObjectMapperResults readValue(String src, Class clazz) {
- try {
- return new ObjectMapperResults(mapper.readValue(src, clazz));
- } catch (Exception ex) {
- return new ObjectMapperResults(ex);
- }
- }
-
- /**
- * Convert an java object to a class
- * @param src Object to convert
- * @param clazz Class to convert the object to
- * @param The expected class of the value
- * @return the object populated with the data in the json string
- */
- public static ObjectMapperResults readValue(Object src, Class clazz) {
- try {
- if (src instanceof String) {
- return readValue((String)src, clazz);
- }
- return readValue(mapper.writeValueAsString(src), clazz);
- } catch (Exception ex) {
- return new ObjectMapperResults(ex);
- }
- }
-
- /**
- * Converts an object to a list
- * @param object Object to convert
- * @param objectClass Class to convert the object to
- * @param The expected class of the object
- * @return the object list populated with the data in the json string
- */
- public static > ObjectMapperListResults> readListValue(Object object, Class objectClass) {
- return readListValue(object, objectClass, ArrayList.class);
- }
-
- /**
- * Converts an object to a list
- * @param object Object to convert
- * @param objectClass Class to convert the object to
- * @param listClass List type to make
- * @param The expected class of the object
- * @param The expect class of the list
- * @return the object list populated with the data in the json string
- */
- public static > ObjectMapperListResults> readListValue(Object object, Class objectClass, Class listClass) {
- try {
- if (object instanceof String) {
- return readListValue((String)object, objectClass, listClass);
- }
- return readListValue(mapper.writeValueAsString(object), objectClass, listClass);
- } catch (Exception ex) {
- return new ObjectMapperListResults<>(ex);
- }
- }
-
- /**
- * Converts an object to a list
- * @param src Source to convert
- * @param objectClass Class to convert the object to
- * @param listClass List type to make
- * @param The expected class of the object
- * @param The expect class of the list
- * @return the object list populated with the data in the json string
- */
- public static > ObjectMapperListResults> readListValue(String src, Class objectClass, Class listClass) {
- try {
- List item = mapper.readValue(src, mapper.getTypeFactory().constructCollectionType(listClass, objectClass));
- return new ObjectMapperListResults<>(item);
- } catch (Exception ex) {
- return new ObjectMapperListResults<>(ex);
- }
- }
-}
\ No newline at end of file
+
+ private static final ObjectMapper mapper;
+
+ static {
+ mapper = new ObjectMapper();
+ mapper.setDefaultPropertyInclusion(Include.NON_NULL);
+ mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
+ }
+
+ /**
+ * Write an object out to json
+ *
+ * @param object Object to convert to json
+ * @return return a string representation of the object converted to json
+ */
+ public static ObjectMapperResults writeValue(Object object) {
+ String results = "";
+ try {
+ results = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
+ } catch (Exception ex) {
+ try {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.setPrettyPrinting();
+ Gson gson = gsonBuilder.create();
+ results = gson.toJson(object);
+ } catch (Throwable e) {
+ return new ObjectMapperResults<>(e);
+ }
+ }
+ return new ObjectMapperResults<>(results);
+ }
+
+ /**
+ * Convert binary data to an object
+ *
+ * @param src Binary data to convert
+ * @param clazz Class to convert the data to
+ * @param The expected class of the value
+ * @return the object populated with the data in the json string
+ */
+ public static ObjectMapperResults readValue(byte[] src, Class clazz) {
+ try {
+ return new ObjectMapperResults(mapper.readValue(src, clazz));
+ } catch (Exception ex) {
+ return new ObjectMapperResults(ex);
+ }
+ }
+
+ /**
+ * Convert a json string to an object
+ *
+ * @param src Json String
+ * @param clazz Class to convert the json string to
+ * @param The expected class of the value
+ * @return the object populated with the data in the json string
+ */
+ public static ObjectMapperResults readValue(String src, Class clazz) {
+ try {
+ return new ObjectMapperResults(mapper.readValue(src, clazz));
+ } catch (Exception ex) {
+ return new ObjectMapperResults(ex);
+ }
+ }
+
+ /**
+ * Convert an java object to a class
+ *
+ * @param src Object to convert
+ * @param clazz Class to convert the object to
+ * @param The expected class of the value
+ * @return the object populated with the data in the json string
+ */
+ public static ObjectMapperResults readValue(Object src, Class clazz) {
+ try {
+ if (src instanceof String) {
+ return readValue((String) src, clazz);
+ }
+ return readValue(mapper.writeValueAsString(src), clazz);
+ } catch (Exception ex) {
+ return new ObjectMapperResults(ex);
+ }
+ }
+
+ /**
+ * Converts an object to a list
+ *
+ * @param object Object to convert
+ * @param objectClass Class to convert the object to
+ * @param The expected class of the object
+ * @return the object list populated with the data in the json string
+ */
+ public static > ObjectMapperListResults> readListValue(Object object, Class objectClass) {
+ return readListValue(object, objectClass, ArrayList.class);
+ }
+
+ /**
+ * Converts an object to a list
+ *
+ * @param object Object to convert
+ * @param objectClass Class to convert the object to
+ * @param listClass List type to make
+ * @param The expected class of the object
+ * @param The expect class of the list
+ * @return the object list populated with the data in the json string
+ */
+ public static > ObjectMapperListResults> readListValue(Object object, Class objectClass, Class listClass) {
+ try {
+ if (object instanceof String) {
+ return readListValue((String) object, objectClass, listClass);
+ }
+ return readListValue(mapper.writeValueAsString(object), objectClass, listClass);
+ } catch (Exception ex) {
+ return new ObjectMapperListResults<>(ex);
+ }
+ }
+
+ /**
+ * Converts an object to a list
+ *
+ * @param src Source to convert
+ * @param objectClass Class to convert the object to
+ * @param listClass List type to make
+ * @param The expected class of the object
+ * @param The expect class of the list
+ * @return the object list populated with the data in the json string
+ */
+ public static > ObjectMapperListResults> readListValue(String src, Class objectClass, Class listClass) {
+ try {
+ List item = mapper.readValue(src, mapper.getTypeFactory().constructCollectionType(listClass, objectClass));
+ return new ObjectMapperListResults<>(item);
+ } catch (Exception ex) {
+ return new ObjectMapperListResults<>(ex);
+ }
+ }
+}
diff --git a/src/main/java/net/locusworks/common/objectmapper/ObjectMapperListResults.java b/src/main/java/net/locusworks/common/objectmapper/ObjectMapperListResults.java
index b1af466..5bbcd8f 100644
--- a/src/main/java/net/locusworks/common/objectmapper/ObjectMapperListResults.java
+++ b/src/main/java/net/locusworks/common/objectmapper/ObjectMapperListResults.java
@@ -4,48 +4,53 @@ import java.util.Collection;
/**
* Holds the results from the object mapper list conversion
+ *
+ * @param class type of the object mapper
* @author Isaac Parenteau
* @version 1.0.0
* @date 02/15/2018
- * @param class type of the object mapper
*/
public class ObjectMapperListResults> extends ObjectMapperResults {
-
- /**
- * Constructor
- * @param results results from the conversion
- */
- public ObjectMapperListResults(T results) {
- this(results, null);
- }
-
- /**
- * Constructor
- * @param exception exception that was thrown during conversion
- */
- public ObjectMapperListResults(Throwable exception) {
- this(null, exception);
- }
-
- /**
- * Constructor
- * @param results results from the conversion
- * @param exception exception that was thrown during conversion
- */
- public ObjectMapperListResults(T results, Throwable exception) {
- super(results, exception);
- }
- /**
- * Add the error handler to the results to retrieve the error that caused
- * the exception
- * @param error the error handler to use
- * @return this
- */
- public ObjectMapperListResults withErrorHandler(ObjectMapperError error) {
- if (this.hasError() && error != null) {
- error.getError(this.getException());
+ /**
+ * Constructor
+ *
+ * @param results results from the conversion
+ */
+ public ObjectMapperListResults(T results) {
+ this(results, null);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param exception exception that was thrown during conversion
+ */
+ public ObjectMapperListResults(Throwable exception) {
+ this(null, exception);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param results results from the conversion
+ * @param exception exception that was thrown during conversion
+ */
+ public ObjectMapperListResults(T results, Throwable exception) {
+ super(results, exception);
+ }
+
+ /**
+ * Add the error handler to the results to retrieve the error that caused
+ * the exception
+ *
+ * @param error the error handler to use
+ * @return this
+ */
+ public ObjectMapperListResults withErrorHandler(ObjectMapperError error) {
+ if (this.hasError() && error != null) {
+ error.getError(this.getException());
+ }
+ return this;
}
- return this;
- }
}
\ No newline at end of file
diff --git a/src/main/java/net/locusworks/common/objectmapper/ObjectMapperResults.java b/src/main/java/net/locusworks/common/objectmapper/ObjectMapperResults.java
index 092be8f..807e5de 100644
--- a/src/main/java/net/locusworks/common/objectmapper/ObjectMapperResults.java
+++ b/src/main/java/net/locusworks/common/objectmapper/ObjectMapperResults.java
@@ -2,92 +2,102 @@ package net.locusworks.common.objectmapper;
/**
* Holds the results from the object mapper list conversion
+ *
+ * @param class type of the object being converted from json to object
* @author Isaac Parenteau
* @version 1.0.0
* @date 02/15/2018
- * @param class type of the object being converted from json to object
*/
public class ObjectMapperResults {
-
- private Throwable exception;
- private T results;
-
- /**
- * Constructor
- * @param results results from the conversion
- */
- public ObjectMapperResults(T results) {
- this(results, null);
- }
-
- /**
- * Constructor
- * @param exception exception that was thrown during conversion
- */
- public ObjectMapperResults(Throwable exception) {
- this(null, exception);
- }
-
- /**
- * Constructor
- * @param results results from the conversion
- * @param exception exception that was thrown during conversion
- */
- public ObjectMapperResults(T results, Throwable exception) {
- this.results = results;
- this.exception = exception;
- }
- /**
- * get the exception that happened during conversion
- * @return exception
- */
- public Throwable getException() {
- return exception;
- }
+ private Throwable exception;
+ private T results;
- /**
- * Set the exception
- * @param exception
- */
- public void setException(Throwable exception) {
- this.exception = exception;
- }
-
- /**
- * Get the result
- * @return the converted results
- */
- public T getResults() {
- return results;
- }
-
- /**
- * set the results
- * @param results results to set
- */
- public void setResults(T results) {
- this.results = results;
- }
-
- /**
- * Check to see if the conversion caused an error
- * @return true if there is an error, false otherwise
- */
- public boolean hasError() {
- return this.exception != null;
- }
-
- /**
- * Add the error handler to the results to retrieve the error that caused
- * the exception
- * @param error the error handler to use
- * @return this
- */
- public ObjectMapperResults withErrorHandler(ObjectMapperError error) {
- if (this.hasError() && error != null) {
- error.getError(this.getException());
+ /**
+ * Constructor
+ *
+ * @param results results from the conversion
+ */
+ public ObjectMapperResults(T results) {
+ this(results, null);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param exception exception that was thrown during conversion
+ */
+ public ObjectMapperResults(Throwable exception) {
+ this(null, exception);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param results results from the conversion
+ * @param exception exception that was thrown during conversion
+ */
+ public ObjectMapperResults(T results, Throwable exception) {
+ this.results = results;
+ this.exception = exception;
+ }
+
+ /**
+ * get the exception that happened during conversion
+ *
+ * @return exception
+ */
+ public Throwable getException() {
+ return exception;
+ }
+
+ /**
+ * Set the exception
+ *
+ * @param exception
+ */
+ public void setException(Throwable exception) {
+ this.exception = exception;
+ }
+
+ /**
+ * Get the result
+ *
+ * @return the converted results
+ */
+ public T getResults() {
+ return results;
+ }
+
+ /**
+ * set the results
+ *
+ * @param results results to set
+ */
+ public void setResults(T results) {
+ this.results = results;
+ }
+
+ /**
+ * Check to see if the conversion caused an error
+ *
+ * @return true if there is an error, false otherwise
+ */
+ public boolean hasError() {
+ return this.exception != null;
+ }
+
+ /**
+ * Add the error handler to the results to retrieve the error that caused
+ * the exception
+ *
+ * @param error the error handler to use
+ * @return this
+ */
+ public ObjectMapperResults withErrorHandler(ObjectMapperError error) {
+ if (this.hasError() && error != null) {
+ error.getError(this.getException());
+ }
+ return this;
}
- return this;
- }
}
diff --git a/src/main/java/net/locusworks/common/properties/ImmutableProperties.java b/src/main/java/net/locusworks/common/properties/ImmutableProperties.java
index 0884479..b8fbe2f 100644
--- a/src/main/java/net/locusworks/common/properties/ImmutableProperties.java
+++ b/src/main/java/net/locusworks/common/properties/ImmutableProperties.java
@@ -1,31 +1,33 @@
package net.locusworks.common.properties;
+import java.io.Serial;
import java.util.Properties;
public class ImmutableProperties extends Properties {
- private static final long serialVersionUID = 65942088008978137L;
-
- public ImmutableProperties() {
- super();
- }
-
- public ImmutableProperties(Properties props) {
- super();
- if (props == null || props.isEmpty()) return;
-
- props.entrySet().forEach(item -> this.put(item.getKey(), item.getValue()));
- }
-
- @Override
- public synchronized Object setProperty(String key, String value) {
- return put(key, value);
- }
-
- public synchronized Object put(Object key, Object value) {
- if (containsKey(key))
- throw new RuntimeException("Cannot change key value once its set: " + key);
- return super.put(key, value);
- }
+ @Serial
+ private static final long serialVersionUID = 65942088008978137L;
+
+ public ImmutableProperties() {
+ super();
+ }
+
+ public ImmutableProperties(Properties props) {
+ super();
+ if (props == null || props.isEmpty()) return;
+
+ this.putAll(props);
+ }
+
+ @Override
+ public synchronized Object setProperty(String key, String value) {
+ return put(key, value);
+ }
+
+ public synchronized Object put(Object key, Object value) {
+ if (containsKey(key))
+ throw new RuntimeException("Cannot change key value once its set: " + key);
+ return super.put(key, value);
+ }
}
diff --git a/src/main/java/net/locusworks/common/properties/OrderedProperties.java b/src/main/java/net/locusworks/common/properties/OrderedProperties.java
index dcefa70..a8ca4d3 100644
--- a/src/main/java/net/locusworks/common/properties/OrderedProperties.java
+++ b/src/main/java/net/locusworks/common/properties/OrderedProperties.java
@@ -1,38 +1,7 @@
package net.locusworks.common.properties;
-/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
- * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- */
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-import java.io.OutputStreamWriter;
-import java.io.BufferedWriter;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
@@ -67,7 +36,7 @@ import java.util.Set;
* {@link #store(java.io.Writer, java.lang.String) store(Writer, String)}
* methods load and store properties from and to a character based stream
* in a simple line-oriented format specified below.
- *
+ *
* The {@link #load(java.io.InputStream) load(InputStream)} /
* {@link #store(java.io.OutputStream, java.lang.String) store(OutputStream, String)}
* methods work the same way as the load(Reader)/store(Writer, String) pair, except
@@ -111,916 +80,898 @@ import java.util.Set;
*
This class is thread-safe: multiple threads can share a single
* Properties object without the need for external synchronization.
*
+ * @author Arthur van Hoff
+ * @author Michael McCloskey
+ * @author Xueming Shen
* @see native2ascii tool for Solaris
* @see native2ascii tool for Windows
- *
- * @author Arthur van Hoff
- * @author Michael McCloskey
- * @author Xueming Shen
- * @since JDK1.0
+ * @since JDK1.0
*/
-public class OrderedProperties extends LinkedHashMap