1 /*
2  * Copyright (C) 2014 jsonwebtoken.io
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package io.jsonwebtoken.lang;
17
18 import java.io.Closeable;
19 import java.io.IOException;
20 import java.lang.reflect.Array;
21 import java.util.Arrays;
22
23 public final class Objects {
24
25     //for code coverage
26     private static final Objects INSTANCE = new Objects();
27
28     private Objects(){}
29
30     private static final int INITIAL_HASH = 7;
31     private static final int MULTIPLIER   = 31;
32
33     private static final String EMPTY_STRING            = "";
34     private static final String NULL_STRING             = "null";
35     private static final String ARRAY_START             = "{";
36     private static final String ARRAY_END               = "}";
37     private static final String EMPTY_ARRAY             = ARRAY_START + ARRAY_END;
38     private static final String ARRAY_ELEMENT_SEPARATOR = ", ";
39
40     /**
41      * Return whether the given throwable is a checked exception:
42      * that is, neither a RuntimeException nor an Error.
43      *
44      * @param ex the throwable to check
45      * @return whether the throwable is a checked exception
46      * @see java.lang.Exception
47      * @see java.lang.RuntimeException
48      * @see java.lang.Error
49      */

50     public static boolean isCheckedException(Throwable ex) {
51         return !(ex instanceof RuntimeException || ex instanceof Error);
52     }
53
54     /**
55      * Check whether the given exception is compatible with the exceptions
56      * declared in a throws clause.
57      *
58      * @param ex                 the exception to checked
59      * @param declaredExceptions the exceptions declared in the throws clause
60      * @return whether the given exception is compatible
61      */

62     public static boolean isCompatibleWithThrowsClause(Throwable ex, Class[] declaredExceptions) {
63         if (!isCheckedException(ex)) {
64             return true;
65         }
66         if (declaredExceptions != null) {
67             int i = 0;
68             while (i < declaredExceptions.length) {
69                 if (declaredExceptions[i].isAssignableFrom(ex.getClass())) {
70                     return true;
71                 }
72                 i++;
73             }
74         }
75         return false;
76     }
77
78     /**
79      * Determine whether the given object is an array:
80      * either an Object array or a primitive array.
81      *
82      * @param obj the object to check
83      */

84     public static boolean isArray(Object obj) {
85         return (obj != null && obj.getClass().isArray());
86     }
87
88     /**
89      * Determine whether the given array is empty:
90      * i.e. <code>null</code> or of zero length.
91      *
92      * @param array the array to check
93      */

94     public static boolean isEmpty(Object[] array) {
95         return (array == null || array.length == 0);
96     }
97
98     /**
99      * Returns {@code trueif the specified byte array is null or of zero length, {@code false} otherwise.
100      *
101      * @param array the byte array to check
102      * @return {@code trueif the specified byte array is null or of zero length, {@code false} otherwise.
103      */

104     public static boolean isEmpty(byte[] array) {
105         return array == null || array.length == 0;
106     }
107
108     /**
109      * Check whether the given array contains the given element.
110      *
111      * @param array   the array to check (may be <code>null</code>,
112      *                in which case the return value will always be <code>false</code>)
113      * @param element the element to check for
114      * @return whether the element has been found in the given array
115      */

116     public static boolean containsElement(Object[] array, Object element) {
117         if (array == null) {
118             return false;
119         }
120         for (Object arrayEle : array) {
121             if (nullSafeEquals(arrayEle, element)) {
122                 return true;
123             }
124         }
125         return false;
126     }
127
128     /**
129      * Check whether the given array of enum constants contains a constant with the given name,
130      * ignoring case when determining a match.
131      *
132      * @param enumValues the enum values to check, typically the product of a call to MyEnum.values()
133      * @param constant   the constant name to find (must not be null or empty string)
134      * @return whether the constant has been found in the given array
135      */

136     public static boolean containsConstant(Enum<?>[] enumValues, String constant) {
137         return containsConstant(enumValues, constant, false);
138     }
139
140     /**
141      * Check whether the given array of enum constants contains a constant with the given name.
142      *
143      * @param enumValues    the enum values to check, typically the product of a call to MyEnum.values()
144      * @param constant      the constant name to find (must not be null or empty string)
145      * @param caseSensitive whether case is significant in determining a match
146      * @return whether the constant has been found in the given array
147      */

