mirror of
https://github.com/zyphlar/LanternPowerMonitor.git
synced 2024-03-08 14:07:47 +00:00
Initial Commit
This commit is contained in:
65
util/lantern-util-common/pom.xml
Normal file
65
util/lantern-util-common/pom.xml
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.lanternsoftware.util</groupId>
|
||||
<artifactId>lantern-util-common</artifactId>
|
||||
<name>lantern-util-common</name>
|
||||
<version>1.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.29</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>testCompile</goal>
|
||||
</goals>
|
||||
<phase>compile</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<optimize>true</optimize>
|
||||
<showDeprecation>true</showDeprecation>
|
||||
<encoding>UTF-8</encoding>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,935 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.RandomAccess;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class CollectionUtils {
|
||||
public static <T> T getFirst(Collection<T> _collObjects) {
|
||||
if ((_collObjects != null) && !_collObjects.isEmpty())
|
||||
return _collObjects.iterator().next();
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> T removeFirst(Collection<T> _objects) {
|
||||
if (_objects == null)
|
||||
return null;
|
||||
Iterator<T> iter = _objects.iterator();
|
||||
if (iter.hasNext()) {
|
||||
T t = iter.next();
|
||||
iter.remove();
|
||||
return t;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> T removeOne(Collection<T> _coll, IQualifier<T> _qualifier) {
|
||||
if ((_coll == null) || (_qualifier == null))
|
||||
return null;
|
||||
Iterator<T> iter = _coll.iterator();
|
||||
while (iter.hasNext()) {
|
||||
T t = iter.next();
|
||||
if (_qualifier.qualifies(t)) {
|
||||
iter.remove();
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> List<T> removeAll(Collection<T> _coll, IQualifier<T> _qualifier) {
|
||||
if ((_coll == null) || (_qualifier == null))
|
||||
return null;
|
||||
List<T> ret = new ArrayList<>();
|
||||
Iterator<T> iter = _coll.iterator();
|
||||
while (iter.hasNext()) {
|
||||
T t = iter.next();
|
||||
if (_qualifier.qualifies(t)) {
|
||||
iter.remove();
|
||||
ret.add(t);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static <T> T getLast(Collection<T> _collObjects) {
|
||||
if ((_collObjects == null) || _collObjects.isEmpty())
|
||||
return null;
|
||||
if (_collObjects instanceof RandomAccess) {
|
||||
List<T> listObjects = (List<T>) _collObjects;
|
||||
return listObjects.get(listObjects.size() - 1);
|
||||
}
|
||||
if (_collObjects instanceof Deque) {
|
||||
Deque<T> listObjects = (Deque<T>) _collObjects;
|
||||
return listObjects.getLast();
|
||||
}
|
||||
T t = null;
|
||||
Iterator<T> iter = _collObjects.iterator();
|
||||
while (iter.hasNext()) {
|
||||
t = iter.next();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
public static <T> T getFirst(T[] _arrObjects) {
|
||||
if (size(_arrObjects) > 0)
|
||||
return _arrObjects[0];
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> boolean isEmpty(Collection<T> _collObjects) {
|
||||
return (_collObjects == null) || _collObjects.isEmpty();
|
||||
}
|
||||
|
||||
public static <T> boolean isNotEmpty(Collection<T> _collObjects) {
|
||||
return (_collObjects != null) && !_collObjects.isEmpty();
|
||||
}
|
||||
|
||||
public static <T,V> boolean isEmpty(Map<T,V> _map) {
|
||||
return (_map == null) || _map.isEmpty();
|
||||
}
|
||||
|
||||
public static <T,V> boolean isNotEmpty(Map<T,V> _map) {
|
||||
return (_map != null) && !_map.isEmpty();
|
||||
}
|
||||
|
||||
public static <T> Collection<T> makeNotNull(Collection<T> _collObjects) {
|
||||
if (_collObjects != null)
|
||||
return _collObjects;
|
||||
return new ArrayList<T>();
|
||||
}
|
||||
|
||||
public static <T> List<T> makeNotNull(List<T> _listObjects) {
|
||||
if (_listObjects != null)
|
||||
return _listObjects;
|
||||
return new ArrayList<T>();
|
||||
}
|
||||
|
||||
public static <T, V> Map<T, V> makeNotNull(Map<T, V> _mapObjects) {
|
||||
if (_mapObjects != null)
|
||||
return _mapObjects;
|
||||
return new HashMap<T, V>();
|
||||
}
|
||||
|
||||
public static int size(Collection<?> _collObjects) {
|
||||
if (_collObjects == null)
|
||||
return 0;
|
||||
return _collObjects.size();
|
||||
}
|
||||
|
||||
public static <T,V> int size(Map<T, V> _collObjects) {
|
||||
if (_collObjects == null)
|
||||
return 0;
|
||||
return _collObjects.size();
|
||||
}
|
||||
|
||||
public static <T> int size(T[] _arr) {
|
||||
if (_arr == null)
|
||||
return 0;
|
||||
return _arr.length;
|
||||
}
|
||||
|
||||
public static <T> T get(List<T> _list, int _idx) {
|
||||
if (_list == null)
|
||||
return null;
|
||||
if ((_idx < 0) || (_idx >= _list.size()))
|
||||
return null;
|
||||
return _list.get(_idx);
|
||||
}
|
||||
|
||||
public static <T> T get(T[] _t, int _idx) {
|
||||
if (_t == null)
|
||||
return null;
|
||||
if ((_idx < 0) || (_idx >= _t.length))
|
||||
return null;
|
||||
return _t[_idx];
|
||||
}
|
||||
|
||||
public static <T, V> List<V> get(Map<T, V> _map, Collection<T> _keys) {
|
||||
if (_keys == null)
|
||||
return null;
|
||||
List<V> ret = new ArrayList<>();
|
||||
for (T t : _keys) {
|
||||
ret.add(_map.get(t));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static <T> T last(T[] _arr) {
|
||||
if (_arr == null || _arr.length == 0)
|
||||
return null;
|
||||
return _arr[_arr.length - 1];
|
||||
}
|
||||
|
||||
public static <T> boolean contains(Collection<T> _coll, T _t) {
|
||||
if (_coll == null)
|
||||
return false;
|
||||
return _coll.contains(_t);
|
||||
}
|
||||
|
||||
public static <T> boolean containsAny(Collection<T> _coll, T... _t) {
|
||||
return containsAny(_coll, asArrayList(_t));
|
||||
}
|
||||
|
||||
public static <T> boolean containsAny(Collection<T> _coll, Collection<T> _values) {
|
||||
if (size(_values) == 0)
|
||||
return false;
|
||||
for (T t : _values) {
|
||||
if (contains(_coll, t))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static <T> boolean containsAll(Collection<T> _coll, T... _t) {
|
||||
return containsAll(_coll, asArrayList(_t));
|
||||
}
|
||||
|
||||
public static <T> boolean containsAll(Collection<T> _coll, Collection<T> _values) {
|
||||
if (size(_values) == 0)
|
||||
return true;
|
||||
for (T t : _values) {
|
||||
if (!contains(_coll, t))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static <T> boolean containsNone(Collection<T> _coll, T... _t) {
|
||||
return containsNone(_coll, asArrayList(_t));
|
||||
}
|
||||
|
||||
public static <T> boolean containsNone(Collection<T> _coll, Collection<T> _values) {
|
||||
if (size(_values) == 0)
|
||||
return true;
|
||||
for (T t : _values) {
|
||||
if (contains(_coll, t))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static <T> List<T> merge(Collection<List<T>> _colls) {
|
||||
List<T> list = new ArrayList<>();
|
||||
for (List<? extends T> coll : makeNotNull(_colls)) {
|
||||
list.addAll(coll);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T> List<T> merge(Collection<? extends T> _coll1, Collection<? extends T> _coll2) {
|
||||
List<T> list = new ArrayList<>(makeNotNull(_coll1));
|
||||
list.addAll(makeNotNull(_coll2));
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T, V> List<V> aggregate(Collection<T> _coll, IAggregator<T, V> _aggregator) {
|
||||
List<V> list = new ArrayList<>();
|
||||
for (T t : makeNotNull(_coll)) {
|
||||
List<V> vs = _aggregator.aggregate(t);
|
||||
if (vs != null)
|
||||
list.addAll(vs);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T, V, U> Map<U, V> aggregateToMap(Collection<T> _coll, IAggregator<T, V> _aggregator, ITransformer<V, U> _keyTransformer) {
|
||||
return transformToMap(aggregate(_coll, _aggregator), _keyTransformer);
|
||||
}
|
||||
|
||||
public static byte[] merge(byte[]... _arrs) {
|
||||
int iSize = 0;
|
||||
for (byte[] curArr : _arrs) {
|
||||
if (curArr != null)
|
||||
iSize += curArr.length;
|
||||
}
|
||||
byte[] arr = new byte[iSize];
|
||||
int offset = 0;
|
||||
for (byte[] curArr : _arrs) {
|
||||
if (curArr == null)
|
||||
continue;
|
||||
System.arraycopy(curArr, 0, arr, offset, curArr.length);
|
||||
offset += curArr.length;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static <T, V> List<V> getMultiMapList(T _key, Map<T, List<V>> _map) {
|
||||
List<V> list = _map.get(_key);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
_map.put(_key, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T, V> Set<V> getMultiMapSet(T _key, Map<T, Set<V>> _map) {
|
||||
Set<V> set = _map.get(_key);
|
||||
if (set == null) {
|
||||
set = new HashSet<>();
|
||||
_map.put(_key, set);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
public static <T, V> List<V> addToMultiMap(T _key, V _value, Map<T, List<V>> _map) {
|
||||
List<V> list = getMultiMapList(_key, _map);
|
||||
list.add(_value);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T, V> Set<V> addToMultiMapSet(T _key, V _value, Map<T, Set<V>> _map) {
|
||||
Set<V> set = getMultiMapSet(_key, _map);
|
||||
set.add(_value);
|
||||
return set;
|
||||
}
|
||||
|
||||
public static int sumIntegers(Collection<Integer> _coll) {
|
||||
int sum = 0;
|
||||
for (Integer val : makeNotNull(_coll)) {
|
||||
if (val != null)
|
||||
sum += val;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public static Double sum(Collection<Double> _coll) {
|
||||
double sum = 0.0;
|
||||
for (Double val : makeNotNull(_coll)) {
|
||||
if (val != null)
|
||||
sum += val;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public static Double mean(Collection<Double> _coll) {
|
||||
int cnt = 0;
|
||||
double total = 0.0;
|
||||
for (Double val : makeNotNull(_coll)) {
|
||||
if (val != null) {
|
||||
cnt++;
|
||||
total += val;
|
||||
}
|
||||
}
|
||||
if (cnt == 0)
|
||||
return 0.0;
|
||||
return total / cnt;
|
||||
}
|
||||
|
||||
public static Double variance(Collection<Double> _coll) {
|
||||
double mean = mean(_coll);
|
||||
int cnt = 0;
|
||||
double total = 0.0;
|
||||
for (Double val : makeNotNull(_coll)) {
|
||||
if (val != null) {
|
||||
cnt++;
|
||||
total += (val - mean) * (val - mean);
|
||||
}
|
||||
}
|
||||
if (cnt == 0)
|
||||
return 0.0;
|
||||
return total / cnt;
|
||||
}
|
||||
|
||||
public static Double standardDeviation(Collection<Double> _coll) {
|
||||
return Math.sqrt(variance(_coll));
|
||||
}
|
||||
|
||||
public static <T> List<List<T>> split(List<T> _list, int _size) {
|
||||
if (_list == null)
|
||||
return Collections.emptyList();
|
||||
int iPieces = (_list.size() / _size) + 1;
|
||||
List<List<T>> list = new ArrayList<>(iPieces);
|
||||
for (int i = 0; i < iPieces; i++) {
|
||||
list.add(_list.subList(i * _size, Math.min(_list.size(), (i + 1) * _size)));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T> List<List<T>> splitEvenly(List<T> _list, int _maxSize) {
|
||||
if (isEmpty(_list))
|
||||
return Collections.emptyList();
|
||||
return splitIntoPieces(_list, ((_list.size()-1) / _maxSize) + 1);
|
||||
}
|
||||
|
||||
public static <T> List<List<T>> splitIntoPieces(List<T> _list, int _pieces) {
|
||||
return splitIntoPieces(_list, _pieces, false);
|
||||
}
|
||||
|
||||
public static <T> List<List<T>> splitIntoPieces(List<T> _list, int _pieces, boolean _createNewLists) {
|
||||
if (isEmpty(_list))
|
||||
return Collections.emptyList();
|
||||
if (_list.size() < _pieces)
|
||||
return Collections.singletonList(_list);
|
||||
int size = (int)Math.ceil(((double)_list.size())/_pieces);
|
||||
List<List<T>> list = new ArrayList<>(_pieces);
|
||||
int offset = 0;
|
||||
while (offset < _list.size()) {
|
||||
List<T> subList = _list.subList(offset, Math.min(_list.size(), offset+size));
|
||||
list.add(_createNewLists?new ArrayList<>(subList):subList);
|
||||
offset += size;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T> ArrayList<T> asArrayList(T... _values) {
|
||||
if (_values == null)
|
||||
return new ArrayList<>(0);
|
||||
ArrayList<T> list = new ArrayList<>(_values.length);
|
||||
for (T t : _values)
|
||||
list.add(t);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T> HashSet<T> asHashSet(T... _values) {
|
||||
HashSet<T> setValues = new HashSet<>();
|
||||
if (_values == null)
|
||||
return setValues;
|
||||
for (T t : _values)
|
||||
setValues.add(t);
|
||||
return setValues;
|
||||
}
|
||||
|
||||
public static <K, V> HashMap<K, V> asHashMap(K _key, V _value) {
|
||||
HashMap<K, V> map = new HashMap<>();
|
||||
map.put(_key, _value);
|
||||
return map;
|
||||
}
|
||||
|
||||
public static <T> ArrayList<T> asArrayList(Iterable<T> _iterable) {
|
||||
if (_iterable == null)
|
||||
return new ArrayList<T>(0);
|
||||
ArrayList<T> list = new ArrayList<>();
|
||||
for (T t : _iterable)
|
||||
list.add(t);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T> ArrayList<T> asArrayList(Iterator<T> _iter) {
|
||||
if (_iter == null)
|
||||
return new ArrayList<T>(0);
|
||||
ArrayList<T> list = new ArrayList<>();
|
||||
while (_iter.hasNext())
|
||||
list.add(_iter.next());
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T> HashSet<T> asHashSet(Iterable<T> _iterable) {
|
||||
HashSet<T> setValues = new HashSet<>();
|
||||
if (_iterable == null)
|
||||
return setValues;
|
||||
for (T t : _iterable)
|
||||
setValues.add(t);
|
||||
return setValues;
|
||||
}
|
||||
|
||||
public static <T> HashSet<T> asHashSet(Iterator<T> _iter) {
|
||||
HashSet<T> setValues = new HashSet<>();
|
||||
if (_iter == null)
|
||||
return setValues;
|
||||
while (_iter.hasNext())
|
||||
setValues.add(_iter.next());
|
||||
return setValues;
|
||||
}
|
||||
|
||||
public static <T> boolean allQualify(Collection<T> _coll, IQualifier<T> _qualifier) {
|
||||
if ((_coll == null) || (_qualifier == null))
|
||||
return false;
|
||||
for (T t : _coll) {
|
||||
if ((t == null) || !_qualifier.qualifies(t))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static <T> boolean anyQualify(Collection<T> _coll, IQualifier<T> _qualifier) {
|
||||
if ((_coll == null) || (_qualifier == null))
|
||||
return false;
|
||||
for (T t : _coll) {
|
||||
if ((t != null) && _qualifier.qualifies(t))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static <T> boolean noneQualify(Collection<T> _coll, IQualifier<T> _qualifier) {
|
||||
if ((_coll == null) || (_qualifier == null))
|
||||
return true;
|
||||
for (T t : _coll) {
|
||||
if ((t != null) && _qualifier.qualifies(t))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static <T> List<T> filter(Collection<? extends T> _coll, IFilter<T> _filter) {
|
||||
if ((_coll == null) || (_filter == null))
|
||||
return new ArrayList<>();
|
||||
List<T> listValues = new ArrayList<>();
|
||||
for (T t : _coll) {
|
||||
if (_filter.isFiltered(t))
|
||||
listValues.add(t);
|
||||
}
|
||||
return listValues;
|
||||
}
|
||||
|
||||
public static <T> T filterOne(Collection<? extends T> _coll, IFilter<T> _filter) {
|
||||
if ((_coll == null) || (_filter == null))
|
||||
return null;
|
||||
for (T t : _coll) {
|
||||
if (_filter.isFiltered(t))
|
||||
return t;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> int indexOf(List<? extends T> _list, IQualifier<T> _qual) {
|
||||
if ((_list == null) || (_qual == null))
|
||||
return -1;
|
||||
int i = 0;
|
||||
for (T t : _list) {
|
||||
if (_qual.qualifies(t))
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static <T> void filterMod(Iterable<? extends T> _iterable, IFilter<T> _filter) {
|
||||
if ((_iterable == null) || (_filter == null))
|
||||
return;
|
||||
Iterator<? extends T> iter = _iterable.iterator();
|
||||
while (iter.hasNext()) {
|
||||
if (!_filter.isFiltered(iter.next()))
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T, V> List<V> filterToType(Iterable<? extends T> _iterable, Class<V> _class) {
|
||||
List<V> list = new ArrayList<>();
|
||||
if (_iterable == null)
|
||||
return list;
|
||||
for (T t : _iterable) {
|
||||
if (_class.isInstance(t))
|
||||
list.add(_class.cast(t));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
public static <T> void edit(Iterable<T> _coll, IEditor<T> _editor) {
|
||||
if ((_coll == null) || (_editor == null))
|
||||
return;
|
||||
for (T t : _coll) {
|
||||
_editor.edit(t);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T, V> List<V> transform(Collection<T> _coll, ITransformer<? super T, V> _transformer) {
|
||||
return transform(_coll, _transformer, false);
|
||||
}
|
||||
|
||||
public static <T, V> List<V> transform(Iterable<T> _iter, ITransformer<? super T, V> _transformer) {
|
||||
return transform(_iter, _transformer, false);
|
||||
}
|
||||
|
||||
public static <T, V> List<V> transform(Iterable<T> _iter, ITransformer<? super T, V> _transformer, boolean _excludeNulls) {
|
||||
if ((_iter == null) || (_transformer == null))
|
||||
return new ArrayList<>();
|
||||
List<V> listValues = new ArrayList<>();
|
||||
for (T t : _iter) {
|
||||
if (_excludeNulls && (t == null))
|
||||
continue;
|
||||
V v = _transformer.transform(t);
|
||||
if (!_excludeNulls || (v != null))
|
||||
listValues.add(v);
|
||||
}
|
||||
return listValues;
|
||||
}
|
||||
|
||||
public static <T, V> List<V> transform(Collection<T> _coll, ITransformer<? super T, V> _transformer, boolean _excludeNulls) {
|
||||
if ((_coll == null) || (_transformer == null))
|
||||
return new ArrayList<>();
|
||||
List<V> listValues = new ArrayList<>(_coll.size());
|
||||
for (T t : _coll) {
|
||||
V v = _transformer.transform(t);
|
||||
if (!_excludeNulls || (v != null))
|
||||
listValues.add(v);
|
||||
}
|
||||
return listValues;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T, V> V[] transform(T[] _coll, ITransformer<? super T, V> _transformer, Class<V> _destType) {
|
||||
V[] ret = (V[])Array.newInstance(_destType, size(_coll));
|
||||
for (int i=0; i < size(_coll); i++) {
|
||||
ret[i] = _transformer.transform(_coll[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static <T, V> Map<V, T> transformToMap(Collection<T> _coll, ITransformer<? super T, V> _transformer) {
|
||||
Map<V, T> mapValues = new HashMap<>();
|
||||
if ((_coll == null) || (_transformer == null))
|
||||
return mapValues;
|
||||
for (T t : _coll) {
|
||||
V v = _transformer.transform(t);
|
||||
if (v != null)
|
||||
mapValues.put(v, t);
|
||||
}
|
||||
return mapValues;
|
||||
}
|
||||
|
||||
public static <T, V, U> Map<V, U> transformToMap(Collection<T> _coll, ITransformer<? super T, V> _keyTrans, ITransformer<? super T, U> _valTrans) {
|
||||
Map<V, U> mapValues = new HashMap<>();
|
||||
if ((_coll == null) || (_keyTrans == null) || (_valTrans == null))
|
||||
return mapValues;
|
||||
for (T t : _coll) {
|
||||
V v = _keyTrans.transform(t);
|
||||
U u = _valTrans.transform(t);
|
||||
if ((v != null) && (u != null))
|
||||
mapValues.put(v, u);
|
||||
}
|
||||
return mapValues;
|
||||
}
|
||||
|
||||
public static <T, V> Map<V, List<T>> transformToMultiMap(Collection<T> _coll, ITransformer<? super T, V> _transformer) {
|
||||
Map<V, List<T>> mapValues = new HashMap<>();
|
||||
if ((_coll == null) || (_transformer == null))
|
||||
return mapValues;
|
||||
for (T t : _coll) {
|
||||
V v = _transformer.transform(t);
|
||||
if (v != null)
|
||||
addToMultiMap(v, t, mapValues);
|
||||
}
|
||||
return mapValues;
|
||||
}
|
||||
|
||||
public static <T, V, U> Map<V, List<U>> transformToMultiMap(Collection<T> _coll, ITransformer<? super T, V> _keyTrans, ITransformer<? super T, U> _valTrans) {
|
||||
Map<V, List<U>> mapValues = new HashMap<>();
|
||||
if ((_coll == null) || (_keyTrans == null) || (_valTrans == null))
|
||||
return mapValues;
|
||||
for (T t : _coll) {
|
||||
V v = _keyTrans.transform(t);
|
||||
U u = _valTrans.transform(t);
|
||||
if ((v != null) && (u != null))
|
||||
addToMultiMap(v, u, mapValues);
|
||||
}
|
||||
return mapValues;
|
||||
}
|
||||
|
||||
public static <T,V> void addAllToMap(Collection<T> _coll, ITransformer<? super T, V> _keyTrans, Map<V, T> _map) {
|
||||
for (T t : makeNotNull(_coll)) {
|
||||
V v = _keyTrans.transform(t);
|
||||
if (v != null)
|
||||
_map.put(v, t);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T,V> void addAllToMultiMap(Collection<T> _coll, ITransformer<? super T, V> _keyTrans, Map<V, List<T>> _map) {
|
||||
for (T t : makeNotNull(_coll)) {
|
||||
V v = _keyTrans.transform(t);
|
||||
if (v != null)
|
||||
addToMultiMap(v, t, _map);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> String transformToCommaSeparated(Collection<T> _coll, ITransformer<? super T, String> _transformer) {
|
||||
return transformToCommaSeparated(_coll, _transformer, false);
|
||||
}
|
||||
|
||||
public static <T> String transformToCommaSeparated(Collection<T> _coll, ITransformer<? super T, String> _transformer, boolean _spaceAfterComma) {
|
||||
if (_transformer == null)
|
||||
return null;
|
||||
return commaSeparated(transform(_coll, _transformer), _spaceAfterComma);
|
||||
}
|
||||
|
||||
public static <T> String transformAndDelimit(Collection<T> _coll, ITransformer<? super T, String> _transformer, String _delimiter) {
|
||||
return transformAndDelimit(_coll, _transformer, _delimiter, false);
|
||||
}
|
||||
|
||||
public static <T> String transformAndDelimit(Collection<T> _coll, ITransformer<? super T, String> _transformer, String _delimiter, boolean _discardEmptyValues) {
|
||||
if (_transformer == null)
|
||||
return null;
|
||||
return delimit(transform(_coll, _transformer), _delimiter, _discardEmptyValues);
|
||||
}
|
||||
|
||||
public static String commaSeparated(Collection<String> _values) {
|
||||
return commaSeparated(_values, false);
|
||||
}
|
||||
|
||||
public static String commaSeparated(Collection<String> _values, boolean _spaceAfterComma) {
|
||||
return delimit(_values, _spaceAfterComma ? ", " : ",");
|
||||
}
|
||||
|
||||
public static String delimit(Collection<String> _values, String _delimiter) {
|
||||
return delimit(_values, _delimiter, false);
|
||||
}
|
||||
|
||||
public static String delimit(Collection<String> _values, String _delimiter, boolean _discardEmptyValues) {
|
||||
StringBuilder builder = null;
|
||||
for (String value : makeNotNull(_values)) {
|
||||
if (_discardEmptyValues && NullUtils.isEmpty(value))
|
||||
continue;
|
||||
if (builder == null)
|
||||
builder = new StringBuilder();
|
||||
else
|
||||
builder.append(_delimiter);
|
||||
builder.append(value);
|
||||
}
|
||||
if (builder != null)
|
||||
return builder.toString();
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<String> undelimit(String _value, String _delimiter) {
|
||||
return undelimit(_value, _delimiter, true);
|
||||
}
|
||||
|
||||
public static List<String> undelimit(String _value, String _delimiter, boolean _discardEmptyValues) {
|
||||
if (_value == null)
|
||||
return new ArrayList<>();
|
||||
return asArrayList(_discardEmptyValues?NullUtils.cleanSplit(_value, _delimiter): _value.split(_delimiter));
|
||||
}
|
||||
|
||||
public static <T, V> Set<V> transformToSet(Collection<T> _coll, ITransformer<T, V> _transformer) {
|
||||
Set<V> setValues = new HashSet<V>();
|
||||
if ((_coll == null) || (_transformer == null))
|
||||
return setValues;
|
||||
for (T t : _coll) {
|
||||
if (t != null) {
|
||||
V v = _transformer.transform(t);
|
||||
if (v != null)
|
||||
setValues.add(v);
|
||||
}
|
||||
}
|
||||
return setValues;
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> T getSmallest(Collection<T> _collObjects)
|
||||
{
|
||||
return getSmallest(_collObjects, new Comparator<T>()
|
||||
{
|
||||
@Override
|
||||
public int compare(T o1, T o2)
|
||||
{
|
||||
return NullUtils.compare(o1, o2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static <T> T getSmallest(Collection<T> _objects, Comparator<T> _comparator)
|
||||
{
|
||||
if (_objects == null)
|
||||
return null;
|
||||
T ret = null;
|
||||
for (T t : _objects)
|
||||
{
|
||||
if (t == null)
|
||||
continue;
|
||||
if ((ret == null) || (_comparator.compare(t, ret) < 0))
|
||||
ret = t;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> List<T> getAllSmallest(Collection<T> _collObjects)
|
||||
{
|
||||
return getAllSmallest(_collObjects, new Comparator<T>()
|
||||
{
|
||||
@Override
|
||||
public int compare(T o1, T o2)
|
||||
{
|
||||
return NullUtils.compare(o1, o2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static <T> List<T> getAllSmallest(Collection<T> _objects, Comparator<T> _comparator)
|
||||
{
|
||||
final List<T> ret = new ArrayList<>();
|
||||
if (_objects == null)
|
||||
return ret;
|
||||
for (T t : _objects) {
|
||||
if (t == null)
|
||||
continue;
|
||||
if (ret.isEmpty())
|
||||
ret.add(t);
|
||||
else {
|
||||
int comp = _comparator.compare(t, CollectionUtils.getFirst(ret));
|
||||
if (comp == 0)
|
||||
ret.add(t);
|
||||
else if (comp < 0) {
|
||||
ret.clear();
|
||||
ret.add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> T getLargest(Collection<T> _collObjects)
|
||||
{
|
||||
return getLargest(_collObjects, new Comparator<T>()
|
||||
{
|
||||
@Override
|
||||
public int compare(T o1, T o2)
|
||||
{
|
||||
return NullUtils.compare(o1, o2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static <T> T getLargest(Collection<T> _objects, Comparator<T> _comparator)
|
||||
{
|
||||
if (_objects == null)
|
||||
return null;
|
||||
T ret = null;
|
||||
for (T t : _objects)
|
||||
{
|
||||
if (t == null)
|
||||
continue;
|
||||
if ((ret == null) || (_comparator.compare(t, ret) > 0))
|
||||
ret = t;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static <T> List<T> getSmallest(Collection<T> _objects, Comparator<T> _comparator, int _count)
|
||||
{
|
||||
return getSmallest(_objects, _comparator, _count, null);
|
||||
}
|
||||
|
||||
public static <T> List<T> getSmallest(Collection<T> _objects, Comparator<T> _comparator, int _count, IFilter<T> _filter)
|
||||
{
|
||||
if (_objects == null)
|
||||
return null;
|
||||
if (_count * 4 > _objects.size())
|
||||
{
|
||||
List<T> items = new ArrayList<T>();
|
||||
for (T t : _objects)
|
||||
{
|
||||
if ((_filter == null) || !_filter.isFiltered(t))
|
||||
items.add(t);
|
||||
}
|
||||
Collections.sort(items, _comparator);
|
||||
return subList(items, 0, _count);
|
||||
}
|
||||
TreeMap<T, List<T>> mapReturn = new TreeMap<>(_comparator);
|
||||
for (T t : _objects)
|
||||
{
|
||||
if ((t == null) || ((_filter != null) && _filter.isFiltered(t)))
|
||||
continue;
|
||||
if (mapReturn.size() < _count)
|
||||
addToMultiMap(t, t, mapReturn);
|
||||
else
|
||||
{
|
||||
Iterator<T> iter = mapReturn.descendingKeySet().iterator();
|
||||
if (_comparator.compare(t, iter.next()) < 0)
|
||||
{
|
||||
iter.remove();
|
||||
addToMultiMap(t, t, mapReturn);
|
||||
}
|
||||
}
|
||||
}
|
||||
List<T> items = new ArrayList<T>(_count);
|
||||
for (List<T> list : mapReturn.values())
|
||||
{
|
||||
items.addAll(list);
|
||||
}
|
||||
return subList(items, 0, _count);
|
||||
}
|
||||
|
||||
public static <T> List<T> subList(List<T> _list, int _fromIndex, int _toIndex) {
|
||||
if ((_list == null) || (_fromIndex > _list.size() - 1))
|
||||
return new ArrayList<T>();
|
||||
return _list.subList(_fromIndex, Math.min(_toIndex, _list.size()));
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> T mostCommon(Collection<T> _collObjects) {
|
||||
return mostCommon(_collObjects, new Comparator<T>() {
|
||||
@Override
|
||||
public int compare(T _o1, T _o2) {
|
||||
return NullUtils.compare(_o1, _o2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static <T> T mostCommon(Collection<T> _collObjects, Comparator<? super T> _comparator) {
|
||||
int iMax = 0;
|
||||
Map<T, AtomicInteger> mapCounts = new TreeMap<T, AtomicInteger>(_comparator);
|
||||
for (T t : makeNotNull(_collObjects)) {
|
||||
AtomicInteger i = mapCounts.get(t);
|
||||
if (i == null) {
|
||||
mapCounts.put(t, new AtomicInteger(1));
|
||||
if (iMax == 0)
|
||||
iMax = 1;
|
||||
} else {
|
||||
if (i.incrementAndGet() > iMax)
|
||||
iMax = i.intValue();
|
||||
}
|
||||
}
|
||||
for (Entry<T, AtomicInteger> e : mapCounts.entrySet()) {
|
||||
if (e.getValue().intValue() == iMax)
|
||||
return e.getKey();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T,V> List<V> getAll(Map<T, V> _map, Collection<T> _keys) {
|
||||
List<V> ret = new ArrayList<>();
|
||||
if (_map == null)
|
||||
return ret;
|
||||
for (T t : makeNotNull(_keys)) {
|
||||
V v = _map.get(t);
|
||||
if (v != null)
|
||||
ret.add(v);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(Collection<Integer> _integers) {
|
||||
if (isEmpty(_integers))
|
||||
return null;
|
||||
ByteBuffer bb = ByteBuffer.allocate(_integers.size() * 4);
|
||||
for (Integer i : _integers) {
|
||||
bb.putInt(i);
|
||||
}
|
||||
return bb.array();
|
||||
}
|
||||
|
||||
public static List<Integer> fromByteArrayOfIntegers(byte[] _btIntegers) {
|
||||
if (length(_btIntegers) > 0) {
|
||||
List<Integer> auxIds = new ArrayList<>(_btIntegers.length / 4);
|
||||
ByteBuffer bb = ByteBuffer.wrap(_btIntegers);
|
||||
while (bb.hasRemaining()) {
|
||||
auxIds.add(bb.getInt());
|
||||
}
|
||||
return auxIds;
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public static int length(byte[] _arr)
|
||||
{
|
||||
if (_arr == null)
|
||||
return 0;
|
||||
return _arr.length;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,658 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public abstract class DateUtils {
|
||||
public static long toLong(Date _dt) {
|
||||
if (_dt == null)
|
||||
return Long.MIN_VALUE;
|
||||
return _dt.getTime();
|
||||
}
|
||||
|
||||
public static Date toDate(long _epochOffset) {
|
||||
if (_epochOffset == Long.MIN_VALUE)
|
||||
return null;
|
||||
return new Date(_epochOffset);
|
||||
}
|
||||
|
||||
public static Date millisecondsFromNow(long _milliseconds) {
|
||||
return new Date(new Date().getTime() + _milliseconds);
|
||||
}
|
||||
|
||||
public static Date secondsFromNow(long _seconds) {
|
||||
return addSeconds(new Date(), _seconds);
|
||||
}
|
||||
|
||||
public static Date minutesFromNow(int _minutes) {
|
||||
return addMinutes(new Date(), _minutes);
|
||||
}
|
||||
|
||||
public static Date hoursFromNow(int _hours) {
|
||||
return addHours(new Date(), _hours);
|
||||
}
|
||||
|
||||
public static Date daysFromNow(int _days) {
|
||||
return addDays(new Date(), _days);
|
||||
}
|
||||
|
||||
public static Date addSeconds(Date _dt, long _seconds) {
|
||||
if (_dt == null)
|
||||
return null;
|
||||
return new Date(_dt.getTime() + _seconds * 1000L);
|
||||
}
|
||||
|
||||
public static Date addMinutes(Date _dt, int _minutes) {
|
||||
if (_dt == null)
|
||||
return null;
|
||||
return new Date(_dt.getTime() + _minutes * 60000L);
|
||||
}
|
||||
|
||||
public static Date addHours(Date _dt, int _hours) {
|
||||
if (_dt == null)
|
||||
return null;
|
||||
return new Date(_dt.getTime() + _hours * 3600000L);
|
||||
}
|
||||
|
||||
public static Date addDays(Date _dt, int _days) {
|
||||
if (_dt == null)
|
||||
return null;
|
||||
return new Date(_dt.getTime() + _days * 86400000L);
|
||||
}
|
||||
|
||||
public static Date addDays(Date _dt, int _days, TimeZone _tz) {
|
||||
if (_dt == null)
|
||||
return null;
|
||||
Calendar cal = toCalendar(_dt, _tz);
|
||||
cal.add(Calendar.DAY_OF_YEAR, _days);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
public static Date addMonths(Date _dt, int _months) {
|
||||
Calendar cal = GregorianCalendar.getInstance();
|
||||
cal.setTime(_dt);
|
||||
cal.add(Calendar.MONTH, _months);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
public static Date addMonths(Date _dt, int _months, TimeZone _tz) {
|
||||
Calendar cal = toCalendar(_dt, _tz);
|
||||
if (cal == null)
|
||||
return null;
|
||||
cal.add(Calendar.MONTH, _months);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
public static Date addMonthKeepDayOfWeek(Date _dt, int _months, TimeZone _tz) {
|
||||
Calendar cal = toCalendar(_dt, _tz);
|
||||
if (cal == null)
|
||||
return null;
|
||||
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
|
||||
int dayOfWeekInMonth = cal.get(Calendar.DAY_OF_WEEK_IN_MONTH);
|
||||
cal.add(Calendar.MONTH, _months);
|
||||
cal.set(Calendar.DAY_OF_WEEK, dayOfWeek);
|
||||
cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, dayOfWeekInMonth);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
public static Date addYears(Date _dt, int _years) {
|
||||
Calendar cal = GregorianCalendar.getInstance();
|
||||
cal.setTime(_dt);
|
||||
cal.add(Calendar.YEAR, _years);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
public static Date addYears(Date _dt, int _years, TimeZone _tz) {
|
||||
Calendar cal = toCalendar(_dt, _tz);
|
||||
if (cal == null)
|
||||
return null;
|
||||
cal.add(Calendar.YEAR, _years);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
public static long diffInMilliseconds(Date _dt1, Date _dt2) {
|
||||
return diffInMilliseconds(_dt1, _dt2, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static long diffInMilliseconds(Date _dt1, Date _dt2, long _defaultIfNull) {
|
||||
if ((_dt1 == null) || (_dt2 == null))
|
||||
return _defaultIfNull;
|
||||
return Math.abs(_dt1.getTime() - _dt2.getTime());
|
||||
}
|
||||
|
||||
public static long diffInSeconds(Date _dt1, Date _dt2) {
|
||||
return diffInSeconds(_dt1, _dt2, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static long diffInSeconds(Date _dt1, Date _dt2, long _defaultIfNull) {
|
||||
if ((_dt1 == null) || (_dt2 == null))
|
||||
return _defaultIfNull;
|
||||
return Math.abs(_dt1.getTime() - _dt2.getTime()) / 1000;
|
||||
}
|
||||
|
||||
public static long diffInMinutes(Date _dt1, Date _dt2) {
|
||||
return diffInMinutes(_dt1, _dt2, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static long diffInMinutes(Date _dt1, Date _dt2, long _defaultIfNull) {
|
||||
if ((_dt1 == null) || (_dt2 == null))
|
||||
return _defaultIfNull;
|
||||
return Math.abs(_dt1.getTime() - _dt2.getTime()) / 60000;
|
||||
}
|
||||
|
||||
public static long diffInHours(Date _dt1, Date _dt2) {
|
||||
return diffInHours(_dt1, _dt2, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static long diffInHours(Date _dt1, Date _dt2, long _defaultIfNull) {
|
||||
if ((_dt1 == null) || (_dt2 == null))
|
||||
return _defaultIfNull;
|
||||
return Math.abs(_dt1.getTime() - _dt2.getTime()) / 3600000;
|
||||
}
|
||||
|
||||
public static boolean isAfter(Date _dt1, Date _dt2) {
|
||||
return isAfter(_dt1, _dt2, false);
|
||||
}
|
||||
|
||||
public static boolean isAfter(Date _dt1, Date _dt2, boolean _defaultIfNull) {
|
||||
if ((_dt1 == null) || (_dt2 == null))
|
||||
return _defaultIfNull;
|
||||
return _dt1.after(_dt2);
|
||||
}
|
||||
|
||||
public static boolean isAfterOrEqualTo(Date _dt1, Date _dt2) {
|
||||
return isAfterOrEqualTo(_dt1, _dt2, false);
|
||||
}
|
||||
|
||||
public static boolean isAfterOrEqualTo(Date _dt1, Date _dt2, boolean _defaultIfNull) {
|
||||
if ((_dt1 == null) || (_dt2 == null))
|
||||
return _defaultIfNull;
|
||||
return _dt1.getTime() >= _dt2.getTime();
|
||||
}
|
||||
|
||||
public static boolean isBefore(Date _dt1, Date _dt2) {
|
||||
return isBefore(_dt1, _dt2, false);
|
||||
}
|
||||
|
||||
public static boolean isBefore(Date _dt1, Date _dt2, boolean _defaultIfNull) {
|
||||
if ((_dt1 == null) || (_dt2 == null))
|
||||
return _defaultIfNull;
|
||||
return _dt1.before(_dt2);
|
||||
}
|
||||
|
||||
public static boolean isBeforeOrEqualTo(Date _dt1, Date _dt2) {
|
||||
return isBeforeOrEqualTo(_dt1, _dt2, false);
|
||||
}
|
||||
|
||||
public static boolean isBeforeOrEqualTo(Date _dt1, Date _dt2, boolean _defaultIfNull) {
|
||||
if ((_dt1 == null) || (_dt2 == null))
|
||||
return _defaultIfNull;
|
||||
return _dt1.getTime() <= _dt2.getTime();
|
||||
}
|
||||
|
||||
public static String getAge(Date _dtDOB) {
|
||||
if (_dtDOB == null)
|
||||
return "";
|
||||
return getAge(_dtDOB, getMidnightBeforeNow());
|
||||
}
|
||||
|
||||
public static String getAge(Date _dtDOB, Date _dtReference) {
|
||||
if (_dtDOB == null)
|
||||
return "";
|
||||
return getAge(_dtDOB.getTime(), _dtReference.getTime());
|
||||
}
|
||||
|
||||
public static String getAge(long _dob, long _reference) {
|
||||
long lAge = _reference - _dob;
|
||||
if (lAge < 24 * 3600000) // less than a day old
|
||||
return String.format("%.2d:%.2d hours", lAge / 3600000, (lAge % 3600000) / 60000);
|
||||
if (lAge < 7 * 24 * 3600000) // less than a week old
|
||||
return String.format("%d days", lAge / (24 * 3600000));
|
||||
Date dtStart = new Date(_dob);
|
||||
Date dtEnd = new Date(_reference);
|
||||
int iMonths = getMonthsBetween(dtStart, dtEnd);
|
||||
if (iMonths == 0)
|
||||
return String.format("%d days", (dtEnd.getTime() - dtStart.getTime()) / (7 * 24 * 3600000));
|
||||
int iYears = getYearsBetween(dtStart, dtEnd);
|
||||
if (iYears < 2)
|
||||
return String.format("%d months", iMonths);
|
||||
return String.format("%d years", iYears);
|
||||
}
|
||||
|
||||
public static int getMonthsBetween(Date _dtStart, Date _dtEnd) {
|
||||
Calendar calStart = getGMTCalendar(_dtStart.getTime());
|
||||
Calendar calEnd = getGMTCalendar(_dtEnd.getTime());
|
||||
int diff = calEnd.get(Calendar.YEAR) * 24 + calEnd.get(Calendar.MONTH) - calStart.get(Calendar.YEAR) * 24 + calStart.get(Calendar.MONTH);
|
||||
if (calStart.get(Calendar.DAY_OF_MONTH) > calEnd.get(Calendar.DAY_OF_MONTH))
|
||||
diff--;
|
||||
return diff;
|
||||
}
|
||||
|
||||
public static int getYearsBetween(Date _dtStart, Date _dtEnd) {
|
||||
Calendar calStart = getGMTCalendar(_dtStart.getTime());
|
||||
Calendar calEnd = getGMTCalendar(_dtEnd.getTime());
|
||||
int diff = calEnd.get(Calendar.YEAR) - calStart.get(Calendar.YEAR);
|
||||
if (isLaterInYear(calStart, calEnd))
|
||||
diff--;
|
||||
return diff;
|
||||
}
|
||||
|
||||
public static int getAgeInYears(Date _dtDOB) {
|
||||
if (_dtDOB == null)
|
||||
return 0;
|
||||
return getAgeInYears(_dtDOB.getTime());
|
||||
}
|
||||
|
||||
public static int getAgeInYears(Date _dtDOB, Date _dtReference) {
|
||||
if (_dtDOB == null)
|
||||
return 0;
|
||||
return getAgeInYears(_dtDOB.getTime(), _dtReference);
|
||||
}
|
||||
|
||||
public static int getAgeInYears(long _lDOB) {
|
||||
return getAgeInYears(_lDOB, getMidnightBeforeNow());
|
||||
}
|
||||
|
||||
public static int getAgeInYears(long _lDOB, Date _dtReference) {
|
||||
if (_lDOB == 0 || _dtReference == null)
|
||||
return 0;
|
||||
Calendar calDOB = getGMTCalendar(_lDOB);
|
||||
Calendar calToday = getGMTCalendar(_dtReference.getTime());
|
||||
|
||||
int age = calToday.get(Calendar.YEAR) - calDOB.get(Calendar.YEAR);
|
||||
if (!isLaterInYear(calToday, calDOB))
|
||||
age--;
|
||||
return age;
|
||||
}
|
||||
|
||||
public static Calendar getGMTCalendar(long _lTime) {
|
||||
return toCalendar(_lTime, TimeZone.getTimeZone("GMT"));
|
||||
}
|
||||
|
||||
private static boolean isLaterInYear(Calendar _cal1, Calendar _cal2) {
|
||||
if (_cal1.get(Calendar.MONTH) > _cal2.get(Calendar.MONTH))
|
||||
return true;
|
||||
return (_cal1.get(Calendar.MONTH) == _cal2.get(Calendar.MONTH)) && (_cal1.get(Calendar.DAY_OF_MONTH) >= _cal2.get(Calendar.DAY_OF_MONTH));
|
||||
}
|
||||
|
||||
public static boolean isSameDay(Date _d1, Date _d2, TimeZone _tz) {
|
||||
return getMidnightBefore(_d1, _tz).equals(getMidnightBefore(_d2, _tz));
|
||||
}
|
||||
|
||||
public static boolean isSameDayOfWeek(Date _d1, Date _d2, TimeZone _tz) {
|
||||
return getDayOfWeek(_d1, _tz) == getDayOfWeek(_d2, _tz);
|
||||
}
|
||||
|
||||
public static boolean isSameTimeOfDay(Date _d1, Date _d2, TimeZone _tz) {
|
||||
Calendar cal1 = toCalendar(_d1, _tz);
|
||||
Calendar cal2 = toCalendar(_d2, _tz);
|
||||
if ((cal1 == null) || (cal2 == null))
|
||||
return false;
|
||||
if (cal1.get(Calendar.HOUR_OF_DAY) != cal2.get(Calendar.HOUR_OF_DAY))
|
||||
return false;
|
||||
if (cal1.get(Calendar.MINUTE) != cal2.get(Calendar.MINUTE))
|
||||
return false;
|
||||
if (cal1.get(Calendar.SECOND) != cal2.get(Calendar.SECOND))
|
||||
return false;
|
||||
return (cal1.get(Calendar.MILLISECOND) == cal2.get(Calendar.MILLISECOND));
|
||||
}
|
||||
|
||||
public static Date getMidnightBeforeNow() {
|
||||
return getMidnightBeforeNow(TimeZone.getTimeZone("GMT"));
|
||||
}
|
||||
|
||||
public static Date getMidnightBeforeNow(TimeZone _tz) {
|
||||
return hoursAfterMidnight(new Date(), 0, _tz);
|
||||
}
|
||||
|
||||
public static Calendar getMidnightBeforeNowCal(TimeZone _tz) {
|
||||
return hoursAfterMidnightCal(new Date(), 0, _tz);
|
||||
}
|
||||
|
||||
public static Date getMidnightBefore(Date _dt, TimeZone _tz) {
|
||||
return hoursAfterMidnight(_dt, 0, _tz);
|
||||
}
|
||||
|
||||
public static Calendar getMidnightBeforeCal(Date _dt, TimeZone _tz) {
|
||||
return hoursAfterMidnightCal(_dt, 0, _tz);
|
||||
}
|
||||
|
||||
public static Date getMidnightAfterNow() {
|
||||
return getMidnightAfterNow(TimeZone.getTimeZone("GMT"));
|
||||
}
|
||||
|
||||
public static Date getMidnightAfterNow(TimeZone _tz) {
|
||||
return hoursAfterMidnight(new Date(), 24, _tz);
|
||||
}
|
||||
|
||||
public static Calendar getMidnightAfterNowCal(TimeZone _tz) {
|
||||
return hoursAfterMidnightCal(new Date(), 24, _tz);
|
||||
}
|
||||
|
||||
public static Date getMidnightAfter(Date _dt, TimeZone _tz) {
|
||||
return hoursAfterMidnight(_dt, 24, _tz);
|
||||
}
|
||||
|
||||
public static Calendar getMidnightAfterCal(Date _dt, TimeZone _tz) {
|
||||
return hoursAfterMidnightCal(_dt, 24, _tz);
|
||||
}
|
||||
|
||||
public static Date hoursAfterMidnight(Date _dt, int _hours, TimeZone _tz) {
|
||||
return hoursAfterMidnightCal(_dt, _hours, _tz).getTime();
|
||||
}
|
||||
|
||||
public static Calendar hoursAfterMidnightCal(Date _dt, int _hours, TimeZone _tz) {
|
||||
Calendar cal = toCalendar(_dt, _tz);
|
||||
if (cal == null)
|
||||
return null;
|
||||
cal.set(Calendar.HOUR_OF_DAY, _hours);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static boolean isBetween(Date _dt, Date _dtFrom, Date _dtTo) {
|
||||
if (_dt == null)
|
||||
return false;
|
||||
if ((_dtFrom != null) && _dtFrom.after(_dt))
|
||||
return false;
|
||||
return (_dtTo == null) || _dtTo.after(_dt);
|
||||
}
|
||||
|
||||
public static Date setTimeOfDay(Date _date, Date _time, TimeZone _tz) {
|
||||
Calendar date = toCalendar(_date, _tz);
|
||||
Calendar time = toCalendar(_time, _tz);
|
||||
if ((date == null) || (time == null))
|
||||
return null;
|
||||
date.set(Calendar.HOUR_OF_DAY, time.get(Calendar.HOUR_OF_DAY));
|
||||
date.set(Calendar.MINUTE, time.get(Calendar.MINUTE));
|
||||
date.set(Calendar.SECOND, time.get(Calendar.SECOND));
|
||||
date.set(Calendar.MILLISECOND, time.get(Calendar.MILLISECOND));
|
||||
return date.getTime();
|
||||
}
|
||||
|
||||
public static Calendar toCalendar(long _ts, TimeZone _tz) {
|
||||
return toCalendar(new Date(_ts), _tz);
|
||||
}
|
||||
|
||||
public static Calendar toCalendar(Date _date, TimeZone _tz) {
|
||||
if (_date == null)
|
||||
return null;
|
||||
Calendar cal = new GregorianCalendar(_tz);
|
||||
cal.setTime(_date);
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static DateFormat dateFormat(String _format, TimeZone _tz) {
|
||||
SimpleDateFormat format = new SimpleDateFormat(_format);
|
||||
format.setTimeZone(_tz);
|
||||
return format;
|
||||
}
|
||||
|
||||
public static String format(String _format, Date _dt) {
|
||||
return format(_format, TimeZone.getTimeZone("UTC"), _dt);
|
||||
}
|
||||
|
||||
public static String format(String _format, TimeZone _tz, Date _dt) {
|
||||
if (_dt == null)
|
||||
return null;
|
||||
return dateFormat(_format, _tz).format(_dt);
|
||||
}
|
||||
|
||||
public static Date parse(String _format, String _date) {
|
||||
return parse(_format, TimeZone.getTimeZone("UTC"), _date);
|
||||
}
|
||||
|
||||
public static Date parse(String _format, TimeZone _tz, String _date) {
|
||||
if (NullUtils.isEmpty(_date))
|
||||
return null;
|
||||
try {
|
||||
return dateFormat(_format, _tz).parse(_date);
|
||||
}
|
||||
catch (Exception _e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Date date(int _month, int _day, int _year, TimeZone _tz) {
|
||||
return date(_month, _day, _year, 0, 0, 0, 0, _tz);
|
||||
}
|
||||
|
||||
public static Date date(int _month, int _day, int _year, int _hour, int _minutes, int _seconds, int _ms, TimeZone _tz) {
|
||||
Calendar cal = GregorianCalendar.getInstance(_tz);
|
||||
cal.set(Calendar.YEAR, _year);
|
||||
cal.set(Calendar.MONTH, _month - 1);
|
||||
cal.set(Calendar.DAY_OF_MONTH, _day);
|
||||
cal.set(Calendar.HOUR_OF_DAY, _hour);
|
||||
cal.set(Calendar.MINUTE, _minutes);
|
||||
cal.set(Calendar.SECOND, _seconds);
|
||||
cal.set(Calendar.MILLISECOND, _ms);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
public static int getDayOfWeek(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = toCalendar(_dt, _tz);
|
||||
return cal == null ? 0 : cal.get(Calendar.DAY_OF_WEEK);
|
||||
}
|
||||
|
||||
public static Date setDayOfWeek(Date _dt, TimeZone _tz, int _dayOfWeek) {
|
||||
Calendar cal = toCalendar(_dt, _tz);
|
||||
if (cal == null)
|
||||
return null;
|
||||
if ((_dayOfWeek >= Calendar.SUNDAY) && (_dayOfWeek <= Calendar.SATURDAY))
|
||||
cal.set(Calendar.DAY_OF_WEEK, _dayOfWeek);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
public static Date getMidnightBeforeDayOfWeek(Date _dt, TimeZone _tz, int _dayOfWeek) {
|
||||
return getMidnightBefore(setDayOfWeek(_dt, _tz, _dayOfWeek), _tz);
|
||||
}
|
||||
|
||||
public static Date getMidnightAfterDayOfWeek(Date _dt, TimeZone _tz, int _dayOfWeek) {
|
||||
return getMidnightAfter(setDayOfWeek(_dt, _tz, _dayOfWeek), _tz);
|
||||
}
|
||||
|
||||
public static boolean isDstTransitionDay(Date _dt, TimeZone _tz) {
|
||||
Date midnight = getMidnightBefore(_dt, _tz);
|
||||
Calendar cal = toCalendar(midnight, _tz);
|
||||
if (cal == null)
|
||||
return false;
|
||||
cal.set(Calendar.HOUR_OF_DAY, 8);
|
||||
return (cal.getTimeInMillis() - midnight.getTime() != 28800000);
|
||||
}
|
||||
|
||||
public static Date setDayOfWeek(Date _dt, TimeZone _tz, String _dayOfWeek) {
|
||||
Calendar cal = toCalendar(_dt, _tz);
|
||||
if (cal == null)
|
||||
return null;
|
||||
int dayOfWeekInt = 0;
|
||||
switch (_dayOfWeek) {
|
||||
case "Sunday":
|
||||
dayOfWeekInt = Calendar.SUNDAY;
|
||||
break;
|
||||
case "Monday":
|
||||
dayOfWeekInt = Calendar.MONDAY;
|
||||
break;
|
||||
case "Tuesday":
|
||||
dayOfWeekInt = Calendar.TUESDAY;
|
||||
break;
|
||||
case "Wednesday":
|
||||
dayOfWeekInt = Calendar.WEDNESDAY;
|
||||
break;
|
||||
case "Thursday":
|
||||
dayOfWeekInt = Calendar.THURSDAY;
|
||||
break;
|
||||
case "Friday":
|
||||
dayOfWeekInt = Calendar.FRIDAY;
|
||||
break;
|
||||
case "Saturday":
|
||||
dayOfWeekInt = Calendar.SATURDAY;
|
||||
break;
|
||||
}
|
||||
if (dayOfWeekInt > 0)
|
||||
cal.set(Calendar.DAY_OF_WEEK, dayOfWeekInt);
|
||||
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
public static Date getStartOfMinute(TimeZone _tz) {
|
||||
return getStartOfMinute(new Date(), _tz);
|
||||
}
|
||||
|
||||
public static Date getStartOfMinute(Date _dt, TimeZone _tz) {
|
||||
return getStartOfMinuteCal(_dt, _tz).getTime();
|
||||
}
|
||||
|
||||
public static Calendar getStartOfMinuteCal(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = toCalendar(_dt, _tz);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static Date getEndOfMinute(TimeZone _tz) {
|
||||
return getEndOfMinute(new Date(), _tz);
|
||||
}
|
||||
|
||||
public static Date getEndOfMinute(Date _dt, TimeZone _tz) {
|
||||
return getEndOfMinuteCal(_dt, _tz).getTime();
|
||||
}
|
||||
|
||||
public static Calendar getEndOfMinuteCal(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = getStartOfMinuteCal(_dt, _tz);
|
||||
cal.add(Calendar.MINUTE, 1);
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static Date getStartOfHour(TimeZone _tz) {
|
||||
return getStartOfHour(new Date(), _tz);
|
||||
}
|
||||
|
||||
public static Date getStartOfHour(Date _dt, TimeZone _tz) {
|
||||
return getStartOfHourCal(_dt, _tz).getTime();
|
||||
}
|
||||
|
||||
public static Calendar getStartOfHourCal(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = toCalendar(_dt, _tz);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static Date getEndOfHour(TimeZone _tz) {
|
||||
return getEndOfHour(new Date(), _tz);
|
||||
}
|
||||
|
||||
public static Date getEndOfHour(Date _dt, TimeZone _tz) {
|
||||
return getEndOfHourCal(_dt, _tz).getTime();
|
||||
}
|
||||
|
||||
public static Calendar getEndOfHourCal(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = getStartOfHourCal(_dt, _tz);
|
||||
cal.add(Calendar.HOUR_OF_DAY, 1);
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static Date getStartOfWeek(TimeZone _tz) {
|
||||
return getStartOfWeek(new Date(), _tz);
|
||||
}
|
||||
|
||||
public static Date getStartOfWeek(Date _dt, TimeZone _tz) {
|
||||
return getStartOfWeekCal(_dt, _tz).getTime();
|
||||
}
|
||||
|
||||
public static Calendar getStartOfWeekCal(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = toCalendar(_dt, _tz);
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static Date getEndOfWeek(TimeZone _tz) {
|
||||
return getEndOfWeek(new Date(), _tz);
|
||||
}
|
||||
|
||||
public static Date getEndOfWeek(Date _dt, TimeZone _tz) {
|
||||
return getEndOfWeekCal(_dt, _tz).getTime();
|
||||
}
|
||||
|
||||
public static Calendar getEndOfWeekCal(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = getStartOfWeekCal(_dt, _tz);
|
||||
cal.add(Calendar.DAY_OF_YEAR, 7);
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static Date getStartOfMonth(TimeZone _tz) {
|
||||
return getStartOfMonth(new Date(), _tz);
|
||||
}
|
||||
|
||||
public static Date getStartOfMonth(Date _dt, TimeZone _tz) {
|
||||
return getStartOfMonthCal(_dt, _tz).getTime();
|
||||
}
|
||||
|
||||
public static Calendar getStartOfMonthCal(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = toCalendar(_dt, _tz);
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
cal.set(Calendar.DAY_OF_MONTH, 1);
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static Date getEndOfMonth(TimeZone _tz) {
|
||||
return getEndOfMonth(new Date(), _tz);
|
||||
}
|
||||
|
||||
public static Date getEndOfMonth(Date _dt, TimeZone _tz) {
|
||||
return getEndOfMonthCal(_dt, _tz).getTime();
|
||||
}
|
||||
|
||||
public static Calendar getEndOfMonthCal(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = getStartOfMonthCal(_dt, _tz);
|
||||
cal.add(Calendar.MONTH, 1);
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static Date getStartOfYear(TimeZone _tz) {
|
||||
return getStartOfYear(new Date(), _tz);
|
||||
}
|
||||
|
||||
public static Date getStartOfYear(Date _dt, TimeZone _tz) {
|
||||
return getStartOfYearCal(_dt, _tz).getTime();
|
||||
}
|
||||
|
||||
public static Calendar getStartOfYearCal(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = toCalendar(_dt, _tz);
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
cal.set(Calendar.DAY_OF_YEAR, 1);
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static Date getEndOfYear(TimeZone _tz) {
|
||||
return getEndOfYear(new Date(), _tz);
|
||||
}
|
||||
|
||||
public static Date getEndOfYear(Date _dt, TimeZone _tz) {
|
||||
return getEndOfYearCal(_dt, _tz).getTime();
|
||||
}
|
||||
|
||||
public static Calendar getEndOfYearCal(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = getStartOfYearCal(_dt, _tz);
|
||||
cal.add(Calendar.YEAR, 1);
|
||||
return cal;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import com.lanternsoftware.util.tracing.TraceLog;
|
||||
import com.lanternsoftware.util.tracing.TraceTags;
|
||||
import com.lanternsoftware.util.tracing.TracerConfig;
|
||||
import com.lanternsoftware.util.tracing.ITracer;
|
||||
import com.lanternsoftware.util.tracing.TraceContext;
|
||||
import com.lanternsoftware.util.tracing.TraceDuration;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class DebugTimer {
|
||||
private final Logger LOG;
|
||||
private final String name;
|
||||
private final TraceContext context;
|
||||
private Date start;
|
||||
private TraceDuration duration;
|
||||
private TraceTags tags;
|
||||
private List<TraceLog> logs;
|
||||
private final boolean suppressLocalLogs;
|
||||
|
||||
private static ITracer tracer = null;
|
||||
private static TracerConfig config;
|
||||
private static final ThreadLocal<TraceContext> traceContexts = new ThreadLocal<>();
|
||||
|
||||
public DebugTimer(String _name) {
|
||||
this(null, _name, null, false);
|
||||
}
|
||||
|
||||
public DebugTimer(TraceContext _parent, String _name) {
|
||||
this(_parent, _name, null, false);
|
||||
}
|
||||
|
||||
public DebugTimer(String _name, Logger _log) {
|
||||
this(null, _name, _log, false);
|
||||
}
|
||||
|
||||
public DebugTimer(String _context, String _name) {
|
||||
this(TraceContext.deserialize(_context), _name, null, false);
|
||||
}
|
||||
|
||||
public DebugTimer(String _context, String _name, Logger _log) {
|
||||
this(TraceContext.deserialize(_context), _name, _log, false);
|
||||
}
|
||||
|
||||
public DebugTimer(TraceContext _parent, String _name, Logger _log) {
|
||||
this(_parent, _name, _log, false);
|
||||
}
|
||||
|
||||
public DebugTimer(TraceContext _parent, String _name, Logger _log, boolean _suppressLocalLogs) {
|
||||
TraceContext parent = _parent;
|
||||
name = _name;
|
||||
LOG = _log;
|
||||
suppressLocalLogs = _suppressLocalLogs;
|
||||
start = new Date();
|
||||
if ((parent == null) && (config != null) && config.isUseThreadContext()) {
|
||||
parent = traceContexts.get();
|
||||
traceContexts.set(getContext());
|
||||
}
|
||||
context = parent;
|
||||
}
|
||||
|
||||
public static void setTracerConfig(TracerConfig _config) {
|
||||
config = _config;
|
||||
if (tracer == null) {
|
||||
Iterator<ITracer> iter = ServiceLoader.load(ITracer.class).iterator();
|
||||
if (iter.hasNext()) {
|
||||
tracer = iter.next();
|
||||
}
|
||||
}
|
||||
tracer.config(config);
|
||||
}
|
||||
|
||||
private ITracer getTracer() {
|
||||
if (config == null)
|
||||
return null;
|
||||
return tracer;
|
||||
}
|
||||
|
||||
public void tag(String _name, String _value) {
|
||||
if (tags == null)
|
||||
tags = TraceTags.tag(_name, _value);
|
||||
else
|
||||
tags.put(_name, _value);
|
||||
}
|
||||
|
||||
public void log(String _event) {
|
||||
if (logs == null)
|
||||
logs = new ArrayList<>();
|
||||
logs.add(new TraceLog(traceDuration().currentTimeOffset(), _event));
|
||||
}
|
||||
|
||||
private TraceDuration traceDuration() {
|
||||
if (duration != null)
|
||||
return duration;
|
||||
ITracer t = getTracer();
|
||||
duration = (t == null)?new TraceDuration(start):t.createDuration(context, name, start);
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (duration == null)
|
||||
start = new Date();
|
||||
traceDuration().start();
|
||||
}
|
||||
|
||||
public TraceContext stop() {
|
||||
traceDuration().stop();
|
||||
return print();
|
||||
}
|
||||
|
||||
public void stopDoNotPrint() {
|
||||
traceDuration().stop();
|
||||
}
|
||||
|
||||
public long duration() {
|
||||
return traceDuration().duration();
|
||||
}
|
||||
|
||||
public TraceContext getContext() {
|
||||
return traceDuration().getContext();
|
||||
}
|
||||
|
||||
public TraceContext print() {
|
||||
StringBuilder b = new StringBuilder(name);
|
||||
b.append(": ");
|
||||
b.append(traceDuration().duration());
|
||||
b.append("ms");
|
||||
TraceContext newContext = traceDuration().getContext();
|
||||
ITracer t = getTracer();
|
||||
if (t != null)
|
||||
t.trace(name, duration, tags, logs);
|
||||
if (!suppressLocalLogs && ((config == null) || !config.isSuppressLocalLog())) {
|
||||
if (LOG != null)
|
||||
LOG.debug(b.toString());
|
||||
else
|
||||
System.out.println(b.toString());
|
||||
}
|
||||
traceContexts.set(context);
|
||||
return newContext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IAggregator<T, V> {
|
||||
List<V> aggregate(T _t);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
public interface IEditor<T> {
|
||||
void edit(T _t);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
public interface IEquals<T> {
|
||||
boolean equals(T _t1, T _t2);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
public interface IFilter<T> {
|
||||
boolean isFiltered(T _t);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
public interface IQualifier<T> {
|
||||
boolean qualifies(T _t);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
public interface ISupplier<T> {
|
||||
T get();
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
public interface ITransformer<T, V> {
|
||||
V transform(T _t);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
public abstract class LanternFiles {
|
||||
public static final String SOURCE_PATH = "C:\\lantern\\wc\\opensource\\LanternPowerMonitor\\";
|
||||
public static final String OPS_PATH = "D:\\zwave\\";
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
public class MapUtils {
|
||||
private static final double RADIUS_EARTH = 6371000;
|
||||
|
||||
/**
|
||||
* @return Distance between the two points in meters
|
||||
*/
|
||||
public static double distance(double _latitude1, double _longitude1, double _latitude2, double _longitude2)
|
||||
{
|
||||
double latitude = Math.toRadians(_latitude2 - _latitude1);
|
||||
double longitude = Math.toRadians(_longitude2 - _longitude1);
|
||||
double a = Math.sin(latitude / 2) * Math.sin(latitude / 2) + Math.cos(Math.toRadians(_latitude1)) * Math.cos(Math.toRadians(_latitude2)) * Math.sin(longitude / 2) * Math.sin(longitude / 2);
|
||||
return RADIUS_EARTH * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Time in ms to travel from one point to another as the crow flies at the given speed
|
||||
*/
|
||||
public static long travelTime(double _latitude1, double _longitude1, double _latitude2, double _longitude2, double _speedMetersPerSecond) {
|
||||
return (long)(1000*distance(_latitude1, _longitude1, _latitude2, _longitude2)/_speedMetersPerSecond);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
public class MemoryStats {
|
||||
public static long size(Object _o) {
|
||||
return size(_o, new HashSet<Integer>());
|
||||
}
|
||||
|
||||
private static long size(Object _o, Set<Integer> _counted) {
|
||||
int hash = System.identityHashCode(_o);
|
||||
if (_counted.contains(hash))
|
||||
return 0;
|
||||
_counted.add(hash);
|
||||
long size = 0;
|
||||
for (Field f : allFields(_o.getClass())) {
|
||||
if (Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers()))
|
||||
continue;
|
||||
f.setAccessible(true);
|
||||
try {
|
||||
Object child = f.get(_o);
|
||||
if (child != null) {
|
||||
if (f.getType().equals(String.class))
|
||||
size += ((String)child).length();
|
||||
else if (f.getType().equals(Date.class))
|
||||
size += 8;
|
||||
else if (f.getType().equals(Double.class) || f.getType().equals(Double.TYPE))
|
||||
size += 8;
|
||||
else if (f.getType().equals(Float.class) || f.getType().equals(Float.TYPE))
|
||||
size += 4;
|
||||
else if (f.getType().equals(Long.class) || f.getType().equals(Long.TYPE))
|
||||
size += 8;
|
||||
else if (f.getType().equals(Integer.class) || f.getType().equals(Integer.TYPE))
|
||||
size += 4;
|
||||
else if (f.getType().equals(Short.class) || f.getType().equals(Short.TYPE))
|
||||
size += 2;
|
||||
else if (f.getType().equals(Byte.class) || f.getType().equals(Byte.TYPE))
|
||||
size += 1;
|
||||
else if (f.getType().equals(Character.class) || f.getType().equals(Character.TYPE))
|
||||
size += 1;
|
||||
else if (f.getType().equals(Boolean.class) || f.getType().equals(Boolean.TYPE))
|
||||
size += 1;
|
||||
else if (f.getType().equals(byte[].class))
|
||||
size += ((byte[])child).length;
|
||||
else if (f.getType().equals(char[].class))
|
||||
size += ((char[])child).length;
|
||||
else if (Collection.class.isAssignableFrom(f.getType())) {
|
||||
for (Object childElement : ((Collection)child)) {
|
||||
size += size(childElement, _counted);
|
||||
}
|
||||
}
|
||||
else if (Map.class.isAssignableFrom(f.getType())) {
|
||||
Set<Entry<?, ?>> entries = ((Map)child).entrySet();
|
||||
for (Entry<?, ?> childElement : entries) {
|
||||
size += size(childElement.getKey(), _counted);
|
||||
size += size(childElement.getValue(), _counted);
|
||||
}
|
||||
}
|
||||
else
|
||||
size += size(child, _counted);
|
||||
}
|
||||
} catch (IllegalAccessException _e) {
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
private static List<Field> allFields(Class _c) {
|
||||
if (_c == null)
|
||||
return Collections.emptyList();
|
||||
List<Field> fields = CollectionUtils.asArrayList(_c.getDeclaredFields());
|
||||
fields.addAll(allFields(_c.getSuperclass()));
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,397 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class NullUtils {
|
||||
public static boolean isNotEqual(Object a, Object b) {
|
||||
return !isEqual(a, b);
|
||||
}
|
||||
|
||||
public static boolean isEqual(Object a, Object b) {
|
||||
if (a != null)
|
||||
return (b != null) && a.equals(b);
|
||||
return (b == null);
|
||||
}
|
||||
|
||||
public static <T> boolean isNotEqual(T a, T b, IEquals<T> _equals) {
|
||||
return !isEqual(a, b, _equals);
|
||||
}
|
||||
|
||||
public static <T> boolean isEqual(T a, T b, IEquals<T> _equals) {
|
||||
if (a != null)
|
||||
return (b != null) && _equals.equals(a, b);
|
||||
return (b == null);
|
||||
}
|
||||
|
||||
public static boolean equalsIgnoreCase(String a, String b) {
|
||||
if (a != null)
|
||||
return a.equalsIgnoreCase(b);
|
||||
return (b == null);
|
||||
}
|
||||
|
||||
public static int length(String _val) {
|
||||
if (_val == null)
|
||||
return 0;
|
||||
return _val.length();
|
||||
}
|
||||
|
||||
public static boolean isEmpty(String _sVal) {
|
||||
return (_sVal == null) || (_sVal.length() == 0);
|
||||
}
|
||||
|
||||
public static boolean isAnyEmpty(String... _vals) {
|
||||
if (_vals == null)
|
||||
return true;
|
||||
for (String val : _vals) {
|
||||
if (isEmpty(val))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isNotEmpty(String _sVal) {
|
||||
return !isEmpty(_sVal);
|
||||
}
|
||||
|
||||
public static boolean isAnyNotEmpty(String... _vals) {
|
||||
if (_vals == null)
|
||||
return false;
|
||||
for (String val : _vals) {
|
||||
if (isNotEmpty(val))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isAnyNull(Object... _o) {
|
||||
if ((_o == null) || (_o.length == 0))
|
||||
return false;
|
||||
for (Object o : _o) {
|
||||
if (o == null)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isOneOf(Object _o, Object... _values) {
|
||||
if ((_o == null) || (_values == null) || (_values.length == 0))
|
||||
return false;
|
||||
for (Object o : _values) {
|
||||
if (_o.equals(o))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String trim(String _val) {
|
||||
if (_val == null)
|
||||
return null;
|
||||
return _val.trim();
|
||||
}
|
||||
|
||||
public static String toString(byte[] _arrBytes) {
|
||||
if (_arrBytes == null)
|
||||
return null;
|
||||
try {
|
||||
return new String(_arrBytes, "UTF-8");
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(String _value) {
|
||||
if (_value == null)
|
||||
return null;
|
||||
try {
|
||||
return _value.getBytes("UTF-8");
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static int toInteger(String _value) {
|
||||
try {
|
||||
return Integer.valueOf(makeNotNull(_value));
|
||||
}
|
||||
catch (NumberFormatException _e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static long toLong(String _value) {
|
||||
try {
|
||||
return Long.valueOf(makeNotNull(_value));
|
||||
}
|
||||
catch (NumberFormatException _e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static double toDouble(String _value) {
|
||||
try {
|
||||
return Double.valueOf(makeNotNull(_value));
|
||||
}
|
||||
catch (NumberFormatException _e) {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
public static float toFloat(String _value) {
|
||||
try {
|
||||
return Float.valueOf(makeNotNull(_value));
|
||||
}
|
||||
catch (NumberFormatException _e) {
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
public static String urlEncode(String _url) {
|
||||
try {
|
||||
return URLEncoder.encode(makeNotNull(_url), "UTF-8");
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
return _url;
|
||||
}
|
||||
}
|
||||
|
||||
public static String urlDecode(String _url) {
|
||||
try {
|
||||
return URLDecoder.decode(makeNotNull(_url), "UTF-8");
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
return _url;
|
||||
}
|
||||
}
|
||||
|
||||
public static String makeNotNull(String _value) {
|
||||
if (_value != null)
|
||||
return _value;
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String after(String _value, String _search) {
|
||||
if (_value == null)
|
||||
return "";
|
||||
int iPos = _value.lastIndexOf(_search);
|
||||
if (iPos < 0)
|
||||
return "";
|
||||
return iPos < _value.length() - _search.length() ? _value.substring(iPos + _search.length()) : "";
|
||||
}
|
||||
|
||||
public static <T extends Enum<T>> T toEnum(Class<T> _enumType, String _sValue) {
|
||||
return toEnum(_enumType, _sValue, null);
|
||||
}
|
||||
|
||||
public static <T extends Enum<T>> T toEnum(Class<T> _enumType, String _sValue, T _default) {
|
||||
T e = null;
|
||||
try {
|
||||
e = Enum.valueOf(_enumType, _sValue);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
return _default;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
public static <T extends Enum<T>> List<T> toEnums(Class<T> _enumType, Collection<String> _values) {
|
||||
List<T> listEnums = new ArrayList<T>();
|
||||
for (String value : CollectionUtils.makeNotNull(_values)) {
|
||||
T e = toEnum(_enumType, value, null);
|
||||
if (e != null)
|
||||
listEnums.add(e);
|
||||
}
|
||||
return listEnums;
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> int compare(T a, T b) {
|
||||
return compare(a, b, true);
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> int compare(T a, T b, boolean _bNullsFirst) {
|
||||
if (a != null) {
|
||||
if (b != null)
|
||||
return a.compareTo(b);
|
||||
else
|
||||
return _bNullsFirst ? 1 : -1;
|
||||
}
|
||||
if (b != null)
|
||||
return _bNullsFirst ? -1 : 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int min(int... values) {
|
||||
int iMin = Integer.MAX_VALUE;
|
||||
for (int value : values) {
|
||||
if (value < iMin)
|
||||
iMin = value;
|
||||
}
|
||||
return iMin;
|
||||
}
|
||||
|
||||
public static String[] cleanSplit(String _sValue, String _sRegex) {
|
||||
if (_sValue == null)
|
||||
return new String[0];
|
||||
return removeEmpties(_sValue.split(_sRegex));
|
||||
}
|
||||
|
||||
public static String[] removeEmpties(String[] _arr) {
|
||||
if (_arr == null)
|
||||
return new String[0];
|
||||
int valid = 0;
|
||||
for (String s : _arr) {
|
||||
if (NullUtils.isNotEmpty(s))
|
||||
valid++;
|
||||
}
|
||||
if (valid == _arr.length)
|
||||
return _arr;
|
||||
String[] ret = new String[valid];
|
||||
valid = 0;
|
||||
for (String s : _arr) {
|
||||
if (NullUtils.isNotEmpty(s))
|
||||
ret[valid++] = s;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static String wrap(String _input, int _lineLength) {
|
||||
return wrap(_input, _lineLength, false);
|
||||
}
|
||||
|
||||
public static String wrap(String _input, int _lineLength, boolean carriageReturn) {
|
||||
if (_input == null)
|
||||
return null;
|
||||
StringBuilder output = new StringBuilder();
|
||||
int i = 0;
|
||||
while (i < _input.length()) {
|
||||
if ((i + _lineLength) > _input.length())
|
||||
output.append(_input.substring(i, _input.length()));
|
||||
else {
|
||||
output.append(_input.substring(i, i + _lineLength));
|
||||
if (carriageReturn)
|
||||
output.append("\r");
|
||||
output.append("\n");
|
||||
}
|
||||
i += _lineLength;
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
public static <T> Class<? extends T> getClass(String _className, Class<T> _superClass) {
|
||||
try {
|
||||
return Class.forName(_className).asSubclass(_superClass);
|
||||
}
|
||||
catch (ClassNotFoundException _e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String terminateWith(String _value, String _suffix) {
|
||||
if (_value == null)
|
||||
return _suffix;
|
||||
if (_value.endsWith(_suffix))
|
||||
return _value;
|
||||
return _value + _suffix;
|
||||
}
|
||||
|
||||
public static String toUpperCase(String _value) {
|
||||
if (_value == null)
|
||||
return null;
|
||||
return _value.toUpperCase();
|
||||
}
|
||||
|
||||
public static String toLowerCase(String _value) {
|
||||
if (_value == null)
|
||||
return null;
|
||||
return _value.toLowerCase();
|
||||
}
|
||||
|
||||
public static Map<String, List<String>> parseQueryParams(String _queryString) {
|
||||
Map<String, List<String>> queryParameters = new HashMap<>();
|
||||
if (isEmpty(_queryString)) {
|
||||
return queryParameters;
|
||||
}
|
||||
String[] parameters = _queryString.split("&");
|
||||
for (String parameter : parameters) {
|
||||
String[] keyValuePair = parameter.split("=");
|
||||
if (keyValuePair.length > 1)
|
||||
CollectionUtils.addToMultiMap(keyValuePair[0], keyValuePair[1], queryParameters);
|
||||
}
|
||||
return queryParameters;
|
||||
}
|
||||
|
||||
public static String toQueryString(Map<String, List<String>> _queryParameters) {
|
||||
StringBuilder queryString = null;
|
||||
for (Entry<String, List<String>> entry : CollectionUtils.makeNotNull(_queryParameters).entrySet()) {
|
||||
for (String param : CollectionUtils.makeNotNull(entry.getValue())) {
|
||||
if (NullUtils.isEmpty(param))
|
||||
continue;
|
||||
if (queryString == null)
|
||||
queryString = new StringBuilder();
|
||||
else
|
||||
queryString.append("&");
|
||||
queryString.append(entry.getKey());
|
||||
queryString.append("=");
|
||||
queryString.append(param);
|
||||
}
|
||||
}
|
||||
return queryString == null?"":queryString.toString();
|
||||
}
|
||||
|
||||
public static String toHex(String _sValue)
|
||||
{
|
||||
return toHex(toByteArray(_sValue));
|
||||
}
|
||||
|
||||
public static String toHexBytes(byte[] _btData)
|
||||
{
|
||||
List<String> bytes = new ArrayList<>(_btData.length);
|
||||
for (byte b : _btData) {
|
||||
bytes.add(String.format("%02X ", b));
|
||||
}
|
||||
return CollectionUtils.delimit(bytes, " ");
|
||||
}
|
||||
|
||||
public static String toHex(byte[] _btData)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new String(Hex.encodeHex(_btData));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] fromHex(String _sValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Hex.decodeHex(makeNotNull(_sValue).toCharArray());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static int bound(int _value, int _min, int _max) {
|
||||
if (_value < _min)
|
||||
return _min;
|
||||
if (_value > _max)
|
||||
return _max;
|
||||
return _value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class ResourceLoader {
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(ResourceLoader.class);
|
||||
|
||||
public static String getStringResource(Class clazz, String _sResourceFileName) {
|
||||
String sReply = null;
|
||||
InputStream stream = null;
|
||||
try {
|
||||
stream = clazz.getResourceAsStream(_sResourceFileName);
|
||||
if (stream != null)
|
||||
sReply = IOUtils.toString(stream);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Failed to load resource: " + _sResourceFileName, e);
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(stream);
|
||||
}
|
||||
return sReply == null ? "" : sReply;
|
||||
}
|
||||
|
||||
public static byte[] getByteArrayResource(Class clazz, String _sResourceFileName) {
|
||||
byte[] btReply = null;
|
||||
InputStream stream = null;
|
||||
try {
|
||||
stream = clazz.getResourceAsStream(_sResourceFileName);
|
||||
if (stream != null)
|
||||
btReply = IOUtils.toByteArray(stream);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error("Failed to load resource: " + _sResourceFileName, e);
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(stream);
|
||||
}
|
||||
return btReply;
|
||||
}
|
||||
|
||||
public static String loadFileAsString(String _fileName) {
|
||||
return loadFileAsString(new File(_fileName));
|
||||
}
|
||||
|
||||
public static String loadFileAsString(File _file) {
|
||||
return NullUtils.toString(loadFile(_file));
|
||||
}
|
||||
|
||||
public static List<String> loadFileLines(String _fileName) {
|
||||
return loadFileLines(new File(_fileName));
|
||||
}
|
||||
|
||||
public static List<String> loadFileLines(File _file) {
|
||||
if ((_file == null) || !_file.exists())
|
||||
return null;
|
||||
FileReader is = null;
|
||||
try {
|
||||
is = new FileReader(_file);
|
||||
BufferedReader reader = new BufferedReader(is);
|
||||
List<String> lines = new ArrayList<>();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
lines.add(line);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
LOG.error("Failed to load file: " + _file.getAbsolutePath(), t);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] loadFile(String _fileName) {
|
||||
return loadFile(new File(_fileName));
|
||||
}
|
||||
|
||||
public static byte[] loadFile(File _file) {
|
||||
if ((_file == null) || !_file.exists())
|
||||
return null;
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = new FileInputStream(_file);
|
||||
return IOUtils.toByteArray(is);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
LOG.error("Failed to load file: " + _file.getAbsolutePath(), t);
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeFile(String _sFile, String _data) {
|
||||
writeFile(_sFile, NullUtils.toByteArray(_data));
|
||||
}
|
||||
|
||||
public static void writeFile(String _sFile, byte[] _btData) {
|
||||
FileOutputStream os = null;
|
||||
try {
|
||||
os = new FileOutputStream(_sFile, false);
|
||||
os.write(_btData);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
LOG.error("Failed to write file: " + _sFile, t);
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(os);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeFileLines(String _sFile, List<String> _lines) {
|
||||
FileOutputStream os = null;
|
||||
try {
|
||||
os = new FileOutputStream(_sFile, false);
|
||||
for (String line : CollectionUtils.makeNotNull(_lines)) {
|
||||
os.write(NullUtils.toByteArray(line));
|
||||
os.write((char)10);
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
LOG.error("Failed to write file: " + _sFile, t);
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(os);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.lanternsoftware.util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class ZipUtils {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ZipUtils.class);
|
||||
|
||||
public static byte[] zip(byte[] _btData) {
|
||||
if (_btData == null)
|
||||
return null;
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
GZIPOutputStream stream = null;
|
||||
try {
|
||||
stream = new GZIPOutputStream(out);
|
||||
stream.write(_btData);
|
||||
IOUtils.closeQuietly(stream);
|
||||
return out.toByteArray();
|
||||
}
|
||||
catch (IOException e) {
|
||||
IOUtils.closeQuietly(stream);
|
||||
LOG.error("Failed to zip data", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] unzip(byte[] _btData) {
|
||||
if ((_btData == null) || (_btData.length == 0))
|
||||
return null;
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(_btData);
|
||||
GZIPInputStream stream = null;
|
||||
try {
|
||||
stream = new GZIPInputStream(in);
|
||||
return IOUtils.toByteArray(stream);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error("Failed to unzip data", e);
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.lanternsoftware.util.concurrency;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public abstract class ConcurrencyUtils
|
||||
{
|
||||
private static final Object m_mutex = new Object();
|
||||
private static Map<String, String> mapMutexes = null;
|
||||
|
||||
public static void sleep(long _lDuration)
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_lDuration);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void wait(Object _object)
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(_object)
|
||||
{
|
||||
_object.wait();
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void wait(Object _object, int _iTimeout)
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(_object)
|
||||
{
|
||||
_object.wait(_iTimeout);
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void notify(Object _object)
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(_object)
|
||||
{
|
||||
_object.notify();
|
||||
}
|
||||
}
|
||||
catch (IllegalMonitorStateException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void notifyAll(Object _object)
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(_object)
|
||||
{
|
||||
_object.notifyAll();
|
||||
}
|
||||
}
|
||||
catch (IllegalMonitorStateException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getMutex(String _sKey)
|
||||
{
|
||||
synchronized (m_mutex)
|
||||
{
|
||||
if (mapMutexes == null)
|
||||
mapMutexes = new HashMap<String, String>();
|
||||
String sMutex = mapMutexes.get(_sKey);
|
||||
if (sMutex != null)
|
||||
return sMutex;
|
||||
mapMutexes.put(_sKey, _sKey);
|
||||
return _sKey;
|
||||
}
|
||||
}
|
||||
|
||||
public static void destroy()
|
||||
{
|
||||
if (mapMutexes != null)
|
||||
{
|
||||
mapMutexes.clear();
|
||||
mapMutexes = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void getAll(Future<?>... _futures)
|
||||
{
|
||||
if (_futures == null)
|
||||
return;
|
||||
getAll(Arrays.asList(_futures));
|
||||
}
|
||||
|
||||
public static void getAll(Collection<Future<?>> _collFutures)
|
||||
{
|
||||
if (_collFutures == null)
|
||||
return;
|
||||
for (Future<?> f : _collFutures)
|
||||
{
|
||||
try
|
||||
{
|
||||
f.get();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.lanternsoftware.util.concurrency;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public abstract class Execution implements Callable<ExecutionResult> {
|
||||
public abstract void run() throws Exception;
|
||||
public final ExecutionResult call(){
|
||||
try {
|
||||
run();
|
||||
}
|
||||
catch (Exception _e) {
|
||||
return new ExecutionResult(_e);
|
||||
}
|
||||
return new ExecutionResult(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.lanternsoftware.util.concurrency;
|
||||
|
||||
public class ExecutionResult {
|
||||
private final Exception e;
|
||||
|
||||
public ExecutionResult(Exception _e) {
|
||||
e = _e;
|
||||
}
|
||||
|
||||
public Exception getException() {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.lanternsoftware.util.concurrency;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
|
||||
public abstract class ExecutionUtil {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ExecutionUtil.class);
|
||||
|
||||
public static void waitForExecution(Collection<Future<ExecutionResult>> futures) throws Exception {
|
||||
Exception e = null;
|
||||
for (Future<ExecutionResult> f : futures) {
|
||||
ExecutionResult result = f.get();
|
||||
if (result.getException() != null)
|
||||
e = result.getException();
|
||||
}
|
||||
if (e != null)
|
||||
throw e;
|
||||
}
|
||||
|
||||
public static void waitForExecution(Logger _logger, Collection<Future<?>> futures) {
|
||||
for (Future<?> f : futures) {
|
||||
try {
|
||||
f.get();
|
||||
}
|
||||
catch (Exception _e) {
|
||||
_logger.error("Exception occurred during execution", _e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void waitForExecution(Future<ExecutionResult>... futures) throws Exception {
|
||||
Exception e = null;
|
||||
for (Future<ExecutionResult> f : futures) {
|
||||
ExecutionResult result = f.get();
|
||||
if (result.getException() != null)
|
||||
e = result.getException();
|
||||
}
|
||||
if (e != null)
|
||||
throw e;
|
||||
}
|
||||
|
||||
public static void waitForExecution(Logger _logger, Future<?>... futures) {
|
||||
for (Future<?> f : futures) {
|
||||
try {
|
||||
f.get();
|
||||
}
|
||||
catch (Exception _e) {
|
||||
_logger.error("Exception occurred during execution", _e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T get(Future<T> _futures) {
|
||||
return CollectionUtils.getFirst(getAll(Collections.singletonList(_futures)));
|
||||
}
|
||||
|
||||
public static <T> List<T> getAll(Future<T>... _futures) {
|
||||
return getAll(Arrays.asList(_futures));
|
||||
}
|
||||
|
||||
public static <T> List<T> getAll(Collection<Future<T>> _futures) {
|
||||
return getAll(_futures, false);
|
||||
}
|
||||
|
||||
public static <T> List<T> getAll(Collection<Future<T>> _futures, boolean _includeNulls) {
|
||||
List<T> ret = new ArrayList<>();
|
||||
for (Future<T> future : CollectionUtils.makeNotNull(_futures)) {
|
||||
try {
|
||||
T t = future.get();
|
||||
if (_includeNulls || (t != null))
|
||||
ret.add(t);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Exception while getting future", e);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.lanternsoftware.util.concurrency;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class ExecutorUtil {
|
||||
public static ThreadPoolExecutor fixedThreadPool(int _threadCount) {
|
||||
ThreadPoolExecutor executor = new ThreadPoolExecutor(_threadCount, _threadCount,60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
|
||||
executor.allowCoreThreadTimeOut(true);
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
package com.lanternsoftware.util.cryptography;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.LongBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
|
||||
public class AESTool {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AESTool.class);
|
||||
|
||||
private final SecretKey key;
|
||||
private final static SecureRandom rng = rng();
|
||||
private final byte[] iv;
|
||||
|
||||
private static SecureRandom rng() {
|
||||
try {
|
||||
SecureRandom rng = SecureRandom.getInstance("SHA1PRNG");
|
||||
rng.generateSeed(16);
|
||||
return rng;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
LOG.error("Failed to initialize SecureRandom with SHA1PRNG", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] randomIV() {
|
||||
return rng.generateSeed(16);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a randomly generated AES secret key
|
||||
*/
|
||||
public static SecretKey generateRandomSecretKey() {
|
||||
try {
|
||||
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
||||
KeySpec spec = new PBEKeySpec(Base64.encodeBase64String(new SecureRandom().generateSeed(32)).toCharArray(), new SecureRandom().generateSeed(32), 65536, 256);
|
||||
SecretKey key = factory.generateSecret(spec);
|
||||
return new SecretKeySpec(key.getEncoded(), "AES");
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to generate a random AES secret key", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void printRandomSecretKey() {
|
||||
SecretKey key = generateRandomSecretKey();
|
||||
byte[] btKey = key.getEncoded();
|
||||
StringBuilder builder = null;
|
||||
for (long lValue : toLongs(btKey)) {
|
||||
if (builder == null)
|
||||
builder = new StringBuilder("new AESTool(");
|
||||
else
|
||||
builder.append(",");
|
||||
builder.append(lValue);
|
||||
builder.append("L");
|
||||
}
|
||||
builder.append(");");
|
||||
System.out.println(builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _btKey the encoded form of a {@link SecretKey} object. See the {@link SecretKey#getEncoded()} method.
|
||||
*/
|
||||
public AESTool(byte[] _btKey) {
|
||||
this(new SecretKeySpec(_btKey, "AES"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _btKey the encoded form of a {@link SecretKey} object. See the {@link SecretKey#getEncoded()} method.
|
||||
* @param _iv the initialization vector to use. If this is set, every call of encrypt for a given input will produce the same output. If null is passed, every call of encrypt for a given input will generate a random IV and the output will be different each time (recommended).
|
||||
*/
|
||||
public AESTool(byte[] _btKey, byte[] _iv) {
|
||||
this(new SecretKeySpec(_btKey, "AES"), _iv);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _arrKey the encoded form of a {@link SecretKey} object converted to an array of long values using the {@link AESTool#toLongs(byte[])} method. See the {@link SecretKey#getEncoded()} method.
|
||||
*/
|
||||
public AESTool(long... _arrKey) {
|
||||
this(new SecretKeySpec(toByteArray(_arrKey), "AES"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _arrKey the encoded form of a {@link SecretKey} object converted to an array of long values using the {@link AESTool#toLongs(byte[])} method. See the {@link SecretKey#getEncoded()} method.
|
||||
* @param _iv the initialization vector to use. If this is set, every call of encrypt for a given input will produce the same output. If null is passed, every call of encrypt for a given input will generate a random IV and the output will be different each time (recommended).
|
||||
*/
|
||||
public AESTool(byte[] _iv, long... _arrKey) {
|
||||
this(new SecretKeySpec(toByteArray(_arrKey), "AES"), _iv);
|
||||
}
|
||||
|
||||
public AESTool(SecretKey _key) {
|
||||
this(_key, null);
|
||||
}
|
||||
|
||||
public AESTool(SecretKey _key, byte[] _iv) {
|
||||
key = _key;
|
||||
if ((_iv != null) && (_iv.length != 16))
|
||||
throw new RuntimeException("Initialization Vector must be null or exactly 16 bytes in length");
|
||||
iv = _iv;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _data a string to be encrypted with this tool's secret key
|
||||
* @return the encrypted data as a base64 encoded string
|
||||
*/
|
||||
public String encryptToBase64(String _data) {
|
||||
return encryptToBase64(toByteArray(_data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _btData the binary data to be encrypted with this tool's secret key
|
||||
* @return the encrypted data as a base64 encoded string
|
||||
*/
|
||||
public String encryptToBase64(byte[] _btData) {
|
||||
if (_btData == null)
|
||||
return null;
|
||||
return Base64.encodeBase64String(encrypt(_btData));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _data a string to be encrypted with this tool's secret key
|
||||
* @return the encrypted data as a url safe base64 encoded string
|
||||
*/
|
||||
public String encryptToUrlSafeBase64(String _data) {
|
||||
return encryptToUrlSafeBase64(toByteArray(_data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _btData the binary data to be encrypted with this tool's secret key
|
||||
* @return the encrypted data as a url safe base64 encoded string
|
||||
*/
|
||||
public String encryptToUrlSafeBase64(byte[] _btData) {
|
||||
if (_btData == null)
|
||||
return null;
|
||||
return Base64.encodeBase64URLSafeString(encrypt(_btData));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _data a string to be encrypted with this tool's secret key
|
||||
* @return the encrypted data in binary form
|
||||
*/
|
||||
public byte[] encrypt(String _data) {
|
||||
return encrypt(toByteArray(_data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _btData the binary data to be encrypted with this tool's secret key
|
||||
* @return the encrypted data in binary form
|
||||
*/
|
||||
public byte[] encrypt(byte[] _btData) {
|
||||
if (_btData == null)
|
||||
return null;
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
byte[] btIV = (iv != null) ? iv : randomIV();
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(btIV));
|
||||
if (iv != null)
|
||||
return cipher.doFinal(_btData);
|
||||
else {
|
||||
byte[] btSalt = rng.generateSeed(16);
|
||||
return CollectionUtils.merge(btIV, cipher.doFinal(CollectionUtils.merge(btSalt, _btData)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to encrypt data", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _base64 the base64 encoded representation of the aes encrypted byte array to be decrypted with this tool's
|
||||
* secret key
|
||||
* @return the decrypted byte array transformed to a string.
|
||||
*/
|
||||
public String decryptFromBase64ToString(String _base64) {
|
||||
return toString(decryptFromBase64(_base64));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _base64 the base64 encoded representation of the aes encrypted byte array to be decrypted with this tool's
|
||||
* secret key
|
||||
* @return the decrypted byte array
|
||||
*/
|
||||
public byte[] decryptFromBase64(String _base64) {
|
||||
return _base64 == null ? null : decrypt(Base64.decodeBase64(_base64));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _btData the encrypted byte array to be decrypted with this tool's secret key
|
||||
* @return the decrypted byte array transformed to a string
|
||||
*/
|
||||
public String decryptToString(byte[] _btData) {
|
||||
return toString(decrypt(_btData));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _btData the encrypted byte array to be decrypted with this tool's secret key
|
||||
* @return the decrypted byte array
|
||||
*/
|
||||
public byte[] decrypt(byte[] _btData) {
|
||||
if (_btData == null)
|
||||
return null;
|
||||
try {
|
||||
Cipher decipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
if (iv == null) {
|
||||
decipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(Arrays.copyOfRange(_btData, 0, 16)));
|
||||
byte[] btData = decipher.doFinal(Arrays.copyOfRange(_btData, 16, _btData.length));
|
||||
return Arrays.copyOfRange(btData, 16, btData.length);
|
||||
} else {
|
||||
decipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
|
||||
return decipher.doFinal(_btData);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to decrypt data", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _btData a byte array to convert to an array of longs
|
||||
* @return the array of long values that contains the data from the byte array.
|
||||
*/
|
||||
public static long[] toLongs(byte[] _btData) {
|
||||
if (_btData == null)
|
||||
return null;
|
||||
long[] lData = new long[_btData.length / 8];
|
||||
LongBuffer data = ByteBuffer.wrap(_btData).order(ByteOrder.BIG_ENDIAN).asLongBuffer();
|
||||
data.get(lData);
|
||||
return lData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _arrLongs an array of longs to convert into a byte array representing the same data
|
||||
* @return the converted byte array
|
||||
*/
|
||||
public static byte[] toByteArray(long... _arrLongs) {
|
||||
ByteBuffer input = ByteBuffer.allocate(_arrLongs.length * 8).order(ByteOrder.BIG_ENDIAN);
|
||||
for (long lInput : _arrLongs) {
|
||||
input.putLong(lInput);
|
||||
}
|
||||
return input.array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles and logs the missing encoding exception that will never happen.
|
||||
*
|
||||
* @param _btString the UTF-8 encoded representation of a string
|
||||
* @return the String object created from the byte array
|
||||
*/
|
||||
public static String toString(byte[] _btString) {
|
||||
if (_btString == null)
|
||||
return null;
|
||||
return new String(_btString, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles and logs the missing encoding exception that will never happen.
|
||||
*
|
||||
* @param _value the string to turn into a byte array
|
||||
* @return the UTF-8 encoded byte array representation of the string
|
||||
*/
|
||||
public static byte[] toByteArray(String _value) {
|
||||
if (_value == null)
|
||||
return null;
|
||||
return _value.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
package com.lanternsoftware.util.cryptography;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.KeyStore;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.RSAPrivateKeySpec;
|
||||
import java.security.spec.RSAPublicKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
|
||||
public abstract class RSAUtils {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(RSAUtils.class);
|
||||
|
||||
public static KeyPair generateRandomRSAKeyPair() {
|
||||
try {
|
||||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||
keyPairGenerator.initialize(2048);
|
||||
return keyPairGenerator.genKeyPair();
|
||||
}
|
||||
catch (NoSuchAlgorithmException _e) {
|
||||
LOG.error("Failed to generate RSA key pair", _e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String toString(RSAPrivateKey _key) {
|
||||
if (_key == null)
|
||||
return null;
|
||||
StringBuilder b = new StringBuilder(Base64.encodeBase64String(_key.getModulus().toByteArray()));
|
||||
b.append(",");
|
||||
b.append(Base64.encodeBase64String(_key.getPrivateExponent().toByteArray()));
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public static String toString(RSAPublicKey _key) {
|
||||
if (_key == null)
|
||||
return null;
|
||||
StringBuilder b = new StringBuilder(Base64.encodeBase64String(_key.getModulus().toByteArray()));
|
||||
b.append(",");
|
||||
b.append(Base64.encodeBase64String(_key.getPublicExponent().toByteArray()));
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public static String toPEM(RSAPublicKey _key) {
|
||||
StringBuilder pem = new StringBuilder("-----BEGIN PUBLIC KEY-----\r\n");
|
||||
pem.append(NullUtils.wrap(Base64.encodeBase64String(_key.getEncoded()), 64, true));
|
||||
pem.append("\r\n-----END PUBLIC KEY-----");
|
||||
return pem.toString();
|
||||
}
|
||||
|
||||
public static String toPEM(Certificate _cert) {
|
||||
try {
|
||||
StringBuilder pem = new StringBuilder("-----BEGIN CERTIFICATE-----\r\n");
|
||||
pem.append(NullUtils.wrap(Base64.encodeBase64String(_cert.getEncoded()), 64, true));
|
||||
pem.append("\r\n-----END CERTIFICATE-----");
|
||||
return pem.toString();
|
||||
} catch (CertificateEncodingException _e) {
|
||||
LOG.error("Failed to generate certificate PEM", _e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String toPEM(RSAPrivateKey _key) {
|
||||
StringBuilder pem = new StringBuilder("-----BEGIN RSA PRIVATE KEY-----\r\n");
|
||||
pem.append(NullUtils.wrap(Base64.encodeBase64String(_key.getEncoded()), 64, true));
|
||||
pem.append("\r\n-----END RSA PRIVATE KEY-----");
|
||||
return pem.toString();
|
||||
}
|
||||
|
||||
public static RSAPrivateKey toPrivateKey(String _privateKey64) {
|
||||
try {
|
||||
String[] parts = NullUtils.makeNotNull(_privateKey64).split(",");
|
||||
if (CollectionUtils.size(parts) == 2) {
|
||||
KeyFactory fact = KeyFactory.getInstance("RSA");
|
||||
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(new BigInteger(Base64.decodeBase64(parts[0])), new BigInteger(Base64.decodeBase64(parts[1])));
|
||||
return (RSAPrivateKey) fact.generatePrivate(keySpec);
|
||||
}
|
||||
}
|
||||
catch (Exception _e) {
|
||||
LOG.error("Failed to generate RSA private key", _e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static RSAPublicKey toPublicKey(String _publicKey64) {
|
||||
try {
|
||||
String[] parts = NullUtils.makeNotNull(_publicKey64).split(",");
|
||||
if (CollectionUtils.size(parts) == 2) {
|
||||
KeyFactory fact = KeyFactory.getInstance("RSA");
|
||||
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(new BigInteger(Base64.decodeBase64(parts[0])), new BigInteger(Base64.decodeBase64(parts[1])));
|
||||
return (RSAPublicKey) fact.generatePublic(keySpec);
|
||||
}
|
||||
}
|
||||
catch (Exception _e) {
|
||||
LOG.error("Failed to generate RSA public key", _e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static RSAPublicKey fromPEMtoPublicKey(String _pem) {
|
||||
if (_pem == null)
|
||||
return null;
|
||||
String pem = _pem.replaceAll("(-+BEGIN PUBLIC KEY-+|-+END PUBLIC KEY-+|\\r|\\n)", "");
|
||||
X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decodeBase64(pem));
|
||||
try {
|
||||
KeyFactory fact = KeyFactory.getInstance("RSA");
|
||||
return (RSAPublicKey) fact.generatePublic(spec);
|
||||
}
|
||||
catch (Exception _e) {
|
||||
LOG.error("Failed to generate RSA public key", _e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Certificate fromPEMtoCertificate(String _pem) {
|
||||
String pem = _pem.replaceAll("(-+BEGIN CERTIFICATE-+|-+END CERTIFICATE-+|\\r|\\n)", "");
|
||||
ByteArrayInputStream is = null;
|
||||
try {
|
||||
is = new ByteArrayInputStream(Base64.decodeBase64(pem));
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
return cf.generateCertificate(is);
|
||||
}
|
||||
catch (Exception _e) {
|
||||
LOG.error("Failed to generate RSA certificate", _e);
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
}
|
||||
|
||||
public static Certificate loadCert(String _keystoreFileName, String _keystorePassword, String _certAlias) {
|
||||
return loadCert(loadKeystore(_keystoreFileName, _keystorePassword), _certAlias);
|
||||
}
|
||||
|
||||
public static Certificate loadCert(InputStream _is, String _keystorePassword, String _certAlias) {
|
||||
return loadCert(loadKeystore(_is, _keystorePassword), _certAlias);
|
||||
}
|
||||
|
||||
public static Certificate loadCert(KeyStore _keystore, String _certAlias) {
|
||||
try {
|
||||
return _keystore.getCertificate(_certAlias);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Failed to load certificate {}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static PrivateKey loadPrivateKey(String _keystoreFileName, String _password, String _certAlias) {
|
||||
return loadPrivateKey(_keystoreFileName, _password, _password, _certAlias);
|
||||
}
|
||||
|
||||
public static PrivateKey loadPrivateKey(InputStream _is, String _password, String _certAlias) {
|
||||
return loadPrivateKey(_is, _password, _password, _certAlias);
|
||||
}
|
||||
|
||||
public static PrivateKey loadPrivateKey(String _keystoreFileName, String _keystorePassword, String _certPassword, String _certAlias) {
|
||||
return getPrivateKey(loadKeystore(_keystoreFileName, _keystorePassword), _certPassword, _certAlias);
|
||||
}
|
||||
|
||||
public static PrivateKey loadPrivateKey(InputStream _is, String _keystorePassword, String _certPassword, String _certAlias) {
|
||||
return getPrivateKey(loadKeystore(_is, _keystorePassword), _certPassword, _certAlias);
|
||||
}
|
||||
|
||||
public static PrivateKey getPrivateKey(KeyStore _keystore, String _certPassword, String _certAlias) {
|
||||
try {
|
||||
return (PrivateKey) _keystore.getKey(_certAlias, _certPassword.toCharArray());
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Failed to load key: {}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static KeyStore loadKeystore(String _keystoreFileName, String _keystorePassword) {
|
||||
try {
|
||||
return loadKeystore(new FileInputStream(_keystoreFileName), _keystorePassword);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Failed to load keystore: {}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static KeyStore loadKeystore(InputStream _is, String _keystorePassword) {
|
||||
try {
|
||||
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keystore.load(_is, _keystorePassword.toCharArray());
|
||||
return keystore;
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Failed to load keystore: {}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(_is);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.lanternsoftware.util.csv;
|
||||
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CSV {
|
||||
public final int columns;
|
||||
public final int rows;
|
||||
|
||||
private final List<String> header;
|
||||
private final List<CSVCell[]> data;
|
||||
|
||||
public CSV() {
|
||||
this(null, null, 0);
|
||||
}
|
||||
|
||||
public CSV(List<String> _header, List<List<String>> _data, int _columnCount) {
|
||||
header = _header;
|
||||
if (_data == null) {
|
||||
columns = 0;
|
||||
rows = 0;
|
||||
data = new ArrayList<>(0);
|
||||
}
|
||||
else {
|
||||
rows = _data.size();
|
||||
columns = _columnCount;
|
||||
data = new ArrayList<>(rows);
|
||||
for (List<String> listSourceRow : _data) {
|
||||
CSVCell[] row = new CSVCell[columns];
|
||||
int iCol = 0;
|
||||
for (String sCol : CollectionUtils.makeNotNull(listSourceRow)) {
|
||||
row[iCol] = new CSVCell(sCol, sCol);
|
||||
iCol++;
|
||||
}
|
||||
while (iCol < columns) {
|
||||
row[iCol] = new CSVCell("", "");
|
||||
iCol++;
|
||||
}
|
||||
data.add(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CSV(List<String> _header, List<List<CSVCell>> _data) {
|
||||
header = _header;
|
||||
if (_data == null) {
|
||||
columns = 0;
|
||||
rows = 0;
|
||||
data = new ArrayList<>(0);
|
||||
}
|
||||
else {
|
||||
rows = _data.size();
|
||||
data = new ArrayList<>(rows);
|
||||
int iMaxColumn = CollectionUtils.size(header);
|
||||
for (List<CSVCell> listSourceRow : _data) {
|
||||
iMaxColumn = Math.max(iMaxColumn, CollectionUtils.size(listSourceRow));
|
||||
}
|
||||
columns = iMaxColumn;
|
||||
for (List<CSVCell> listSourceRow : _data) {
|
||||
CSVCell[] row = new CSVCell[columns];
|
||||
int iCol = 0;
|
||||
for (CSVCell cell : CollectionUtils.makeNotNull(listSourceRow)) {
|
||||
row[iCol] = cell == null ? new CSVCell("", "") : cell;
|
||||
iCol++;
|
||||
}
|
||||
while (iCol < columns) {
|
||||
row[iCol] = new CSVCell("", "");
|
||||
iCol++;
|
||||
}
|
||||
data.add(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String cell(int _row, int _column) {
|
||||
if ((_row < 0) || (_row >= rows) || (_column < 0) || (_column >= columns))
|
||||
return "";
|
||||
CSVCell cell = data.get(_row)[_column];
|
||||
if ((cell == null) || (cell.display == null))
|
||||
return "";
|
||||
return cell.display;
|
||||
}
|
||||
|
||||
public List<String> getHeaders() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public String getHeader(int _column) {
|
||||
return NullUtils.makeNotNull(CollectionUtils.get(header, _column));
|
||||
}
|
||||
|
||||
public int getRows() {
|
||||
return rows;
|
||||
}
|
||||
|
||||
public int getColumns() {
|
||||
return columns;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.lanternsoftware.util.csv;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
|
||||
public class CSVCell implements Comparable<CSVCell> {
|
||||
public final String display;
|
||||
public final Object comparable;
|
||||
public final boolean reverseSort;
|
||||
|
||||
public CSVCell(String _display) {
|
||||
this(_display, _display);
|
||||
}
|
||||
|
||||
public CSVCell(String _display, Object _comparable) {
|
||||
this(_display, _comparable, false);
|
||||
}
|
||||
|
||||
public CSVCell(String _display, Object _comparable, boolean _reverseSort) {
|
||||
display = _display;
|
||||
comparable = _comparable;
|
||||
reverseSort = _reverseSort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(CSVCell _o) {
|
||||
if (_o == null)
|
||||
return 1;
|
||||
Object type = (comparable == null) ? _o.comparable : comparable;
|
||||
if (type instanceof String)
|
||||
return NullUtils.compare((String) comparable, (String) _o.comparable, false);
|
||||
if (type instanceof Date)
|
||||
return NullUtils.compare((Date) comparable, (Date) _o.comparable, false);
|
||||
if (type instanceof Integer)
|
||||
return NullUtils.compare((Integer) comparable, (Integer) _o.comparable, false);
|
||||
if (type instanceof Long)
|
||||
return NullUtils.compare((Long) comparable, (Long) _o.comparable, false);
|
||||
if (type instanceof Double)
|
||||
return NullUtils.compare((Double) comparable, (Double) _o.comparable, false);
|
||||
if (type instanceof Boolean)
|
||||
return NullUtils.compare((Boolean) comparable, (Boolean) _o.comparable, false);
|
||||
if (type instanceof Float)
|
||||
return NullUtils.compare((Float) comparable, (Float) _o.comparable, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static List<CSVCell> asList(String... _data) {
|
||||
if (_data == null)
|
||||
return new ArrayList<CSVCell>(0);
|
||||
List<CSVCell> listCells = new ArrayList<CSVCell>(_data.length);
|
||||
for (String data : _data) {
|
||||
listCells.add(new CSVCell(data));
|
||||
}
|
||||
return listCells;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.lanternsoftware.util.csv;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class CSVReader
|
||||
{
|
||||
public static CSV loadCSVFromFile(String _filename)
|
||||
{
|
||||
return loadCSVFromFile(_filename, false);
|
||||
}
|
||||
|
||||
public static CSV loadCSVFromFile(String _filename, boolean _firstRowIsHeader)
|
||||
{
|
||||
FileInputStream is = null;
|
||||
try
|
||||
{
|
||||
int iMaxColumns = 0;
|
||||
List<List<String>> listLines = new LinkedList<List<String>>();
|
||||
is = new FileInputStream(_filename);
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(is));
|
||||
List<String> listHeader = null;
|
||||
List<String> listCurLine = new ArrayList<String>();
|
||||
String sRemainder = null;
|
||||
String sLine = r.readLine();
|
||||
while (sLine != null)
|
||||
{
|
||||
if (sRemainder == null)
|
||||
sRemainder = parseLine(sLine, listCurLine);
|
||||
else
|
||||
sRemainder = parseLine(sRemainder+sLine, listCurLine);
|
||||
if (sRemainder == null)
|
||||
{
|
||||
if (_firstRowIsHeader && (listHeader == null))
|
||||
listHeader = listCurLine;
|
||||
else
|
||||
listLines.add(listCurLine);
|
||||
iMaxColumns = Math.max(iMaxColumns, listCurLine.size());
|
||||
listCurLine = new ArrayList<String>();
|
||||
}
|
||||
sLine = r.readLine();
|
||||
}
|
||||
return new CSV(listHeader, listLines, iMaxColumns);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
t.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
}
|
||||
|
||||
public static CSV parseCSV(String _csv)
|
||||
{
|
||||
return parseCSV(_csv, false);
|
||||
}
|
||||
|
||||
public static CSV parseCSV(String _csv, boolean _bFirstRowIsHeader)
|
||||
{
|
||||
_csv = _csv.replace("\r","");
|
||||
int iMaxColumns = 0;
|
||||
List<List<String>> listLines = new LinkedList<List<String>>();
|
||||
List<String> listHeader = null;
|
||||
List<String> listCurLine = new ArrayList<String>();
|
||||
String sRemainder = null;
|
||||
for (String sLine : _csv.split("\n"))
|
||||
{
|
||||
if (sRemainder == null)
|
||||
sRemainder = parseLine(sLine, listCurLine);
|
||||
else
|
||||
sRemainder = parseLine(sRemainder+sLine, listCurLine);
|
||||
if (sRemainder == null)
|
||||
{
|
||||
if (_bFirstRowIsHeader && (listHeader == null))
|
||||
listHeader = listCurLine;
|
||||
else
|
||||
listLines.add(listCurLine);
|
||||
iMaxColumns = Math.max(iMaxColumns, listCurLine.size());
|
||||
listCurLine = new ArrayList<String>();
|
||||
}
|
||||
}
|
||||
return new CSV(listHeader, listLines, iMaxColumns);
|
||||
}
|
||||
|
||||
public static String parseLine(String _sLine, List<String> _listCurLine)
|
||||
{
|
||||
int i=0;
|
||||
while (i < _sLine.length())
|
||||
{
|
||||
if (_sLine.charAt(i) == '"')
|
||||
{
|
||||
int iPos = _sLine.indexOf("\",",i+1);
|
||||
if (iPos < 0)
|
||||
{
|
||||
if (!_sLine.endsWith("\""))
|
||||
return _sLine.substring(i);
|
||||
else
|
||||
{
|
||||
_listCurLine.add(_sLine.substring(i+1, _sLine.length()-1));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_listCurLine.add(_sLine.substring(i+1, iPos));
|
||||
i = iPos+2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int iPos = _sLine.indexOf(",",i);
|
||||
if (iPos < 0)
|
||||
{
|
||||
_listCurLine.add(_sLine.substring(i));
|
||||
return null;
|
||||
}
|
||||
_listCurLine.add(_sLine.substring(i, iPos));
|
||||
i = iPos+1;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,528 @@
|
||||
package com.lanternsoftware.util.email;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class EmailValidator {
|
||||
private static final String SPECIAL_CHARS = "\\p{Cntrl}\\(\\)<>@,;:'\\\\\\\"\\.\\[\\]";
|
||||
private static final String VALID_CHARS = "[^\\s" + SPECIAL_CHARS + "]";
|
||||
private static final String QUOTED_USER = "(\"[^\"]*\")";
|
||||
private static final String WORD = "((" + VALID_CHARS + "|')+|" + QUOTED_USER + ")";
|
||||
|
||||
private static final String LEGAL_ASCII_REGEX = "^\\p{ASCII}+$";
|
||||
private static final String EMAIL_REGEX = "^\\s*?(.+)@(.+?)\\s*$";
|
||||
private static final String IP_DOMAIN_REGEX = "^\\[(.*)\\]$";
|
||||
private static final String USER_REGEX = "^\\s*" + WORD + "(\\." + WORD + ")*$";
|
||||
|
||||
private static final Pattern MATCH_ASCII_PATTERN = Pattern.compile(LEGAL_ASCII_REGEX);
|
||||
private static final Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_REGEX);
|
||||
private static final Pattern IP_DOMAIN_PATTERN = Pattern.compile(IP_DOMAIN_REGEX);
|
||||
private static final Pattern USER_PATTERN = Pattern.compile(USER_REGEX);
|
||||
|
||||
private static final String IPV4_REGEX = "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
|
||||
private final RegexValidator ipv4Validator = new RegexValidator(IPV4_REGEX);
|
||||
|
||||
private static final String DOMAIN_LABEL_REGEX = "\\p{Alnum}(?>[\\p{Alnum}-]*\\p{Alnum})*";
|
||||
private static final String TOP_LABEL_REGEX = "\\p{Alpha}{2,}";
|
||||
private static final String DOMAIN_NAME_REGEX = "^(?:" + DOMAIN_LABEL_REGEX + "\\.)+" + "(" + TOP_LABEL_REGEX + ")$";
|
||||
|
||||
/** RegexValidator for matching domains. */
|
||||
private final RegexValidator domainRegex = new RegexValidator(DOMAIN_NAME_REGEX);
|
||||
|
||||
private static final String[] INFRASTRUCTURE_TLDS = new String[] { "arpa", "root" };
|
||||
|
||||
private static final String[] GENERIC_TLDS = new String[] { "aero", // air transport industry
|
||||
"asia", // Pan-Asia/Asia Pacific
|
||||
"biz", // businesses
|
||||
"cat", // Catalan linguistic/cultural community
|
||||
"com", // commercial enterprises
|
||||
"coop", // cooperative associations
|
||||
"info", // informational sites
|
||||
"jobs", // Human Resource managers
|
||||
"mobi", // mobile products and services
|
||||
"museum", // museums, surprisingly enough
|
||||
"name", // individuals' sites
|
||||
"net", // internet support infrastructure/business
|
||||
"org", // noncommercial organizations
|
||||
"pro", // credentialed professionals and entities
|
||||
"tel", // contact data for businesses and individuals
|
||||
"travel", // entities in the travel industry
|
||||
"gov", // United States Government
|
||||
"edu", // accredited postsecondary US education entities
|
||||
"mil", // United States Military
|
||||
"int" // organizations established by international treaty
|
||||
};
|
||||
|
||||
private static final String[] COUNTRY_CODE_TLDS = new String[] { "ac", // Ascension Island
|
||||
"ad", // Andorra
|
||||
"ae", // United Arab Emirates
|
||||
"af", // Afghanistan
|
||||
"ag", // Antigua and Barbuda
|
||||
"ai", // Anguilla
|
||||
"al", // Albania
|
||||
"am", // Armenia
|
||||
"an", // Netherlands Antilles
|
||||
"ao", // Angola
|
||||
"aq", // Antarctica
|
||||
"ar", // Argentina
|
||||
"as", // American Samoa
|
||||
"at", // Austria
|
||||
"au", // Australia (includes Ashmore and Cartier Islands and Coral Sea Islands)
|
||||
"aw", // Aruba
|
||||
"ax", // Åland
|
||||
"az", // Azerbaijan
|
||||
"ba", // Bosnia and Herzegovina
|
||||
"bb", // Barbados
|
||||
"bd", // Bangladesh
|
||||
"be", // Belgium
|
||||
"bf", // Burkina Faso
|
||||
"bg", // Bulgaria
|
||||
"bh", // Bahrain
|
||||
"bi", // Burundi
|
||||
"bj", // Benin
|
||||
"bm", // Bermuda
|
||||
"bn", // Brunei Darussalam
|
||||
"bo", // Bolivia
|
||||
"br", // Brazil
|
||||
"bs", // Bahamas
|
||||
"bt", // Bhutan
|
||||
"bv", // Bouvet Island
|
||||
"bw", // Botswana
|
||||
"by", // Belarus
|
||||
"bz", // Belize
|
||||
"ca", // Canada
|
||||
"cc", // Cocos (Keeling) Islands
|
||||
"cd", // Democratic Republic of the Congo (formerly Zaire)
|
||||
"cf", // Central African Republic
|
||||
"cg", // Republic of the Congo
|
||||
"ch", // Switzerland
|
||||
"ci", // Côte d'Ivoire
|
||||
"ck", // Cook Islands
|
||||
"cl", // Chile
|
||||
"cm", // Cameroon
|
||||
"cn", // China, mainland
|
||||
"co", // Colombia
|
||||
"cr", // Costa Rica
|
||||
"cu", // Cuba
|
||||
"cv", // Cape Verde
|
||||
"cx", // Christmas Island
|
||||
"cy", // Cyprus
|
||||
"cz", // Czech Republic
|
||||
"de", // Germany
|
||||
"dj", // Djibouti
|
||||
"dk", // Denmark
|
||||
"dm", // Dominica
|
||||
"do", // Dominican Republic
|
||||
"dz", // Algeria
|
||||
"ec", // Ecuador
|
||||
"ee", // Estonia
|
||||
"eg", // Egypt
|
||||
"er", // Eritrea
|
||||
"es", // Spain
|
||||
"et", // Ethiopia
|
||||
"eu", // European Union
|
||||
"fi", // Finland
|
||||
"fj", // Fiji
|
||||
"fk", // Falkland Islands
|
||||
"fm", // Federated States of Micronesia
|
||||
"fo", // Faroe Islands
|
||||
"fr", // France
|
||||
"ga", // Gabon
|
||||
"gb", // Great Britain (United Kingdom)
|
||||
"gd", // Grenada
|
||||
"ge", // Georgia
|
||||
"gf", // French Guiana
|
||||
"gg", // Guernsey
|
||||
"gh", // Ghana
|
||||
"gi", // Gibraltar
|
||||
"gl", // Greenland
|
||||
"gm", // The Gambia
|
||||
"gn", // Guinea
|
||||
"gp", // Guadeloupe
|
||||
"gq", // Equatorial Guinea
|
||||
"gr", // Greece
|
||||
"gs", // South Georgia and the South Sandwich Islands
|
||||
"gt", // Guatemala
|
||||
"gu", // Guam
|
||||
"gw", // Guinea-Bissau
|
||||
"gy", // Guyana
|
||||
"hk", // Hong Kong
|
||||
"hm", // Heard Island and McDonald Islands
|
||||
"hn", // Honduras
|
||||
"hr", // Croatia (Hrvatska)
|
||||
"ht", // Haiti
|
||||
"hu", // Hungary
|
||||
"id", // Indonesia
|
||||
"ie", // Ireland (Éire)
|
||||
"il", // Israel
|
||||
"im", // Isle of Man
|
||||
"in", // India
|
||||
"io", // British Indian Ocean Territory
|
||||
"iq", // Iraq
|
||||
"ir", // Iran
|
||||
"is", // Iceland
|
||||
"it", // Italy
|
||||
"je", // Jersey
|
||||
"jm", // Jamaica
|
||||
"jo", // Jordan
|
||||
"jp", // Japan
|
||||
"ke", // Kenya
|
||||
"kg", // Kyrgyzstan
|
||||
"kh", // Cambodia (Khmer)
|
||||
"ki", // Kiribati
|
||||
"km", // Comoros
|
||||
"kn", // Saint Kitts and Nevis
|
||||
"kp", // North Korea
|
||||
"kr", // South Korea
|
||||
"kw", // Kuwait
|
||||
"ky", // Cayman Islands
|
||||
"kz", // Kazakhstan
|
||||
"la", // Laos (currently being marketed as the official domain for Los Angeles)
|
||||
"lb", // Lebanon
|
||||
"lc", // Saint Lucia
|
||||
"li", // Liechtenstein
|
||||
"lk", // Sri Lanka
|
||||
"lr", // Liberia
|
||||
"ls", // Lesotho
|
||||
"lt", // Lithuania
|
||||
"lu", // Luxembourg
|
||||
"lv", // Latvia
|
||||
"ly", // Libya
|
||||
"ma", // Morocco
|
||||
"mc", // Monaco
|
||||
"md", // Moldova
|
||||
"me", // Montenegro
|
||||
"mg", // Madagascar
|
||||
"mh", // Marshall Islands
|
||||
"mk", // Republic of Macedonia
|
||||
"ml", // Mali
|
||||
"mm", // Myanmar
|
||||
"mn", // Mongolia
|
||||
"mo", // Macau
|
||||
"mp", // Northern Mariana Islands
|
||||
"mq", // Martinique
|
||||
"mr", // Mauritania
|
||||
"ms", // Montserrat
|
||||
"mt", // Malta
|
||||
"mu", // Mauritius
|
||||
"mv", // Maldives
|
||||
"mw", // Malawi
|
||||
"mx", // Mexico
|
||||
"my", // Malaysia
|
||||
"mz", // Mozambique
|
||||
"na", // Namibia
|
||||
"nc", // New Caledonia
|
||||
"ne", // Niger
|
||||
"nf", // Norfolk Island
|
||||
"ng", // Nigeria
|
||||
"ni", // Nicaragua
|
||||
"nl", // Netherlands
|
||||
"no", // Norway
|
||||
"np", // Nepal
|
||||
"nr", // Nauru
|
||||
"nu", // Niue
|
||||
"nz", // New Zealand
|
||||
"om", // Oman
|
||||
"pa", // Panama
|
||||
"pe", // Peru
|
||||
"pf", // French Polynesia With Clipperton Island
|
||||
"pg", // Papua New Guinea
|
||||
"ph", // Philippines
|
||||
"pk", // Pakistan
|
||||
"pl", // Poland
|
||||
"pm", // Saint-Pierre and Miquelon
|
||||
"pn", // Pitcairn Islands
|
||||
"pr", // Puerto Rico
|
||||
"ps", // Palestinian territories (PA-controlled West Bank and Gaza Strip)
|
||||
"pt", // Portugal
|
||||
"pw", // Palau
|
||||
"py", // Paraguay
|
||||
"qa", // Qatar
|
||||
"re", // Réunion
|
||||
"ro", // Romania
|
||||
"rs", // Serbia
|
||||
"ru", // Russia
|
||||
"rw", // Rwanda
|
||||
"sa", // Saudi Arabia
|
||||
"sb", // Solomon Islands
|
||||
"sc", // Seychelles
|
||||
"sd", // Sudan
|
||||
"se", // Sweden
|
||||
"sg", // Singapore
|
||||
"sh", // Saint Helena
|
||||
"si", // Slovenia
|
||||
"sj", // Svalbard and Jan Mayen Islands Not in use (Norwegian dependencies; see .no)
|
||||
"sk", // Slovakia
|
||||
"sl", // Sierra Leone
|
||||
"sm", // San Marino
|
||||
"sn", // Senegal
|
||||
"so", // Somalia
|
||||
"sr", // Suriname
|
||||
"st", // São Tomé and Príncipe
|
||||
"su", // Soviet Union (deprecated)
|
||||
"sv", // El Salvador
|
||||
"sy", // Syria
|
||||
"sz", // Swaziland
|
||||
"tc", // Turks and Caicos Islands
|
||||
"td", // Chad
|
||||
"tf", // French Southern and Antarctic Lands
|
||||
"tg", // Togo
|
||||
"th", // Thailand
|
||||
"tj", // Tajikistan
|
||||
"tk", // Tokelau
|
||||
"tl", // East Timor (deprecated old code)
|
||||
"tm", // Turkmenistan
|
||||
"tn", // Tunisia
|
||||
"to", // Tonga
|
||||
"tp", // East Timor
|
||||
"tr", // Turkey
|
||||
"tt", // Trinidad and Tobago
|
||||
"tv", // Tuvalu
|
||||
"tw", // Taiwan, Republic of China
|
||||
"tz", // Tanzania
|
||||
"ua", // Ukraine
|
||||
"ug", // Uganda
|
||||
"uk", // United Kingdom
|
||||
"um", // United States Minor Outlying Islands
|
||||
"us", // United States of America
|
||||
"uy", // Uruguay
|
||||
"uz", // Uzbekistan
|
||||
"va", // Vatican City State
|
||||
"vc", // Saint Vincent and the Grenadines
|
||||
"ve", // Venezuela
|
||||
"vg", // British Virgin Islands
|
||||
"vi", // U.S. Virgin Islands
|
||||
"vn", // Vietnam
|
||||
"vu", // Vanuatu
|
||||
"wf", // Wallis and Futuna
|
||||
"ws", // Samoa (formerly Western Samoa)
|
||||
"ye", // Yemen
|
||||
"yt", // Mayotte
|
||||
"yu", // Serbia and Montenegro (originally Yugoslavia)
|
||||
"za", // South Africa
|
||||
"zm", // Zambia
|
||||
"zw", // Zimbabwe
|
||||
};
|
||||
|
||||
private static final List<String> INFRASTRUCTURE_TLD_LIST = Arrays.asList(INFRASTRUCTURE_TLDS);
|
||||
private static final List<String> GENERIC_TLD_LIST = Arrays.asList(GENERIC_TLDS);
|
||||
private static final Set<String> COUNTRY_CODE_TLD_LIST = new HashSet<String>(Arrays.asList(COUNTRY_CODE_TLDS));
|
||||
|
||||
private static final EmailValidator EMAIL_VALIDATOR = new EmailValidator();
|
||||
|
||||
public static EmailValidator getInstance()
|
||||
{
|
||||
return EMAIL_VALIDATOR;
|
||||
}
|
||||
|
||||
public boolean isValid(String email)
|
||||
{
|
||||
if (email == null)
|
||||
return false;
|
||||
|
||||
Matcher asciiMatcher = MATCH_ASCII_PATTERN.matcher(email);
|
||||
if (!asciiMatcher.matches())
|
||||
return false;
|
||||
|
||||
// Check the whole email address structure
|
||||
Matcher emailMatcher = EMAIL_PATTERN.matcher(email);
|
||||
if (!emailMatcher.matches())
|
||||
return false;
|
||||
|
||||
if (email.endsWith("."))
|
||||
return false;
|
||||
|
||||
if (!isValidUser(emailMatcher.group(1)))
|
||||
return false;
|
||||
|
||||
if (!isValidDomain(emailMatcher.group(2)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isValidDomain(String domain)
|
||||
{
|
||||
// see if domain is an IP address in brackets
|
||||
Matcher ipDomainMatcher = IP_DOMAIN_PATTERN.matcher(domain);
|
||||
|
||||
if (ipDomainMatcher.matches())
|
||||
return isValidInet4Address(ipDomainMatcher.group(1));
|
||||
else
|
||||
return isValidTldDomain(domain);
|
||||
}
|
||||
|
||||
protected boolean isValidInet4Address(String inet4Address)
|
||||
{
|
||||
// verify that address conforms to generic IPv4 format
|
||||
String[] groups = ipv4Validator.match(inet4Address);
|
||||
|
||||
if (groups == null)
|
||||
return false;
|
||||
|
||||
// verify that address subgroups are legal
|
||||
for (int i = 0; i <= 3; i++)
|
||||
{
|
||||
String ipSegment = groups[i];
|
||||
if (ipSegment == null || ipSegment.length() <= 0)
|
||||
return false;
|
||||
|
||||
int iIpSegment = 0;
|
||||
|
||||
try
|
||||
{
|
||||
iIpSegment = Integer.parseInt(ipSegment);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (iIpSegment > 255)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isValidUser(String user)
|
||||
{
|
||||
return USER_PATTERN.matcher(user).matches();
|
||||
}
|
||||
|
||||
protected boolean isValidTldDomain(String domain)
|
||||
{
|
||||
String[] groups = domainRegex.match(domain);
|
||||
if (groups != null && groups.length > 0)
|
||||
return isValidTld(groups[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isValidTld(String tld)
|
||||
{
|
||||
return isValidInfrastructureTld(tld) || isValidGenericTld(tld) || isValidCountryCodeTld(tld);
|
||||
}
|
||||
|
||||
protected boolean isValidInfrastructureTld(String iTld)
|
||||
{
|
||||
return INFRASTRUCTURE_TLD_LIST.contains(chompLeadingDot(iTld.toLowerCase()));
|
||||
}
|
||||
|
||||
protected boolean isValidGenericTld(String gTld)
|
||||
{
|
||||
return GENERIC_TLD_LIST.contains(chompLeadingDot(gTld.toLowerCase()));
|
||||
}
|
||||
|
||||
protected boolean isValidCountryCodeTld(String ccTld)
|
||||
{
|
||||
return COUNTRY_CODE_TLD_LIST.contains(chompLeadingDot(ccTld.toLowerCase()));
|
||||
}
|
||||
|
||||
private String chompLeadingDot(String str)
|
||||
{
|
||||
if (str.startsWith("."))
|
||||
return str.substring(1);
|
||||
else
|
||||
return str;
|
||||
}
|
||||
|
||||
private class RegexValidator implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = -8832409930574867162L;
|
||||
|
||||
private final Pattern[] patterns;
|
||||
|
||||
/** Construct a <i>case sensitive</i> validator for a single regular expression.
|
||||
*
|
||||
* @param regex
|
||||
* The regular expression this validator will validate against */
|
||||
public RegexValidator(String regex)
|
||||
{
|
||||
this(regex, true);
|
||||
}
|
||||
|
||||
/** Construct a validator for a single regular expression with the specified case sensitivity.
|
||||
*
|
||||
* @param regex
|
||||
* The regular expression this validator will validate against
|
||||
* @param caseSensitive
|
||||
* when <code>true</code> matching is <i>case sensitive</i>, otherwise matching is <i>case in-sensitive</i> */
|
||||
public RegexValidator(String regex, boolean caseSensitive)
|
||||
{
|
||||
this(new String[] { regex }, caseSensitive);
|
||||
}
|
||||
|
||||
/** Construct a validator that matches any one of the set of regular expressions with the specified case sensitivity.
|
||||
*
|
||||
* @param regexs
|
||||
* The set of regular expressions this validator will validate against
|
||||
* @param caseSensitive
|
||||
* when <code>true</code> matching is <i>case sensitive</i>, otherwise matching is <i>case in-sensitive</i> */
|
||||
public RegexValidator(String[] regexs, boolean caseSensitive)
|
||||
{
|
||||
if (regexs == null || regexs.length == 0)
|
||||
{
|
||||
throw new IllegalArgumentException("Regular expressions are missing");
|
||||
}
|
||||
patterns = new Pattern[regexs.length];
|
||||
int flags = (caseSensitive ? 0 : Pattern.CASE_INSENSITIVE);
|
||||
for (int i = 0; i < regexs.length; i++)
|
||||
{
|
||||
if (regexs[i] == null || regexs[i].length() == 0)
|
||||
{
|
||||
throw new IllegalArgumentException("Regular expression[" + i + "] is missing");
|
||||
}
|
||||
patterns[i] = Pattern.compile(regexs[i], flags);
|
||||
}
|
||||
}
|
||||
|
||||
/** Validate a value against the set of regular expressions returning the array of matched groups.
|
||||
*
|
||||
* @param value
|
||||
* The value to validate.
|
||||
* @return String array of the <i>groups</i> matched if valid or <code>null</code> if invalid */
|
||||
public String[] match(String value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < patterns.length; i++)
|
||||
{
|
||||
Matcher matcher = patterns[i].matcher(value);
|
||||
if (matcher.matches())
|
||||
{
|
||||
int count = matcher.groupCount();
|
||||
String[] groups = new String[count];
|
||||
for (int j = 0; j < count; j++)
|
||||
{
|
||||
groups[j] = matcher.group(j + 1);
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Provide a String representation of this validator.
|
||||
*
|
||||
* @return A String representation of this validator */
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("RegexValidator{");
|
||||
for (int i = 0; i < patterns.length; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
buffer.append(",");
|
||||
}
|
||||
buffer.append(patterns[i].pattern());
|
||||
}
|
||||
buffer.append("}");
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.lanternsoftware.util.hash;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
|
||||
public abstract class AbstractHashTool {
|
||||
private final Logger LOG = LoggerFactory.getLogger(getClass());
|
||||
|
||||
protected final MessageDigest digest;
|
||||
protected final byte[] staticSalt;
|
||||
protected final boolean prependSalt;
|
||||
protected final int iterations;
|
||||
|
||||
public AbstractHashTool(String _algorithm, String _staticSalt, boolean _prependSalt, int _iterationCount) {
|
||||
prependSalt = _prependSalt;
|
||||
MessageDigest digestInstance = null;
|
||||
try {
|
||||
digestInstance = MessageDigest.getInstance(_algorithm);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Failed to create digest: " + _algorithm, e);
|
||||
}
|
||||
digest = digestInstance;
|
||||
staticSalt = NullUtils.toByteArray(_staticSalt);
|
||||
iterations = Math.max(1, _iterationCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _value a string value to hash using the static salt and algorithm of this hash tool
|
||||
* @return the hex encoded hashed value
|
||||
*/
|
||||
public synchronized String hashHex(String _value) {
|
||||
return hashHex(_value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _value a string value to hash using the static salt and algorithm of this hash tool
|
||||
* @param _salt a salt to use for this hash operation along with the static salt of this hash tool
|
||||
* @return the hex encoded hashed value
|
||||
*/
|
||||
public synchronized String hashHex(String _value, String _salt) {
|
||||
return new String(Hex.encodeHex(hash(_value, _salt)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _value a string value to hash using the static salt and algorithm of this hash tool
|
||||
* @return the base64 encoded hashed value
|
||||
*/
|
||||
public synchronized String hash64(String _value) {
|
||||
return hash64(_value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _value a string value to hash using the static salt and algorithm of this hash tool
|
||||
* @param _salt a salt to use for this hash operation along with the static salt of this hash tool
|
||||
* @return the base64 encoded hashed value
|
||||
*/
|
||||
public synchronized String hash64(String _value, String _salt) {
|
||||
return new String(Base64.encodeBase64(hash(_value, _salt)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _value a string value to hash using the static salt and algorithm of this hash tool
|
||||
* @return the hashed value
|
||||
*/
|
||||
public synchronized byte[] hash(String _value) {
|
||||
return hash(_value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _value a string value to hash using the static salt and algorithm of this hash tool
|
||||
* @param _salt a salt to use for this hash operation along with the static salt of this hash tool
|
||||
* @return the hashed value
|
||||
*/
|
||||
public synchronized byte[] hash(String _value, String _salt) {
|
||||
byte[] btValue = NullUtils.toByteArray(_value);
|
||||
byte[] btSalt = NullUtils.toByteArray(_salt);
|
||||
for (int i = 0; i < iterations; i++)
|
||||
btValue = hash(salt(btValue, btSalt));
|
||||
return btValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _value a byte array to hash using the static salt and algorithm of this hash tool
|
||||
* @return the base64 encoded hashed value
|
||||
*/
|
||||
public synchronized String hash64(byte[] _value) {
|
||||
return new String(Base64.encodeBase64(hash(_value)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _value a byte array to hash using the static salt and algorithm of this hash tool
|
||||
* @return the hashed value
|
||||
*/
|
||||
public synchronized byte[] hash(byte[] _value) {
|
||||
return digest.digest(_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _value a byte array to hash using the static salt and algorithm of this hash tool
|
||||
* @param _salt a salt to use for this hash operation along with the static salt of this hash tool
|
||||
* @return the hashed value
|
||||
*/
|
||||
public synchronized byte[] salt(byte[] _value, byte[] _salt) {
|
||||
if (prependSalt)
|
||||
return CollectionUtils.merge(staticSalt, _salt, _value);
|
||||
return CollectionUtils.merge(_value, staticSalt, _salt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.lanternsoftware.util.hash;
|
||||
|
||||
public class MD5HashTool extends AbstractHashTool {
|
||||
/**
|
||||
* Creates an MD5 hash tool with no static salt that performs only one hash iteration
|
||||
*/
|
||||
public MD5HashTool() {
|
||||
this(null, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an MD5 hash tool with the specified static salt that performs only one hash iteration
|
||||
* @param _salt the salt to attach each time a hash is performed with this tool
|
||||
*/
|
||||
public MD5HashTool(String _salt) {
|
||||
this(_salt, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an MD5 hash tool with the specified static salt that performs the specified number of iterations each time a hash is performed
|
||||
* @param _salt the salt to attach each time a hash is performed with this tool
|
||||
* @param _iterations the number of times to hash values
|
||||
*/
|
||||
public MD5HashTool(String _salt, int _iterations) {
|
||||
super("MD5", _salt, false, _iterations);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.lanternsoftware.util.hash;
|
||||
|
||||
public class SHA1HashTool extends AbstractHashTool {
|
||||
/**
|
||||
* Creates an SHA-1 hash tool with no static salt that performs only one hash iteration
|
||||
*/
|
||||
public SHA1HashTool() {
|
||||
this(null, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SHA-1 hash tool with the specified static salt that performs only one hash iteration
|
||||
* @param _salt the salt to attach each time a hash is performed with this tool
|
||||
*/
|
||||
public SHA1HashTool(String _salt) {
|
||||
this(_salt, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SHA-1 hash tool with the specified static salt that performs the specified number of iterations each time a hash is performed
|
||||
* @param _salt the salt to attach each time a hash is performed with this tool
|
||||
* @param _iterations the number of times to hash values
|
||||
*/
|
||||
public SHA1HashTool(String _salt, int _iterations) {
|
||||
super("SHA-1", _salt, true, _iterations);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.lanternsoftware.util.hash;
|
||||
|
||||
public class SHA512HashTool extends AbstractHashTool {
|
||||
/**
|
||||
* Creates an SHA-512 hash tool with no static salt that performs only one hash iteration
|
||||
*/
|
||||
public SHA512HashTool() {
|
||||
this(null, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SHA-512 hash tool with the specified static salt that performs only one hash iteration
|
||||
* @param _salt the salt to attach each time a hash is performed with this tool
|
||||
*/
|
||||
public SHA512HashTool(String _salt) {
|
||||
this(_salt, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SHA-512 hash tool with the specified static salt that performs the specified number of iterations each time a hash is performed
|
||||
* @param _salt the salt to attach each time a hash is performed with this tool
|
||||
* @param _iterations the number of times to hash values
|
||||
*/
|
||||
public SHA512HashTool(String _salt, int _iterations) {
|
||||
super("SHA-512", _salt, true, _iterations);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.lanternsoftware.util.tracing;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface ITracer {
|
||||
void config(TracerConfig _config);
|
||||
TraceDuration createDuration(TraceContext _parent, String _name, Date _start);
|
||||
void trace(String _name, TraceDuration _duration, TraceTags _tags, List<TraceLog> _logs);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.lanternsoftware.util.tracing;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
|
||||
public class TraceContext extends HashMap<String, String> {
|
||||
public String serialize() {
|
||||
StringBuilder s = null;
|
||||
for (Map.Entry<String, String> e : entrySet()) {
|
||||
if (s == null)
|
||||
s = new StringBuilder();
|
||||
else
|
||||
s.append("~");
|
||||
s.append(e.getKey());
|
||||
s.append(".");
|
||||
s.append(e.getValue());
|
||||
}
|
||||
return (s == null)?"":s.toString();
|
||||
}
|
||||
|
||||
public static TraceContext deserialize(String _context) {
|
||||
TraceContext context = new TraceContext();
|
||||
for (String key : NullUtils.cleanSplit(_context, "~")) {
|
||||
String[] parts = NullUtils.cleanSplit(key, "\\.");
|
||||
if (parts.length == 2)
|
||||
context.put(parts[0], parts[1]);
|
||||
}
|
||||
return context.isEmpty()?null:context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.lanternsoftware.util.tracing;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class TraceDuration {
|
||||
private long start;
|
||||
private long curStart;
|
||||
private long duration = 0;
|
||||
|
||||
public TraceDuration(Date _start) {
|
||||
start = curStart = _start.getTime();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
curStart = new Date().getTime();
|
||||
if (duration == 0)
|
||||
start = curStart;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
duration += (new Date().getTime()-curStart);
|
||||
}
|
||||
|
||||
public Date currentTimeOffset() {
|
||||
return new Date(start + duration + (new Date().getTime()-curStart));
|
||||
}
|
||||
|
||||
public long duration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public long end() {
|
||||
return start + duration;
|
||||
}
|
||||
|
||||
public TraceContext getContext() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.lanternsoftware.util.tracing;
|
||||
|
||||
public enum TraceFrequencyType {
|
||||
ALL,
|
||||
PERCENTAGE,
|
||||
MAX_TRACES_PER_SECOND,
|
||||
REMOTE_CONTROLLED
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.lanternsoftware.util.tracing;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class TraceLog {
|
||||
private final Date timeStamp;
|
||||
private final String event;
|
||||
|
||||
public TraceLog(Date _timeStamp, String _event) {
|
||||
timeStamp = _timeStamp;
|
||||
event = _event;
|
||||
}
|
||||
|
||||
public Date getTimeStamp() {
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
public String getEvent() {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.lanternsoftware.util.tracing;
|
||||
|
||||
public interface TraceSpan {
|
||||
void setTag(String _name, String _value);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.lanternsoftware.util.tracing;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class TraceTags extends HashMap<String, String> {
|
||||
public static TraceTags tag(String _name, String _value) {
|
||||
TraceTags tags = new TraceTags();
|
||||
tags.put(_name, _value);
|
||||
return tags;
|
||||
}
|
||||
|
||||
public TraceTags withTag(String _name, String _value) {
|
||||
put(_name, _value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.lanternsoftware.util.tracing;
|
||||
|
||||
public class TracerConfig {
|
||||
private final String appName;
|
||||
private final String endpoint;
|
||||
private final boolean suppressLocalLog;
|
||||
private TraceFrequencyType frequencyType;
|
||||
private double frequency;
|
||||
private boolean useThreadContext = false;
|
||||
|
||||
public TracerConfig(String _appName, String _endpoint) {
|
||||
this(_appName, _endpoint, true);
|
||||
}
|
||||
|
||||
public TracerConfig(String _appName, String _endpoint, boolean _suppressLocalLog) {
|
||||
appName = _appName;
|
||||
endpoint = _endpoint;
|
||||
suppressLocalLog = _suppressLocalLog;
|
||||
frequencyType = TraceFrequencyType.ALL;
|
||||
frequency = 0.0;
|
||||
}
|
||||
|
||||
public TracerConfig withFrequency(TraceFrequencyType _type, double _frequency) {
|
||||
frequencyType = _type;
|
||||
frequency = _frequency;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TracerConfig tracePercentage(double _percentage) {
|
||||
return withFrequency(TraceFrequencyType.PERCENTAGE, _percentage);
|
||||
}
|
||||
|
||||
public TracerConfig traceMaximumPerSecond(int _max) {
|
||||
return withFrequency(TraceFrequencyType.MAX_TRACES_PER_SECOND, _max);
|
||||
}
|
||||
|
||||
public TracerConfig traceRateControlledRemotely() {
|
||||
return withFrequency(TraceFrequencyType.REMOTE_CONTROLLED, 0.0);
|
||||
}
|
||||
|
||||
public TracerConfig traceAll() {
|
||||
return withFrequency(TraceFrequencyType.ALL, 1.0);
|
||||
}
|
||||
|
||||
public TracerConfig useThreadContext(boolean _useThreadContext) {
|
||||
setUseThreadContext(_useThreadContext);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
public String getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
public boolean isSuppressLocalLog() {
|
||||
return suppressLocalLog;
|
||||
}
|
||||
|
||||
public TraceFrequencyType getFrequencyType() {
|
||||
return frequencyType;
|
||||
}
|
||||
|
||||
public double getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public boolean isUseThreadContext() {
|
||||
return useThreadContext;
|
||||
}
|
||||
|
||||
public void setUseThreadContext(boolean _useThreadContext) {
|
||||
useThreadContext = _useThreadContext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.lanternsoftware.util.xml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
|
||||
public class XmlNode
|
||||
{
|
||||
private String content;
|
||||
private final Map<String, String> attributes = new HashMap<String, String>();
|
||||
private final Map<String, List<XmlNode>> children = new HashMap<String, List<XmlNode>>();
|
||||
|
||||
public String getContent()
|
||||
{
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String _content)
|
||||
{
|
||||
content = _content;
|
||||
}
|
||||
|
||||
public Map<String, String> getAttributes()
|
||||
{
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public Map<String, List<XmlNode>> getChildren()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
public void addChild(String _name, XmlNode _node)
|
||||
{
|
||||
CollectionUtils.addToMultiMap(_name, _node, children);
|
||||
}
|
||||
|
||||
public XmlNode getChild(List<String> _path)
|
||||
{
|
||||
if (CollectionUtils.isEmpty(_path))
|
||||
return this;
|
||||
XmlNode node = CollectionUtils.getFirst(children.get(CollectionUtils.getFirst(_path)));
|
||||
if (node == null)
|
||||
return null;
|
||||
return node.getChild(_path.subList(1, _path.size()));
|
||||
}
|
||||
|
||||
public List<XmlNode> getChildren(List<String> _path)
|
||||
{
|
||||
if (CollectionUtils.size(_path) == 1)
|
||||
return CollectionUtils.makeNotNull(children.get(_path.get(0)));
|
||||
List<XmlNode> nodes = new ArrayList<XmlNode>();
|
||||
for (XmlNode node : CollectionUtils.makeNotNull(children.get(CollectionUtils.getFirst(_path))))
|
||||
{
|
||||
nodes.addAll(node.getChildren(_path.subList(1, _path.size())));
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
|
||||
public XmlNode getChild(List<String> _path, String _attributeName, String _attributeValue)
|
||||
{
|
||||
for (XmlNode node : getChildren(_path))
|
||||
{
|
||||
if (NullUtils.isEqual(node.getAttributes().get(_attributeName), _attributeValue))
|
||||
return node;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getChildContent(List<String> _path, String _attributeName, String _attributeValue)
|
||||
{
|
||||
XmlNode node = getChild(_path, _attributeName, _attributeValue);
|
||||
if (node == null)
|
||||
return null;
|
||||
return node.getContent();
|
||||
}
|
||||
|
||||
public String getChildAttribute(List<String> _path, String _attributeName)
|
||||
{
|
||||
XmlNode child = getChild(_path);
|
||||
if (child == null)
|
||||
return null;
|
||||
return child.getAttributes().get(_attributeName);
|
||||
}
|
||||
|
||||
|
||||
public String getChildContent(List<String> _path)
|
||||
{
|
||||
XmlNode node = getChild(_path);
|
||||
if (node == null)
|
||||
return null;
|
||||
return node.getContent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.lanternsoftware.util.xml;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamConstants;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class XmlParser {
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(XmlParser.class);
|
||||
|
||||
public static XmlNode loadXmlFile(String _filePath) {
|
||||
FileInputStream is = null;
|
||||
try {
|
||||
is = new FileInputStream(_filePath);
|
||||
return parseXml(is);
|
||||
}
|
||||
catch (Exception _e) {
|
||||
LOG.error("Failed to load xml file", _e);
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
}
|
||||
|
||||
public static XmlNode parseXml(InputStream _is) {
|
||||
XMLStreamReader reader = null;
|
||||
try {
|
||||
XmlNode node = null;
|
||||
StringBuilder content = null;
|
||||
Stack<XmlNode> stack = new Stack<XmlNode>();
|
||||
reader = XMLInputFactory.newInstance().createXMLStreamReader(_is);
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.next()) {
|
||||
case XMLStreamConstants.START_ELEMENT: {
|
||||
node = new XmlNode();
|
||||
content = new StringBuilder();
|
||||
for (int i = 0; i < reader.getAttributeCount(); i++) {
|
||||
node.getAttributes().put(reader.getAttributeLocalName(i), reader.getAttributeValue(i));
|
||||
}
|
||||
stack.push(node);
|
||||
break;
|
||||
}
|
||||
case XMLStreamConstants.CHARACTERS: {
|
||||
content.append(NullUtils.makeNotNull(reader.getText()));
|
||||
break;
|
||||
}
|
||||
case XMLStreamConstants.END_ELEMENT: {
|
||||
node = stack.pop();
|
||||
if (stack.empty())
|
||||
return node;
|
||||
stack.peek().addChild(reader.getLocalName(), node);
|
||||
if (content != null)
|
||||
node.setContent(content.toString().trim());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception _e) {
|
||||
LOG.error("Failed to parse XML", _e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
reader.close();
|
||||
}
|
||||
catch (XMLStreamException _e) {
|
||||
LOG.error("Failed to close XML stream", _e);
|
||||
}
|
||||
IOUtils.closeQuietly(_is);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user