mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-04-25 00:00:03 -04:00
Moving files around
This commit is contained in:
@@ -0,0 +1,612 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
import com.twelvemonkeys.util.convert.ConversionException;
|
||||
import com.twelvemonkeys.util.convert.Converter;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Map;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A utility class with some useful bean-related functions.
|
||||
* <p/>
|
||||
* <em>NOTE: This class is not considered part of the public API and may be
|
||||
* changed without notice</em>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/BeanUtil.java#2 $
|
||||
*/
|
||||
public final class BeanUtil {
|
||||
|
||||
// Disallow creating objects of this type
|
||||
private BeanUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a property value from the given object, using reflection.
|
||||
* Now supports getting values from properties of properties
|
||||
* (recursive).
|
||||
*
|
||||
* @param pObject The object to get the property from
|
||||
* @param pProperty The name of the property
|
||||
*
|
||||
* @return A string containing the value of the given property, or null
|
||||
* if it can not be found.
|
||||
* @todo Remove System.err's... Create new Exception? Hmm..
|
||||
*/
|
||||
public static Object getPropertyValue(Object pObject, String pProperty) {
|
||||
//
|
||||
// TODO: Support get(Object) method of Collections!
|
||||
// Handle lists and arrays with [] (index) operator
|
||||
//
|
||||
|
||||
if (pObject == null || pProperty == null || pProperty.length() < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class objClass = pObject.getClass();
|
||||
|
||||
Object result = pObject;
|
||||
|
||||
// Method for method...
|
||||
String subProp;
|
||||
int begIdx = 0;
|
||||
int endIdx = begIdx;
|
||||
|
||||
while (begIdx < pProperty.length() && begIdx >= 0) {
|
||||
|
||||
endIdx = pProperty.indexOf(".", endIdx + 1);
|
||||
if (endIdx > 0) {
|
||||
subProp = pProperty.substring(begIdx, endIdx);
|
||||
begIdx = endIdx + 1;
|
||||
}
|
||||
else {
|
||||
// The final property!
|
||||
// If there's just the first-level property, subProp will be
|
||||
// equal to property
|
||||
subProp = pProperty.substring(begIdx);
|
||||
begIdx = -1;
|
||||
}
|
||||
|
||||
// Check for "[" and "]"
|
||||
Object[] param = null;
|
||||
Class[] paramClass = new Class[0];
|
||||
|
||||
int begBracket;
|
||||
if ((begBracket = subProp.indexOf("[")) > 0) {
|
||||
// An error if there is no matching bracket
|
||||
if (!subProp.endsWith("]")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String between = subProp.substring(begBracket + 1,
|
||||
subProp.length() - 1);
|
||||
subProp = subProp.substring(0, begBracket);
|
||||
|
||||
// If brackets exist, check type of argument between brackets
|
||||
param = new Object[1];
|
||||
paramClass = new Class[1];
|
||||
|
||||
//try {
|
||||
// TODO: isNumber returns true, even if too big for integer...
|
||||
if (StringUtil.isNumber(between)) {
|
||||
// We have a number
|
||||
// Integer -> array subscript -> getXXX(int i)
|
||||
try {
|
||||
// Insert param and it's Class
|
||||
param[0] = Integer.valueOf(between);
|
||||
paramClass[0] = Integer.TYPE; // int.class
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
// ??
|
||||
// Probably too small or too large value..
|
||||
}
|
||||
}
|
||||
else {
|
||||
//catch (NumberFormatException e) {
|
||||
// Not a number... Try String
|
||||
// String -> Hashtable key -> getXXX(String str)
|
||||
// Insert param and it's Class
|
||||
param[0] = between.toLowerCase();
|
||||
paramClass[0] = String.class;
|
||||
}
|
||||
}
|
||||
|
||||
Method method;
|
||||
String methodName = "get" + StringUtil.capitalize(subProp);
|
||||
try {
|
||||
// Try to get the "get" method for the given property
|
||||
method = objClass.getMethod(methodName, paramClass);
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
System.err.print("No method named \"" + methodName + "()\"");
|
||||
// The array might be of size 0...
|
||||
if (paramClass != null && paramClass.length > 0) {
|
||||
System.err.print(" with the parameter "
|
||||
+ paramClass[0].getName());
|
||||
}
|
||||
|
||||
System.err.println(" in class " + objClass.getName() + "!");
|
||||
return null;
|
||||
}
|
||||
|
||||
// If method for some reason should be null, give up
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// We have a method, try to invoke it
|
||||
// The resutling object will be either the property we are
|
||||
// Looking for, or the parent
|
||||
|
||||
// System.err.println("Trying " + objClass.getName() + "." + method.getName() + "(" + ((param != null && param.length > 0) ? param[0] : "") + ")");
|
||||
result = method.invoke(result, param);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
System.err.println("property=" + pProperty + " & result="
|
||||
+ result + " & param=" + Arrays.toString(param));
|
||||
e.getTargetException().printStackTrace();
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
System.err.println(objClass.getName() + "." + method.getName()
|
||||
+ "(" + ((paramClass != null && paramClass.length > 0) ? paramClass[0].getName() : "") + ")");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
// Get the class of the reulting object
|
||||
objClass = result.getClass();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
} // while
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the property value to an object using reflection.
|
||||
* Supports setting values of properties that are properties of
|
||||
* properties (recursive).
|
||||
*
|
||||
* @param pObject The object to get a property from
|
||||
* @param pProperty The name of the property
|
||||
* @param pValue The property value
|
||||
*
|
||||
* @throws NoSuchMethodException if there's no write method for the
|
||||
* given property
|
||||
* @throws InvocationTargetException if invoking the write method failed
|
||||
* @throws IllegalAccessException if the caller class has no access to the
|
||||
* write method
|
||||
*/
|
||||
public static void setPropertyValue(Object pObject, String pProperty,
|
||||
Object pValue)
|
||||
throws NoSuchMethodException, InvocationTargetException,
|
||||
IllegalAccessException {
|
||||
|
||||
//
|
||||
// TODO: Support set(Object, Object)/put(Object, Object) methods
|
||||
// of Collections!
|
||||
// Handle lists and arrays with [] (index) operator
|
||||
|
||||
Class paramType = pValue != null ? pValue.getClass() : Object.class;
|
||||
|
||||
// Preserve references
|
||||
Object obj = pObject;
|
||||
String property = pProperty;
|
||||
|
||||
// Recurse and find real parent if property contains a '.'
|
||||
int dotIdx = property.indexOf('.');
|
||||
if (dotIdx >= 0) {
|
||||
// Get real parent
|
||||
obj = getPropertyValue(obj, property.substring(0, dotIdx));
|
||||
// Get the property of the parent
|
||||
property = property.substring(dotIdx + 1);
|
||||
}
|
||||
|
||||
// Find method
|
||||
Object[] params = {pValue};
|
||||
Method method = getMethodMayModifyParams(obj, "set" + StringUtil.capitalize(property),
|
||||
new Class[] {paramType}, params);
|
||||
|
||||
// Invoke it
|
||||
method.invoke(obj, params);
|
||||
}
|
||||
|
||||
private static Method getMethodMayModifyParams(Object pObject, String pName, Class[] pParams, Object[] pValues) throws NoSuchMethodException {
|
||||
// NOTE: This method assumes pParams.length == 1 && pValues.length == 1
|
||||
|
||||
Method method = null;
|
||||
Class paramType = pParams[0];
|
||||
|
||||
try {
|
||||
method = pObject.getClass().getMethod(pName, pParams);
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
// No direct match
|
||||
|
||||
// 1: If primitive wrapper, try unwrap conversion first
|
||||
/*if (paramType.isPrimitive()) { // NOTE: Can't be primitive type
|
||||
params[0] = ReflectUtil.wrapType(paramType);
|
||||
}
|
||||
else*/ if (ReflectUtil.isPrimitiveWrapper(paramType)) {
|
||||
pParams[0] = ReflectUtil.unwrapType(paramType);
|
||||
}
|
||||
|
||||
try {
|
||||
// If this does not throw an excption, it works
|
||||
method = pObject.getClass().getMethod(pName, pParams);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
// 2: Try any supertypes of paramType, to see if we have a match
|
||||
if (method == null) {
|
||||
while ((paramType = paramType.getSuperclass()) != null) {
|
||||
pParams[0] = paramType;
|
||||
try {
|
||||
// If this does not throw an excption, it works
|
||||
method = pObject.getClass().getMethod(pName, pParams);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
// Ignore/Continue
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 3: Try to find a different method with the same name, that has
|
||||
// a parameter type we can convert to...
|
||||
// NOTE: There's no ordering here..
|
||||
// TODO: Should we try to do that? What would the ordering be?
|
||||
if (method == null) {
|
||||
Method[] methods = pObject.getClass().getMethods();
|
||||
for (Method candidate : methods) {
|
||||
if (Modifier.isPublic(candidate.getModifiers())
|
||||
&& candidate.getName().equals(pName)
|
||||
&& candidate.getReturnType() == Void.TYPE
|
||||
&& candidate.getParameterTypes().length == 1) {
|
||||
// NOTE: Assumes paramTypes.length == 1
|
||||
|
||||
Class type = candidate.getParameterTypes()[0];
|
||||
|
||||
try {
|
||||
pValues[0] = convertValueToType(pValues[0], type);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We were able to convert the parameter, let's try
|
||||
method = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Give up...
|
||||
if (method == null) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
private static Object convertValueToType(Object pValue, Class pType) throws ConversionException {
|
||||
if (pType.isPrimitive()) {
|
||||
if (pType == Boolean.TYPE && pValue instanceof Boolean) {
|
||||
return pValue;
|
||||
}
|
||||
else if (pType == Byte.TYPE && pValue instanceof Byte) {
|
||||
return pValue;
|
||||
}
|
||||
else if (pType == Character.TYPE && pValue instanceof Character) {
|
||||
return pValue;
|
||||
}
|
||||
else if (pType == Double.TYPE && pValue instanceof Double) {
|
||||
return pValue;
|
||||
}
|
||||
else if (pType == Float.TYPE && pValue instanceof Float) {
|
||||
return pValue;
|
||||
}
|
||||
else if (pType == Integer.TYPE && pValue instanceof Integer) {
|
||||
return pValue;
|
||||
}
|
||||
else if (pType == Long.TYPE && pValue instanceof Long) {
|
||||
return pValue;
|
||||
}
|
||||
else if (pType == Short.TYPE && pValue instanceof Short) {
|
||||
return pValue;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Convert other types
|
||||
if (pValue instanceof String) {
|
||||
Converter converter = Converter.getInstance();
|
||||
return converter.toObject((String) pValue, pType);
|
||||
}
|
||||
else if (pType == String.class) {
|
||||
Converter converter = Converter.getInstance();
|
||||
return converter.toString(pValue);
|
||||
}
|
||||
else {
|
||||
throw new ConversionException("Cannot convert " + pValue.getClass().getName() + " to " + pType.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object from the given class' single argument constructor.
|
||||
*
|
||||
* @param pClass The class to create instance from
|
||||
* @param pParam The parameters to the constructor
|
||||
*
|
||||
* @return The object created from the constructor.
|
||||
* If the constructor could not be invoked for any reason, null is
|
||||
* returned.
|
||||
*
|
||||
* @throws InvocationTargetException if the constructor failed
|
||||
*/
|
||||
// TODO: Move to ReflectUtil
|
||||
public static Object createInstance(Class pClass, Object pParam)
|
||||
throws InvocationTargetException {
|
||||
return createInstance(pClass, new Object[] {pParam});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object from the given class' constructor that matches
|
||||
* the given paramaters.
|
||||
*
|
||||
* @param pClass The class to create instance from
|
||||
* @param pParams The parameters to the constructor
|
||||
*
|
||||
* @return The object created from the constructor.
|
||||
* If the constructor could not be invoked for any reason, null is
|
||||
* returned.
|
||||
*
|
||||
* @throws InvocationTargetException if the constructor failed
|
||||
*/
|
||||
// TODO: Move to ReflectUtil
|
||||
public static Object createInstance(Class pClass, Object... pParams)
|
||||
throws InvocationTargetException {
|
||||
Object value;
|
||||
|
||||
try {
|
||||
// Create param and argument arrays
|
||||
Class[] paramTypes = null;
|
||||
if (pParams != null && pParams.length > 0) {
|
||||
paramTypes = new Class[pParams.length];
|
||||
for (int i = 0; i < pParams.length; i++) {
|
||||
paramTypes[i] = pParams[i].getClass();
|
||||
}
|
||||
}
|
||||
|
||||
// Get constructor
|
||||
//Constructor constructor = pClass.getDeclaredConstructor(paramTypes);
|
||||
Constructor constructor = pClass.getConstructor(paramTypes);
|
||||
|
||||
// Invoke and create instance
|
||||
value = constructor.newInstance(pParams);
|
||||
}
|
||||
/* All this to let InvocationTargetException pass on */
|
||||
catch (NoSuchMethodException nsme) {
|
||||
return null;
|
||||
}
|
||||
catch (IllegalAccessException iae) {
|
||||
return null;
|
||||
}
|
||||
catch (IllegalArgumentException iarge) {
|
||||
return null;
|
||||
}
|
||||
catch (InstantiationException ie) {
|
||||
return null;
|
||||
}
|
||||
catch (ExceptionInInitializerError err) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object from any given static method, with the given parameter.
|
||||
*
|
||||
* @param pClass The class to invoke method on
|
||||
* @param pMethod The name of the method to invoke
|
||||
* @param pParam The parameter to the method
|
||||
*
|
||||
* @return The object returned by the static method.
|
||||
* If the return type of the method is a primitive type, it is wrapped in
|
||||
* the corresponding wrapper object (int is wrapped in an Integer).
|
||||
* If the return type of the method is void, null is returned.
|
||||
* If the method could not be invoked for any reason, null is returned.
|
||||
*
|
||||
* @throws InvocationTargetException if the invocaton failed
|
||||
*/
|
||||
// TODO: Move to ReflectUtil
|
||||
// TODO: Rename to invokeStatic?
|
||||
public static Object invokeStaticMethod(Class pClass, String pMethod,
|
||||
Object pParam)
|
||||
throws InvocationTargetException {
|
||||
|
||||
return invokeStaticMethod(pClass, pMethod, new Object[] {pParam});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object from any given static method, with the given parameter.
|
||||
*
|
||||
* @param pClass The class to invoke method on
|
||||
* @param pMethod The name of the method to invoke
|
||||
* @param pParams The parameters to the method
|
||||
*
|
||||
* @return The object returned by the static method.
|
||||
* If the return type of the method is a primitive type, it is wrapped in
|
||||
* the corresponding wrapper object (int is wrapped in an Integer).
|
||||
* If the return type of the method is void, null is returned.
|
||||
* If the method could not be invoked for any reason, null is returned.
|
||||
*
|
||||
* @throws InvocationTargetException if the invocaton failed
|
||||
*/
|
||||
// TODO: Move to ReflectUtil
|
||||
// TODO: Rename to invokeStatic?
|
||||
public static Object invokeStaticMethod(Class pClass, String pMethod,
|
||||
Object[] pParams)
|
||||
throws InvocationTargetException {
|
||||
|
||||
Object value = null;
|
||||
|
||||
try {
|
||||
// Create param and argument arrays
|
||||
Class[] paramTypes = new Class[pParams.length];
|
||||
for (int i = 0; i < pParams.length; i++) {
|
||||
paramTypes[i] = pParams[i].getClass();
|
||||
}
|
||||
|
||||
// Get method
|
||||
// *** If more than one such method is found in the class, and one
|
||||
// of these methods has a RETURN TYPE that is more specific than
|
||||
// any of the others, that method is reflected; otherwise one of
|
||||
// the methods is chosen ARBITRARILY.
|
||||
// java/lang/Class.html#getMethod(java.lang.String, java.lang.Class[])
|
||||
Method method = pClass.getMethod(pMethod, paramTypes);
|
||||
|
||||
// Invoke public static method
|
||||
if (Modifier.isPublic(method.getModifiers())
|
||||
&& Modifier.isStatic(method.getModifiers())) {
|
||||
value = method.invoke(null, pParams);
|
||||
}
|
||||
|
||||
}
|
||||
/* All this to let InvocationTargetException pass on */
|
||||
catch (NoSuchMethodException nsme) {
|
||||
return null;
|
||||
}
|
||||
catch (IllegalAccessException iae) {
|
||||
return null;
|
||||
}
|
||||
catch (IllegalArgumentException iarge) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the bean according to the given mapping.
|
||||
* For each {@code Map.Entry} in {@code Map.values()},
|
||||
* a method named
|
||||
* {@code set + capitalize(entry.getKey())} is called on the bean,
|
||||
* with {@code entry.getValue()} as its argument.
|
||||
* <p/>
|
||||
* Properties that has no matching set-method in the bean, are simply
|
||||
* discarded.
|
||||
*
|
||||
* @param pBean The bean to configure
|
||||
* @param pMapping The mapping for the bean
|
||||
*
|
||||
* @throws NullPointerException if any of the parameters are null.
|
||||
* @throws InvocationTargetException if an error occurs when invoking the
|
||||
* setter-method.
|
||||
*/
|
||||
// TODO: Add a version that takes a ConfigurationErrorListener callback interface
|
||||
// TODO: ...or a boolean pFailOnError parameter
|
||||
// TODO: ...or return Exceptions as an array?!
|
||||
// TODO: ...or something whatsoever that makes clients able to determine something's not right
|
||||
public static void configure(final Object pBean, final Map<String, ?> pMapping) throws InvocationTargetException {
|
||||
configure(pBean, pMapping, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the bean according to the given mapping.
|
||||
* For each {@code Map.Entry} in {@code Map.values()},
|
||||
* a method named
|
||||
* {@code set + capitalize(entry.getKey())} is called on the bean,
|
||||
* with {@code entry.getValue()} as its argument.
|
||||
* <p/>
|
||||
* Optionally, lisp-style names are allowed, and automatically converted
|
||||
* to Java-style camel-case names.
|
||||
* <p/>
|
||||
* Properties that has no matching set-method in the bean, are simply
|
||||
* discarded.
|
||||
*
|
||||
* @see StringUtil#lispToCamel(String)
|
||||
*
|
||||
* @param pBean The bean to configure
|
||||
* @param pMapping The mapping for the bean
|
||||
* @param pLispToCamel Allow lisp-style names, and automatically convert
|
||||
* them to Java-style camel-case.
|
||||
*
|
||||
* @throws NullPointerException if any of the parameters are null.
|
||||
* @throws InvocationTargetException if an error occurs when invoking the
|
||||
* setter-method.
|
||||
*/
|
||||
public static void configure(final Object pBean, final Map<String, ?> pMapping, final boolean pLispToCamel) throws InvocationTargetException {
|
||||
// Loop over properties in mapping
|
||||
for (final Map.Entry<String, ?> entry : pMapping.entrySet()) {
|
||||
try {
|
||||
// Configure each property in turn
|
||||
final String property = StringUtil.valueOf(entry.getKey());
|
||||
try {
|
||||
setPropertyValue(pBean, property, entry.getValue());
|
||||
}
|
||||
catch (NoSuchMethodException ignore) {
|
||||
// If invocation failed, convert lisp-style and try again
|
||||
if (pLispToCamel && property.indexOf('-') > 0) {
|
||||
setPropertyValue(pBean, StringUtil.lispToCamel(property, false),
|
||||
entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NoSuchMethodException nsme) {
|
||||
// This property was not configured
|
||||
}
|
||||
catch (IllegalAccessException iae) {
|
||||
// This property was not configured
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* A utility class with useful date manipulation methods and constants.
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/DateUtil.java#1 $
|
||||
*/
|
||||
public final class DateUtil {
|
||||
|
||||
/** One second: 1000 milliseconds. */
|
||||
public static final long SECOND = 1000l;
|
||||
|
||||
/** One minute: 60 seconds (60 000 milliseconds). */
|
||||
public static final long MINUTE = 60l * SECOND;
|
||||
|
||||
/**
|
||||
* One hour: 60 minutes (3 600 000 milliseconds).
|
||||
* 60 minutes = 3 600 seconds = 3 600 000 milliseconds
|
||||
*/
|
||||
public static final long HOUR = 60l * MINUTE;
|
||||
|
||||
/**
|
||||
* One day: 24 hours (86 400 000 milliseconds).
|
||||
* 24 hours = 1 440 minutes = 86 400 seconds = 86 400 000 milliseconds.
|
||||
*/
|
||||
public static final long DAY = 24l * HOUR;
|
||||
|
||||
/**
|
||||
* One calendar year: 365.2425 days (31556952000 milliseconds).
|
||||
* 365.2425 days = 8765.82 hours = 525949.2 minutes = 31556952 seconds
|
||||
* = 31556952000 milliseconds.
|
||||
*/
|
||||
public static final long CALENDAR_YEAR = 3652425l * 24l * 60l * 6l;
|
||||
|
||||
private DateUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time between the given start time and now (as defined by
|
||||
* {@link System#currentTimeMillis()}).
|
||||
*
|
||||
* @param pStart the start time
|
||||
*
|
||||
* @return the time between the given start time and now.
|
||||
*/
|
||||
public static long delta(long pStart) {
|
||||
return System.currentTimeMillis() - pStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time between the given start time and now (as defined by
|
||||
* {@link System#currentTimeMillis()}).
|
||||
*
|
||||
* @param pStart the start time
|
||||
*
|
||||
* @return the time between the given start time and now.
|
||||
*/
|
||||
public static long delta(Date pStart) {
|
||||
return System.currentTimeMillis() - pStart.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current time, rounded down to the closest second.
|
||||
* Equivalent to invoking
|
||||
* {@code roundToSecond(System.currentTimeMillis())}.
|
||||
*
|
||||
* @return the current time, rounded to the closest second.
|
||||
*/
|
||||
public static long currentTimeSecond() {
|
||||
return roundToSecond(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current time, rounded down to the closest minute.
|
||||
* Equivalent to invoking
|
||||
* {@code roundToMinute(System.currentTimeMillis())}.
|
||||
*
|
||||
* @return the current time, rounded to the closest minute.
|
||||
*/
|
||||
public static long currentTimeMinute() {
|
||||
return roundToMinute(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current time, rounded down to the closest hour.
|
||||
* Equivalent to invoking
|
||||
* {@code roundToHour(System.currentTimeMillis())}.
|
||||
*
|
||||
* @return the current time, rounded to the closest hour.
|
||||
*/
|
||||
public static long currentTimeHour() {
|
||||
return roundToHour(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current time, rounded down to the closest day.
|
||||
* Equivalent to invoking
|
||||
* {@code roundToDay(System.currentTimeMillis())}.
|
||||
*
|
||||
* @return the current time, rounded to the closest day.
|
||||
*/
|
||||
public static long currentTimeDay() {
|
||||
return roundToDay(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the given time down to the closest second.
|
||||
*
|
||||
* @param pTime time
|
||||
* @return the time rounded to the closest second.
|
||||
*/
|
||||
public static long roundToSecond(long pTime) {
|
||||
return (pTime / SECOND) * SECOND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the given time down to the closest minute.
|
||||
*
|
||||
* @param pTime time
|
||||
* @return the time rounded to the closest minute.
|
||||
*/
|
||||
public static long roundToMinute(long pTime) {
|
||||
return (pTime / MINUTE) * MINUTE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the given time down to the closest hour, using the default timezone.
|
||||
*
|
||||
* @param pTime time
|
||||
* @return the time rounded to the closest hour.
|
||||
*/
|
||||
public static long roundToHour(long pTime) {
|
||||
// TODO: What if timezone offset is sub hour? Are there any? I think so...
|
||||
return ((pTime / HOUR) * HOUR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the given time down to the closest day, using the default timezone.
|
||||
*
|
||||
* @param pTime time
|
||||
* @return the time rounded to the closest day.
|
||||
*/
|
||||
public static long roundToDay(long pTime) {
|
||||
return roundToDay(pTime, TimeZone.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the given time down to the closest day, using the given timezone.
|
||||
*
|
||||
* @param pTime time
|
||||
* @param pTimeZone the timezone to use when rounding
|
||||
* @return the time rounded to the closest day.
|
||||
*/
|
||||
public static long roundToDay(long pTime, TimeZone pTimeZone) {
|
||||
int offset = pTimeZone.getOffset(pTime);
|
||||
return (((pTime + offset) / DAY) * DAY) - offset;
|
||||
}
|
||||
|
||||
public static void main(String[] pArgs) throws ParseException {
|
||||
DateFormat format = new SimpleDateFormat("yyyy.MM.dd HH.mm.ss S");
|
||||
|
||||
long time = pArgs.length > 0 ? format.parse(pArgs[0]).getTime() : System.currentTimeMillis();
|
||||
|
||||
System.out.println(time + ": " + format.format(new Date(time)));
|
||||
time = roundToSecond(time);
|
||||
System.out.println(time + ": " + format.format(new Date(time)));
|
||||
time = roundToMinute(time);
|
||||
System.out.println(time + ": " + format.format(new Date(time)));
|
||||
time = roundToHour(time);
|
||||
System.out.println(time + ": " + format.format(new Date(time)));
|
||||
time = roundToDay(time);
|
||||
System.out.println(time + ": " + format.format(new Date(time)));
|
||||
}
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* ExceptionUtil
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/ExceptionUtil.java#2 $
|
||||
*/
|
||||
public final class ExceptionUtil {
|
||||
|
||||
/*public*/ static void launder(final Throwable pThrowable, Class<? extends Throwable>... pExpectedTypes) {
|
||||
if (pThrowable instanceof Error) {
|
||||
throw (Error) pThrowable;
|
||||
}
|
||||
if (pThrowable instanceof RuntimeException) {
|
||||
throw (RuntimeException) pThrowable;
|
||||
}
|
||||
|
||||
for (Class<? extends Throwable> expectedType : pExpectedTypes) {
|
||||
if (expectedType.isInstance(pThrowable)) {
|
||||
throw new RuntimeException(pThrowable);
|
||||
}
|
||||
}
|
||||
|
||||
throw new UndeclaredThrowableException(pThrowable);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "UnusedDeclaration"})
|
||||
static <T extends Throwable> void throwAs(final Class<T> pType, final Throwable pThrowable) throws T {
|
||||
throw (T) pThrowable;
|
||||
}
|
||||
|
||||
public static void throwUnchecked(final Throwable pThrowable) {
|
||||
throwAs(RuntimeException.class, pThrowable);
|
||||
}
|
||||
|
||||
/*public*/ static void handle(final Throwable pThrowable, final ThrowableHandler<? extends Throwable>... pHandler) {
|
||||
handleImpl(pThrowable, pHandler);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private static <T extends Throwable> void handleImpl(final Throwable pThrowable, final ThrowableHandler<T>... pHandler) {
|
||||
// TODO: Sort more specific throwable handlers before less specific?
|
||||
for (ThrowableHandler<T> handler : pHandler) {
|
||||
if (handler.handles(pThrowable)) {
|
||||
handler.handle((T) pThrowable);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throwUnchecked(pThrowable);
|
||||
}
|
||||
|
||||
public static abstract class ThrowableHandler<T extends Throwable> {
|
||||
private Class<? extends T>[] mThrowables;
|
||||
|
||||
protected ThrowableHandler(final Class<? extends T>... pThrowables) {
|
||||
// TODO: Assert not null
|
||||
mThrowables = pThrowables.clone();
|
||||
}
|
||||
|
||||
final public boolean handles(final Throwable pThrowable) {
|
||||
for (Class<? extends T> throwable : mThrowables) {
|
||||
if (throwable.isAssignableFrom(pThrowable.getClass())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract void handle(T pThrowable);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"InfiniteLoopStatement"})
|
||||
public static void main(String[] pArgs) {
|
||||
while (true) {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
|
||||
private static void foo() {
|
||||
try {
|
||||
bar();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
handle(t,
|
||||
new ThrowableHandler<IOException>(IOException.class) {
|
||||
public void handle(final IOException pThrowable) {
|
||||
System.out.println("IOException: " + pThrowable + " handled");
|
||||
}
|
||||
},
|
||||
new ThrowableHandler<Exception>(SQLException.class, NumberFormatException.class) {
|
||||
public void handle(final Exception pThrowable) {
|
||||
System.out.println("Exception: " + pThrowable + " handled");
|
||||
}
|
||||
},
|
||||
new ThrowableHandler<Throwable>(Throwable.class) {
|
||||
public void handle(final Throwable pThrowable) {
|
||||
System.err.println("Generic throwable: " + pThrowable + " NOT handled");
|
||||
throwUnchecked(pThrowable);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static void bar() {
|
||||
baz();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"ThrowableInstanceNeverThrown"})
|
||||
private static void baz() {
|
||||
double random = Math.random();
|
||||
if (random < (1.0 / 3.0)) {
|
||||
throwUnchecked(new FileNotFoundException("FNF Boo"));
|
||||
}
|
||||
if (random < (2.0 / 3.0)) {
|
||||
throwUnchecked(new SQLException("SQL Boo"));
|
||||
}
|
||||
else {
|
||||
throwUnchecked(new Exception("Some Boo"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
/**
|
||||
* The class MathUtil contains methods for performing basic numeric operations
|
||||
* such as the elementary exponential, logarithm, square root, and
|
||||
* trigonometric functions.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/MathUtil.java#1 $
|
||||
*/
|
||||
public final class MathUtil {
|
||||
|
||||
/** */
|
||||
private MathUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an angle measured in degrees to the equivalent angle measured
|
||||
* in radians.
|
||||
* This method is a replacement for the Math.toRadians() method in
|
||||
* Java versions < 1.2 (typically for Applets).
|
||||
*
|
||||
* @param pAngDeg an angle, in degrees
|
||||
* @return the measurement of the angle {@code angdeg} in radians.
|
||||
*
|
||||
* @see java.lang.Math#toRadians(double)
|
||||
*/
|
||||
public static double toRadians(final double pAngDeg) {
|
||||
return pAngDeg * Math.PI / 180.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an angle measured in radians to the equivalent angle measured
|
||||
* in degrees.
|
||||
* This method is a replacement for the Math.toDegrees() method in
|
||||
* Java versions < 1.2 (typically for Applets).
|
||||
*
|
||||
* @param pAngRad an angle, in radians
|
||||
* @return the measurement of the angle {@code angrad} in degrees.
|
||||
*
|
||||
* @see java.lang.Math#toDegrees(double)
|
||||
*/
|
||||
public static double toDegrees(final double pAngRad) {
|
||||
return pAngRad * 180.0 / Math.PI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the natural logarithm (base <I>e</I>) of a double value.
|
||||
* Equivalent to {@code java.lang.Math.log}, just with a proper name.
|
||||
*
|
||||
* @param pArg a number greater than 0.0.
|
||||
* @return the value ln {@code pArg}, the natural logarithm of
|
||||
* {@code pArg}.
|
||||
*
|
||||
* @see java.lang.Math#log(double)
|
||||
*/
|
||||
public static double ln(final double pArg) {
|
||||
return Math.log(pArg);
|
||||
}
|
||||
|
||||
private final static double LN_10 = Math.log(10);
|
||||
|
||||
/**
|
||||
* Returns the base 10 logarithm of a double value.
|
||||
*
|
||||
* @param pArg a number greater than 0.0.
|
||||
* @return the value log {@code pArg}, the base 10 logarithm of
|
||||
* {@code pArg}.
|
||||
*/
|
||||
public static double log(final double pArg) {
|
||||
return Math.log(pArg) / LN_10;
|
||||
}
|
||||
|
||||
private final static double LN_2 = Math.log(10);
|
||||
|
||||
/**
|
||||
* Returns the base 2 logarithm of a double value.
|
||||
*
|
||||
* @param pArg a number greater than 0.0.
|
||||
* @return the value log<SUB>2</SUB> {@code pArg}, the base 2
|
||||
* logarithm of {@code pArg}.
|
||||
*/
|
||||
public static double log2(final double pArg) {
|
||||
return Math.log(pArg) / LN_2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base <i>N</i> logarithm of a double value, for a given base
|
||||
* <i>N</i>.
|
||||
*
|
||||
* @param pArg a number greater than 0.0.
|
||||
* @param pBase a number greater than 0.0.
|
||||
*
|
||||
* @return the value log<SUB>pBase</SUB> {@code pArg}, the base
|
||||
* {@code pBase} logarithm of {@code pArg}.
|
||||
*/
|
||||
public static double log(final double pArg, final double pBase) {
|
||||
return Math.log(pArg) / Math.log(pBase);
|
||||
}
|
||||
|
||||
/**
|
||||
* A replacement for {@code Math.abs}, that never returns negative values.
|
||||
* {@code Math.abs(long)} does this for {@code Long.MIN_VALUE}.
|
||||
*
|
||||
* @see Math#abs(long)
|
||||
* @see Long#MIN_VALUE
|
||||
*
|
||||
* @param pNumber
|
||||
* @return the absolute value of {@code pNumber}
|
||||
*
|
||||
* @throws ArithmeticException if {@code pNumber == Long.MIN_VALUE}
|
||||
*/
|
||||
public static long abs(final long pNumber) {
|
||||
if (pNumber == Long.MIN_VALUE) {
|
||||
throw new ArithmeticException("long overflow: 9223372036854775808");
|
||||
}
|
||||
return (pNumber < 0) ? -pNumber : pNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* A replacement for {@code Math.abs}, that never returns negative values.
|
||||
* {@code Math.abs(int)} does this for {@code Integer.MIN_VALUE}.
|
||||
*
|
||||
* @see Math#abs(int)
|
||||
* @see Integer#MIN_VALUE
|
||||
*
|
||||
* @param pNumber
|
||||
* @return the absolute value of {@code pNumber}
|
||||
*
|
||||
* @throws ArithmeticException if {@code pNumber == Integer.MIN_VALUE}
|
||||
*/
|
||||
public static int abs(final int pNumber) {
|
||||
if (pNumber == Integer.MIN_VALUE) {
|
||||
throw new ArithmeticException("int overflow: 2147483648");
|
||||
}
|
||||
return (pNumber < 0) ? -pNumber : pNumber;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
/**
|
||||
* Platform
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/Platform.java#1 $
|
||||
*/
|
||||
public final class Platform {
|
||||
/**
|
||||
* Normalized operating system constant
|
||||
*/
|
||||
final OperatingSystem mOS;
|
||||
|
||||
/**
|
||||
* Unormalized operating system version constant (for completeness)
|
||||
*/
|
||||
final String mVersion;
|
||||
|
||||
/**
|
||||
* Normalized system architecture constant
|
||||
*/
|
||||
final Architecture mArchitecture;
|
||||
|
||||
static final private Platform INSTANCE = new Platform();
|
||||
|
||||
private Platform() {
|
||||
mOS = normalizeOperatingSystem();
|
||||
mVersion = System.getProperty("os.version");
|
||||
mArchitecture = normalizeArchitecture(mOS);
|
||||
}
|
||||
|
||||
private static OperatingSystem normalizeOperatingSystem() {
|
||||
String os = System.getProperty("os.name");
|
||||
if (os == null) {
|
||||
throw new IllegalStateException("System property \"os.name\" == null");
|
||||
}
|
||||
|
||||
os = os.toLowerCase();
|
||||
if (os.startsWith("windows")) {
|
||||
return OperatingSystem.Windows;
|
||||
}
|
||||
else if (os.startsWith("linux")) {
|
||||
return OperatingSystem.Linux;
|
||||
}
|
||||
else if (os.startsWith("mac os")) {
|
||||
return OperatingSystem.MacOS;
|
||||
}
|
||||
else if (os.startsWith("solaris") || os.startsWith("sunos")) {
|
||||
return OperatingSystem.Solaris;
|
||||
}
|
||||
|
||||
return OperatingSystem.Unknown;
|
||||
}
|
||||
|
||||
private static Architecture normalizeArchitecture(final OperatingSystem pOsName) {
|
||||
String arch = System.getProperty("os.arch");
|
||||
if (arch == null) {
|
||||
throw new IllegalStateException("System property \"os.arch\" == null");
|
||||
}
|
||||
|
||||
arch = arch.toLowerCase();
|
||||
if (pOsName == OperatingSystem.Windows
|
||||
&& (arch.startsWith("x86") || arch.startsWith("i386"))) {
|
||||
return Architecture.X86;
|
||||
// TODO: 64 bit
|
||||
}
|
||||
else if (pOsName == OperatingSystem.Linux) {
|
||||
if (arch.startsWith("x86") || arch.startsWith("i386")) {
|
||||
return Architecture.I386;
|
||||
}
|
||||
else if (arch.startsWith("i686")) {
|
||||
return Architecture.I686;
|
||||
}
|
||||
// TODO: More Linux options?
|
||||
// TODO: 64 bit
|
||||
}
|
||||
else if (pOsName == OperatingSystem.MacOS) {
|
||||
if (arch.startsWith("power") || arch.startsWith("ppc")) {
|
||||
return Architecture.PPC;
|
||||
}
|
||||
else if (arch.startsWith("i386")) {
|
||||
return Architecture.I386;
|
||||
}
|
||||
}
|
||||
else if (pOsName == OperatingSystem.Solaris) {
|
||||
if (arch.startsWith("sparc")) {
|
||||
return Architecture.SPARC;
|
||||
}
|
||||
if (arch.startsWith("x86")) {
|
||||
// TODO: Should we use i386 as Linux and Mac does?
|
||||
return Architecture.X86;
|
||||
}
|
||||
// TODO: 64 bit
|
||||
}
|
||||
|
||||
return Architecture.Unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current {@code Platform}.
|
||||
* @return the current {@code Platform}.
|
||||
*/
|
||||
public static Platform get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return this platform's OS.
|
||||
*/
|
||||
public OperatingSystem getOS() {
|
||||
return mOS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return this platform's OS version.
|
||||
*/
|
||||
public String getVersion() {
|
||||
return mVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return this platform's architecture.
|
||||
*/
|
||||
public Architecture getArchitecture() {
|
||||
return mArchitecture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shorthand for {@code Platform.get().getOS()}.
|
||||
* @return the current {@code OperatingSystem}.
|
||||
*/
|
||||
public static OperatingSystem os() {
|
||||
return INSTANCE.mOS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shorthand for {@code Platform.get().getVersion()}.
|
||||
* @return the current OS version.
|
||||
*/
|
||||
public static String version() {
|
||||
return INSTANCE.mVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shorthand for {@code Platform.get().getArchitecture()}.
|
||||
* @return the current {@code Architecture}.
|
||||
*/
|
||||
public static Architecture arch() {
|
||||
return INSTANCE.mArchitecture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumeration of common System {@code Architecture}s.
|
||||
* <p/>
|
||||
* For {@link #Unknown unknown architectures}, {@code toString()} will return
|
||||
* the the same value as {@code System.getProperty("os.arch")}.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/Platform.java#1 $
|
||||
*/
|
||||
public static enum Architecture {
|
||||
X86("x86"),
|
||||
I386("i386"),
|
||||
I686("i686"),
|
||||
PPC("ppc"),
|
||||
SPARC("sparc"),
|
||||
|
||||
Unknown(System.getProperty("os.arch"));
|
||||
|
||||
final String mName;// for debug only
|
||||
|
||||
private Architecture(String pName) {
|
||||
mName = pName;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return mName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumeration of common {@code OperatingSystem}s.
|
||||
* <p/>
|
||||
* For {@link #Unknown unknown operating systems}, {@code getName()} will return
|
||||
* the the same value as {@code System.getProperty("os.name")}.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/Platform.java#1 $
|
||||
*/
|
||||
public static enum OperatingSystem {
|
||||
Windows("Windows", "win"),
|
||||
Linux("Linux", "lnx"),
|
||||
Solaris("Solaris", "sun"),
|
||||
MacOS("Mac OS", "osx"),
|
||||
|
||||
Unknown(System.getProperty("os.name"), "");
|
||||
|
||||
final String mId;
|
||||
final String mName;// for debug only
|
||||
|
||||
private OperatingSystem(String pName, String pId) {
|
||||
mName = pName;
|
||||
mId = pId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return mId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
/**
|
||||
* Util class for various reflection-based operations.
|
||||
* <p/>
|
||||
* <em>NOTE: This class is not considered part of the public API and may be
|
||||
* changed without notice</em>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/ReflectUtil.java#1 $
|
||||
*/
|
||||
public final class ReflectUtil {
|
||||
|
||||
/** Don't allow instances */
|
||||
private ReflectUtil() {}
|
||||
|
||||
/**
|
||||
* Returns the primitive type for the given wrapper type.
|
||||
*
|
||||
* @param pType the wrapper type
|
||||
*
|
||||
* @return the primitive type
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code pType} is not a primitive
|
||||
* wrapper
|
||||
*/
|
||||
public static Class unwrapType(Class pType) {
|
||||
if (pType == Boolean.class) {
|
||||
return Boolean.TYPE;
|
||||
}
|
||||
else if (pType == Byte.class) {
|
||||
return Byte.TYPE;
|
||||
}
|
||||
else if (pType == Character.class) {
|
||||
return Character.TYPE;
|
||||
}
|
||||
else if (pType == Double.class) {
|
||||
return Double.TYPE;
|
||||
}
|
||||
else if (pType == Float.class) {
|
||||
return Float.TYPE;
|
||||
}
|
||||
else if (pType == Integer.class) {
|
||||
return Integer.TYPE;
|
||||
}
|
||||
else if (pType == Long.class) {
|
||||
return Long.TYPE;
|
||||
}
|
||||
else if (pType == Short.class) {
|
||||
return Short.TYPE;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Not a primitive wrapper: " + pType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wrapper type for the given primitive type.
|
||||
*
|
||||
* @param pType the primitive tpye
|
||||
*
|
||||
* @return the wrapper type
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code pType} is not a primitive
|
||||
* type
|
||||
*/
|
||||
public static Class wrapType(Class pType) {
|
||||
if (pType == Boolean.TYPE) {
|
||||
return Boolean.class;
|
||||
}
|
||||
else if (pType == Byte.TYPE) {
|
||||
return Byte.class;
|
||||
}
|
||||
else if (pType == Character.TYPE) {
|
||||
return Character.class;
|
||||
}
|
||||
else if (pType == Double.TYPE) {
|
||||
return Double.class;
|
||||
}
|
||||
else if (pType == Float.TYPE) {
|
||||
return Float.class;
|
||||
}
|
||||
else if (pType == Integer.TYPE) {
|
||||
return Integer.class;
|
||||
}
|
||||
else if (pType == Long.TYPE) {
|
||||
return Long.class;
|
||||
}
|
||||
else if (pType == Short.TYPE) {
|
||||
return Short.class;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Not a primitive type: " + pType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the given type is a primitive wrapper.
|
||||
*
|
||||
* @param pType
|
||||
*
|
||||
* @return {@code true} if the given type is a primitive wrapper, otherwise
|
||||
* {@code false}
|
||||
*/
|
||||
public static boolean isPrimitiveWrapper(Class pType) {
|
||||
return pType == Boolean.class || pType == Byte.class
|
||||
|| pType == Character.class || pType == Double.class
|
||||
|| pType == Float.class || pType == Integer.class
|
||||
|| pType == Long.class || pType == Short.class;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,693 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
import com.twelvemonkeys.util.XMLProperties;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* A utility class with some useful system-related functions.
|
||||
* <p/>
|
||||
* <em>NOTE: This class is not considered part of the public API and may be
|
||||
* changed without notice</em>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/SystemUtil.java#3 $
|
||||
*
|
||||
*/
|
||||
public final class SystemUtil {
|
||||
/** {@code ".xml"} */
|
||||
public static String XML_PROPERTIES = ".xml";
|
||||
/** {@code ".properties"} */
|
||||
public static String STD_PROPERTIES = ".properties";
|
||||
|
||||
// Disallow creating objects of this type
|
||||
private SystemUtil() {
|
||||
}
|
||||
|
||||
/** This class marks an inputstream as containing XML, does nothing */
|
||||
private static class XMLPropertiesInputStream extends FilterInputStream {
|
||||
public XMLPropertiesInputStream(InputStream pIS) {
|
||||
super(pIS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the named resource as a stream from the given Class' Classoader.
|
||||
* If the pGuessSuffix parameter is true, the method will try to append
|
||||
* typical properties file suffixes, such as ".properties" or ".xml".
|
||||
*
|
||||
* @param pClassLoader the class loader to use
|
||||
* @param pName name of the resource
|
||||
* @param pGuessSuffix guess suffix
|
||||
*
|
||||
* @return an input stream reading from the resource
|
||||
*/
|
||||
private static InputStream getResourceAsStream(ClassLoader pClassLoader, String pName,
|
||||
boolean pGuessSuffix) {
|
||||
InputStream is;
|
||||
|
||||
if (!pGuessSuffix) {
|
||||
is = pClassLoader.getResourceAsStream(pName);
|
||||
|
||||
// If XML, wrap stream
|
||||
if (is != null && pName.endsWith(XML_PROPERTIES)) {
|
||||
is = new XMLPropertiesInputStream(is);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Try normal properties
|
||||
is = pClassLoader.getResourceAsStream(pName + STD_PROPERTIES);
|
||||
|
||||
// Try XML
|
||||
if (is == null) {
|
||||
is = pClassLoader.getResourceAsStream(pName + XML_PROPERTIES);
|
||||
|
||||
// Wrap stream
|
||||
if (is != null) {
|
||||
is = new XMLPropertiesInputStream(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return stream
|
||||
return is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the named file as a stream from the current directory.
|
||||
* If the pGuessSuffix parameter is true, the method will try to append
|
||||
* typical properties file suffixes, such as ".properties" or ".xml".
|
||||
*
|
||||
* @param pName name of the resource
|
||||
* @param pGuessSuffix guess suffix
|
||||
*
|
||||
* @return an input stream reading from the resource
|
||||
*/
|
||||
private static InputStream getFileAsStream(String pName,
|
||||
boolean pGuessSuffix) {
|
||||
InputStream is = null;
|
||||
File propertiesFile;
|
||||
|
||||
try {
|
||||
if (!pGuessSuffix) {
|
||||
// Get file
|
||||
propertiesFile = new File(pName);
|
||||
|
||||
if (propertiesFile.exists()) {
|
||||
is = new FileInputStream(propertiesFile);
|
||||
|
||||
// If XML, wrap stream
|
||||
if (pName.endsWith(XML_PROPERTIES)) {
|
||||
is = new XMLPropertiesInputStream(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Try normal properties
|
||||
propertiesFile = new File(pName + STD_PROPERTIES);
|
||||
|
||||
if (propertiesFile.exists()) {
|
||||
is = new FileInputStream(propertiesFile);
|
||||
}
|
||||
else {
|
||||
// Try XML
|
||||
propertiesFile = new File(pName + XML_PROPERTIES);
|
||||
|
||||
if (propertiesFile.exists()) {
|
||||
// Wrap stream
|
||||
is = new XMLPropertiesInputStream(new FileInputStream(propertiesFile));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException fnf) {
|
||||
// Should not happen, as we always test that the file .exists()
|
||||
// before creating InputStream
|
||||
// assert false;
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for loading a named properties-file for a class.
|
||||
* <P>
|
||||
* The properties-file is loaded through either:
|
||||
* <OL>
|
||||
* <LI>The given class' class loader (from classpath)</LI>
|
||||
* <LI>Or, the system class loader (from classpath)</LI>
|
||||
* <LI>Or, if it cannot be found in the classpath, an attempt to read from
|
||||
* the current directory (or full path if given).</LI>
|
||||
* </OL>
|
||||
* <P>
|
||||
* Both normal java.util.Properties and com.twelvemonkeys.util.XMLProperties
|
||||
* are supported (XML-properties must have ".xml" as its file extension).
|
||||
*
|
||||
* @param pClass The class to load properties for. If this parameter is
|
||||
* {@code null}, the method will work exactly as
|
||||
* {@link #loadProperties(String)}
|
||||
* @param pName The name of the properties-file. If this parameter is
|
||||
* {@code null}, the method will work exactly as
|
||||
* {@link #loadProperties(Class)}
|
||||
*
|
||||
* @return A Properties mapping read from the given file or for the given
|
||||
* class. <!--If no properties-file was found, an empty Properties object is
|
||||
* returned.-->
|
||||
*
|
||||
* @throws NullPointerException if both {@code pName} and
|
||||
* {@code pClass} paramters are {@code null}
|
||||
* @throws IOException if an error occurs during load.
|
||||
* @throws FileNotFoundException if no properties-file could be found.
|
||||
*
|
||||
* @see #loadProperties(String)
|
||||
* @see #loadProperties(Class)
|
||||
* @see java.lang.ClassLoader#getResourceAsStream
|
||||
* @see java.lang.ClassLoader#getSystemResourceAsStream
|
||||
*
|
||||
* @todo Reconsider ever using the System ClassLoader: http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html
|
||||
* @todo Consider using Context Classloader instead?
|
||||
*/
|
||||
public static Properties loadProperties(Class pClass, String pName)
|
||||
throws IOException
|
||||
{
|
||||
// Convert to name the classloader understands
|
||||
String name = !StringUtil.isEmpty(pName) ? pName : pClass.getName().replace('.', '/');
|
||||
|
||||
// Should we try to guess suffix?
|
||||
boolean guessSuffix = (pName == null || pName.indexOf('.') < 0);
|
||||
|
||||
InputStream is;
|
||||
|
||||
// TODO: WHAT IF MULTIPLE RESOURCES EXISTS?!
|
||||
// Try loading resource through the current class' classloader
|
||||
if (pClass != null
|
||||
&& (is = getResourceAsStream(pClass.getClassLoader(), name, guessSuffix)) != null) {
|
||||
//&& (is = getResourceAsStream(pClass, name, guessSuffix)) != null) {
|
||||
// Nothing to do
|
||||
//System.out.println(((is instanceof XMLPropertiesInputStream) ?
|
||||
// "XML-properties" : "Normal .properties")
|
||||
// + " from Class' ClassLoader");
|
||||
}
|
||||
// If that fails, try the system classloader
|
||||
else if ((is = getResourceAsStream(ClassLoader.getSystemClassLoader(),
|
||||
name, guessSuffix)) != null) {
|
||||
//else if ((is = getSystemResourceAsStream(name, guessSuffix)) != null) {
|
||||
// Nothing to do
|
||||
//System.out.println(((is instanceof XMLPropertiesInputStream) ?
|
||||
// "XML-properties" : "Normal .properties")
|
||||
// + " from System ClassLoader");
|
||||
}
|
||||
// All failed, try loading from file
|
||||
else if ((is = getFileAsStream(name, guessSuffix)) != null) {
|
||||
//System.out.println(((is instanceof XMLPropertiesInputStream) ?
|
||||
// "XML-properties" : "Normal .properties")
|
||||
// + " from System ClassLoader");
|
||||
}
|
||||
else {
|
||||
if (guessSuffix) {
|
||||
// TODO: file extension iterator or something...
|
||||
throw new FileNotFoundException(name + ".properties or " + name + ".xml");
|
||||
}
|
||||
else {
|
||||
throw new FileNotFoundException(name);
|
||||
}
|
||||
}
|
||||
|
||||
// We have inputstream now, load...
|
||||
try {
|
||||
return loadProperties(is);
|
||||
}
|
||||
finally {
|
||||
// NOTE: If is == null, a FileNotFoundException must have been thrown above
|
||||
try {
|
||||
is.close();
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
// Not critical...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for loading a properties-file for a given class.
|
||||
* The properties are searched for on the form
|
||||
* "com/package/ClassName.properties" or
|
||||
* "com/package/ClassName.xml".
|
||||
* <P>
|
||||
* The properties-file is loaded through either:
|
||||
* <OL>
|
||||
* <LI>The given class' class loader (from classpath)</LI>
|
||||
* <LI>Or, the system class loader (from classpath)</LI>
|
||||
* <LI>Or, if it cannot be found in the classpath, an attempt to read from
|
||||
* the current directory (or full path if given).</LI>
|
||||
* </OL>
|
||||
* <P>
|
||||
* Both normal java.util.Properties and com.twelvemonkeys.util.XMLProperties
|
||||
* are supported (XML-properties must have ".xml" as its file extension).
|
||||
*
|
||||
* @param pClass The class to load properties for
|
||||
* @return A Properties mapping for the given class. <!--If no properties-
|
||||
* file was found, an empty Properties object is returned.-->
|
||||
*
|
||||
* @throws NullPointerException if the {@code pClass} paramters is
|
||||
* {@code null}
|
||||
* @throws IOException if an error occurs during load.
|
||||
* @throws FileNotFoundException if no properties-file could be found.
|
||||
*
|
||||
* @see #loadProperties(String)
|
||||
* @see #loadProperties(Class, String)
|
||||
* @see java.lang.ClassLoader#getResourceAsStream
|
||||
* @see java.lang.ClassLoader#getSystemResourceAsStream
|
||||
*
|
||||
*/
|
||||
public static Properties loadProperties(Class pClass) throws IOException {
|
||||
return loadProperties(pClass, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for loading a named properties-file.
|
||||
* <P>
|
||||
* The properties-file is loaded through either:
|
||||
* <OL>
|
||||
* <LI>The system class loader (from classpath)</LI>
|
||||
* <LI>Or, if it cannot be found in the classpath, an attempt to read from
|
||||
* the current directory.</LI>
|
||||
* </OL>
|
||||
* <P>
|
||||
* Both normal java.util.Properties and com.twelvemonkeys.util.XMLProperties
|
||||
* are supported (XML-properties must have ".xml" as its file extension).
|
||||
*
|
||||
* @param pName The name of the properties-file.
|
||||
* @return A Properties mapping read from the given file. <!--If no properties-
|
||||
* file was found, an empty Properties object is returned.-->
|
||||
*
|
||||
* @throws NullPointerException if the {@code pName} paramters is
|
||||
* {@code null}
|
||||
* @throws IOException if an error occurs during load.
|
||||
* @throws FileNotFoundException if no properties-file could be found.
|
||||
*
|
||||
* @see #loadProperties(Class)
|
||||
* @see #loadProperties(Class, String)
|
||||
* @see java.lang.ClassLoader#getSystemResourceAsStream
|
||||
*
|
||||
*/
|
||||
public static Properties loadProperties(String pName) throws IOException {
|
||||
return loadProperties(null, pName);
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility method for loading a properties-file.
|
||||
* <P>
|
||||
* The properties files may also be contained in a zip/jar-file named
|
||||
* by the {@code com.twelvemonkeys.util.Config} system property (use "java -D"
|
||||
* to override). Default is "config.zip" in the current directory.
|
||||
*
|
||||
* @param pName The name of the file to loaded
|
||||
* @return A Properties mapping for the given class. If no properties-
|
||||
* file was found, an empty Properties object is returned.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
public static Properties loadProperties(String pName) throws IOException {
|
||||
// Use XML?
|
||||
boolean useXML = pName.endsWith(XML_PROPERTIES) ? true : false;
|
||||
|
||||
InputStream is = null;
|
||||
|
||||
File file = new File(pName);
|
||||
|
||||
String configName = System.getProperty("com.twelvemonkeys.util.Config");
|
||||
File configArchive = new File(!StringUtil.isEmpty(configName)
|
||||
? configName : DEFAULT_CONFIG);
|
||||
|
||||
// Get input stream to the file containing the properties
|
||||
if (file.exists()) {
|
||||
// Try reading from file, normal way
|
||||
is = new FileInputStream(file);
|
||||
}
|
||||
else if (configArchive.exists()) {
|
||||
// Try reading properties from zip-file
|
||||
ZipFile zip = new ZipFile(configArchive);
|
||||
ZipEntry ze = zip.getEntry(pName);
|
||||
if (ze != null) {
|
||||
is = zip.getInputStream(ze);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Do the loading
|
||||
try {
|
||||
// Load the properties
|
||||
return loadProperties(is, useXML);
|
||||
}
|
||||
finally {
|
||||
// Try closing the archive to free resources
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
// Not critical...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a Properties, loaded from the given inputstream. If the given
|
||||
* inputstream is null, then an empty Properties object is returned.
|
||||
*
|
||||
* @param pInput the inputstream to read from
|
||||
*
|
||||
* @return a Properties object read from the given stream, or an empty
|
||||
* Properties mapping, if the stream is null.
|
||||
*
|
||||
* @throws IOException if an error occurred when reading from the input
|
||||
* stream.
|
||||
*
|
||||
*/
|
||||
private static Properties loadProperties(InputStream pInput)
|
||||
throws IOException {
|
||||
|
||||
if (pInput == null) {
|
||||
throw new IllegalArgumentException("InputStream == null!");
|
||||
}
|
||||
|
||||
Properties mapping;
|
||||
if (pInput instanceof XMLPropertiesInputStream) {
|
||||
mapping = new XMLProperties();
|
||||
}
|
||||
else {
|
||||
mapping = new Properties();
|
||||
}
|
||||
|
||||
// Load the properties
|
||||
mapping.load(pInput);
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"SuspiciousSystemArraycopy"})
|
||||
public static Object clone(final Cloneable pObject) throws CloneNotSupportedException {
|
||||
if (pObject == null) {
|
||||
return null; // Null is clonable.. Easy. ;-)
|
||||
}
|
||||
|
||||
// All arrays does have a clone method, but it's invisible for reflection...
|
||||
// By luck, multi-dimensional primitive arrays are instances of Object[]
|
||||
if (pObject instanceof Object[]) {
|
||||
return ((Object[]) pObject).clone();
|
||||
}
|
||||
else if (pObject.getClass().isArray()) {
|
||||
// One-dimensional primitive array, cloned manually
|
||||
int lenght = Array.getLength(pObject);
|
||||
Object clone = Array.newInstance(pObject.getClass().getComponentType(), lenght);
|
||||
System.arraycopy(pObject, 0, clone, 0, lenght);
|
||||
return clone;
|
||||
}
|
||||
|
||||
try {
|
||||
// Find the clone method
|
||||
Method clone = null;
|
||||
Class clazz = pObject.getClass();
|
||||
do {
|
||||
try {
|
||||
clone = clazz.getDeclaredMethod("clone");
|
||||
break; // Found, or throws exception above
|
||||
}
|
||||
catch (NoSuchMethodException ignore) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
while ((clazz = clazz.getSuperclass()) != null);
|
||||
|
||||
// NOTE: This should never happen
|
||||
if (clone == null) {
|
||||
throw new CloneNotSupportedException(pObject.getClass().getName());
|
||||
}
|
||||
|
||||
// Override access if needed
|
||||
if (!clone.isAccessible()) {
|
||||
clone.setAccessible(true);
|
||||
}
|
||||
|
||||
// Invoke clone method on original object
|
||||
return clone.invoke(pObject);
|
||||
}
|
||||
catch (SecurityException e) {
|
||||
CloneNotSupportedException cns = new CloneNotSupportedException(pObject.getClass().getName());
|
||||
cns.initCause(e);
|
||||
throw cns;
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new CloneNotSupportedException(pObject.getClass().getName());
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
if (e.getTargetException() instanceof CloneNotSupportedException) {
|
||||
throw (CloneNotSupportedException) e.getTargetException();
|
||||
}
|
||||
else if (e.getTargetException() instanceof RuntimeException) {
|
||||
throw (RuntimeException) e.getTargetException();
|
||||
}
|
||||
else if (e.getTargetException() instanceof Error) {
|
||||
throw (Error) e.getTargetException();
|
||||
}
|
||||
|
||||
throw new CloneNotSupportedException(pObject.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
// public static void loadLibrary(String pLibrary) {
|
||||
// NativeLoader.loadLibrary(pLibrary);
|
||||
// }
|
||||
//
|
||||
// public static void loadLibrary(String pLibrary, ClassLoader pLoader) {
|
||||
// NativeLoader.loadLibrary(pLibrary, pLoader);
|
||||
// }
|
||||
|
||||
public static void main(String[] args) throws CloneNotSupportedException {
|
||||
|
||||
System.out.println("clone: " + args.clone().length + " (" + args.length + ")");
|
||||
System.out.println("copy: " + ((String[]) clone(args)).length + " (" + args.length + ")");
|
||||
|
||||
int[] ints = {1,2,3};
|
||||
int[] copies = (int[]) clone(ints);
|
||||
System.out.println("Copies: " + copies.length + " (" + ints.length + ")");
|
||||
|
||||
int[][] intsToo = {{1}, {2,3}, {4,5,6}};
|
||||
int[][] copiesToo = (int[][]) clone(intsToo);
|
||||
System.out.println("Copies: " + copiesToo.length + " (" + intsToo.length + ")");
|
||||
System.out.println("Copies0: " + copiesToo[0].length + " (" + intsToo[0].length + ")");
|
||||
System.out.println("Copies1: " + copiesToo[1].length + " (" + intsToo[1].length + ")");
|
||||
System.out.println("Copies2: " + copiesToo[2].length + " (" + intsToo[2].length + ")");
|
||||
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
|
||||
for (String arg : args) {
|
||||
map.put(arg, arg);
|
||||
}
|
||||
|
||||
Map copy = (Map) clone((Cloneable) map);
|
||||
|
||||
System.out.println("Map : " + map);
|
||||
System.out.println("Copy: " + copy);
|
||||
|
||||
/*
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
|
||||
try {
|
||||
System.setSecurityManager(new SecurityManager() {
|
||||
public void checkPermission(Permission perm) {
|
||||
if (perm.getName().equals("suppressAccessChecks")) {
|
||||
throw new SecurityException();
|
||||
}
|
||||
//super.checkPermission(perm);
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
Cloneable cloneable = new Cloneable() {}; // No public clone method
|
||||
Cloneable clone = (Cloneable) clone(cloneable);
|
||||
|
||||
System.out.println("cloneable: " + cloneable);
|
||||
System.out.println("clone: " + clone);
|
||||
|
||||
/*
|
||||
}
|
||||
finally {
|
||||
System.setSecurityManager(sm);
|
||||
}
|
||||
*/
|
||||
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
return null;
|
||||
}
|
||||
}, AccessController.getContext());
|
||||
|
||||
//String string = args.length > 0 ? args[0] : "jaffa";
|
||||
//clone(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a named class is generally available.
|
||||
* If a class is considered available, a call to
|
||||
* {@code Class.forName(pClassName)} will not result in an exception.
|
||||
*
|
||||
* @param pClassName the class name to test
|
||||
* @return {@code true} if available
|
||||
*/
|
||||
public static boolean isClassAvailable(String pClassName) {
|
||||
return isClassAvailable(pClassName, (ClassLoader) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a named class is available from another class.
|
||||
* If a class is considered available, a call to
|
||||
* {@code Class.forName(pClassName, true, pFromClass.getClassLoader())}
|
||||
* will not result in an exception.
|
||||
*
|
||||
* @param pClassName the class name to test
|
||||
* @param pFromClass the class to test from
|
||||
* @return {@code true} if available
|
||||
*/
|
||||
public static boolean isClassAvailable(String pClassName, Class pFromClass) {
|
||||
ClassLoader loader = pFromClass != null ? pFromClass.getClassLoader() : null;
|
||||
return isClassAvailable(pClassName, loader);
|
||||
}
|
||||
|
||||
private static boolean isClassAvailable(String pClassName, ClassLoader pLoader) {
|
||||
try {
|
||||
// TODO: Sometimes init is not needed, but need to find a way to know...
|
||||
getClass(pClassName, true, pLoader);
|
||||
return true;
|
||||
}
|
||||
catch (SecurityException ignore) {
|
||||
// Ignore
|
||||
}
|
||||
catch (ClassNotFoundException ignore) {
|
||||
// Ignore
|
||||
}
|
||||
catch (LinkageError ignore) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isFieldAvailable(final String pClassName, final String pFieldName) {
|
||||
return isFieldAvailable(pClassName, pFieldName, (ClassLoader) null);
|
||||
}
|
||||
|
||||
public static boolean isFieldAvailable(final String pClassName, final String pFieldName, final Class pFromClass) {
|
||||
ClassLoader loader = pFromClass != null ? pFromClass.getClassLoader() : null;
|
||||
return isFieldAvailable(pClassName, pFieldName, loader);
|
||||
}
|
||||
|
||||
private static boolean isFieldAvailable(final String pClassName, final String pFieldName, final ClassLoader pLoader) {
|
||||
try {
|
||||
Class cl = getClass(pClassName, false, pLoader);
|
||||
|
||||
Field field = cl.getField(pFieldName);
|
||||
if (field != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ignore) {
|
||||
// Ignore
|
||||
}
|
||||
catch (LinkageError ignore) {
|
||||
// Ignore
|
||||
}
|
||||
catch (NoSuchFieldException ignore) {
|
||||
// Ignore
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isMethodAvailable(String pClassName, String pMethodName) {
|
||||
// Finds void only
|
||||
return isMethodAvailable(pClassName, pMethodName, null, (ClassLoader) null);
|
||||
}
|
||||
|
||||
public static boolean isMethodAvailable(String pClassName, String pMethodName, Class[] pParams) {
|
||||
return isMethodAvailable(pClassName, pMethodName, pParams, (ClassLoader) null);
|
||||
}
|
||||
|
||||
public static boolean isMethodAvailable(String pClassName, String pMethodName, Class[] pParams, Class pFromClass) {
|
||||
ClassLoader loader = pFromClass != null ? pFromClass.getClassLoader() : null;
|
||||
return isMethodAvailable(pClassName, pMethodName, pParams, loader);
|
||||
}
|
||||
|
||||
private static boolean isMethodAvailable(String pClassName, String pMethodName, Class[] pParams, ClassLoader pLoader) {
|
||||
try {
|
||||
Class cl = getClass(pClassName, false, pLoader);
|
||||
|
||||
Method method = cl.getMethod(pMethodName, pParams);
|
||||
if (method != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ignore) {
|
||||
// Ignore
|
||||
}
|
||||
catch (LinkageError ignore) {
|
||||
// Ignore
|
||||
}
|
||||
catch (NoSuchMethodException ignore) {
|
||||
// Ignore
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Class getClass(String pClassName, boolean pInitialize, ClassLoader pLoader) throws ClassNotFoundException {
|
||||
// NOTE: We need the context classloader, as SystemUtil's
|
||||
// classloader may have a totally different classloader than
|
||||
// the original caller class (as in Class.forName(cn, false, null)).
|
||||
ClassLoader loader = pLoader != null ? pLoader :
|
||||
Thread.currentThread().getContextClassLoader();
|
||||
|
||||
return Class.forName(pClassName, pInitialize, loader);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Kind of like {@code org.apache.commons.lang.Validate}. Just smarter. ;-)
|
||||
* <p/>
|
||||
* Uses type parameterized return values, thus making it possible to check
|
||||
* constructor arguments before
|
||||
* they are passed on to {@code super} or {@code this} type constructors.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/Validate.java#1 $
|
||||
*/
|
||||
public final class Validate {
|
||||
private static final String UNSPECIFIED_PARAM_NAME = "method parameter";
|
||||
|
||||
private Validate() {}
|
||||
|
||||
// Not null...
|
||||
|
||||
public static <T> T notNull(final T pParameter) {
|
||||
return notNull(pParameter, null);
|
||||
}
|
||||
|
||||
public static <T> T notNull(final T pParameter, final String pParamName) {
|
||||
if (pParameter == null) {
|
||||
throw new IllegalArgumentException(String.format("%s may not be null", pParamName == null ? UNSPECIFIED_PARAM_NAME : pParamName));
|
||||
}
|
||||
return pParameter;
|
||||
}
|
||||
|
||||
// Not empty...
|
||||
|
||||
public static <T extends CharSequence> T notEmpty(final T pParameter) {
|
||||
return notEmpty(pParameter, null);
|
||||
}
|
||||
|
||||
public static <T extends CharSequence> T notEmpty(final T pParameter, final String pParamName) {
|
||||
if (pParameter == null || pParameter.length() == 0) {
|
||||
throw new IllegalArgumentException(String.format("%s may not be empty", pParamName == null ? UNSPECIFIED_PARAM_NAME : pParamName));
|
||||
}
|
||||
|
||||
return pParameter;
|
||||
}
|
||||
|
||||
public static <T> T[] notEmpty(final T[] pParameter) {
|
||||
return notEmpty(pParameter, null);
|
||||
}
|
||||
|
||||
public static <T> T[] notEmpty(final T[] pParameter, final String pParamName) {
|
||||
if (pParameter == null || pParameter.length == 0) {
|
||||
throw new IllegalArgumentException(String.format("%s may not be empty", pParamName == null ? UNSPECIFIED_PARAM_NAME : pParamName));
|
||||
}
|
||||
|
||||
return pParameter;
|
||||
}
|
||||
|
||||
public static <T> Collection<T> notEmpty(final Collection<T> pParameter) {
|
||||
return notEmpty(pParameter, null);
|
||||
}
|
||||
|
||||
public static <T> Collection<T> notEmpty(final Collection<T> pParameter, final String pParamName) {
|
||||
if (pParameter == null || pParameter.isEmpty()) {
|
||||
throw new IllegalArgumentException(String.format("%s may not be empty", pParamName == null ? UNSPECIFIED_PARAM_NAME : pParamName));
|
||||
}
|
||||
|
||||
return pParameter;
|
||||
}
|
||||
|
||||
public static <K, V> Map<K, V> notEmpty(final Map<K, V> pParameter) {
|
||||
return notEmpty(pParameter, null);
|
||||
}
|
||||
|
||||
public static <K, V> Map<K, V> notEmpty(final Map<K, V> pParameter, final String pParamName) {
|
||||
if (pParameter == null || pParameter.isEmpty()) {
|
||||
throw new IllegalArgumentException(String.format("%s may not be empty", pParamName == null ? UNSPECIFIED_PARAM_NAME : pParamName));
|
||||
}
|
||||
|
||||
return pParameter;
|
||||
}
|
||||
|
||||
// No null elements
|
||||
|
||||
public static <T> T[] noNullElements(final T[] pParameter) {
|
||||
return noNullElements(pParameter, null);
|
||||
}
|
||||
|
||||
public static <T> T[] noNullElements(final T[] pParameter, final String pParamName) {
|
||||
noNullElements(Arrays.asList(pParameter), pParamName);
|
||||
return pParameter;
|
||||
}
|
||||
|
||||
public static <T> Collection<T> noNullElements(final Collection<T> pParameter) {
|
||||
return noNullElements(pParameter, null);
|
||||
}
|
||||
|
||||
public static <T> Collection<T> noNullElements(final Collection<T> pParameter, final String pParamName) {
|
||||
for (T element : pParameter) {
|
||||
if (element == null) {
|
||||
throw new IllegalArgumentException(String.format("%s may not contain null elements", pParamName == null ? UNSPECIFIED_PARAM_NAME : pParamName));
|
||||
}
|
||||
}
|
||||
|
||||
return pParameter;
|
||||
}
|
||||
|
||||
public static <K, V> Map<K, V> noNullElements(final Map<K, V> pParameter) {
|
||||
return noNullElements(pParameter, null);
|
||||
}
|
||||
|
||||
public static <K, V> Map<K, V> noNullElements(final Map<K, V> pParameter, final String pParamName) {
|
||||
for (V element : pParameter.values()) {
|
||||
if (element == null) {
|
||||
throw new IllegalArgumentException(String.format("%s may not contain null elements", pParamName == null ? UNSPECIFIED_PARAM_NAME : pParamName));
|
||||
}
|
||||
}
|
||||
|
||||
return pParameter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
*Contains utils/helpers for classes in {@code java.lang}.
|
||||
*/
|
||||
package com.twelvemonkeys.lang;
|
||||
Reference in New Issue
Block a user