148     public static boolean containsConstant(Enum<?>[] enumValues, String constant, boolean caseSensitive) {
149         for (Enum<?> candidate : enumValues) {
150             if (caseSensitive ?
151                 candidate.toString().equals(constant) :
152                 candidate.toString().equalsIgnoreCase(constant)) {
153                 return true;
154             }
155         }
156         return false;
157     }
158
159     /**
160      * Case insensitive alternative to {@link Enum#valueOf(Class, String)}.
161      *
162      * @param <E>        the concrete Enum type
163      * @param enumValues the array of all Enum constants in question, usually per Enum.values()
164      * @param constant   the constant to get the enum value of
165      * @throws IllegalArgumentException if the given constant is not found in the given array
166      *                                  of enum values. Use {@link #containsConstant(Enum[], String)} as a guard to
167      *                                  avoid this exception.
168      */

169     public static <E extends Enum<?>> E caseInsensitiveValueOf(E[] enumValues, String constant) {
170         for (E candidate : enumValues) {
171             if (candidate.toString().equalsIgnoreCase(constant)) {
172                 return candidate;
173             }
174         }
175         throw new IllegalArgumentException(
176             String.format("constant [%s] does not exist in enum type %s",
177                           constant, enumValues.getClass().getComponentType().getName()));
178     }
179
180     /**
181      * Append the given object to the given array, returning a new array
182      * consisting of the input array contents plus the given object.
183      *
184      * @param array the array to append to (can be <code>null</code>)
185      * @param obj   the object to append
186      * @return the new array (of the same component type; never <code>null</code>)
187      */

188     public static <A, O extends A> A[] addObjectToArray(A[] array, O obj) {
189         Class<?> compType = Object.class;
190         if (array != null) {
191             compType = array.getClass().getComponentType();
192         } else if (obj != null) {
193             compType = obj.getClass();
194         }
195         int newArrLength = (array != null ? array.length + 1 : 1);
196         @SuppressWarnings("unchecked")
197         A[] newArr = (A[]) Array.newInstance(compType, newArrLength);
198         if (array != null) {
199             System.arraycopy(array, 0, newArr, 0, array.length);
200         }
201         newArr[newArr.length - 1] = obj;
202         return newArr;
203     }
204
205     /**
206      * Convert the given array (which may be a primitive array) to an
207      * object array (if necessary of primitive wrapper objects).
208      * <p>A <code>null</code> source value will be converted to an
209      * empty Object array.
210      *
211      * @param source the (potentially primitive) array
212      * @return the corresponding object array (never <code>null</code>)
213      * @throws IllegalArgumentException if the parameter is not an array
214      */

215     public static Object[] toObjectArray(Object source) {
216         if (source instanceof Object[]) {
217             return (Object[]) source;
218         }
219         if (source == null) {
220             return new Object[0];
221         }
222         if (!source.getClass().isArray()) {
223             throw new IllegalArgumentException("Source is not an array: " + source);
224         }
225         int length = Array.getLength(source);
226         if (length == 0) {
227             return new Object[0];
228         }
229         Class wrapperType = Array.get(source, 0).getClass();
230         Object[] newArray = (Object[]) Array.newInstance(wrapperType, length);
231         for (int i = 0; i < length; i++) {
232             newArray[i] = Array.get(source, i);
233         }
234         return newArray;
235     }
236
237
238     //---------------------------------------------------------------------
239     // Convenience methods for content-based equality/hash-code handling
240     //---------------------------------------------------------------------
241
242     /**
243      * Determine if the given objects are equal, returning <code>true</code>
244      * if both are <code>null</code> or <code>false</code> if only one is
245      * <code>null</code>.
246      * <p>Compares arrays with <code>Arrays.equals</code>, performing an equality
247      * check based on the array elements rather than the array reference.
248      *
249      * @param o1 first Object to compare
250      * @param o2 second Object to compare
251      * @return whether the given objects are equal
252      * @see java.util.Arrays#equals
253      */

