|
|
|
package com.jayway.jsonpath.internal;
|
|
|
|
|
|
|
|
import com.jayway.jsonpath.InvalidConversionException;
|
|
|
|
|
|
|
|
import java.io.*;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
public class Utils {
|
|
|
|
|
|
|
|
public static final String CR = System.getProperty("line.separator");
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a range of integers from start (inclusive) to end (exclusive)
|
|
|
|
*
|
|
|
|
* @param start
|
|
|
|
* @param end
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public static List<Integer> createRange(int start, int end) {
|
|
|
|
List<Integer> range = new ArrayList<Integer>();
|
|
|
|
for (int i = start; i < end; i++) {
|
|
|
|
range.add(i);
|
|
|
|
}
|
|
|
|
return range;
|
|
|
|
}
|
|
|
|
|
|
|
|
// accept a collection of objects, since all objects have toString()
|
|
|
|
public static String join(String delimiter, String wrap, Iterable<? extends Object> objs) {
|
|
|
|
Iterator<? extends Object> iter = objs.iterator();
|
|
|
|
if (!iter.hasNext()) {
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
StringBuilder buffer = new StringBuilder();
|
|
|
|
buffer.append(wrap).append(iter.next()).append(wrap);
|
|
|
|
while (iter.hasNext()) {
|
|
|
|
buffer.append(delimiter).append(wrap).append(iter.next()).append(wrap);
|
|
|
|
}
|
|
|
|
return buffer.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
// accept a collection of objects, since all objects have toString()
|
|
|
|
public static String join(String delimiter, Iterable<? extends Object> objs) {
|
|
|
|
return join(delimiter, "", objs);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
//
|
|
|
|
// IO
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
public static void closeQuietly(Closeable closeable) {
|
|
|
|
try {
|
|
|
|
if (closeable != null) {
|
|
|
|
closeable.close();
|
|
|
|
}
|
|
|
|
} catch (IOException ignore) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Strings
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------
|
|
|
|
public static boolean isInt(String str) {
|
|
|
|
if (str == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
int sz = str.length();
|
|
|
|
for (int i = 0; i < sz; i++) {
|
|
|
|
if (Character.isDigit(str.charAt(i)) == false) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean isNumeric(String str) {
|
|
|
|
if (str == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
int sz = str.length();
|
|
|
|
for (int i = 0; i < sz; i++) {
|
|
|
|
if (Character.isDigit(str.charAt(i)) == false && !(str.charAt(i) == '.')) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Checks if a CharSequence is empty ("") or null.</p>
|
|
|
|
* <p/>
|
|
|
|
* <pre>
|
|
|
|
* StringUtils.isEmpty(null) = true
|
|
|
|
* StringUtils.isEmpty("") = true
|
|
|
|
* StringUtils.isEmpty(" ") = false
|
|
|
|
* StringUtils.isEmpty("bob") = false
|
|
|
|
* StringUtils.isEmpty(" bob ") = false
|
|
|
|
* </pre>
|
|
|
|
* <p/>
|
|
|
|
* <p>NOTE: This method changed in Lang version 2.0.
|
|
|
|
* It no longer trims the CharSequence.
|
|
|
|
* That functionality is available in isBlank().</p>
|
|
|
|
*
|
|
|
|
* @param cs the CharSequence to check, may be null
|
|
|
|
* @return {@code true} if the CharSequence is empty or null
|
|
|
|
* @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
|
|
|
|
*/
|
|
|
|
public static boolean isEmpty(CharSequence cs) {
|
|
|
|
return cs == null || cs.length() == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Used by the indexOf(CharSequence methods) as a green implementation of indexOf.
|
|
|
|
*
|
|
|
|
* @param cs the {@code CharSequence} to be processed
|
|
|
|
* @param searchChar the {@code CharSequence} to be searched for
|
|
|
|
* @param start the start index
|
|
|
|
* @return the index where the search sequence was found
|
|
|
|
*/
|
|
|
|
static int indexOf(CharSequence cs, CharSequence searchChar, int start) {
|
|
|
|
return cs.toString().indexOf(searchChar.toString(), start);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Counts how many times the substring appears in the larger string.</p>
|
|
|
|
* <p/>
|
|
|
|
* <p>A {@code null} or empty ("") String input returns {@code 0}.</p>
|
|
|
|
* <p/>
|
|
|
|
* <pre>
|
|
|
|
* StringUtils.countMatches(null, *) = 0
|
|
|
|
* StringUtils.countMatches("", *) = 0
|
|
|
|
* StringUtils.countMatches("abba", null) = 0
|
|
|
|
* StringUtils.countMatches("abba", "") = 0
|
|
|
|
* StringUtils.countMatches("abba", "a") = 2
|
|
|
|
* StringUtils.countMatches("abba", "ab") = 1
|
|
|
|
* StringUtils.countMatches("abba", "xxx") = 0
|
|
|
|
* </pre>
|
|
|
|
*
|
|
|
|
* @param str the CharSequence to check, may be null
|
|
|
|
* @param sub the substring to count, may be null
|
|
|
|
* @return the number of occurrences, 0 if either CharSequence is {@code null}
|
|
|
|
* @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence)
|
|
|
|
*/
|
|
|
|
public static int countMatches(CharSequence str, CharSequence sub) {
|
|
|
|
if (isEmpty(str) || isEmpty(sub)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int count = 0;
|
|
|
|
int idx = 0;
|
|
|
|
while ((idx = indexOf(str, sub, idx)) != -1) {
|
|
|
|
count++;
|
|
|
|
idx += sub.length();
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Validators
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Validate that the specified argument is not {@code null};
|
|
|
|
* otherwise throwing an exception with the specified message.
|
|
|
|
* <p/>
|
|
|
|
* <pre>Validate.notNull(myObject, "The object must not be null");</pre>
|
|
|
|
*
|
|
|
|
* @param <T> the object type
|
|
|
|
* @param object the object to check
|
|
|
|
* @param message the {@link String#format(String, Object...)} exception message if invalid, not null
|
|
|
|
* @param values the optional values for the formatted exception message
|
|
|
|
* @return the validated object (never {@code null} for method chaining)
|
|
|
|
* @throws NullPointerException if the object is {@code null}
|
|
|
|
*/
|
|
|
|
public static <T> T notNull(T object, String message, Object... values) {
|
|
|
|
if (object == null) {
|
|
|
|
throw new IllegalArgumentException(String.format(message, values));
|
|
|
|
}
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Validate that the argument condition is {@code true}; otherwise
|
|
|
|
* throwing an exception with the specified message. This method is useful when
|
|
|
|
* validating according to an arbitrary boolean expression, such as validating a
|
|
|
|
* primitive number or using your own custom validation expression.</p>
|
|
|
|
* <p/>
|
|
|
|
* <pre>Validate.isTrue(i > 0.0, "The value must be greater than zero: %d", i);</pre>
|
|
|
|
* <p/>
|
|
|
|
* <p>For performance reasons, the long value is passed as a separate parameter and
|
|
|
|
* appended to the exception message only in the case of an error.</p>
|
|
|
|
*
|
|
|
|
* @param expression the boolean expression to check
|
|
|
|
* @param message
|
|
|
|
* @throws IllegalArgumentException if expression is {@code false}
|
|
|
|
*/
|
|
|
|
public static void isTrue(boolean expression, String message) {
|
|
|
|
if (expression == false) {
|
|
|
|
throw new IllegalArgumentException(message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Validate that the specified argument character sequence is
|
|
|
|
* neither {@code null} nor a length of zero (no characters);
|
|
|
|
* otherwise throwing an exception with the specified message.
|
|
|
|
* <p/>
|
|
|
|
* <pre>Validate.notEmpty(myString, "The string must not be empty");</pre>
|
|
|
|
*
|
|
|
|
* @param <T> the character sequence type
|
|
|
|
* @param chars the character sequence to check, validated not null by this method
|
|
|
|
* @param message the {@link String#format(String, Object...)} exception message if invalid, not null
|
|
|
|
* @param values the optional values for the formatted exception message, null array not recommended
|
|
|
|
* @return the validated character sequence (never {@code null} method for chaining)
|
|
|
|
* @throws NullPointerException if the character sequence is {@code null}
|
|
|
|
* @throws IllegalArgumentException if the character sequence is empty
|
|
|
|
*/
|
|
|
|
public static <T extends CharSequence> T notEmpty(T chars, String message, Object... values) {
|
|
|
|
if (chars == null) {
|
|
|
|
throw new IllegalArgumentException(String.format(message, values));
|
|
|
|
}
|
|
|
|
if (chars.length() == 0) {
|
|
|
|
throw new IllegalArgumentException(String.format(message, values));
|
|
|
|
}
|
|
|
|
return chars;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Converters
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
/**
|
|
|
|
* converts to Integer with radix 10
|
|
|
|
*
|
|
|
|
* @param o object to convert
|
|
|
|
* @return converted value
|
|
|
|
*/
|
|
|
|
public static Integer toInt(Object o) {
|
|
|
|
if (null == o)
|
|
|
|
return null;
|
|
|
|
if (o instanceof Number)
|
|
|
|
return ((Number) o).intValue();
|
|
|
|
try {
|
|
|
|
return Integer.valueOf(o.toString().trim(), 10);
|
|
|
|
} catch (Exception e) {
|
|
|
|
throw new InvalidConversionException("Could not convert " + o.toString() + " to Integer");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* converts to Long with radix 10
|
|
|
|
*
|
|
|
|
* @param o object to convert
|
|
|
|
* @return converted value
|
|
|
|
*/
|
|
|
|
public static Long toLong(Object o) {
|
|
|
|
if (null == o)
|
|
|
|
return null;
|
|
|
|
if (o instanceof Number)
|
|
|
|
return ((Number) o).longValue();
|
|
|
|
try {
|
|
|
|
return Long.valueOf(o.toString().trim(), 10);
|
|
|
|
} catch (Exception e) {
|
|
|
|
throw new InvalidConversionException("Could not convert " + o.toString() + " to Long");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* converts to Double with radix 10
|
|
|
|
*
|
|
|
|
* @param o object to convert
|
|
|
|
* @return converted value
|
|
|
|
*/
|
|
|
|
public static Double toDouble(Object o) {
|
|
|
|
if (null == o)
|
|
|
|
return null;
|
|
|
|
if (o instanceof Number)
|
|
|
|
return ((Number) o).doubleValue();
|
|
|
|
try {
|
|
|
|
return Double.valueOf(o.toString().trim());
|
|
|
|
} catch (Exception e) {
|
|
|
|
throw new InvalidConversionException("Could not convert " + o.toString() + " to Double");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String toString(Object o) {
|
|
|
|
if (null == o) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return o.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Serialization
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Deep clone an {@code Object} using serialization.</p>
|
|
|
|
* <p/>
|
|
|
|
* <p>This is many times slower than writing clone methods by hand
|
|
|
|
* on all objects in your object graph. However, for complex object
|
|
|
|
* graphs, or for those that don't support deep cloning this can
|
|
|
|
* be a simple alternative implementation. Of course all the objects
|
|
|
|
* must be {@code Serializable}.</p>
|
|
|
|
*
|
|
|
|
* @param <T> the type of the object involved
|
|
|
|
* @param object the {@code Serializable} object to clone
|
|
|
|
* @return the cloned object
|
|
|
|
*/
|
|
|
|
public static <T extends Serializable> T clone(T object) {
|
|
|
|
if (object == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
byte[] objectData = serialize(object);
|
|
|
|
ByteArrayInputStream bais = new ByteArrayInputStream(objectData);
|
|
|
|
|
|
|
|
ClassLoaderAwareObjectInputStream in = null;
|
|
|
|
try {
|
|
|
|
// stream closed in the finally
|
|
|
|
in = new ClassLoaderAwareObjectInputStream(bais, object.getClass().getClassLoader());
|
|
|
|
/*
|
|
|
|
* when we serialize and deserialize an object,
|
|
|
|
* it is reasonable to assume the deserialized object
|
|
|
|
* is of the same type as the original serialized object
|
|
|
|
*/
|
|
|
|
@SuppressWarnings("unchecked") // see above
|
|
|
|
T readObject = (T) in.readObject();
|
|
|
|
return readObject;
|
|
|
|
|
|
|
|
} catch (ClassNotFoundException ex) {
|
|
|
|
throw new RuntimeException("ClassNotFoundException while reading cloned object data", ex);
|
|
|
|
} catch (IOException ex) {
|
|
|
|
throw new RuntimeException("IOException while reading cloned object data", ex);
|
|
|
|
} finally {
|
|
|
|
try {
|
|
|
|
if (in != null) {
|
|
|
|
in.close();
|
|
|
|
}
|
|
|
|
} catch (IOException ex) {
|
|
|
|
throw new RuntimeException("IOException on closing cloned object data InputStream.", ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Serializes an {@code Object} to the specified stream.</p>
|
|
|
|
* <p/>
|
|
|
|
* <p>The stream will be closed once the object is written.
|
|
|
|
* This avoids the need for a finally clause, and maybe also exception
|
|
|
|
* handling, in the application code.</p>
|
|
|
|
* <p/>
|
|
|
|
* <p>The stream passed in is not buffered internally within this method.
|
|
|
|
* This is the responsibility of your application if desired.</p>
|
|
|
|
*
|
|
|
|
* @param obj the object to serialize to bytes, may be null
|
|
|
|
* @param outputStream the stream to write to, must not be null
|
|
|
|
* @throws IllegalArgumentException if {@code outputStream} is {@code null}
|
|
|
|
* @throws RuntimeException (runtime) if the serialization fails
|
|
|
|
*/
|
|
|
|
public static void serialize(Serializable obj, OutputStream outputStream) {
|
|
|
|
if (outputStream == null) {
|
|
|
|
throw new IllegalArgumentException("The OutputStream must not be null");
|
|
|
|
}
|
|
|
|
ObjectOutputStream out = null;
|
|
|
|
try {
|
|
|
|
// stream closed in the finally
|
|
|
|
out = new ObjectOutputStream(outputStream);
|
|
|
|
out.writeObject(obj);
|
|
|
|
|
|
|
|
} catch (IOException ex) {
|
|
|
|
throw new RuntimeException(ex);
|
|
|
|
} finally {
|
|
|
|
try {
|
|
|
|
if (out != null) {
|
|
|
|
out.close();
|
|
|
|
}
|
|
|
|
} catch (IOException ex) { // NOPMD
|
|
|
|
// ignore close exception
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Serializes an {@code Object} to a byte array for
|
|
|
|
* storage/serialization.</p>
|
|
|
|
*
|
|
|
|
* @param obj the object to serialize to bytes
|
|
|
|
* @return a byte[] with the converted Serializable
|
|
|
|
* @throws RuntimeException (runtime) if the serialization fails
|
|
|
|
*/
|
|
|
|
public static byte[] serialize(Serializable obj) {
|
|
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
|
|
|
|
serialize(obj, baos);
|
|
|
|
return baos.toByteArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Deserialize
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Deserializes an {@code Object} from the specified stream.</p>
|
|
|
|
* <p/>
|
|
|
|
* <p>The stream will be closed once the object is written. This
|
|
|
|
* avoids the need for a finally clause, and maybe also exception
|
|
|
|
* handling, in the application code.</p>
|
|
|
|
* <p/>
|
|
|
|
* <p>The stream passed in is not buffered internally within this method.
|
|
|
|
* This is the responsibility of your application if desired.</p>
|
|
|
|
*
|
|
|
|
* @param inputStream the serialized object input stream, must not be null
|
|
|
|
* @return the deserialized object
|
|
|
|
* @throws IllegalArgumentException if {@code inputStream} is {@code null}
|
|
|
|
* @throws RuntimeException (runtime) if the serialization fails
|
|
|
|
*/
|
|
|
|
public static Object deserialize(InputStream inputStream) {
|
|
|
|
if (inputStream == null) {
|
|
|
|
throw new IllegalArgumentException("The InputStream must not be null");
|
|
|
|
}
|
|
|
|
ObjectInputStream in = null;
|
|
|
|
try {
|
|
|
|
// stream closed in the finally
|
|
|
|
in = new ObjectInputStream(inputStream);
|
|
|
|
return in.readObject();
|
|
|
|
|
|
|
|
} catch (ClassNotFoundException ex) {
|
|
|
|
throw new RuntimeException(ex);
|
|
|
|
} catch (IOException ex) {
|
|
|
|
throw new RuntimeException(ex);
|
|
|
|
} finally {
|
|
|
|
try {
|
|
|
|
if (in != null) {
|
|
|
|
in.close();
|
|
|
|
}
|
|
|
|
} catch (IOException ex) { // NOPMD
|
|
|
|
// ignore close exception
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Deserializes a single {@code Object} from an array of bytes.</p>
|
|
|
|
*
|
|
|
|
* @param objectData the serialized object, must not be null
|
|
|
|
* @return the deserialized object
|
|
|
|
* @throws IllegalArgumentException if {@code objectData} is {@code null}
|
|
|
|
* @throws RuntimeException (runtime) if the serialization fails
|
|
|
|
*/
|
|
|
|
public static Object deserialize(byte[] objectData) {
|
|
|
|
if (objectData == null) {
|
|
|
|
throw new IllegalArgumentException("The byte[] must not be null");
|
|
|
|
}
|
|
|
|
ByteArrayInputStream bais = new ByteArrayInputStream(objectData);
|
|
|
|
return deserialize(bais);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Custom specialization of the standard JDK {@link java.io.ObjectInputStream}
|
|
|
|
* that uses a custom <code>ClassLoader</code> to resolve a class.
|
|
|
|
* If the specified <code>ClassLoader</code> is not able to resolve the class,
|
|
|
|
* the context classloader of the current thread will be used.
|
|
|
|
* This way, the standard deserialization work also in web-application
|
|
|
|
* containers and application servers, no matter in which of the
|
|
|
|
* <code>ClassLoader</code> the particular class that encapsulates
|
|
|
|
* serialization/deserialization lives. </p>
|
|
|
|
* <p/>
|
|
|
|
* <p>For more in-depth information about the problem for which this
|
|
|
|
* class here is a workaround, see the JIRA issue LANG-626. </p>
|
|
|
|
*/
|
|
|
|
static class ClassLoaderAwareObjectInputStream extends ObjectInputStream {
|
|
|
|
private ClassLoader classLoader;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
*
|
|
|
|
* @param in The <code>InputStream</code>.
|
|
|
|
* @param classLoader classloader to use
|
|
|
|
* @throws IOException if an I/O error occurs while reading stream header.
|
|
|
|
* @see java.io.ObjectInputStream
|
|
|
|
*/
|
|
|
|
public ClassLoaderAwareObjectInputStream(InputStream in, ClassLoader classLoader) throws IOException {
|
|
|
|
super(in);
|
|
|
|
this.classLoader = classLoader;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Overriden version that uses the parametrized <code>ClassLoader</code> or the <code>ClassLoader</code>
|
|
|
|
* of the current <code>Thread</code> to resolve the class.
|
|
|
|
*
|
|
|
|
* @param desc An instance of class <code>ObjectStreamClass</code>.
|
|
|
|
* @return A <code>Class</code> object corresponding to <code>desc</code>.
|
|
|
|
* @throws IOException Any of the usual Input/Output exceptions.
|
|
|
|
* @throws ClassNotFoundException If class of a serialized object cannot be found.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
|
|
|
|
String name = desc.getName();
|
|
|
|
try {
|
|
|
|
return Class.forName(name, false, classLoader);
|
|
|
|
} catch (ClassNotFoundException ex) {
|
|
|
|
return Class.forName(name, false, Thread.currentThread().getContextClassLoader());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|