edu.internet2.middleware.subject.SubjectUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of grouper Show documentation
Show all versions of grouper Show documentation
Internet2 Groups Management Toolkit
/**
* Copyright 2014 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author mchyzer
* $Id: SubjectUtils.java,v 1.5 2009-03-22 02:49:27 mchyzer Exp $
*/
package edu.internet2.middleware.subject;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.MapContext;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
*
*/
public class SubjectUtils {
/**
* string format of dates
*/
public static final String DATE_FORMAT = "yyyyMMdd";
/**
* format including minutes and seconds: yyyy/MM/dd HH:mm:ss
*/
public static final String DATE_MINUTES_SECONDS_FORMAT = "yyyy/MM/dd HH:mm:ss";
/**
* format including minutes and seconds: yyyyMMdd HH:mm:ss
*/
public static final String DATE_MINUTES_SECONDS_NO_SLASH_FORMAT = "yyyyMMdd HH:mm:ss";
/**
* date format, make sure to synchronize
*/
final static SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
/**
* synchronize code that uses this standard formatter for dates with minutes and seconds
*/
final static SimpleDateFormat dateMinutesSecondsFormat = new SimpleDateFormat(
DATE_MINUTES_SECONDS_FORMAT);
/**
* synchronize code that uses this standard formatter for dates with minutes and seconds
*/
final static SimpleDateFormat dateMinutesSecondsNoSlashFormat = new SimpleDateFormat(
DATE_MINUTES_SECONDS_NO_SLASH_FORMAT);
/**
* format on screen of config for milestone: yyyy/MM/dd HH:mm:ss.SSS
*/
public static final String TIMESTAMP_FORMAT = "yyyy/MM/dd HH:mm:ss.SSS";
/**
* start of error parsing messages
*/
private static final String errorStart = "Invalid timestamp, please use any of the formats: "
+ DATE_FORMAT + ", " + TIMESTAMP_FORMAT + ", " + DATE_MINUTES_SECONDS_FORMAT + ": ";
/**
* format on screen of config for milestone: yyyyMMdd HH:mm:ss.SSS
*/
public static final String TIMESTAMP_NO_SLASH_FORMAT = "yyyyMMdd HH:mm:ss.SSS";
/**
* format: yyyy/MM/dd HH:mm:ss.SSS synchronize code that uses this standard formatter for timestamps
*/
final static SimpleDateFormat timestampFormat = new SimpleDateFormat(TIMESTAMP_FORMAT);
/**
* synchronize code that uses this standard formatter for timestamps
*/
final static SimpleDateFormat timestampNoSlashFormat = new SimpleDateFormat(
TIMESTAMP_NO_SLASH_FORMAT);
/**
* special number when a number is not found
*/
public static final int NOT_FOUND = -999999999;
/**
* The name says it all.
*/
public static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
/** logger */
private static Log log = edu.internet2.middleware.grouper.util.GrouperUtil.getLog(SubjectUtils.class);
/**
* cache the properties read from resource
*/
private static Map resourcePropertiesCache = new HashMap();
/**
* create one jexlEngine instance so we can cache expressions
*/
private static final JexlEngine jexlEngine = new JexlEngine();
/**
* settings for jexlEngine
*/
static {
jexlEngine.setCache(512);
jexlEngine.setSilent(false);
}
/**
* do a case-insensitive matching
* @param theEnumClass class of the enum
* @param generic type
*
* @param string
* @param exceptionOnNotFound true if exception should be thrown on not found
* @return the enum or null or exception if not found
* @throws RuntimeException if there is a problem
*/
public static > E enumValueOfIgnoreCase(Class theEnumClass, String string,
boolean exceptionOnNotFound) throws RuntimeException {
return enumValueOfIgnoreCase(theEnumClass, string, exceptionOnNotFound, true);
}
/**
* equalsignorecase
* @param str1
* @param str2
* @return true if the strings are equal ignore case
*/
public static boolean equalsIgnoreCase(String str1, String str2) {
return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);
}
/**
* split a string based on a separator into an array, and trim each entry (see
* the Commons Util trim() for more details)
*
* @param input
* is the delimited input to split and trim
* @param separator
* is what to split on
*
* @return the array of items after split and trimmed, or null if input is null. will be trimmed to empty
*/
public static String[] splitTrim(String input, String separator) {
return splitTrim(input, separator, true);
}
/**
* split a string based on a separator into an array, and trim each entry (see
* the Commons Util trim() for more details)
*
* @param input
* is the delimited input to split and trim
* @param separator
* is what to split on
*
* @return the set of items after split and trimmed, or null if input is null. will be trimmed to empty
*/
public static Set splitTrimToSet(String input, String separator) {
if (isBlank(input)) {
return null;
}
String[] array = splitTrim(input, separator);
return toSet(array);
}
/**
* split a string based on a separator into an array, and trim each entry (see
* the Commons Util trim() for more details)
*
* @param input
* is the delimited input to split and trim
* @param separator
* is what to split on
* @param treatAdjacentSeparatorsAsOne
* @return the array of items after split and trimmed, or null if input is null. will be trimmed to empty
*/
public static String[] splitTrim(String input, String separator, boolean treatAdjacentSeparatorsAsOne) {
if (isBlank(input)) {
return null;
}
//first split
String[] items = treatAdjacentSeparatorsAsOne ? splitByWholeSeparator(input, separator) :
split(input, separator);
//then trim
for (int i = 0; (items != null) && (i < items.length); i++) {
items[i] = trim(items[i]);
}
//return the array
return items;
}
/**
* Splits the provided text into an array, separator string specified.
*
* The separator(s) will not be included in the returned String array.
* Adjacent separators are treated as one separator.
*
* A null
input String returns null
.
* A null
separator splits on whitespace.
*
*
* StringUtils.split(null, *) = null
* StringUtils.split("", *) = []
* StringUtils.split("ab de fg", null) = ["ab", "de", "fg"]
* StringUtils.split("ab de fg", null) = ["ab", "de", "fg"]
* StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
* StringUtils.split("abstemiouslyaeiouyabstemiously", "aeiouy") = ["bst", "m", "sl", "bst", "m", "sl"]
* StringUtils.split("abstemiouslyaeiouyabstemiously", "aeiouy") = ["abstemiously", "abstemiously"]
*
*
* @param str the String to parse, may be null
* @param separator String containing the String to be used as a delimiter,
* null
splits on whitespace
* @return an array of parsed Strings, null
if null String was input
*/
public static String[] splitByWholeSeparator(String str, String separator) {
return splitByWholeSeparator(str, separator, -1);
}
/**
* Splits the provided text into an array, separator string specified.
* Returns a maximum of max
substrings.
*
* The separator(s) will not be included in the returned String array.
* Adjacent separators are treated as one separator.
*
* A null
input String returns null
.
* A null
separator splits on whitespace.
*
*
* StringUtils.splitByWholeSeparator(null, *, *) = null
* StringUtils.splitByWholeSeparator("", *, *) = []
* StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"]
* StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"]
* StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd"]
* StringUtils.splitByWholeSeparator("abstemiouslyaeiouyabstemiously", "aeiouy", 2) = ["bst", "m"]
* StringUtils.splitByWholeSeparator("abstemiouslyaeiouyabstemiously", "aeiouy", 2) = ["abstemiously", "abstemiously"]
*
*
* @param str the String to parse, may be null
* @param separator String containing the String to be used as a delimiter,
* null
splits on whitespace
* @param max the maximum number of elements to include in the returned
* array. A zero or negative value implies no limit.
* @return an array of parsed Strings, null
if null String was input
*/
public static String[] splitByWholeSeparator(String str, String separator, int max) {
if (str == null) {
return null;
}
int len = str.length();
if (len == 0) {
return EMPTY_STRING_ARRAY;
}
if ((separator == null) || ("".equals(separator))) {
// Split on whitespace.
return split(str, null, max);
}
int separatorLength = separator.length();
ArrayList substrings = new ArrayList();
int numberOfSubstrings = 0;
int beg = 0;
int end = 0;
while (end < len) {
end = str.indexOf(separator, beg);
if (end > -1) {
if (end > beg) {
numberOfSubstrings += 1;
if (numberOfSubstrings == max) {
end = len;
substrings.add(str.substring(beg));
} else {
// The following is OK, because String.substring( beg, end ) excludes
// the character at the position 'end'.
substrings.add(str.substring(beg, end));
// Set the starting point for the next search.
// The following is equivalent to beg = end + (separatorLength - 1) + 1,
// which is the right calculation:
beg = end + separatorLength;
}
} else {
// We found a consecutive occurrence of the separator, so skip it.
beg = end + separatorLength;
}
} else {
// String.substring( beg ) goes from 'beg' to the end of the String.
substrings.add(str.substring(beg));
end = len;
}
}
return (String[]) substrings.toArray(new String[substrings.size()]);
}
/**
* do a case-insensitive matching
* @param theEnumClass class of the enum
* @param generic type
*
* @param string
* @param exceptionOnNotFound true if exception should be thrown on not found
* @param exceptionIfInvalid if there is a string, but it is invalid, if should throw exception
* @return the enum or null or exception if not found
* @throws RuntimeException if there is a problem
*/
public static > E enumValueOfIgnoreCase(Class theEnumClass, String string,
boolean exceptionOnNotFound, boolean exceptionIfInvalid) throws RuntimeException {
if (!exceptionOnNotFound && isBlank(string)) {
return null;
}
for (E e : theEnumClass.getEnumConstants()) {
if (equalsIgnoreCase(string, e.name())) {
return e;
}
}
if (!exceptionIfInvalid) {
return null;
}
StringBuilder error = new StringBuilder(
"Cant find " + theEnumClass.getSimpleName() + " from string: '").append(string);
error.append("', expecting one of: ");
for (E e : theEnumClass.getEnumConstants()) {
error.append(e.name()).append(", ");
}
throw new RuntimeException(error.toString());
}
/**
* If we can, inject this into the exception, else return false
* @param t
* @param message
* @return true if success, false if not
*/
public static boolean injectInException(Throwable t, String message) {
String throwableFieldName = null;//GrouperConfig.getProperty("throwable.data.field.name");
//if (StringUtils.isBlank(throwableFieldName)) {
//this is the field for sun java 1.5
throwableFieldName = "detailMessage";
//}
try {
String currentValue = t.getMessage();
if (!isBlank(currentValue)) {
currentValue += ",\n" + message;
} else {
currentValue = message;
}
assignField(t, throwableFieldName, currentValue);
return true;
} catch (Throwable t2) {
//dont worry about what the problem is, return false so the caller can log
log.error(message);
return false;
}
}
/**
* assign data to a field
*
* @param theClass
* the class which has the method
* @param invokeOn
* to call on or null for static
* @param fieldName
* method name to call
* @param dataToAssign
* data
* @param callOnSupers
* if static and method not exists, try on supers
* @param overrideSecurity
* true to call on protected or private etc methods
* @param typeCast
* true if we should typecast
* @param annotationWithValueOverride
* annotation with value of override
*/
public static void assignField(Class theClass, Object invokeOn,
String fieldName, Object dataToAssign, boolean callOnSupers,
boolean overrideSecurity, boolean typeCast,
Class extends Annotation> annotationWithValueOverride) {
if (theClass == null && invokeOn != null) {
theClass = invokeOn.getClass();
}
Field field = field(theClass, fieldName, callOnSupers, true);
assignField(field, invokeOn, dataToAssign, overrideSecurity, typeCast,
annotationWithValueOverride);
}
/**
* assign data to a field. Will find the field in superclasses, will
* typecast, and will override security (private, protected, etc)
*
* @param theClass
* the class which has the method
* @param invokeOn
* to call on or null for static
* @param fieldName
* method name to call
* @param dataToAssign
* data
* @param annotationWithValueOverride
* annotation with value of override
*/
public static void assignField(Class theClass, Object invokeOn,
String fieldName, Object dataToAssign,
Class extends Annotation> annotationWithValueOverride) {
assignField(theClass, invokeOn, fieldName, dataToAssign, true, true,
true, annotationWithValueOverride);
}
/**
* assign data to a field
*
* @param field
* is the field to assign to
* @param invokeOn
* to call on or null for static
* @param dataToAssign
* data
* @param overrideSecurity
* true to call on protected or private etc methods
* @param typeCast
* true if we should typecast
*/
public static void assignField(Field field, Object invokeOn,
Object dataToAssign, boolean overrideSecurity, boolean typeCast) {
try {
Class> fieldType = field.getType();
// typecast
if (typeCast) {
dataToAssign =
typeCast(dataToAssign, fieldType,
true, true);
}
if (overrideSecurity) {
field.setAccessible(true);
}
field.set(invokeOn, dataToAssign);
} catch (Exception e) {
throw new RuntimeException("Cant assign reflection field: "
+ (field == null ? null : field.getName()) + ", on: "
+ className(invokeOn) + ", with args: "
+ classNameCollection(dataToAssign), e);
}
}
/**
* assign data to a field
*
* @param field
* is the field to assign to
* @param invokeOn
* to call on or null for static
* @param dataToAssign
* data
* @param overrideSecurity
* true to call on protected or private etc methods
* @param typeCast
* true if we should typecast
* @param annotationWithValueOverride
* annotation with value of override, or null if none
*/
@SuppressWarnings("unchecked")
public static void assignField(Field field, Object invokeOn,
Object dataToAssign, boolean overrideSecurity, boolean typeCast,
Class extends Annotation> annotationWithValueOverride) {
if (annotationWithValueOverride != null) {
// see if in annotation
Annotation annotation = field
.getAnnotation(annotationWithValueOverride);
if (annotation != null) {
// type of the value, or String if not specific Class
// typeOfAnnotationValue = typeCast ? field.getType() :
// String.class; dataToAssign =
// AnnotationUtils.retrieveAnnotationValue(
// typeOfAnnotationValue, annotation, "value");
throw new RuntimeException("Not supported");
}
}
assignField(field, invokeOn, dataToAssign, overrideSecurity, typeCast);
}
/**
* assign data to a field. Will find the field in superclasses, will
* typecast, and will override security (private, protected, etc)
*
* @param invokeOn
* to call on or null for static
* @param fieldName
* method name to call
* @param dataToAssign
* data
*/
public static void assignField(Object invokeOn, String fieldName,
Object dataToAssign) {
assignField(null, invokeOn, fieldName, dataToAssign, true, true, true,
null);
}
/**
* get a field object for a class, potentially in superclasses
*
* @param theClass
* @param fieldName
* @param callOnSupers
* true if superclasses should be looked in for the field
* @param throwExceptionIfNotFound
* will throw runtime exception if not found
* @return the field object or null if not found (or exception if param is
* set)
*/
public static Field field(Class theClass, String fieldName,
boolean callOnSupers, boolean throwExceptionIfNotFound) {
try {
Field field = theClass.getDeclaredField(fieldName);
// found it
return field;
} catch (NoSuchFieldException e) {
// if method not found
// if traversing up, and not Object, and not instance method
if (callOnSupers && !theClass.equals(Object.class)) {
return field(theClass.getSuperclass(), fieldName, callOnSupers,
throwExceptionIfNotFound);
}
}
// maybe throw an exception
if (throwExceptionIfNotFound) {
throw new RuntimeException("Cant find field: " + fieldName
+ ", in: " + theClass + ", callOnSupers: " + callOnSupers);
}
return null;
}
/**
* If necessary, convert an object to another type. if type is Object.class, just return the input.
* Do not convert null to an empty primitive
* @param is template type
* @param value
* @param theClass
* @return the object of that instance converted into something else
*/
public static T typeCast(Object value, Class theClass) {
//default behavior is not to convert null to empty primitive
return typeCast(value, theClass, false, false);
}
/**
* If necessary, convert an object to another type. if type is Object.class, just return the input
* @param is the type to return
* @param value
* @param theClass
* @param convertNullToDefaultPrimitive if the value is null, and theClass is primitive, should we
* convert the null to a primitive default value
* @param useNewInstanceHooks if theClass is not recognized, then honor the string "null", "newInstance",
* or get a constructor with one param, and call it
* @return the object of that instance converted into something else
*/
@SuppressWarnings({ "unchecked", "cast" })
public static T typeCast(Object value, Class theClass,
boolean convertNullToDefaultPrimitive, boolean useNewInstanceHooks) {
if (Object.class.equals(theClass)) {
return (T)value;
}
if (value==null) {
if (convertNullToDefaultPrimitive && theClass.isPrimitive()) {
if ( theClass == boolean.class ) {
return (T)Boolean.FALSE;
}
if ( theClass == char.class ) {
return (T)(Object)0;
}
//convert 0 to the type
return typeCast(0, theClass, false, false);
}
return null;
}
if (theClass.isInstance(value)) {
return (T)value;
}
//if array, get the base class
if (theClass.isArray() && theClass.getComponentType() != null) {
theClass = (Class)theClass.getComponentType();
}
Object resultValue = null;
//loop through and see the primitive types etc
if (theClass.equals(Date.class)) {
resultValue = dateValue(value);
} else if (theClass.equals(String.class)) {
resultValue = stringValue(value);
} else if (theClass.equals(Timestamp.class)) {
resultValue = toTimestamp(value);
} else if (theClass.equals(Boolean.class) || theClass.equals(boolean.class)) {
resultValue = booleanObjectValue(value);
} else if (theClass.equals(Integer.class) || theClass.equals(int.class)) {
resultValue = intObjectValue(value, true);
} else if (theClass.equals(Double.class) || theClass.equals(double.class)) {
resultValue = doubleObjectValue(value, true);
} else if (theClass.equals(Float.class) || theClass.equals(float.class)) {
resultValue = floatObjectValue(value, true);
} else if (theClass.equals(Long.class) || theClass.equals(long.class)) {
resultValue = longObjectValue(value, true);
} else if (theClass.equals(Byte.class) || theClass.equals(byte.class)) {
resultValue = byteObjectValue(value);
} else if (theClass.equals(Character.class) || theClass.equals(char.class)) {
resultValue = charObjectValue(value);
} else if (theClass.equals(Short.class) || theClass.equals(short.class)) {
resultValue = shortObjectValue(value);
} else if ( theClass.isEnum() && (value instanceof String) ) {
resultValue = Enum.valueOf((Class)theClass, (String) value);
} else if ( theClass.equals(Class.class) && (value instanceof String) ) {
resultValue = forName((String)value);
} else if (useNewInstanceHooks && value instanceof String) {
String stringValue = (String)value;
if ( StringUtils.equals("null", stringValue)) {
resultValue = null;
} else if (StringUtils.equals("newInstance", stringValue)) {
resultValue = newInstance(theClass);
} else { // instantiate using string
//note, we could typecast this to fit whatever is there... right now this is used for annotation
try {
Constructor constructor = theClass.getConstructor(new Class[] {String.class} );
resultValue = constructor.newInstance(new Object[] {stringValue} );
} catch (Exception e) {
throw new RuntimeException("Cant find constructor with string for class: " + theClass);
}
}
} else {
throw new RuntimeException("Cannot convert from type: " + value.getClass() + " to type: " + theClass);
}
return (T)resultValue;
}
/**
*
* Convert an object to a java.util.Date. allows, dates, null, blank,
* yyyymmdd or yyyymmdd hh24:mm:ss
* or yyyy/MM/dd HH:mm:ss.SSS
*
* @param inputObject
* is the String or Date to convert
*
* @return the Date
*/
public static Date dateValue(Object inputObject) {
if (inputObject == null) {
return null;
}
if (inputObject instanceof java.util.Date) {
return (Date)inputObject;
}
if (inputObject instanceof String) {
String input = (String)inputObject;
//trim and handle null and empty
if (StringUtils.isBlank(input)) {
return null;
}
try {
if (input.length() == 8) {
return dateFormat().parse(input);
}
if (!StringUtils.contains(input, '.')) {
if (StringUtils.contains(input, '/')) {
return dateMinutesSecondsFormat.parse(input);
}
//else no slash
return dateMinutesSecondsNoSlashFormat.parse(input);
}
if (StringUtils.contains(input, '/')) {
//see if the period is 6 back
int lastDotIndex = input.lastIndexOf('.');
if (lastDotIndex == input.length() - 7) {
String nonNanoInput = input.substring(0,input.length()-3);
Date date = timestampFormat.parse(nonNanoInput);
//get the last 3
String lastThree = input.substring(input.length()-3,input.length());
int lastThreeInt = Integer.parseInt(lastThree);
Timestamp timestamp = new Timestamp(date.getTime());
timestamp.setNanos(timestamp.getNanos() + (lastThreeInt * 1000));
return timestamp;
}
return timestampFormat.parse(input);
}
//else no slash
return timestampNoSlashFormat.parse(input);
} catch (ParseException pe) {
throw new RuntimeException(errorStart + toStringForLog(input));
}
}
throw new RuntimeException("Cannot convert Object to date : " + toStringForLog(inputObject));
}
/**
* See if the input is null or if string, if it is empty or blank (whitespace)
* @param input
* @return true if blank
*/
public static boolean isBlank(Object input) {
if (null == input) {
return true;
}
return (input instanceof String && StringUtils.isBlank((String)input));
}
/**
* get the Integer value of an object
*
* @param input
* is a number or String
* @param allowNullBlank true if convert null or blank to null
*
* @return the Integer equivalent
*/
public static Integer intObjectValue(Object input, boolean allowNullBlank) {
if (input instanceof Integer) {
return (Integer) input;
}
if (allowNullBlank && isBlank(input)) {
return null;
}
return Integer.valueOf(intValue(input));
}
/**
* convert an object to a int
* @param input
* @return the number
*/
public static int intValue(Object input) {
if (input instanceof String) {
String string = (String)input;
return Integer.parseInt(string);
}
if (input instanceof Number) {
return ((Number)input).intValue();
}
if (false) {
if (input == null) {
return 0;
}
if (input instanceof String || StringUtils.isBlank((String)input)) {
return 0;
}
}
throw new RuntimeException("Cannot convert to int: " + className(input));
}
/**
* convert an object to a int
* @param input
* @param valueIfNull is if the input is null or empty, return this value
* @return the number
*/
public static int intValue(Object input, int valueIfNull) {
if (input == null || "".equals(input)) {
return valueIfNull;
}
return intObjectValue(input, false);
}
/**
* get the int value of an object, do not throw an exception if there is an
* error
*
* @param input
* is a number or String
*
* @return the int equivalent
*/
public static int intValueNoError(Object input) {
if (input == null || (input instanceof String
&& StringUtils.isBlank((String)input))) {
return NOT_FOUND;
}
try {
return intValue(input);
} catch (Exception e) {
//no need to log here
}
return NOT_FOUND;
}
/**
* convert a date to the standard string yyyymmdd
* @param date
* @return the string value
*/
public static String stringValue(java.util.Date date) {
synchronized (SubjectUtils.class) {
if (date == null) {
return null;
}
String theString = dateFormat().format(date);
return theString;
}
}
/**
* convert an object to a string
*
* @param input
* is the object to convert
*
* @return the String conversion of the object
*/
public static String stringValue(Object input) {
//this isnt needed
if (input == null) {
return (String) input;
}
if (input instanceof Timestamp) {
//convert to yyyy/MM/dd HH:mm:ss.SSS
return timestampToString((Timestamp) input);
}
if (input instanceof Date) {
//convert to yyyymmdd
return stringValue((Date) input);
}
if (input instanceof Number) {
DecimalFormat decimalFormat = new DecimalFormat(
"###################.###############");
return decimalFormat.format(((Number) input).doubleValue());
}
return input.toString();
}
/**
* Convert a timestamp into a string: yyyy/MM/dd HH:mm:ss.SSS
* @param timestamp
* @return the string representation
*/
public synchronized static String timestampToString(Date timestamp) {
if (timestamp == null) {
return null;
}
return timestampFormat.format(timestamp);
}
/**
* Get the contents of an InputStream
as a String.
* @param input the InputStream
to read from
* @param encoding The name of a supported character encoding. See the
* IANA
* Charset Registry for a list of valid encoding types.
* @return the requested String
* @throws IOException In case of an I/O problem
*/
public static String toString(InputStream input, String encoding) throws IOException {
StringWriter sw = new StringWriter();
copy(input, sw, encoding);
return sw.toString();
}
/**
*
* Convert a string or object to a timestamp (could be string, date, timestamp, etc)
* yyyymmdd
* or
* yyyy/MM/dd HH:mm:ss
* or
* yyyy/MM/dd HH:mm:ss.SSS
* or
* yyyy/MM/dd HH:mm:ss.SSSSSS
*
*
*
* @param input
* @return the timestamp
* @throws RuntimeException if invalid format
*/
public static Timestamp toTimestamp(Object input) {
if (null == input) {
return null;
} else if (input instanceof java.sql.Timestamp) {
return (Timestamp) input;
} else if (input instanceof String) {
return stringToTimestamp((String) input);
} else if (input instanceof Date) {
return new Timestamp(((Date)input).getTime());
} else if (input instanceof java.sql.Date) {
return new Timestamp(((java.sql.Date)input).getTime());
} else {
throw new RuntimeException("Cannot convert Object to timestamp : " + input);
}
}
/**
* null safe classname method, gets the unenhanced name
*
* @param object
* @return the classname
*/
public static String className(Object object) {
return object == null ? null : object.getClass()
.getName();
}
/**
* null safe classname method, max out at 20
*
* @param object
* @return the classname
*/
public static String classNameCollection(Object object) {
if (object == null) {
return null;
}
StringBuffer result = new StringBuffer();
Iterator iterator = iterator(object);
int length = length(object);
for (int i = 0; i < length && i < 20; i++) {
result.append(className(next(object, iterator, i)));
if (i != length - 1) {
result.append(", ");
}
}
return result.toString();
}
/**
* Convert an object to a byte, allow nulls
* @param input
* @return the boolean object value
*/
public static BigDecimal bigDecimalObjectValue(Object input) {
if (input instanceof BigDecimal) {
return (BigDecimal)input;
}
if (isBlank(input)) {
return null;
}
return BigDecimal.valueOf(doubleValue(input));
}
/**
* get the Boolean value for an object
*
* @param object
* @return the Boolean or null if null or empty
*/
public static Boolean booleanObjectValue(Object object) {
if (nullOrBlank(object)) {
return null;
}
return booleanValue(object);
}
/**
* get the boolean value for an object, cant be null or blank
*
* @param object
* @return the boolean
*/
public static boolean booleanValue(Object object) {
// first handle blanks
if (nullOrBlank(object)) {
throw new RuntimeException(
"Expecting something which can be converted to boolean, but is null or blank: '"
+ object + "'");
}
// its not blank, just convert
if (object instanceof Boolean) {
return (Boolean) object;
}
if (object instanceof String) {
String string = (String) object;
if (StringUtils.equalsIgnoreCase(string, "true")
|| StringUtils.equalsIgnoreCase(string, "t")
|| StringUtils.equalsIgnoreCase(string, "yes")
|| StringUtils.equalsIgnoreCase(string, "y")) {
return true;
}
if (StringUtils.equalsIgnoreCase(string, "false")
|| StringUtils.equalsIgnoreCase(string, "f")
|| StringUtils.equalsIgnoreCase(string, "no")
|| StringUtils.equalsIgnoreCase(string, "n")) {
return false;
}
throw new RuntimeException(
"Invalid string to boolean conversion: '" + string
+ "' expecting true|false or t|f or yes|no or y|n case insensitive");
}
throw new RuntimeException("Cant convert object to boolean: "
+ object.getClass());
}
/**
* get the boolean value for an object
*
* @param object
* @param defaultBoolean
* if object is null or empty
* @return the boolean
*/
public static boolean booleanValue(Object object, boolean defaultBoolean) {
if (nullOrBlank(object)) {
return defaultBoolean;
}
return booleanValue(object);
}
/**
* Convert an object to a byte, allow nulls
* @param input
* @return the boolean object value
*/
public static Byte byteObjectValue(Object input) {
if (input instanceof Byte) {
return (Byte)input;
}
if (isBlank(input)) {
return null;
}
return Byte.valueOf(byteValue(input));
}
/**
* convert an object to a byte
* @param input
* @return the byte
*/
public static byte byteValue(Object input) {
if (input instanceof String) {
String string = (String)input;
return Byte.parseByte(string);
}
if (input instanceof Number) {
return ((Number)input).byteValue();
}
throw new RuntimeException("Cannot convert to byte: " + className(input));
}
/**
* get the Character wrapper value for the input
* @param input allow null, return null
* @return the Character object wrapper
*/
public static Character charObjectValue(Object input) {
if (input instanceof Character) {
return (Character) input;
}
if (isBlank(input)) {
return null;
}
return new Character(charValue(input));
}
/**
* convert an object to a char
* @param input
* @return the number
*/
public static char charValue(Object input) {
if (input instanceof Character) {
return ((Character) input).charValue();
}
//if string length 1, thats ok
if (input instanceof String) {
String inputString = (String) input;
if (inputString.length() == 1) {
return inputString.charAt(0);
}
}
throw new RuntimeException("Cannot convert to char: "
+ (input == null ? null : (input.getClass() + ", " + input)));
}
/**
* get the Double value of an object
*
* @param input
* is a number or String
* @param allowNullBlank used to default to false, if true, return null if nul inputted
*
* @return the Double equivalent
*/
public static Double doubleObjectValue(Object input, boolean allowNullBlank) {
if (input instanceof Double) {
return (Double) input;
}
if (allowNullBlank && isBlank(input)) {
return null;
}
return Double.valueOf(doubleValue(input));
}
/**
* get the double value of an object
*
* @param input
* is a number or String
*
* @return the double equivalent
*/
public static double doubleValue(Object input) {
if (input instanceof String) {
String string = (String)input;
return Double.parseDouble(string);
}
if (input instanceof Number) {
return ((Number)input).doubleValue();
}
throw new RuntimeException("Cannot convert to double: " + className(input));
}
/**
* get the double value of an object, do not throw an
* exception if there is an
* error
*
* @param input
* is a number or String
*
* @return the double equivalent
*/
public static double doubleValueNoError(Object input) {
if (input == null || (input instanceof String
&& StringUtils.isBlank((String)input))) {
return NOT_FOUND;
}
try {
return doubleValue(input);
} catch (Exception e) {
//no need to log here
}
return NOT_FOUND;
}
/**
* get the Float value of an object
*
* @param input
* is a number or String
* @param allowNullBlank true if allow null or blank
*
* @return the Float equivalent
*/
public static Float floatObjectValue(Object input, boolean allowNullBlank) {
if (input instanceof Float) {
return (Float) input;
}
if (allowNullBlank && isBlank(input)) {
return null;
}
return Float.valueOf(floatValue(input));
}
/**
* get the float value of an object
*
* @param input
* is a number or String
*
* @return the float equivalent
*/
public static float floatValue(Object input) {
if (input instanceof String) {
String string = (String)input;
return Float.parseFloat(string);
}
if (input instanceof Number) {
return ((Number)input).floatValue();
}
throw new RuntimeException("Cannot convert to float: " + className(input));
}
/**
* get the float value of an object, do not throw an exception if there is an
* error
*
* @param input
* is a number or String
*
* @return the float equivalent
*/
public static float floatValueNoError(Object input) {
if (input == null || (input instanceof String
&& StringUtils.isBlank((String)input))) {
return NOT_FOUND;
}
try {
return floatValue(input);
} catch (Exception e) {
log.error(e);
}
return NOT_FOUND;
}
/**
* get the Long value of an object
*
* @param input
* is a number or String
* @param allowNullBlank true if null or blank converts to null
*
* @return the Long equivalent
*/
public static Long longObjectValue(Object input, boolean allowNullBlank) {
if (input instanceof Long) {
return (Long) input;
}
if (allowNullBlank && isBlank(input)) {
return null;
}
return Long.valueOf(longValue(input));
}
/**
* convert an object to a long
* @param input
* @return the number
*/
public static long longValue(Object input) {
if (input instanceof String) {
String string = (String)input;
return Long.parseLong(string);
}
if (input instanceof Number) {
return ((Number)input).longValue();
}
throw new RuntimeException("Cannot convert to long: " + className(input));
}
/**
* convert an object to a long
* @param input
* @param valueIfNull is if the input is null or empty, return this value
* @return the number
*/
public static long longValue(Object input, long valueIfNull) {
if (input == null || "".equals(input)) {
return valueIfNull;
}
return longObjectValue(input, false);
}
/**
* get the long value of an object, do not throw an exception if there is an
* error
*
* @param input
* is a number or String
*
* @return the long equivalent
*/
public static long longValueNoError(Object input) {
if (input == null || (input instanceof String
&& StringUtils.isBlank((String)input))) {
return NOT_FOUND;
}
try {
return longValue(input);
} catch (Exception e) {
//no need to log here
}
return NOT_FOUND;
}
/**
* get the Short value of an object. converts null or blank to null
*
* @param input
* is a number or String
*
* @return the Long equivalent
*/
public static Short shortObjectValue(Object input) {
if (input instanceof Short) {
return (Short) input;
}
if (isBlank(input)) {
return null;
}
return Short.valueOf(shortValue(input));
}
/**
* convert an object to a short
* @param input
* @return the number
*/
public static short shortValue(Object input) {
if (input instanceof String) {
String string = (String)input;
return Short.parseShort(string);
}
if (input instanceof Number) {
return ((Number)input).shortValue();
}
throw new RuntimeException("Cannot convert to short: " + className(input));
}
/**
* Returns the class object.
* @param origClassName is fully qualified
* @return the class
*/
public static Class forName(String origClassName) {
try {
return Class.forName(origClassName);
} catch (Throwable t) {
throw new RuntimeException("Problem loading class: " + origClassName, t);
}
}
/**
* Construct a class
* @param template type
* @param theClass
* @return the instance
*/
public static T newInstance(Class theClass) {
try {
return theClass.newInstance();
} catch (Throwable e) {
if (theClass != null && Modifier.isAbstract(theClass.getModifiers())) {
throw new RuntimeException("Problem with class: " + theClass + ", maybe because it is abstract!", e);
}
throw new RuntimeException("Problem with class: " + theClass, e);
}
}
/**
* get the timestamp format for this thread
* if you call this make sure to synchronize on FastDateUtils.class
* @return the timestamp format
*/
synchronized static SimpleDateFormat dateFormat() {
return dateFormat;
}
/**
* print out various types of objects
*
* @param object
* @return the string value
*/
public static String toStringForLog(Object object) {
StringBuilder result = new StringBuilder();
toStringForLogHelper(object, -1, result);
return result.toString();
}
/**
* print out various types of objects
*
* @param object
* @param maxChars is the max chars that should be returned (abbreviate if longer), or -1 for any amount
* @return the string value
*/
public static String toStringForLog(Object object, int maxChars) {
StringBuilder result = new StringBuilder();
toStringForLogHelper(object, -1, result);
String resultString = result.toString();
if (maxChars != -1) {
return StringUtils.abbreviate(resultString, maxChars);
}
return resultString;
}
/**
* print out various types of objects
*
* @param object
* @param maxChars is where it should stop when figuring out object. note, result might be longer than max...
* need to abbreviate when back
* @param result is where to append to
*/
@SuppressWarnings("unchecked")
private static void toStringForLogHelper(Object object, int maxChars, StringBuilder result) {
try {
if (object == null) {
result.append("null");
} else if (object.getClass().isArray()) {
// handle arrays
int length = Array.getLength(object);
if (length == 0) {
result.append("Empty array");
} else {
result.append("Array size: ").append(length).append(": ");
for (int i = 0; i < length; i++) {
result.append("[").append(i).append("]: ").append(
Array.get(object, i)).append("\n");
if (maxChars != -1 && result.length() > maxChars) {
return;
}
}
}
} else if (object instanceof Collection) {
//give size and type if collection
Collection