254     public static boolean nullSafeEquals(Object o1, Object o2) {
255         if (o1 == o2) {
256             return true;
257         }
258         if (o1 == null || o2 == null) {
259             return false;
260         }
261         if (o1.equals(o2)) {
262             return true;
263         }
264         if (o1.getClass().isArray() && o2.getClass().isArray()) {
265             if (o1 instanceof Object[] && o2 instanceof Object[]) {
266                 return Arrays.equals((Object[]) o1, (Object[]) o2);
267             }
268             if (o1 instanceof boolean[] && o2 instanceof boolean[]) {
269                 return Arrays.equals((boolean[]) o1, (boolean[]) o2);
270             }
271             if (o1 instanceof byte[] && o2 instanceof byte[]) {
272                 return Arrays.equals((byte[]) o1, (byte[]) o2);
273             }
274             if (o1 instanceof char[] && o2 instanceof char[]) {
275                 return Arrays.equals((char[]) o1, (char[]) o2);
276             }
277             if (o1 instanceof double[] && o2 instanceof double[]) {
278                 return Arrays.equals((double[]) o1, (double[]) o2);
279             }
280             if (o1 instanceof float[] && o2 instanceof float[]) {
281                 return Arrays.equals((float[]) o1, (float[]) o2);
282             }
283             if (o1 instanceof int[] && o2 instanceof int[]) {
284                 return Arrays.equals((int[]) o1, (int[]) o2);
285             }
286             if (o1 instanceof long[] && o2 instanceof long[]) {
287                 return Arrays.equals((long[]) o1, (long[]) o2);
288             }
289             if (o1 instanceof short[] && o2 instanceof short[]) {
290                 return Arrays.equals((short[]) o1, (short[]) o2);
291             }
292         }
293         return false;
294     }
295
296     /**
297      * Return as hash code for the given object; typically the value of
298      * <code>{@link Object#hashCode()}</code>. If the object is an array,
299      * this method will delegate to any of the <code>nullSafeHashCode</code>
300      * methods for arrays in this class. If the object is <code>null</code>,
301      * this method returns 0.
302      *
303      * @see #nullSafeHashCode(Object[])
304      * @see #nullSafeHashCode(boolean[])
305      * @see #nullSafeHashCode(byte[])
306      * @see #nullSafeHashCode(char[])
307      * @see #nullSafeHashCode(double[])
308      * @see #nullSafeHashCode(float[])
309      * @see #nullSafeHashCode(int[])
310      * @see #nullSafeHashCode(long[])
311      * @see #nullSafeHashCode(short[])
312      */

313     public static int nullSafeHashCode(Object obj) {
314         if (obj == null) {
315             return 0;
316         }
317         if (obj.getClass().isArray()) {
318             if (obj instanceof Object[]) {
319                 return nullSafeHashCode((Object[]) obj);
320             }
321             if (obj instanceof boolean[]) {
322                 return nullSafeHashCode((boolean[]) obj);
323             }
324             if (obj instanceof byte[]) {
325                 return nullSafeHashCode((byte[]) obj);
326             }
327             if (obj instanceof char[]) {
328                 return nullSafeHashCode((char[]) obj);
329             }
330             if (obj instanceof double[]) {
331                 return nullSafeHashCode((double[]) obj);
332             }
333             if (obj instanceof float[]) {
334                 return nullSafeHashCode((float[]) obj);
335             }
336             if (obj instanceof int[]) {
337                 return nullSafeHashCode((int[]) obj);
338             }
339             if (obj instanceof long[]) {
340                 return nullSafeHashCode((long[]) obj);
341             }
342             if (obj instanceof short[]) {
343                 return nullSafeHashCode((short[]) obj);
344             }
345         }
346         return obj.hashCode();
347     }
348
349     /**
350      * Return a hash code based on the contents of the specified array.
351      * If <code>array</code> is <code>null</code>, this method returns 0.
352      */

353     public static int nullSafeHashCode(Object[] array) {
354         if (array == null) {
355             return 0;
356         }
357         int hash = INITIAL_HASH;
358         int arraySize = array.length;
359         for (int i = 0; i < arraySize; i++) {
360             hash = MULTIPLIER * hash + nullSafeHashCode(array[i]);
361         }
362         return hash;
363     }
364
365     /**
366      * Return a hash code based on the contents of the specified array.
367      * If <code>array</code> is <code>null</code>, this method returns 0.
368      */

369     public static int nullSafeHashCode(boolean[] array) {
370         if (array == null) {
371             return 0;
372         }
373         int hash = INITIAL_HASH;
374         int arraySize = array.length;
375         for (int i = 0; i < arraySize; i++) {
376             hash = MULTIPLIER * hash + hashCode(array[i]);
377         }
378         return hash;
379     }
380
381     /**
382      * Return a hash code based on the contents of the specified array.
383      * If <code>array</code> is <code>null</code>, this method returns 0.
384      */

