StringUtils.java

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

  17. package org.jivesoftware.smack.util;

  18. import java.io.UnsupportedEncodingException;
  19. import java.util.Collection;
  20. import java.util.Random;

  21. /**
  22.  * A collection of utility methods for String objects.
  23.  */
  24. public class StringUtils {

  25.     public static final String MD5 = "MD5";
  26.     public static final String SHA1 = "SHA-1";
  27.     public static final String UTF8 = "UTF-8";
  28.     public static final String USASCII = "US-ASCII";

  29.     public static final String QUOTE_ENCODE = """;
  30.     public static final String APOS_ENCODE = "'";
  31.     public static final String AMP_ENCODE = "&";
  32.     public static final String LT_ENCODE = "<";
  33.     public static final String GT_ENCODE = ">";

  34.     public static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();

  35.     /**
  36.      * Escapes all necessary characters in the String so that it can be used
  37.      * in an XML doc.
  38.      *
  39.      * @param string the string to escape.
  40.      * @return the string with appropriate characters escaped.
  41.      */
  42.     public static CharSequence escapeForXML(final String string) {
  43.         if (string == null) {
  44.             return null;
  45.         }
  46.         final char[] input = string.toCharArray();
  47.         final int len = input.length;
  48.         final StringBuilder out = new StringBuilder((int)(len*1.3));
  49.         CharSequence toAppend;
  50.         char ch;
  51.         int last = 0;
  52.         int i = 0;
  53.         while (i < len) {
  54.             toAppend = null;
  55.             ch = input[i];
  56.             switch(ch) {
  57.             case '<':
  58.                 toAppend = LT_ENCODE;
  59.                 break;
  60.             case '>':
  61.                 toAppend = GT_ENCODE;
  62.                 break;
  63.             case '&':
  64.                 toAppend = AMP_ENCODE;
  65.                 break;
  66.             case '"':
  67.                 toAppend = QUOTE_ENCODE;
  68.                 break;
  69.             case '\'':
  70.                 toAppend = APOS_ENCODE;
  71.                 break;
  72.             default:
  73.                 break;
  74.             }
  75.             if (toAppend != null) {
  76.                 if (i > last) {
  77.                     out.append(input, last, i - last);
  78.                 }
  79.                 out.append(toAppend);
  80.                 last = ++i;
  81.             } else {
  82.                 i++;
  83.             }
  84.         }
  85.         if (last == 0) {
  86.             return string;
  87.         }
  88.         if (i > last) {
  89.             out.append(input, last, i - last);
  90.         }
  91.         return out;
  92.     }

  93.     /**
  94.      * Hashes a String using the SHA-1 algorithm and returns the result as a
  95.      * String of hexadecimal numbers. This method is synchronized to avoid
  96.      * excessive MessageDigest object creation. If calling this method becomes
  97.      * a bottleneck in your code, you may wish to maintain a pool of
  98.      * MessageDigest objects instead of using this method.
  99.      * <p>
  100.      * A hash is a one-way function -- that is, given an
  101.      * input, an output is easily computed. However, given the output, the
  102.      * input is almost impossible to compute. This is useful for passwords
  103.      * since we can store the hash and a hacker will then have a very hard time
  104.      * determining the original password.
  105.      *
  106.      * @param data the String to compute the hash of.
  107.      * @return a hashed version of the passed-in String
  108.      * @deprecated use {@link org.jivesoftware.smack.util.SHA1#hex(String)} instead.
  109.      */
  110.     @Deprecated
  111.     public synchronized static String hash(String data) {
  112.         return org.jivesoftware.smack.util.SHA1.hex(data);
  113.     }

  114.     /**
  115.      * Encodes an array of bytes as String representation of hexadecimal.
  116.      *
  117.      * @param bytes an array of bytes to convert to a hex string.
  118.      * @return generated hex string.
  119.      */
  120.     public static String encodeHex(byte[] bytes) {
  121.         char[] hexChars = new char[bytes.length * 2];
  122.         for ( int j = 0; j < bytes.length; j++ ) {
  123.             int v = bytes[j] & 0xFF;
  124.             hexChars[j * 2] = HEX_CHARS[v >>> 4];
  125.             hexChars[j * 2 + 1] = HEX_CHARS[v & 0x0F];
  126.         }
  127.         return new String(hexChars);
  128.     }

  129.     public static byte[] toBytes(String string) {
  130.         try {
  131.             return string.getBytes(StringUtils.UTF8);
  132.         }
  133.         catch (UnsupportedEncodingException e) {
  134.             throw new IllegalStateException("UTF-8 encoding not supported by platform", e);
  135.         }
  136.     }
  137.  
  138.     /**
  139.      * Pseudo-random number generator object for use with randomString().
  140.      * The Random class is not considered to be cryptographically secure, so
  141.      * only use these random Strings for low to medium security applications.
  142.      */
  143.     private static Random randGen = new Random();

  144.     /**
  145.      * Array of numbers and letters of mixed case. Numbers appear in the list
  146.      * twice so that there is a more equal chance that a number will be picked.
  147.      * We can use the array to get a random number or letter by picking a random
  148.      * array index.
  149.      */
  150.     private static char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" +
  151.                     "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();

  152.     /**
  153.      * Returns a random String of numbers and letters (lower and upper case)
  154.      * of the specified length. The method uses the Random class that is
  155.      * built-in to Java which is suitable for low to medium grade security uses.
  156.      * This means that the output is only pseudo random, i.e., each number is
  157.      * mathematically generated so is not truly random.<p>
  158.      *
  159.      * The specified length must be at least one. If not, the method will return
  160.      * null.
  161.      *
  162.      * @param length the desired length of the random String to return.
  163.      * @return a random String of numbers and letters of the specified length.
  164.      */
  165.     public static String randomString(int length) {
  166.         if (length < 1) {
  167.             return null;
  168.         }
  169.         // Create a char buffer to put random letters and numbers in.
  170.         char [] randBuffer = new char[length];
  171.         for (int i=0; i<randBuffer.length; i++) {
  172.             randBuffer[i] = numbersAndLetters[randGen.nextInt(numbersAndLetters.length)];
  173.         }
  174.         return new String(randBuffer);
  175.     }

  176.     /**
  177.      * Returns true if CharSequence is not null and is not empty, false otherwise
  178.      * Examples:
  179.      *    isNotEmpty(null) - false
  180.      *    isNotEmpty("") - false
  181.      *    isNotEmpty(" ") - true
  182.      *    isNotEmpty("empty") - true
  183.      *
  184.      * @param cs checked CharSequence
  185.      * @return true if string is not null and is not empty, false otherwise
  186.      */
  187.     public static boolean isNotEmpty(CharSequence cs) {
  188.         return !isNullOrEmpty(cs);
  189.     }

  190.     /**
  191.      * Returns true if the given CharSequence is null or empty.
  192.      *
  193.      * @param cs
  194.      * @return true if the given CharSequence is null or empty
  195.      */
  196.     public static boolean isNullOrEmpty(CharSequence cs) {
  197.         return cs == null || isEmpty(cs);
  198.     }

  199.     /**
  200.      * Returns true if the given CharSequence is empty
  201.      *
  202.      * @param cs
  203.      * @return true if the given CharSequence is empty
  204.      */
  205.     public static boolean isEmpty(CharSequence cs) {
  206.         return cs.length() == 0;
  207.     }

  208.     public static String collectionToString(Collection<String> collection) {
  209.         StringBuilder sb = new StringBuilder();
  210.         for (String s : collection) {
  211.             sb.append(s);
  212.             sb.append(" ");
  213.         }
  214.         String res = sb.toString();
  215.         // Remove the trailing whitespace
  216.         res = res.substring(0, res.length() - 1);
  217.         return res;
  218.     }

  219.     public static String returnIfNotEmptyTrimmed(String string) {
  220.         if (string == null)
  221.             return null;
  222.         String trimmedString = string.trim();
  223.         if (trimmedString.length() > 0) {
  224.             return trimmedString;
  225.         } else {
  226.             return null;
  227.         }
  228.     }

  229.     public static boolean nullSafeCharSequenceEquals(CharSequence csOne, CharSequence csTwo) {
  230.         return nullSafeCharSequenceComperator(csOne, csTwo) == 0;
  231.     }

  232.     public static int nullSafeCharSequenceComperator(CharSequence csOne, CharSequence csTwo) {
  233.         if (csOne == null ^ csTwo == null) {
  234.             return (csOne == null) ? -1 : 1;
  235.         }
  236.         if (csOne == null && csTwo == null) {
  237.             return 0;
  238.         }
  239.         return csOne.toString().compareTo(csTwo.toString());
  240.     }

  241.     public static <CS extends CharSequence> CS requireNotNullOrEmpty(CS cs, String message) {
  242.         if (isNullOrEmpty(cs)) {
  243.             throw new IllegalArgumentException(message);
  244.         }
  245.         return cs;
  246.     }

  247.     /**
  248.      * Return the String representation of the given char sequence if it is not null.
  249.      *
  250.      * @param cs the char sequence or null.
  251.      * @return the String representation of <code>cs</code> or null.
  252.      */
  253.     public static String maybeToString(CharSequence cs) {
  254.         if (cs == null) {
  255.             return null;
  256.         }
  257.         return cs.toString();
  258.     }
  259. }