385     public static int nullSafeHashCode(byte[] array) {
386         if (array == null) {
387             return 0;
388         }
389         int hash = INITIAL_HASH;
390         int arraySize = array.length;
391         for (int i = 0; i < arraySize; i++) {
392             hash = MULTIPLIER * hash + array[i];
393         }
394         return hash;
395     }
396
397     /**
398      * Return a hash code based on the contents of the specified array.
399      * If <code>array</code> is <code>null</code>, this method returns 0.
400      */

401     public static int nullSafeHashCode(char[] array) {
402         if (array == null) {
403             return 0;
404         }
405         int hash = INITIAL_HASH;
406         int arraySize = array.length;
407         for (int i = 0; i < arraySize; i++) {
408             hash = MULTIPLIER * hash + array[i];
409         }
410         return hash;
411     }
412
413     /**
414      * Return a hash code based on the contents of the specified array.
415      * If <code>array</code> is <code>null</code>, this method returns 0.
416      */

417     public static int nullSafeHashCode(double[] array) {
418         if (array == null) {
419             return 0;
420         }
421         int hash = INITIAL_HASH;
422         int arraySize = array.length;
423         for (int i = 0; i < arraySize; i++) {
424             hash = MULTIPLIER * hash + hashCode(array[i]);
425         }
426         return hash;
427     }
428
429     /**
430      * Return a hash code based on the contents of the specified array.
431      * If <code>array</code> is <code>null</code>, this method returns 0.
432      */

433     public static int nullSafeHashCode(float[] array) {
434         if (array == null) {
435             return 0;
436         }
437         int hash = INITIAL_HASH;
438         int arraySize = array.length;
439         for (int i = 0; i < arraySize; i++) {
440             hash = MULTIPLIER * hash + hashCode(array[i]);
441         }
442         return hash;
443     }
444
445     /**
446      * Return a hash code based on the contents of the specified array.
447      * If <code>array</code> is <code>null</code>, this method returns 0.
448      */

449     public static int nullSafeHashCode(int[] array) {
450         if (array == null) {
451             return 0;
452         }
453         int hash = INITIAL_HASH;
454         int arraySize = array.length;
455         for (int i = 0; i < arraySize; i++) {
456             hash = MULTIPLIER * hash + array[i];
457         }
458         return hash;
459     }
460
461     /**
462      * Return a hash code based on the contents of the specified array.
463      * If <code>array</code> is <code>null</code>, this method returns 0.
464      */

465     public static int nullSafeHashCode(long[] array) {
466         if (array == null) {
467             return 0;
468         }
469         int hash = INITIAL_HASH;
470         int arraySize = array.length;
471         for (int i = 0; i < arraySize; i++) {
472             hash = MULTIPLIER * hash + hashCode(array[i]);
473         }
474         return hash;
475     }
476
477     /**
478      * Return a hash code based on the contents of the specified array.
479      * If <code>array</code> is <code>null</code>, this method returns 0.
480      */

481     public static int nullSafeHashCode(short[] array) {
482         if (array == null) {
483             return 0;
484         }
485         int hash = INITIAL_HASH;
486         int arraySize = array.length;
487         for (int i = 0; i < arraySize; i++) {
488             hash = MULTIPLIER * hash + array[i];
489         }
490         return hash;
491     }
492
493     /**
494      * Return the same value as <code>{@link Boolean#hashCode()}</code>.
495      *
496      * @see Boolean#hashCode()
497      */

498     public static int hashCode(boolean bool) {
499         return bool ? 1231 : 1237;
500     }
501
502     /**
503      * Return the same value as <code>{@link Double#hashCode()}</code>.
504      *
505      * @see Double#hashCode()
506      */

507     public static int hashCode(double dbl) {
508         long bits = Double.doubleToLongBits(dbl);
509         return hashCode(bits);
510     }
511
512     /**
513      * Return the same value as <code>{@link Float#hashCode()}</code>.
514      *
515      * @see Float#hashCode()
516      */

517     public static int hashCode(float flt) {
518         return Float.floatToIntBits(flt);
519     }
520
521     /**
522      * Return the same value as <code>{@link Long#hashCode()}</code>.
523      *
524      * @see Long#hashCode()
525      */

526     public static int hashCode(long lng) {
527         return (int) (lng ^ (lng >>> 32));
528     }
529
530
531     //---------------------------------------------------------------------
532     // Convenience methods for toString output
533     //---------------------------------------------------------------------
534
535     /**
536      * Return a String representation of an object's overall identity.
537      *
538      * @param obj the object (may be <code>null</code>)
539      * @return the object's identity as String representation,
540      * or an empty String if the object was <code>null</code>
541      */

542     public static String identityToString(Object obj) {
543         if (obj == null) {
544             return EMPTY_STRING;
545         }
546         return obj.getClass().getName() + "@" + getIdentityHexString(obj);
547     }
548
549     /**
550      * Return a hex String form of an object's identity hash code.
551      *
552      * @param obj the object
553      * @return the object's identity code in hex notation
554      */

555     public static String getIdentityHexString(Object obj) {
556         return Integer.toHexString(System.identityHashCode(obj));
557     }
558
559     /**
560      * Return a content-based String representation if <code>obj</code> is
561      * not <code>null</code>; otherwise returns an empty String.
562      * <p>Differs from {@link #nullSafeToString(Object)} in that it returns
563      * an empty String rather than "null" for a <code>null</code> value.
564      *
565      * @param obj the object to build a display String for
566      * @return a display String representation of <code>obj</code>
567      * @see #nullSafeToString(Object)
568      */

569     public static String getDisplayString(Object obj) {
570         if (obj == null) {
571             return EMPTY_STRING;
572         }
573         return nullSafeToString(obj);
574     }
575
576     /**
577      * Determine the class name for the given object.
578      * <p>Returns <code>"null"</code> if <code>obj</code> is <code>null</code>.
579      *
580      * @param obj the object to introspect (may be <code>null</code>)
581      * @return the corresponding class name
582      */

583     public static String nullSafeClassName(Object obj) {
584         return (obj != null ? obj.getClass().getName() : NULL_STRING);
585     }
586
587     /**
588      * Return a String representation of the specified Object.
589      * <p>Builds a String representation of the contents in case of an array.
590      * Returns <code>"null"</code> if <code>obj</code> is <code>null</code>.
591      *
592      * @param obj the object to build a String representation for
593      * @return a String representation of <code>obj</code>
594      */

595     public static String nullSafeToString(Object obj) {
596         if (obj == null) {
597             return NULL_STRING;
598         }
599         if (obj instanceof String) {
600             return (String) obj;
601         }
602         if (obj instanceof Object[]) {
603             return nullSafeToString((Object[]) obj);
604         }
605         if (obj instanceof boolean[]) {
606             return nullSafeToString((boolean[]) obj);
607         }
608         if (obj instanceof byte[]) {
609             return nullSafeToString((byte[]) obj);
610         }
611         if (obj instanceof char[]) {
612             return nullSafeToString((char[]) obj);
613         }
614         if (obj instanceof double[]) {
615             return nullSafeToString((double[]) obj);
616         }
617         if (obj instanceof float[]) {
618             return nullSafeToString((float[]) obj);
619         }
620         if (obj instanceof int[]) {
621             return nullSafeToString((int[]) obj);
622         }
623         if (obj instanceof long[]) {
624             return nullSafeToString((long[]) obj);
625         }
626         if (obj instanceof short[]) {
627             return nullSafeToString((short[]) obj);
628         }
629         String str = obj.toString();
630         return (str != null ? str : EMPTY_STRING);
631     }
632
633     /**
634      * Return a String representation of the contents of the specified array.
635      * <p>The String representation consists of a list of the array's elements,
636      * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
637      * by the characters <code>", "</code> (a comma followed by a space). Returns
638      * <code>"null"</code> if <code>array</code> is <code>null</code>.
639      *
640      * @param array the array to build a String representation for
641      * @return a String representation of <code>array</code>
642      */

643     public static String nullSafeToString(Object[] array) {
644         if (array == null) {
645             return NULL_STRING;
646         }
647         int length = array.length;
648         if (length == 0) {
649             return EMPTY_ARRAY;
650         }
651         StringBuilder sb = new StringBuilder();
652         for (int i = 0; i < length; i++) {
653             if (i == 0) {
654                 sb.append(ARRAY_START);
655             } else {
656                 sb.append(ARRAY_ELEMENT_SEPARATOR);
657             }
658             sb.append(String.valueOf(array[i]));
659         }
660         sb.append(ARRAY_END);
661         return sb.toString();
662     }
663
664     /**
665      * Return a String representation of the contents of the specified array.
666      * <p>The String representation consists of a list of the array's elements,
667      * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
668      * by the characters <code>", "</code> (a comma followed by a space). Returns
669      * <code>"null"</code> if <code>array</code> is <code>null</code>.
670      *
671      * @param array the array to build a String representation for
672      * @return a String representation of <code>array</code>
673      */

674     public static String nullSafeToString(boolean[] array) {
675         if (array == null) {
676             return NULL_STRING;
677         }
678         int length = array.length;
679         if (length == 0) {
680             return EMPTY_ARRAY;
681         }
682         StringBuilder sb = new StringBuilder();
683         for (int i = 0; i < length; i++) {
684             if (i == 0) {
685                 sb.append(ARRAY_START);
686             } else {
687                 sb.append(ARRAY_ELEMENT_SEPARATOR);
688             }
689
690             sb.append(array[i]);
691         }
692         sb.append(ARRAY_END);
693         return sb.toString();
694     }
695
696     /**
697      * Return a String representation of the contents of the specified array.
698      * <p>The String representation consists of a list of the array's elements,
699      * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
700      * by the characters <code>", "</code> (a comma followed by a space). Returns
701      * <code>"null"</code> if <code>array</code> is <code>null</code>.
702      *
703      * @param array the array to build a String representation for
704      * @return a String representation of <code>array</code>
705      */

706     public static String nullSafeToString(byte[] array) {
707         if (array == null) {
708             return NULL_STRING;
709         }
710         int length = array.length;
711         if (length == 0) {
712             return EMPTY_ARRAY;
713         }
714         StringBuilder sb = new StringBuilder();
715         for (int i = 0; i < length; i++) {
716             if (i == 0) {
717                 sb.append(ARRAY_START);
718             } else {
719                 sb.append(ARRAY_ELEMENT_SEPARATOR);
720             }
721             sb.append(array[i]);
722         }
723         sb.append(ARRAY_END);
724         return sb.toString();
725     }
726
727     /**
728      * Return a String representation of the contents of the specified array.
729      * <p>The String representation consists of a list of the array's elements,
730      * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
731      * by the characters <code>", "</code> (a comma followed by a space). Returns
732      * <code>"null"</code> if <code>array</code> is <code>null</code>.
733      *
734      * @param array the array to build a String representation for
735      * @return a String representation of <code>array</code>
736      */

737     public static String nullSafeToString(char[] array) {
738         if (array == null) {
739             return NULL_STRING;
740         }
741         int length = array.length;
742         if (length == 0) {
743             return EMPTY_ARRAY;
744         }
745         StringBuilder sb = new StringBuilder();
746         for (int i = 0; i < length; i++) {
747             if (i == 0) {
748                 sb.append(ARRAY_START);
749             } else {
750                 sb.append(ARRAY_ELEMENT_SEPARATOR);
751             }
752             sb.append("'").append(array[i]).append("'");
753         }
754         sb.append(ARRAY_END);
755         return sb.toString();
756     }
757
758     /**
759      * Return a String representation of the contents of the specified array.
760      * <p>The String representation consists of a list of the array's elements,
761      * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
762      * by the characters <code>", "</code> (a comma followed by a space). Returns
763      * <code>"null"</code> if <code>array</code> is <code>null</code>.
764      *
765      * @param array the array to build a String representation for
766      * @return a String representation of <code>array</code>
767      */

768     public static String nullSafeToString(double[] array) {
769         if (array == null) {
770             return NULL_STRING;
771         }
772         int length = array.length;
773         if (length == 0) {
774             return EMPTY_ARRAY;
775         }
776         StringBuilder sb = new StringBuilder();
777         for (int i = 0; i < length; i++) {
778             if (i == 0) {
779                 sb.append(ARRAY_START);
780             } else {
781                 sb.append(ARRAY_ELEMENT_SEPARATOR);
782             }
783
784             sb.append(array[i]);
785         }
786         sb.append(ARRAY_END);
787         return sb.toString();
788     }
789
790     /**
791      * Return a String representation of the contents of the specified array.
792      * <p>The String representation consists of a list of the array's elements,
793      * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
794      * by the characters <code>", "</code> (a comma followed by a space). Returns
795      * <code>"null"</code> if <code>array</code> is <code>null</code>.
796      *
797      * @param array the array to build a String representation for
798      * @return a String representation of <code>array</code>
799      */

800     public static String nullSafeToString(float[] array) {
801         if (array == null) {
802             return NULL_STRING;
803         }
804         int length = array.length;
805         if (length == 0) {
806             return EMPTY_ARRAY;
807         }
808         StringBuilder sb = new StringBuilder();
809         for (int i = 0; i < length; i++) {
810             if (i == 0) {
811                 sb.append(ARRAY_START);
812             } else {
813                 sb.append(ARRAY_ELEMENT_SEPARATOR);
814             }
815
816             sb.append(array[i]);
817         }
818         sb.append(ARRAY_END);
819         return sb.toString();
820     }
821
822     /**
823      * Return a String representation of the contents of the specified array.
824      * <p>The String representation consists of a list of the array's elements,
825      * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
826      * by the characters <code>", "</code> (a comma followed by a space). Returns
827      * <code>"null"</code> if <code>array</code> is <code>null</code>.
828      *
829      * @param array the array to build a String representation for
830      * @return a String representation of <code>array</code>
831      */

832     public static String nullSafeToString(int[] array) {
833         if (array == null) {
834             return NULL_STRING;
835         }
836         int length = array.length;
837         if (length == 0) {
838             return EMPTY_ARRAY;
839         }
840         StringBuilder sb = new StringBuilder();
841         for (int i = 0; i < length; i++) {
842             if (i == 0) {
843                 sb.append(ARRAY_START);
844             } else {
845                 sb.append(ARRAY_ELEMENT_SEPARATOR);
846             }
847             sb.append(array[i]);
848         }
849         sb.append(ARRAY_END);
850         return sb.toString();
851     }
852
853     /**
854      * Return a String representation of the contents of the specified array.
855      * <p>The String representation consists of a list of the array's elements,
856      * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
857      * by the characters <code>", "</code> (a comma followed by a space). Returns
858      * <code>"null"</code> if <code>array</code> is <code>null</code>.
859      *
860      * @param array the array to build a String representation for
861      * @return a String representation of <code>array</code>
862      */

863     public static String nullSafeToString(long[] array) {
864         if (array == null) {
865             return NULL_STRING;
866         }
867         int length = array.length;
868         if (length == 0) {
869             return EMPTY_ARRAY;
870         }
871         StringBuilder sb = new StringBuilder();
872         for (int i = 0; i < length; i++) {
873             if (i == 0) {
874                 sb.append(ARRAY_START);
875             } else {
876                 sb.append(ARRAY_ELEMENT_SEPARATOR);
877             }
878             sb.append(array[i]);
879         }
880         sb.append(ARRAY_END);
881         return sb.toString();
882     }
883
884     /**
885      * Return a String representation of the contents of the specified array.
886      * <p>The String representation consists of a list of the array's elements,
887      * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
888      * by the characters <code>", "</code> (a comma followed by a space). Returns
889      * <code>"null"</code> if <code>array</code> is <code>null</code>.
890      *
891      * @param array the array to build a String representation for
892      * @return a String representation of <code>array</code>
893      */

894     public static String nullSafeToString(short[] array) {
895         if (array == null) {
896             return NULL_STRING;
897         }
898         int length = array.length;
899         if (length == 0) {
900             return EMPTY_ARRAY;
901         }
902         StringBuilder sb = new StringBuilder();
903         for (int i = 0; i < length; i++) {
904             if (i == 0) {
905                 sb.append(ARRAY_START);
906             } else {
907                 sb.append(ARRAY_ELEMENT_SEPARATOR);
908             }
909             sb.append(array[i]);
910         }
911         sb.append(ARRAY_END);
912         return sb.toString();
913     }
914
915     public static void nullSafeClose(Closeable... closeables) {
916         if (closeables == null) {
917             return;
918         }
919
920         for (Closeable closeable : closeables) {
921             if (closeable != null) {
922                 try {
923                     closeable.close();
924                 } catch (IOException e) {
925                     //Ignore the exception during close.
926                 }
927             }
928         }
929     }
930 }
931