From bd210ee7438fd203c19d3e8080ea12b79fe56159 Mon Sep 17 00:00:00 2001 From: ?? ? <ulysseskao@ximple.com.tw> Date: Mon, 09 Jun 2008 17:19:15 +0800 Subject: [PATCH] update for EOFM-117 --- xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/util/StringUtils.java | 5174 +++++++++++++++++++++++++++++----------------------------- 1 files changed, 2,568 insertions(+), 2,606 deletions(-) diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/util/StringUtils.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/util/StringUtils.java index 06e869a..5821070 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/util/StringUtils.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/util/StringUtils.java @@ -1,2806 +1,2770 @@ package com.ximple.eofms.util; -import java.util.Map; -import java.util.HashMap; -import java.util.Set; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Collection; -import java.util.Locale; -import java.util.regex.Pattern; -import java.util.regex.Matcher; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Array; +import java.net.URLEncoder; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; -import java.nio.charset.CharacterCodingException; -import java.nio.CharBuffer; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.lang.reflect.Array; import java.text.BreakIterator; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public abstract class StringUtils { - public static String ENCODING_US_ASCII = "US-ASCII"; - public static String ENCODING_ISO_8859_1 = "ISO-8859-1"; - public static String ENCODING_ISO_8859_2 = "ISO-8859-2"; - public static String ENCODING_ISO_8859_5 = "ISO-8859-5"; - public static String ENCODING_UTF_8 = "UTF-8"; - public static String ENCODING_UTF_16BE = "UTF-16BE"; - public static String ENCODING_UTF_16LE = "UTF-16LE"; - public static String ENCODING_UTF_16 = "UTF-16"; + public static String ENCODING_US_ASCII = "US-ASCII"; + public static String ENCODING_ISO_8859_1 = "ISO-8859-1"; + public static String ENCODING_ISO_8859_2 = "ISO-8859-2"; + public static String ENCODING_ISO_8859_5 = "ISO-8859-5"; + public static String ENCODING_UTF_8 = "UTF-8"; + public static String ENCODING_UTF_16BE = "UTF-16BE"; + public static String ENCODING_UTF_16LE = "UTF-16LE"; + public static String ENCODING_UTF_16 = "UTF-16"; - public static Charset CHARSET_US_ASCII = Charset.forName(StringUtils.ENCODING_US_ASCII); + public static Charset CHARSET_US_ASCII = Charset.forName(StringUtils.ENCODING_US_ASCII); - public static final Pattern BBCODE_COLOR = Pattern.compile("\\[color\\s*=\\s*([#\\w]*)\\s*\\]", Pattern.CASE_INSENSITIVE); - public static final Pattern BBCODE_SIZE = Pattern.compile("\\[size\\s*=\\s*([+\\-]?[0-9]*)\\s*\\]", Pattern.CASE_INSENSITIVE); - public static final Pattern BBCODE_URL_SHORT = Pattern.compile("\\[url\\]\\s*([^\\s]*)\\s*\\[\\/url\\]", Pattern.CASE_INSENSITIVE); - public static final Pattern BBCODE_URL_LONG = Pattern.compile("\\[url=([^\\[]*)\\]([^\\[]*)\\[/url\\]", Pattern.CASE_INSENSITIVE); - public static final Pattern BBCODE_IMG = Pattern.compile("\\[img\\]\\s*([^\\s]*)\\s*\\[\\/img\\]", Pattern.CASE_INSENSITIVE); - public static final Pattern BBCODE_QUOTE_LONG = Pattern.compile("\\[quote=([^\\]]+\\]*)\\]", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); - public static final Pattern BBCODE_BAREURL = Pattern.compile("(?:[^\"'=>\\]]|^)((?:http|ftp)s?://(?:%[\\p{Digit}A-Fa-f][\\p{Digit}A-Fa-f]|[\\-_\\.!~*';\\|/?:@#&=\\+$,\\p{Alnum}])+)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); + public static final Pattern BBCODE_COLOR = Pattern.compile("\\[color\\s*=\\s*([#\\w]*)\\s*\\]", Pattern.CASE_INSENSITIVE); + public static final Pattern BBCODE_SIZE = Pattern.compile("\\[size\\s*=\\s*([+\\-]?[0-9]*)\\s*\\]", Pattern.CASE_INSENSITIVE); + public static final Pattern BBCODE_URL_SHORT = Pattern.compile("\\[url\\]\\s*([^\\s]*)\\s*\\[\\/url\\]", Pattern.CASE_INSENSITIVE); + public static final Pattern BBCODE_URL_LONG = Pattern.compile("\\[url=([^\\[]*)\\]([^\\[]*)\\[/url\\]", Pattern.CASE_INSENSITIVE); + public static final Pattern BBCODE_IMG = Pattern.compile("\\[img\\]\\s*([^\\s]*)\\s*\\[\\/img\\]", Pattern.CASE_INSENSITIVE); + public static final Pattern BBCODE_QUOTE_LONG = Pattern.compile("\\[quote=([^\\]]+\\]*)\\]", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); + public static final Pattern BBCODE_BAREURL = Pattern.compile("(?:[^\"'=>\\]]|^)((?:http|ftp)s?://(?:%[\\p{Digit}A-Fa-f][\\p{Digit}A-Fa-f]|[\\-_\\.!~*';\\|/?:@#&=\\+$,\\p{Alnum}])+)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); - private static final Map<Character, String> AGGRESSIVE_HTML_ENCODE_MAP = new HashMap<Character, String>(); - private static final Map<Character, String> DEFENSIVE_HTML_ENCODE_MAP = new HashMap<Character, String>(); - private static final Map<Character, String> XML_ENCODE_MAP = new HashMap<Character, String>(); - private static final Map<Character, String> STRING_ENCODE_MAP = new HashMap<Character, String>(); - private static final Map<Character, String> SQL_ENCODE_MAP = new HashMap<Character, String>(); - private static final Map<Character, String> LATEX_ENCODE_MAP = new HashMap<Character, String>(); + private static final Map<Character, String> AGGRESSIVE_HTML_ENCODE_MAP = new HashMap<Character, String>(); + private static final Map<Character, String> DEFENSIVE_HTML_ENCODE_MAP = new HashMap<Character, String>(); + private static final Map<Character, String> XML_ENCODE_MAP = new HashMap<Character, String>(); + private static final Map<Character, String> STRING_ENCODE_MAP = new HashMap<Character, String>(); + private static final Map<Character, String> SQL_ENCODE_MAP = new HashMap<Character, String>(); + private static final Map<Character, String> LATEX_ENCODE_MAP = new HashMap<Character, String>(); - private static final Map<String, Character> HTML_DECODE_MAP = new HashMap<String, Character>(); + private static final Map<String, Character> HTML_DECODE_MAP = new HashMap<String, Character>(); - private static final HtmlEncoderFallbackHandler HTML_ENCODER_FALLBACK = new HtmlEncoderFallbackHandler(); + private static final HtmlEncoderFallbackHandler HTML_ENCODER_FALLBACK = new HtmlEncoderFallbackHandler(); - static - { - // Html encoding mapping according to the HTML 4.0 spec - // http://www.w3.org/TR/REC-html40/sgml/entities.html + static + { + // Html encoding mapping according to the HTML 4.0 spec + // http://www.w3.org/TR/REC-html40/sgml/entities.html - // Special characters for HTML - AGGRESSIVE_HTML_ENCODE_MAP.put('\u0026',"&"); - AGGRESSIVE_HTML_ENCODE_MAP.put('\u003C',"<"); - AGGRESSIVE_HTML_ENCODE_MAP.put('\u003E',">"); - AGGRESSIVE_HTML_ENCODE_MAP.put('\u0022',"""); + // Special characters for HTML + AGGRESSIVE_HTML_ENCODE_MAP.put('\u0026', "&"); + AGGRESSIVE_HTML_ENCODE_MAP.put('\u003C', "<"); + AGGRESSIVE_HTML_ENCODE_MAP.put('\u003E', ">"); + AGGRESSIVE_HTML_ENCODE_MAP.put('\u0022', """); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0152',"Œ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0153',"œ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0160',"Š"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0161',"š"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0178',"Ÿ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u02C6',"ˆ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u02DC',"˜"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2002'," "); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2003'," "); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2009'," "); - DEFENSIVE_HTML_ENCODE_MAP.put('\u200C',"‌"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u200D',"‍"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u200E',"‎"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u200F',"‏"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2013',"–"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2014',"—"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2018',"‘"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2019',"’"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u201A',"‚"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u201C',"“"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u201D',"”"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u201E',"„"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2020',"†"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2021',"‡"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2030',"‰"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2039',"‹"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u203A',"›"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u20AC',"€"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0152', "Œ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0153', "œ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0160', "Š"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0161', "š"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0178', "Ÿ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u02C6', "ˆ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u02DC', "˜"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2002', " "); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2003', " "); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2009', " "); + DEFENSIVE_HTML_ENCODE_MAP.put('\u200C', "‌"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u200D', "‍"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u200E', "‎"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u200F', "‏"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2013', "–"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2014', "—"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2018', "‘"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2019', "’"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u201A', "‚"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u201C', "“"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u201D', "”"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u201E', "„"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2020', "†"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2021', "‡"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2030', "‰"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2039', "‹"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u203A', "›"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u20AC', "€"); - // Character entity references for ISO 8859-1 characters - DEFENSIVE_HTML_ENCODE_MAP.put('\u00A0'," "); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00A1',"¡"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00A2',"¢"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00A3',"£"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00A4',"¤"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00A5',"¥"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00A6',"¦"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00A7',"§"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00A8',"¨"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00A9',"©"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00AA',"ª"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00AB',"«"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00AC',"¬"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00AD',"­"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00AE',"®"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00AF',"¯"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00B0',"°"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00B1',"±"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00B2',"²"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00B3',"³"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00B4',"´"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00B5',"µ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00B6',"¶"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00B7',"·"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00B8',"¸"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00B9',"¹"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00BA',"º"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00BB',"»"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00BC',"¼"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00BD',"½"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00BE',"¾"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00BF',"¿"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00C0',"À"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00C1',"Á"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00C2',"Â"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00C3',"Ã"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00C4',"Ä"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00C5',"Å"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00C6',"Æ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00C7',"Ç"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00C8',"È"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00C9',"É"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00CA',"Ê"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00CB',"Ë"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00CC',"Ì"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00CD',"Í"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00CE',"Î"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00CF',"Ï"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00D0',"Ð"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00D1',"Ñ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00D2',"Ò"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00D3',"Ó"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00D4',"Ô"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00D5',"Õ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00D6',"Ö"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00D7',"×"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00D8',"Ø"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00D9',"Ù"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00DA',"Ú"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00DB',"Û"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00DC',"Ü"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00DD',"Ý"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00DE',"Þ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00DF',"ß"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00E0',"à"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00E1',"á"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00E2',"â"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00E3',"ã"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00E4',"ä"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00E5',"å"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00E6',"æ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00E7',"ç"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00E8',"è"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00E9',"é"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00EA',"ê"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00EB',"ë"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00EC',"ì"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00ED',"í"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00EE',"î"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00EF',"ï"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00F0',"ð"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00F1',"ñ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00F2',"ò"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00F3',"ó"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00F4',"ô"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00F5',"õ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00F6',"ö"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00F7',"÷"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00F8',"ø"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00F9',"ù"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00FA',"ú"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00FB',"û"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00FC',"ü"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00FD',"ý"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00FE',"þ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u00FF',"ÿ"); + // Character entity references for ISO 8859-1 characters + DEFENSIVE_HTML_ENCODE_MAP.put('\u00A0', " "); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00A1', "¡"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00A2', "¢"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00A3', "£"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00A4', "¤"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00A5', "¥"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00A6', "¦"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00A7', "§"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00A8', "¨"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00A9', "©"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00AA', "ª"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00AB', "«"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00AC', "¬"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00AD', "­"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00AE', "®"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00AF', "¯"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00B0', "°"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00B1', "±"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00B2', "²"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00B3', "³"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00B4', "´"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00B5', "µ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00B6', "¶"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00B7', "·"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00B8', "¸"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00B9', "¹"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00BA', "º"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00BB', "»"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00BC', "¼"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00BD', "½"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00BE', "¾"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00BF', "¿"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00C0', "À"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00C1', "Á"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00C2', "Â"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00C3', "Ã"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00C4', "Ä"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00C5', "Å"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00C6', "Æ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00C7', "Ç"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00C8', "È"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00C9', "É"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00CA', "Ê"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00CB', "Ë"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00CC', "Ì"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00CD', "Í"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00CE', "Î"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00CF', "Ï"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00D0', "Ð"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00D1', "Ñ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00D2', "Ò"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00D3', "Ó"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00D4', "Ô"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00D5', "Õ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00D6', "Ö"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00D7', "×"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00D8', "Ø"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00D9', "Ù"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00DA', "Ú"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00DB', "Û"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00DC', "Ü"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00DD', "Ý"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00DE', "Þ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00DF', "ß"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00E0', "à"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00E1', "á"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00E2', "â"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00E3', "ã"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00E4', "ä"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00E5', "å"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00E6', "æ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00E7', "ç"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00E8', "è"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00E9', "é"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00EA', "ê"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00EB', "ë"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00EC', "ì"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00ED', "í"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00EE', "î"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00EF', "ï"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00F0', "ð"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00F1', "ñ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00F2', "ò"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00F3', "ó"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00F4', "ô"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00F5', "õ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00F6', "ö"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00F7', "÷"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00F8', "ø"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00F9', "ù"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00FA', "ú"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00FB', "û"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00FC', "ü"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00FD', "ý"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00FE', "þ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u00FF', "ÿ"); - // Mathematical, Greek and Symbolic characters for HTML - DEFENSIVE_HTML_ENCODE_MAP.put('\u0192',"ƒ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0391',"Α"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0392',"Β"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0393',"Γ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0394',"Δ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0395',"Ε"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0396',"Ζ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0397',"Η"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0398',"Θ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u0399',"Ι"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u039A',"Κ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u039B',"Λ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u039C',"Μ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u039D',"Ν"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u039E',"Ξ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u039F',"Ο"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03A0',"Π"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03A1',"Ρ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03A3',"Σ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03A4',"Τ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03A5',"Υ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03A6',"Φ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03A7',"Χ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03A8',"Ψ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03A9',"Ω"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03B1',"α"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03B2',"β"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03B3',"γ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03B4',"δ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03B5',"ε"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03B6',"ζ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03B7',"η"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03B8',"θ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03B9',"ι"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03BA',"κ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03BB',"λ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03BC',"μ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03BD',"ν"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03BE',"ξ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03BF',"ο"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03C0',"π"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03C1',"ρ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03C2',"ς"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03C3',"σ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03C4',"τ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03C5',"υ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03C6',"φ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03C7',"χ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03C8',"ψ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03C9',"ω"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03D1',"ϑ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03D2',"ϒ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u03D6',"ϖ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2022',"•"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2026',"…"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2032',"′"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2033',"″"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u203E',"‾"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2044',"⁄"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2118',"℘"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2111',"ℑ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u211C',"ℜ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2122',"™"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2135',"ℵ"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2190',"←"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2191',"↑"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2192',"→"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2193',"↓"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2194',"↔"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u21B5',"↵"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u21D0',"⇐"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u21D1',"⇑"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u21D2',"⇒"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u21D3',"⇓"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u21D4',"⇔"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2200',"∀"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2202',"∂"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2203',"∃"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2205',"∅"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2207',"∇"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2208',"∈"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2209',"∉"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u220B',"∋"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u220F',"∏"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2211',"∑"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2212',"−"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2217',"∗"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u221A',"√"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u221D',"∝"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u221E',"∞"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2220',"∠"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2227',"∧"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2228',"∨"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2229',"∩"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u222A',"∪"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u222B',"∫"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2234',"∴"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u223C',"∼"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2245',"≅"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2248',"≈"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2260',"≠"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2261',"≡"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2264',"≤"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2265',"≥"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2282',"⊂"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2283',"⊃"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2284',"⊄"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2286',"⊆"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2287',"⊇"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2295',"⊕"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2297',"⊗"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u22A5',"⊥"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u22C5',"⋅"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2308',"⌈"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2309',"⌉"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u230A',"⌊"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u230B',"⌋"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2329',"⟨"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u232A',"⟩"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u25CA',"◊"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2660',"♠"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2663',"♣"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2665',"♥"); - DEFENSIVE_HTML_ENCODE_MAP.put('\u2666',"♦"); + // Mathematical, Greek and Symbolic characters for HTML + DEFENSIVE_HTML_ENCODE_MAP.put('\u0192', "ƒ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0391', "Α"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0392', "Β"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0393', "Γ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0394', "Δ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0395', "Ε"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0396', "Ζ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0397', "Η"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0398', "Θ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u0399', "Ι"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u039A', "Κ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u039B', "Λ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u039C', "Μ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u039D', "Ν"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u039E', "Ξ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u039F', "Ο"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03A0', "Π"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03A1', "Ρ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03A3', "Σ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03A4', "Τ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03A5', "Υ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03A6', "Φ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03A7', "Χ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03A8', "Ψ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03A9', "Ω"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03B1', "α"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03B2', "β"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03B3', "γ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03B4', "δ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03B5', "ε"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03B6', "ζ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03B7', "η"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03B8', "θ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03B9', "ι"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03BA', "κ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03BB', "λ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03BC', "μ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03BD', "ν"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03BE', "ξ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03BF', "ο"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03C0', "π"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03C1', "ρ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03C2', "ς"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03C3', "σ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03C4', "τ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03C5', "υ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03C6', "φ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03C7', "χ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03C8', "ψ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03C9', "ω"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03D1', "ϑ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03D2', "ϒ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u03D6', "ϖ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2022', "•"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2026', "…"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2032', "′"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2033', "″"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u203E', "‾"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2044', "⁄"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2118', "℘"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2111', "ℑ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u211C', "ℜ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2122', "™"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2135', "ℵ"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2190', "←"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2191', "↑"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2192', "→"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2193', "↓"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2194', "↔"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u21B5', "↵"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u21D0', "⇐"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u21D1', "⇑"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u21D2', "⇒"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u21D3', "⇓"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u21D4', "⇔"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2200', "∀"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2202', "∂"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2203', "∃"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2205', "∅"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2207', "∇"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2208', "∈"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2209', "∉"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u220B', "∋"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u220F', "∏"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2211', "∑"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2212', "−"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2217', "∗"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u221A', "√"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u221D', "∝"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u221E', "∞"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2220', "∠"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2227', "∧"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2228', "∨"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2229', "∩"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u222A', "∪"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u222B', "∫"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2234', "∴"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u223C', "∼"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2245', "≅"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2248', "≈"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2260', "≠"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2261', "≡"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2264', "≤"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2265', "≥"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2282', "⊂"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2283', "⊃"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2284', "⊄"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2286', "⊆"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2287', "⊇"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2295', "⊕"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2297', "⊗"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u22A5', "⊥"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u22C5', "⋅"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2308', "⌈"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2309', "⌉"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u230A', "⌊"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u230B', "⌋"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2329', "⟨"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u232A', "⟩"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u25CA', "◊"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2660', "♠"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2663', "♣"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2665', "♥"); + DEFENSIVE_HTML_ENCODE_MAP.put('\u2666', "♦"); - Set<Map.Entry<Character, String>> aggresive_entries = AGGRESSIVE_HTML_ENCODE_MAP.entrySet(); - for (Map.Entry<Character, String> entry : aggresive_entries) - { - HTML_DECODE_MAP.put(entry.getValue(), entry.getKey()); - } + Set<Map.Entry<Character, String>> aggresive_entries = AGGRESSIVE_HTML_ENCODE_MAP.entrySet(); + for (Map.Entry<Character, String> entry : aggresive_entries) + { + HTML_DECODE_MAP.put(entry.getValue(), entry.getKey()); + } - Set<Map.Entry<Character, String>> defensive_entries = DEFENSIVE_HTML_ENCODE_MAP.entrySet(); - for (Map.Entry<Character, String> entry : defensive_entries) - { - HTML_DECODE_MAP.put(entry.getValue(), entry.getKey()); - } + Set<Map.Entry<Character, String>> defensive_entries = DEFENSIVE_HTML_ENCODE_MAP.entrySet(); + for (Map.Entry<Character, String> entry : defensive_entries) + { + HTML_DECODE_MAP.put(entry.getValue(), entry.getKey()); + } - XML_ENCODE_MAP.put('\u0026',"&"); - XML_ENCODE_MAP.put('\'',"'"); - XML_ENCODE_MAP.put('\u0022',"""); - XML_ENCODE_MAP.put('\u003C',"<"); - XML_ENCODE_MAP.put('\u003E',">"); + XML_ENCODE_MAP.put('\u0026', "&"); + XML_ENCODE_MAP.put('\'', "'"); + XML_ENCODE_MAP.put('\u0022', """); + XML_ENCODE_MAP.put('\u003C', "<"); + XML_ENCODE_MAP.put('\u003E', ">"); - SQL_ENCODE_MAP.put('\'',"''"); + SQL_ENCODE_MAP.put('\'', "''"); - STRING_ENCODE_MAP.put('\\',"\\\\"); - STRING_ENCODE_MAP.put('\n',"\\n"); - STRING_ENCODE_MAP.put('\r',"\\r"); - STRING_ENCODE_MAP.put('\t',"\\t"); - STRING_ENCODE_MAP.put('"',"\\\""); + STRING_ENCODE_MAP.put('\\', "\\\\"); + STRING_ENCODE_MAP.put('\n', "\\n"); + STRING_ENCODE_MAP.put('\r', "\\r"); + STRING_ENCODE_MAP.put('\t', "\\t"); + STRING_ENCODE_MAP.put('"', "\\\""); - LATEX_ENCODE_MAP.put('\\',"\\\\"); - LATEX_ENCODE_MAP.put('#',"\\#"); - LATEX_ENCODE_MAP.put('$',"\\$"); - LATEX_ENCODE_MAP.put('%',"\\%"); - LATEX_ENCODE_MAP.put('&',"\\&"); - LATEX_ENCODE_MAP.put('~',"\\~"); - LATEX_ENCODE_MAP.put('_',"\\_"); - LATEX_ENCODE_MAP.put('^',"\\^"); - LATEX_ENCODE_MAP.put('{',"\\{"); - LATEX_ENCODE_MAP.put('}',"\\}"); - LATEX_ENCODE_MAP.put('\u00A1',"!'"); - LATEX_ENCODE_MAP.put('\u00BF',"?'"); - LATEX_ENCODE_MAP.put('\u00C0',"\\`{A}"); - LATEX_ENCODE_MAP.put('\u00C1',"\\'{A}"); - LATEX_ENCODE_MAP.put('\u00C2',"\\^{A}"); - LATEX_ENCODE_MAP.put('\u00C3',"\\H{A}"); - LATEX_ENCODE_MAP.put('\u00C4',"\\\"{A}"); - LATEX_ENCODE_MAP.put('\u00C5',"\\AA"); - LATEX_ENCODE_MAP.put('\u00C6',"\\AE"); - LATEX_ENCODE_MAP.put('\u00C7',"\\c{C}"); - LATEX_ENCODE_MAP.put('\u00C8',"\\`{E}"); - LATEX_ENCODE_MAP.put('\u00C9',"\\'{E}"); - LATEX_ENCODE_MAP.put('\u00CA',"\\^{E}"); - LATEX_ENCODE_MAP.put('\u00CB',"\\\"{E}"); - LATEX_ENCODE_MAP.put('\u00CC',"\\`{I}"); - LATEX_ENCODE_MAP.put('\u00CD',"\\'{I}"); - LATEX_ENCODE_MAP.put('\u00CE',"\\^{I}"); - LATEX_ENCODE_MAP.put('\u00CF',"\\\"{I}"); + LATEX_ENCODE_MAP.put('\\', "\\\\"); + LATEX_ENCODE_MAP.put('#', "\\#"); + LATEX_ENCODE_MAP.put('$', "\\$"); + LATEX_ENCODE_MAP.put('%', "\\%"); + LATEX_ENCODE_MAP.put('&', "\\&"); + LATEX_ENCODE_MAP.put('~', "\\~"); + LATEX_ENCODE_MAP.put('_', "\\_"); + LATEX_ENCODE_MAP.put('^', "\\^"); + LATEX_ENCODE_MAP.put('{', "\\{"); + LATEX_ENCODE_MAP.put('}', "\\}"); + LATEX_ENCODE_MAP.put('\u00A1', "!'"); + LATEX_ENCODE_MAP.put('\u00BF', "?'"); + LATEX_ENCODE_MAP.put('\u00C0', "\\`{A}"); + LATEX_ENCODE_MAP.put('\u00C1', "\\'{A}"); + LATEX_ENCODE_MAP.put('\u00C2', "\\^{A}"); + LATEX_ENCODE_MAP.put('\u00C3', "\\H{A}"); + LATEX_ENCODE_MAP.put('\u00C4', "\\\"{A}"); + LATEX_ENCODE_MAP.put('\u00C5', "\\AA"); + LATEX_ENCODE_MAP.put('\u00C6', "\\AE"); + LATEX_ENCODE_MAP.put('\u00C7', "\\c{C}"); + LATEX_ENCODE_MAP.put('\u00C8', "\\`{E}"); + LATEX_ENCODE_MAP.put('\u00C9', "\\'{E}"); + LATEX_ENCODE_MAP.put('\u00CA', "\\^{E}"); + LATEX_ENCODE_MAP.put('\u00CB', "\\\"{E}"); + LATEX_ENCODE_MAP.put('\u00CC', "\\`{I}"); + LATEX_ENCODE_MAP.put('\u00CD', "\\'{I}"); + LATEX_ENCODE_MAP.put('\u00CE', "\\^{I}"); + LATEX_ENCODE_MAP.put('\u00CF', "\\\"{I}"); // todo \u00D0 - LATEX_ENCODE_MAP.put('\u00D1',"\\H{N}"); - LATEX_ENCODE_MAP.put('\u00D2',"\\`{O}"); - LATEX_ENCODE_MAP.put('\u00D3',"\\'{O}"); - LATEX_ENCODE_MAP.put('\u00D4',"\\^{O}"); - LATEX_ENCODE_MAP.put('\u00D5',"\\H{O}"); - LATEX_ENCODE_MAP.put('\u00D6',"\\\"{O}"); + LATEX_ENCODE_MAP.put('\u00D1', "\\H{N}"); + LATEX_ENCODE_MAP.put('\u00D2', "\\`{O}"); + LATEX_ENCODE_MAP.put('\u00D3', "\\'{O}"); + LATEX_ENCODE_MAP.put('\u00D4', "\\^{O}"); + LATEX_ENCODE_MAP.put('\u00D5', "\\H{O}"); + LATEX_ENCODE_MAP.put('\u00D6', "\\\"{O}"); // todo \u00D7 - LATEX_ENCODE_MAP.put('\u00D8',"\\O"); - LATEX_ENCODE_MAP.put('\u00D9',"\\`{U}"); - LATEX_ENCODE_MAP.put('\u00DA',"\\'{U}"); - LATEX_ENCODE_MAP.put('\u00DB',"\\^{U}"); - LATEX_ENCODE_MAP.put('\u00DC',"\\\"{U}"); - LATEX_ENCODE_MAP.put('\u00DD',"\\'{Y}"); + LATEX_ENCODE_MAP.put('\u00D8', "\\O"); + LATEX_ENCODE_MAP.put('\u00D9', "\\`{U}"); + LATEX_ENCODE_MAP.put('\u00DA', "\\'{U}"); + LATEX_ENCODE_MAP.put('\u00DB', "\\^{U}"); + LATEX_ENCODE_MAP.put('\u00DC', "\\\"{U}"); + LATEX_ENCODE_MAP.put('\u00DD', "\\'{Y}"); // todo \u00DE - LATEX_ENCODE_MAP.put('\u00DF',"\\ss"); - LATEX_ENCODE_MAP.put('\u00E0',"\\`{a}"); - LATEX_ENCODE_MAP.put('\u00E1',"\\'{a}"); - LATEX_ENCODE_MAP.put('\u00E2',"\\^{a}"); - LATEX_ENCODE_MAP.put('\u00E3',"\\H{a}"); - LATEX_ENCODE_MAP.put('\u00E4',"\\\"{a}"); - LATEX_ENCODE_MAP.put('\u00E5',"\\aa"); - LATEX_ENCODE_MAP.put('\u00E6',"\\ae"); - LATEX_ENCODE_MAP.put('\u00E7',"\\c{c}"); - LATEX_ENCODE_MAP.put('\u00E8',"\\`{e}"); - LATEX_ENCODE_MAP.put('\u00E9',"\\'{e}"); - LATEX_ENCODE_MAP.put('\u00EA',"\\^{e}"); - LATEX_ENCODE_MAP.put('\u00EB',"\\\"{e}"); - LATEX_ENCODE_MAP.put('\u00EC',"\\`{i}"); - LATEX_ENCODE_MAP.put('\u00ED',"\\'{i}"); - LATEX_ENCODE_MAP.put('\u00EE',"\\^{i}"); - LATEX_ENCODE_MAP.put('\u00EF',"\\\"{i}"); + LATEX_ENCODE_MAP.put('\u00DF', "\\ss"); + LATEX_ENCODE_MAP.put('\u00E0', "\\`{a}"); + LATEX_ENCODE_MAP.put('\u00E1', "\\'{a}"); + LATEX_ENCODE_MAP.put('\u00E2', "\\^{a}"); + LATEX_ENCODE_MAP.put('\u00E3', "\\H{a}"); + LATEX_ENCODE_MAP.put('\u00E4', "\\\"{a}"); + LATEX_ENCODE_MAP.put('\u00E5', "\\aa"); + LATEX_ENCODE_MAP.put('\u00E6', "\\ae"); + LATEX_ENCODE_MAP.put('\u00E7', "\\c{c}"); + LATEX_ENCODE_MAP.put('\u00E8', "\\`{e}"); + LATEX_ENCODE_MAP.put('\u00E9', "\\'{e}"); + LATEX_ENCODE_MAP.put('\u00EA', "\\^{e}"); + LATEX_ENCODE_MAP.put('\u00EB', "\\\"{e}"); + LATEX_ENCODE_MAP.put('\u00EC', "\\`{i}"); + LATEX_ENCODE_MAP.put('\u00ED', "\\'{i}"); + LATEX_ENCODE_MAP.put('\u00EE', "\\^{i}"); + LATEX_ENCODE_MAP.put('\u00EF', "\\\"{i}"); // todo \u00F0 - LATEX_ENCODE_MAP.put('\u00F1',"\\H{n}"); - LATEX_ENCODE_MAP.put('\u00F2',"\\`{o}"); - LATEX_ENCODE_MAP.put('\u00F3',"\\'{o}"); - LATEX_ENCODE_MAP.put('\u00F4',"\\^{o}"); - LATEX_ENCODE_MAP.put('\u00F5',"\\H{o}"); - LATEX_ENCODE_MAP.put('\u00F6',"\\\"{o}"); + LATEX_ENCODE_MAP.put('\u00F1', "\\H{n}"); + LATEX_ENCODE_MAP.put('\u00F2', "\\`{o}"); + LATEX_ENCODE_MAP.put('\u00F3', "\\'{o}"); + LATEX_ENCODE_MAP.put('\u00F4', "\\^{o}"); + LATEX_ENCODE_MAP.put('\u00F5', "\\H{o}"); + LATEX_ENCODE_MAP.put('\u00F6', "\\\"{o}"); // todo \u00F7 - LATEX_ENCODE_MAP.put('\u00F8',"\\o"); - LATEX_ENCODE_MAP.put('\u00F9',"\\`{u}"); - LATEX_ENCODE_MAP.put('\u00FA',"\\'{u}"); - LATEX_ENCODE_MAP.put('\u00FB',"\\^{u}"); - LATEX_ENCODE_MAP.put('\u00FC',"\\\"{u}"); - LATEX_ENCODE_MAP.put('\u00FD',"\\'{y}"); + LATEX_ENCODE_MAP.put('\u00F8', "\\o"); + LATEX_ENCODE_MAP.put('\u00F9', "\\`{u}"); + LATEX_ENCODE_MAP.put('\u00FA', "\\'{u}"); + LATEX_ENCODE_MAP.put('\u00FB', "\\^{u}"); + LATEX_ENCODE_MAP.put('\u00FC', "\\\"{u}"); + LATEX_ENCODE_MAP.put('\u00FD', "\\'{y}"); // todo \u00FE - LATEX_ENCODE_MAP.put('\u00FF',"\\\"{y}"); - } - - /** - * Transforms a provided <code>String</code> object into a new string, - * containing only valid characters for a java class name. - * - * @param name The string that has to be transformed into a valid class - * name. - * @return The encoded <code>String</code> object. - * @see #encodeUrl(String) - * @see #encodeHtml(String) - * @see #encodeXml(String) - * @see #encodeSql(String) - * @see #encodeLatex(String) - * @see #encodeRegexp(String) - * @since 1.0 - */ - public static String encodeClassname(String name) - { - if (null == name) - { - return null; - } - - Pattern pattern = Pattern.compile("[^\\w]"); - Matcher matcher = pattern.matcher(name); - - return matcher.replaceAll("_"); - } - - private static boolean needsUrlEncoding(String source) - { - if (null == source) - { - return false; - } - - // check if the string needs encoding first since - // the URLEncoder always allocates a StringBuffer, even when the - // string is returned as-is - boolean encode = false; - char ch; - for (int i = 0; i < source.length(); i++) - { - ch = source.charAt(i); - - if (ch >= 'a' && ch <= 'z' || - ch >= 'A' && ch <= 'Z' || - ch >= '0' && ch <= '9' || - ch == '-' || ch == '_' || ch == '.' || ch == '*') - { - continue; - } - - encode = true; - break; - } - - return encode; - } - - /** - * Transforms a provided <code>String</code> object into a new string, - * containing only valid URL characters. - * - * @param source The string that has to be transformed into a valid URL - * string. - * @return The encoded <code>String</code> object. - * @see #encodeClassname(String) - * @see #encodeUrlValue(String) - * @see #encodeHtml(String) - * @see #encodeXml(String) - * @see #encodeSql(String) - * @see #encodeLatex(String) - * @see #encodeRegexp(String) - * @since 1.0 - */ - public static String encodeUrl(String source) - { - if (!needsUrlEncoding(source)) - { - return source; - } - - try - { - return URLEncoder.encode(source, ENCODING_ISO_8859_1); - } - ///CLOVER:OFF - catch (UnsupportedEncodingException e) - { - // this should never happen, ISO-8859-1 is a standard encoding - throw new RuntimeException(e); - } - ///CLOVER:ON - } - - /** - * Transforms a provided <code>String</code> object into a new string, - * only pure US Ascii strings are preserved and URL encoded in a regular - * way. Strings with characters from other encodings will be encoded in a - * RIFE-specific manner to allow international data to passed along the - * query string. - * - * @param source The string that has to be transformed into a valid URL - * parameter string. - * @return The encoded <code>String</code> object. - * @see #decodeUrlValue(String) - * @see #encodeClassname(String) - * @see #encodeUrl(String) - * @see #encodeHtml(String) - * @see #encodeXml(String) - * @see #encodeSql(String) - * @see #encodeLatex(String) - * @see #encodeRegexp(String) - * @since 1.0 - */ - public static String encodeUrlValue(String source) - { - if (!needsUrlEncoding(source)) - { - return source; - } - - // check if the string is valid US-ASCII encoding - boolean valid = true; - CharsetEncoder encoder = CHARSET_US_ASCII.newEncoder(); - try - { - encoder.encode(CharBuffer.wrap(source)); - } - catch (CharacterCodingException e) - { - valid = false; - } - - try - { - // if it is valid US-ASCII, use the regular URL encoding method - if (valid) - { - return URLEncoder.encode(source, ENCODING_US_ASCII); - } - // otherwise, base-64 encode the UTF-8 bytes and mark the string - // as being encoded in a special way - else - { - StringBuilder encoded = new StringBuilder("%02%02"); - String base64 = Base64.encodeToString(source.getBytes(ENCODING_UTF_8), false); - String base64_urlsafe = replace(base64, "=", "%3D"); - encoded.append(base64_urlsafe); - - return encoded.toString(); - } - } - ///CLOVER:OFF - catch (UnsupportedEncodingException e) - { - // this should never happen, ISO-8859-1 is a standard encoding - throw new RuntimeException(e); - } - ///CLOVER:ON - } - - /** - * Decodes a <code>String</code> that has been encoded in a RIFE-specific - * manner for URL usage.. Before calling this method, you should first - * verify if the value needs decoding by using the - * <code>doesUrlValueNeedDecoding(String)</code> method. - * - * @param source the value that has been encoded for URL usage in a - * RIFE-specific way - * @return The decoded <code>String</code> object. - * @see #encodeUrlValue(String) - * @see #doesUrlValueNeedDecoding(String) - * @since 1.0 - */ - public static String decodeUrlValue(String source) - { - try - { - byte[] decoded = Base64.decode(source.substring(2)); - if (null == decoded) - { - return null; - } - else - { - return new String(decoded, StringUtils.ENCODING_UTF_8); - } - } - ///CLOVER:OFF - catch (UnsupportedEncodingException e) - { - // this should never happen, UTF-8 is a standard encoding - throw new RuntimeException(e); - } - ///CLOVER:ON - } - - /** - * Checks if a <code>String</code> is encoded in a RIFE-specific manner - * for URL usage. - * - * @param source the value that might have been encoded for URL usage in a - * RIFE-specific way - * @return <code>true</code> if the value is encoded in the RIFE-specific - * format; and - * <p><code>false</code> otherwise - * @see #encodeUrlValue(String) - * @see #decodeUrlValue(String) - * @since 1.0 - */ - public static boolean doesUrlValueNeedDecoding(String source) - { - if (source != null && - source.length() > 2 && - source.startsWith("\u0002\u0002")) - { - return true; - } - - return false; - } - - private static boolean needsHtmlEncoding(String source, boolean defensive) - { - if (null == source) - { - return false; - } - - boolean encode = false; - char ch; - for (int i = 0; i < source.length(); i++) - { - ch = source.charAt(i); - - if ((defensive || (ch != '\u0022' && ch != '\u0026' && ch != '\u003C' && ch != '\u003E')) && - ch < '\u00A0') - { - continue; - } - - encode = true; - break; - } - - return encode; - } - - /** - * - * @since 1.6 - */ - public static String decodeHtml(String source) - { - if (null == source || - 0 == source.length()) - { - return source; - } - - int current_index = 0; - int delimiter_start_index = 0; - int delimiter_end_index = 0; - - StringBuilder result = null; - - while (current_index <= source.length()) - { - delimiter_start_index = source.indexOf('&', current_index); - if (delimiter_start_index != -1) - { - delimiter_end_index = source.indexOf(';', delimiter_start_index + 1); - if (delimiter_end_index != -1) - { - // ensure that the string builder is setup correctly - if (null == result) - { - result = new StringBuilder(); - } - - // add the text that leads up to this match - if (delimiter_start_index > current_index) - { - result.append(source.substring(current_index, delimiter_start_index)); - } - - // add the decoded entity - String entity = source.substring(delimiter_start_index, delimiter_end_index + 1); - - current_index = delimiter_end_index + 1; - - // try to decoded numeric entities - if (entity.charAt(1) == '#') - { - int start = 2; - int radix = 10; - // check if the number is hexadecimal - if (entity.charAt(2) == 'X' || entity.charAt(2) == 'x') - { - start++; - radix = 16; - } - try - { - Character c = new Character((char)Integer.parseInt(entity.substring(start, entity.length() - 1), radix)); - result.append(c); - } - // when the number of the entity can't be parsed, add the entity as-is - catch (NumberFormatException e) - { - result.append(entity); - } - } - else - { - // try to decode the entity as a literal - Character decoded = HTML_DECODE_MAP.get(entity); - if (decoded != null) - { - result.append(decoded); - } - // if there was no match, add the entity as-is - else - { - result.append(entity); - } - } - } - else - { - break; - } - } - else - { - break; - } - } - - if (null == result) - { - return source; - } - else if (current_index < source.length()) - { - result.append(source.substring(current_index)); - } - - return result.toString(); - } - - /** - * Transforms a provided <code>String</code> object into a new string, - * containing only valid Html characters. - * - * @param source The string that has to be transformed into a valid Html - * string. - * @return The encoded <code>String</code> object. - * @see #encodeClassname(String) - * @see #encodeUrl(String) - * @see #encodeUrlValue(String) - * @see #encodeXml(String) - * @see #encodeSql(String) - * @see #encodeString(String) - * @see #encodeLatex(String) - * @see #encodeRegexp(String) - * @since 1.0 - */ - public static String encodeHtml(String source) - { - if (needsHtmlEncoding(source, false)) - { - return encode(source, HTML_ENCODER_FALLBACK, AGGRESSIVE_HTML_ENCODE_MAP, DEFENSIVE_HTML_ENCODE_MAP); - } - return source; - } - - /** - * Transforms a provided <code>String</code> object into a new string, - * containing as much as possible Html characters. It is safe to already - * feed existing Html to this method since &, < and > will not - * be encoded. - * - * @param source The string that has to be transformed into a valid Html - * string. - * @return The encoded <code>String</code> object. - * @see #encodeClassname(String) - * @see #encodeUrl(String) - * @see #encodeUrlValue(String) - * @see #encodeXml(String) - * @see #encodeSql(String) - * @see #encodeString(String) - * @see #encodeLatex(String) - * @see #encodeRegexp(String) - * @since 1.0 - */ - public static String encodeHtmlDefensive(String source) - { - if (needsHtmlEncoding(source, true)) - { - return encode(source, null, DEFENSIVE_HTML_ENCODE_MAP); - } - return source; - } - - /** - * Transforms a provided <code>String</code> object into a new string, - * containing only valid XML characters. - * - * @param source The string that has to be transformed into a valid XML - * string. - * @return The encoded <code>String</code> object. - * @see #encodeClassname(String) - * @see #encodeUrl(String) - * @see #encodeUrlValue(String) - * @see #encodeHtml(String) - * @see #encodeSql(String) - * @see #encodeString(String) - * @see #encodeLatex(String) - * @see #encodeRegexp(String) - * @since 1.0 - */ - public static String encodeXml(String source) - { - return encode(source, null, XML_ENCODE_MAP); - } - - /** - * Transforms a provided <code>String</code> object into a new string, - * containing only valid <code>String</code> characters. - * - * @param source The string that has to be transformed into a valid - * sequence of <code>String</code> characters. - * @return The encoded <code>String</code> object. - * @see #encodeClassname(String) - * @see #encodeUrl(String) - * @see #encodeUrlValue(String) - * @see #encodeHtml(String) - * @see #encodeXml(String) - * @see #encodeSql(String) - * @see #encodeLatex(String) - * @see #encodeRegexp(String) - * @since 1.0 - */ - public static String encodeString(String source) - { - return encode(source, null, STRING_ENCODE_MAP); - } - - /** - * Transforms a provided <code>String</code> object into a series of - * unicode escape codes. - * - * @param source The string that has to be transformed into a valid - * sequence of unicode escape codes - * @return The encoded <code>String</code> object. - * @see #encodeClassname(String) - * @see #encodeUrl(String) - * @see #encodeUrlValue(String) - * @see #encodeHtml(String) - * @see #encodeXml(String) - * @see #encodeSql(String) - * @see #encodeLatex(String) - * @see #encodeRegexp(String) - * @since 1.0 - */ - public static String encodeUnicode(String source) - { - if (null == source) - { - return null; - } - - StringBuilder encoded = new StringBuilder(); - String hexstring = null; - for (int i = 0; i < source.length(); i++) - { - hexstring = Integer.toHexString((int)source.charAt(i)).toUpperCase(); - encoded.append("\\u"); - // fill with zeros - for (int j = hexstring.length(); j < 4; j++) - { - encoded.append("0"); - } - encoded.append(hexstring); - } - - return encoded.toString(); - } - - /** - * Transforms a provided <code>String</code> object into a new string, - * containing only valid Sql characters. - * - * @param source The string that has to be transformed into a valid Sql - * string. - * @return The encoded <code>String</code> object. - * @see #encodeClassname(String) - * @see #encodeUrl(String) - * @see #encodeUrlValue(String) - * @see #encodeHtml(String) - * @see #encodeXml(String) - * @see #encodeString(String) - * @see #encodeLatex(String) - * @see #encodeRegexp(String) - * @since 1.0 - */ - public static String encodeSql(String source) - { - return encode(source, null, SQL_ENCODE_MAP); - } - - /** - * Transforms a provided <code>String</code> object into a new string, - * containing only valid LaTeX characters. - * - * @param source The string that has to be transformed into a valid LaTeX - * string. - * @return The encoded <code>String</code> object. - * @see #encodeClassname(String) - * @see #encodeUrl(String) - * @see #encodeUrlValue(String) - * @see #encodeHtml(String) - * @see #encodeXml(String) - * @see #encodeSql(String) - * @see #encodeString(String) - * @see #encodeRegexp(String) - * @since 1.0 - */ - public static String encodeLatex(String source) - { - if (null == source) - { - return null; - } - - source = encode(source, null, LATEX_ENCODE_MAP); - source = StringUtils.replace(source, "latex", "\\LaTeX", false); - - return source; - } - - /** - * Transforms a provided <code>String</code> object into a new string, - * using the mapping that are provided through the supplied encoding - * table. - * - * @param source The string that has to be transformed into a valid - * string, using the mappings that are provided through the supplied - * encoding table. - * @param encodingTables A <code>Map</code> object containing the mappings - * to transform characters into valid entities. The keys of this map - * should be <code>Character</code> objects and the values - * <code>String</code> objects. - * @return The encoded <code>String</code> object. - * @since 1.0 - */ - private static String encode(String source, EncoderFallbackHandler fallbackHandler, Map<Character, String>... encodingTables) - { - if (null == source) - { - return null; - } - - if (null == encodingTables || - 0 == encodingTables.length) - { - return source; - } - - StringBuilder encoded_string = null; - char[] string_to_encode_array = source.toCharArray(); - int last_match = -1; - - for (int i = 0; i < string_to_encode_array.length; i++) - { - char char_to_encode = string_to_encode_array[i]; - for (Map<Character, String> encoding_table : encodingTables) - { - if (encoding_table.containsKey(char_to_encode)) - { - encoded_string = prepareEncodedString(source, encoded_string, i, last_match, string_to_encode_array); - - encoded_string.append(encoding_table.get(char_to_encode)); - last_match = i; - } - } - - if (fallbackHandler != null && - last_match < i && - fallbackHandler.hasFallback(char_to_encode)) - { - encoded_string = prepareEncodedString(source, encoded_string, i, last_match, string_to_encode_array); - - fallbackHandler.appendFallback(encoded_string, char_to_encode); - last_match = i; - } - } - - if (null == encoded_string) - { - return source; - } - else - { - int difference = string_to_encode_array.length-(last_match+1); - if (difference > 0) - { - encoded_string.append(string_to_encode_array, last_match+1, difference); - } - return encoded_string.toString(); - } - } - - private static StringBuilder prepareEncodedString(String source, StringBuilder encodedString, int i, int lastMatch, char[] stringToEncodeArray) - { - if (null == encodedString) - { - encodedString = new StringBuilder(source.length()); - } - - int difference = i - (lastMatch + 1); - if (difference > 0) - { - encodedString.append(stringToEncodeArray, lastMatch + 1, difference); - } - - return encodedString; - } - - private static interface EncoderFallbackHandler - { - abstract boolean hasFallback(char character); - abstract void appendFallback(StringBuilder encodedBuffer, char character); - } - - private static class HtmlEncoderFallbackHandler implements EncoderFallbackHandler - { - private final static String PREFIX = "&#"; - private final static String SUFFIX = ";"; - - public boolean hasFallback(char character) - { - if (character < '\u00A0') - { - return false; - } - - return true; - } - - public void appendFallback(StringBuilder encodedBuffer, char character) - { - encodedBuffer.append(PREFIX); - encodedBuffer.append((int)character); - encodedBuffer.append(SUFFIX); - } - } - - /** - * Transforms a provided <code>String</code> object into a literal that can - * be included into a regular expression {@link Pattern} as-is. None of the - * regular expression escapes in the string will be functional anymore. - * - * @param source The string that has to be escaped as a literal - * @return The encoded <code>String</code> object. - * @see #encodeClassname(String) - * @see #encodeUrl(String) - * @see #encodeUrlValue(String) - * @see #encodeHtml(String) - * @see #encodeXml(String) - * @see #encodeSql(String) - * @see #encodeString(String) - * @see #encodeLatex(String) - * @since 1.3 - */ - public static String encodeRegexp(String source) - { - int regexp_quote_start = source.indexOf("\\E"); - if (-1 == regexp_quote_start) - { - return "\\Q" + source + "\\E"; - } - - StringBuilder buffer = new StringBuilder(source.length() * 2); - buffer.append("\\Q"); - - regexp_quote_start = 0; - - int current = 0; - while (-1 == (regexp_quote_start = source.indexOf("\\E", current))) - { - buffer.append(source.substring(current, regexp_quote_start)); - current = regexp_quote_start + 2; - buffer.append("\\E\\\\E\\Q"); - } - - buffer.append(source.substring(current, source.length())); - buffer.append("\\E"); - - return buffer.toString(); + LATEX_ENCODE_MAP.put('\u00FF', "\\\"{y}"); } - /** - * Counts the number of times a substring occures in a provided string in - * a case-sensitive manner. - * - * @param source The <code>String</code> object that will be searched in. - * @param substring The string whose occurances will we counted. - * @return An <code>int</code> value containing the number of occurances - * of the substring. - * @since 1.0 - */ - public static int count(String source, String substring) - { - return count(source, substring, true); - } + /** + * Transforms a provided <code>String</code> object into a new string, + * containing only valid characters for a java class name. + * + * @param name The string that has to be transformed into a valid class + * name. + * @return The encoded <code>String</code> object. + * @see #encodeUrl(String) + * @see #encodeHtml(String) + * @see #encodeXml(String) + * @see #encodeSql(String) + * @see #encodeLatex(String) + * @see #encodeRegexp(String) + * @since 1.0 + */ + public static String encodeClassname(String name) + { + if (null == name) + { + return null; + } - /** - * Counts the number of times a substring occures in a provided string. - * - * @param source The <code>String</code> object that will be searched in. - * @param substring The string whose occurances will we counted. - * @param matchCase A <code>boolean</code> indicating if the match is - * going to be performed in a case-sensitive manner or not. - * @return An <code>int</code> value containing the number of occurances - * of the substring. - * @since 1.0 - */ - public static int count(String source, String substring, boolean matchCase) - { - if (null == source) - { - return 0; - } + Pattern pattern = Pattern.compile("[^\\w]"); + Matcher matcher = pattern.matcher(name); - if (null == substring) - { - return 0; - } + return matcher.replaceAll("_"); + } - int current_index = 0; - int substring_index = 0; - int count = 0; + private static boolean needsUrlEncoding(String source) + { + if (null == source) + { + return false; + } - if (!matchCase) - { - source = source.toLowerCase(); - substring = substring.toLowerCase(); - } + // check if the string needs encoding first since + // the URLEncoder always allocates a StringBuffer, even when the + // string is returned as-is + boolean encode = false; + char ch; + for (int i = 0; i < source.length(); i++) + { + ch = source.charAt(i); - while (current_index < source.length()-1) - { - substring_index = source.indexOf(substring, current_index); + if (ch >= 'a' && ch <= 'z' || + ch >= 'A' && ch <= 'Z' || + ch >= '0' && ch <= '9' || + ch == '-' || ch == '_' || ch == '.' || ch == '*') + { + continue; + } - if (-1 == substring_index) - { - break; - } - else - { - current_index = substring_index + substring.length(); - count++; - } - } + encode = true; + break; + } - return count; - } + return encode; + } - /** - * Splits a string into different parts, using a seperator string to - * detect the seperation boundaries in a case-sensitive manner. The - * seperator will not be included in the list of parts. - * - * @param source The string that will be split into parts. - * @param seperator The seperator string that will be used to determine - * the parts. - * @return An <code>ArrayList</code> containing the parts as - * <code>String</code> objects. - * @since 1.0 - */ - public static ArrayList<String> split(String source, String seperator) - { - return split(source, seperator, true); - } + /** + * Transforms a provided <code>String</code> object into a new string, + * containing only valid URL characters. + * + * @param source The string that has to be transformed into a valid URL + * string. + * @return The encoded <code>String</code> object. + * @see #encodeClassname(String) + * @see #encodeUrlValue(String) + * @see #encodeHtml(String) + * @see #encodeXml(String) + * @see #encodeSql(String) + * @see #encodeLatex(String) + * @see #encodeRegexp(String) + * @since 1.0 + */ + public static String encodeUrl(String source) + { + if (!needsUrlEncoding(source)) + { + return source; + } - /** - * Splits a string into different parts, using a seperator string to - * detect the seperation boundaries. The seperator will not be included in - * the list of parts. - * - * @param source The string that will be split into parts. - * @param seperator The seperator string that will be used to determine - * the parts. - * @param matchCase A <code>boolean</code> indicating if the match is - * going to be performed in a case-sensitive manner or not. - * @return An <code>ArrayList</code> containing the parts as - * <code>String</code> objects. - * @since 1.0 - */ - public static ArrayList<String> split(String source, String seperator, boolean matchCase) - { - ArrayList<String> substrings = new ArrayList<String>(); + try + { + return URLEncoder.encode(source, ENCODING_ISO_8859_1); + } + ///CLOVER:OFF + catch (UnsupportedEncodingException e) + { + // this should never happen, ISO-8859-1 is a standard encoding + throw new RuntimeException(e); + } + ///CLOVER:ON + } - if (null == source) - { - return substrings; - } + /** + * Transforms a provided <code>String</code> object into a new string, + * only pure US Ascii strings are preserved and URL encoded in a regular + * way. Strings with characters from other encodings will be encoded in a + * RIFE-specific manner to allow international data to passed along the + * query string. + * + * @param source The string that has to be transformed into a valid URL + * parameter string. + * @return The encoded <code>String</code> object. + * @see #decodeUrlValue(String) + * @see #encodeClassname(String) + * @see #encodeUrl(String) + * @see #encodeHtml(String) + * @see #encodeXml(String) + * @see #encodeSql(String) + * @see #encodeLatex(String) + * @see #encodeRegexp(String) + * @since 1.0 + */ + public static String encodeUrlValue(String source) + { + if (!needsUrlEncoding(source)) + { + return source; + } - if (null == seperator) - { - substrings.add(source); - return substrings; - } + // check if the string is valid US-ASCII encoding + boolean valid = true; + CharsetEncoder encoder = CHARSET_US_ASCII.newEncoder(); + try + { + encoder.encode(CharBuffer.wrap(source)); + } + catch (CharacterCodingException e) + { + valid = false; + } - int current_index = 0; - int delimiter_index = 0; - String element = null; + try + { + // if it is valid US-ASCII, use the regular URL encoding method + if (valid) + { + return URLEncoder.encode(source, ENCODING_US_ASCII); + } + // otherwise, base-64 encode the UTF-8 bytes and mark the string + // as being encoded in a special way + else + { + StringBuilder encoded = new StringBuilder("%02%02"); + String base64 = Base64.encodeToString(source.getBytes(ENCODING_UTF_8), false); + String base64_urlsafe = replace(base64, "=", "%3D"); + encoded.append(base64_urlsafe); - String source_lookup_reference = null; - if (!matchCase) - { - source_lookup_reference = source.toLowerCase(); - seperator = seperator.toLowerCase(); - } - else - { - source_lookup_reference = source; - } + return encoded.toString(); + } + } + ///CLOVER:OFF + catch (UnsupportedEncodingException e) + { + // this should never happen, ISO-8859-1 is a standard encoding + throw new RuntimeException(e); + } + ///CLOVER:ON + } - while (current_index <= source_lookup_reference.length()) - { - delimiter_index = source_lookup_reference.indexOf(seperator, current_index); + /** + * Decodes a <code>String</code> that has been encoded in a RIFE-specific + * manner for URL usage.. Before calling this method, you should first + * verify if the value needs decoding by using the + * <code>doesUrlValueNeedDecoding(String)</code> method. + * + * @param source the value that has been encoded for URL usage in a + * RIFE-specific way + * @return The decoded <code>String</code> object. + * @see #encodeUrlValue(String) + * @see #doesUrlValueNeedDecoding(String) + * @since 1.0 + */ + public static String decodeUrlValue(String source) + { + try + { + byte[] decoded = Base64.decode(source.substring(2)); + if (null == decoded) + { + return null; + } else + { + return new String(decoded, StringUtils.ENCODING_UTF_8); + } + } + ///CLOVER:OFF + catch (UnsupportedEncodingException e) + { + // this should never happen, UTF-8 is a standard encoding + throw new RuntimeException(e); + } + ///CLOVER:ON + } - if (-1 == delimiter_index) - { - element = new String(source.substring(current_index, source.length())); - substrings.add(element); - current_index = source.length() + 1; - } - else - { - element = new String(source.substring(current_index, delimiter_index)); - substrings.add(element); - current_index = delimiter_index + seperator.length(); - } - } + /** + * Checks if a <code>String</code> is encoded in a RIFE-specific manner + * for URL usage. + * + * @param source the value that might have been encoded for URL usage in a + * RIFE-specific way + * @return <code>true</code> if the value is encoded in the RIFE-specific + * format; and + * <p><code>false</code> otherwise + * @see #encodeUrlValue(String) + * @see #decodeUrlValue(String) + * @since 1.0 + */ + public static boolean doesUrlValueNeedDecoding(String source) + { + if (source != null && + source.length() > 2 && + source.startsWith("\u0002\u0002")) + { + return true; + } - return substrings; - } + return false; + } - /** - * Splits a string into different parts, using a seperator string to - * detect the seperation boundaries in a case-sensitive manner. The - * seperator will not be included in the parts array. - * - * @param source The string that will be split into parts. - * @param seperator The seperator string that will be used to determine - * the parts. - * @return A <code>String[]</code> array containing the seperated parts. - * @since 1.0 - */ - public static String[] splitToArray(String source, String seperator) - { - return splitToArray(source, seperator, true); - } + private static boolean needsHtmlEncoding(String source, boolean defensive) + { + if (null == source) + { + return false; + } - /** - * Splits a string into different parts, using a seperator string to - * detect the seperation boundaries. The seperator will not be included in - * the parts array. - * - * @param source The string that will be split into parts. - * @param seperator The seperator string that will be used to determine - * the parts. - * @param matchCase A <code>boolean</code> indicating if the match is - * going to be performed in a case-sensitive manner or not. - * @return A <code>String[]</code> array containing the seperated parts. - * @since 1.0 - */ - public static String[] splitToArray(String source, String seperator, boolean matchCase) - { - ArrayList<String> substrings = split(source, seperator, matchCase); - String[] substrings_array = new String[substrings.size()]; - substrings_array = substrings.toArray(substrings_array); + boolean encode = false; + char ch; + for (int i = 0; i < source.length(); i++) + { + ch = source.charAt(i); - return substrings_array; - } + if ((defensive || (ch != '\u0022' && ch != '\u0026' && ch != '\u003C' && ch != '\u003E')) && + ch < '\u00A0') + { + continue; + } - /** - * Splits a string into integers, using a seperator string to detect the - * seperation boundaries in a case-sensitive manner. If a part couldn't be - * converted to an integer, it will be omitted from the resulting array. - * - * @param source The string that will be split into integers. - * @param seperator The seperator string that will be used to determine - * the parts. - * @return An <code>int[]</code> array containing the seperated parts. - * @since 1.0 - */ - public static int[] splitToIntArray(String source, String seperator) - { - return splitToIntArray(source, seperator, true); - } + encode = true; + break; + } - /** - * Splits a string into integers, using a seperator string to detect the - * seperation boundaries. If a part couldn't be converted to an integer, - * it will be omitted from the resulting array. - * - * @param source The string that will be split into integers. - * @param seperator The seperator string that will be used to determine - * the parts. - * @param matchCase A <code>boolean</code> indicating if the match is - * going to be performed in a case-sensitive manner or not. - * @return An <code>int[]</code> array containing the seperated parts. - * @since 1.0 - */ - public static int[] splitToIntArray(String source, String seperator, boolean matchCase) - { - ArrayList<String> string_parts = split(source, seperator, matchCase); - int number_of_valid_parts = 0; + return encode; + } - for (String string_part : string_parts) - { - try - { - Integer.parseInt(string_part); - number_of_valid_parts++; - } - catch (NumberFormatException e) - { - // just continue - } - } + /** + * @since 1.6 + */ + public static String decodeHtml(String source) + { + if (null == source || + 0 == source.length()) + { + return source; + } - int[] string_parts_int = (int[]) Array.newInstance(int.class, number_of_valid_parts); - int added_parts = 0; + int current_index = 0; + int delimiter_start_index = 0; + int delimiter_end_index = 0; - for (String string_part : string_parts) - { - try - { - string_parts_int[added_parts] = Integer.parseInt(string_part); - added_parts++; - } - catch (NumberFormatException e) - { - // just continue - } - } + StringBuilder result = null; - return string_parts_int; - } + while (current_index <= source.length()) + { + delimiter_start_index = source.indexOf('&', current_index); + if (delimiter_start_index != -1) + { + delimiter_end_index = source.indexOf(';', delimiter_start_index + 1); + if (delimiter_end_index != -1) + { + // ensure that the string builder is setup correctly + if (null == result) + { + result = new StringBuilder(); + } - /** - * Splits a string into bytes, using a seperator string to detect the - * seperation boundaries in a case-sensitive manner. If a part couldn't be - * converted to a <code>byte</code>, it will be omitted from the resulting - * array. - * - * @param source The string that will be split into bytes. - * @param seperator The seperator string that will be used to determine - * the parts. - * @return A <code>byte[]</code> array containing the bytes. - * @since 1.0 - */ - public static byte[] splitToByteArray(String source, String seperator) - { - return splitToByteArray(source, seperator, true); - } + // add the text that leads up to this match + if (delimiter_start_index > current_index) + { + result.append(source.substring(current_index, delimiter_start_index)); + } - /** - * Splits a string into bytes, using a seperator string to detect the - * seperation boundaries. If a part couldn't be converted to a - * <code>byte</code>, it will be omitted from the resulting array. - * - * @param source The string that will be split into bytes. - * @param seperator The seperator string that will be used to determine - * the parts. - * @param matchCase A <code>boolean</code> indicating if the match is - * going to be performed in a case-sensitive manner or not. - * @return A <code>byte[]</code> array containing the bytes. - * @since 1.0 - */ - public static byte[] splitToByteArray(String source, String seperator, boolean matchCase) - { - ArrayList<String> string_parts = split(source, seperator, matchCase); - int number_of_valid_parts = 0; - for (String string_part : string_parts) - { - try - { - Byte.parseByte(string_part); - number_of_valid_parts++; - } - catch (NumberFormatException e) - { - // just continue - } - } + // add the decoded entity + String entity = source.substring(delimiter_start_index, delimiter_end_index + 1); - byte[] string_parts_byte = (byte[])Array.newInstance(byte.class, number_of_valid_parts); - int added_parts = 0; - for (String string_part : string_parts) - { - try - { - string_parts_byte[added_parts] = Byte.parseByte(string_part); - added_parts++; - } - catch (NumberFormatException e) - { - // just continue - } - } + current_index = delimiter_end_index + 1; - return string_parts_byte; - } + // try to decoded numeric entities + if (entity.charAt(1) == '#') + { + int start = 2; + int radix = 10; + // check if the number is hexadecimal + if (entity.charAt(2) == 'X' || entity.charAt(2) == 'x') + { + start++; + radix = 16; + } + try + { + Character c = new Character((char) Integer.parseInt(entity.substring(start, entity.length() - 1), radix)); + result.append(c); + } + // when the number of the entity can't be parsed, add the entity as-is + catch (NumberFormatException e) + { + result.append(entity); + } + } else + { + // try to decode the entity as a literal + Character decoded = HTML_DECODE_MAP.get(entity); + if (decoded != null) + { + result.append(decoded); + } + // if there was no match, add the entity as-is + else + { + result.append(entity); + } + } + } else + { + break; + } + } else + { + break; + } + } - /** - * Removes all occurances of a string from the front of another string in - * a case-sensitive manner. - * - * @param source The string in which the matching will be done. - * @param stringToStrip The string that will be stripped from the front. - * @return A new <code>String</code> containing the stripped result. - * @since 1.0 - */ - public static String stripFromFront(String source, String stringToStrip) - { - return stripFromFront(source, stringToStrip, true); - } + if (null == result) + { + return source; + } else if (current_index < source.length()) + { + result.append(source.substring(current_index)); + } - /** - * Removes all occurances of a string from the front of another string. - * - * @param source The string in which the matching will be done. - * @param stringToStrip The string that will be stripped from the front. - * @param matchCase A <code>boolean</code> indicating if the match is - * going to be performed in a case-sensitive manner or not. - * @return A new <code>String</code> containing the stripping result. - * @since 1.0 - */ - public static String stripFromFront(String source, String stringToStrip, boolean matchCase) - { - if (null == source) - { - return null; - } + return result.toString(); + } - if (null == stringToStrip) - { - return source; - } + /** + * Transforms a provided <code>String</code> object into a new string, + * containing only valid Html characters. + * + * @param source The string that has to be transformed into a valid Html + * string. + * @return The encoded <code>String</code> object. + * @see #encodeClassname(String) + * @see #encodeUrl(String) + * @see #encodeUrlValue(String) + * @see #encodeXml(String) + * @see #encodeSql(String) + * @see #encodeString(String) + * @see #encodeLatex(String) + * @see #encodeRegexp(String) + * @since 1.0 + */ + public static String encodeHtml(String source) + { + if (needsHtmlEncoding(source, false)) + { + return encode(source, HTML_ENCODER_FALLBACK, AGGRESSIVE_HTML_ENCODE_MAP, DEFENSIVE_HTML_ENCODE_MAP); + } + return source; + } - int strip_length = stringToStrip.length(); - int new_index = 0; - int last_index = 0; + /** + * Transforms a provided <code>String</code> object into a new string, + * containing as much as possible Html characters. It is safe to already + * feed existing Html to this method since &, < and > will not + * be encoded. + * + * @param source The string that has to be transformed into a valid Html + * string. + * @return The encoded <code>String</code> object. + * @see #encodeClassname(String) + * @see #encodeUrl(String) + * @see #encodeUrlValue(String) + * @see #encodeXml(String) + * @see #encodeSql(String) + * @see #encodeString(String) + * @see #encodeLatex(String) + * @see #encodeRegexp(String) + * @since 1.0 + */ + public static String encodeHtmlDefensive(String source) + { + if (needsHtmlEncoding(source, true)) + { + return encode(source, null, DEFENSIVE_HTML_ENCODE_MAP); + } + return source; + } - String source_lookup_reference = null; - if (!matchCase) - { - source_lookup_reference = source.toLowerCase(); - stringToStrip = stringToStrip.toLowerCase(); - } - else - { - source_lookup_reference = source; - } + /** + * Transforms a provided <code>String</code> object into a new string, + * containing only valid XML characters. + * + * @param source The string that has to be transformed into a valid XML + * string. + * @return The encoded <code>String</code> object. + * @see #encodeClassname(String) + * @see #encodeUrl(String) + * @see #encodeUrlValue(String) + * @see #encodeHtml(String) + * @see #encodeSql(String) + * @see #encodeString(String) + * @see #encodeLatex(String) + * @see #encodeRegexp(String) + * @since 1.0 + */ + public static String encodeXml(String source) + { + return encode(source, null, XML_ENCODE_MAP); + } - new_index = source_lookup_reference.indexOf(stringToStrip); - if (0 == new_index) - { - do - { - last_index = new_index; - new_index = source_lookup_reference.indexOf(stringToStrip, new_index+strip_length); - } - while (new_index != -1 && - new_index == last_index+strip_length); + /** + * Transforms a provided <code>String</code> object into a new string, + * containing only valid <code>String</code> characters. + * + * @param source The string that has to be transformed into a valid + * sequence of <code>String</code> characters. + * @return The encoded <code>String</code> object. + * @see #encodeClassname(String) + * @see #encodeUrl(String) + * @see #encodeUrlValue(String) + * @see #encodeHtml(String) + * @see #encodeXml(String) + * @see #encodeSql(String) + * @see #encodeLatex(String) + * @see #encodeRegexp(String) + * @since 1.0 + */ + public static String encodeString(String source) + { + return encode(source, null, STRING_ENCODE_MAP); + } - return source.substring(last_index+strip_length); - } - else - { - return source; - } - } + /** + * Transforms a provided <code>String</code> object into a series of + * unicode escape codes. + * + * @param source The string that has to be transformed into a valid + * sequence of unicode escape codes + * @return The encoded <code>String</code> object. + * @see #encodeClassname(String) + * @see #encodeUrl(String) + * @see #encodeUrlValue(String) + * @see #encodeHtml(String) + * @see #encodeXml(String) + * @see #encodeSql(String) + * @see #encodeLatex(String) + * @see #encodeRegexp(String) + * @since 1.0 + */ + public static String encodeUnicode(String source) + { + if (null == source) + { + return null; + } - /** - * Removes all occurances of a string from the end of another string in a - * case-sensitive manner. - * - * @param source The string in which the matching will be done. - * @param stringToStrip The string that will be stripped from the end. - * @return A new <code>String</code> containing the stripped result. - * @since 1.0 - */ - public static String stripFromEnd(String source, String stringToStrip) - { - return stripFromEnd(source, stringToStrip, true); - } + StringBuilder encoded = new StringBuilder(); + String hexstring = null; + for (int i = 0; i < source.length(); i++) + { + hexstring = Integer.toHexString((int) source.charAt(i)).toUpperCase(); + encoded.append("\\u"); + // fill with zeros + for (int j = hexstring.length(); j < 4; j++) + { + encoded.append("0"); + } + encoded.append(hexstring); + } - /** - * Removes all occurances of a string from the end of another string. - * - * @param source The string in which the matching will be done. - * @param stringToStrip The string that will be stripped from the end. - * @param matchCase A <code>boolean</code> indicating if the match is - * going to be performed in a case-sensitive manner or not. - * @return A new <code>String</code> containing the stripped result. - * @since 1.0 - */ - public static String stripFromEnd(String source, String stringToStrip, boolean matchCase) - { - if (null == source) - { - return null; - } + return encoded.toString(); + } - if (null == stringToStrip) - { - return source; - } + /** + * Transforms a provided <code>String</code> object into a new string, + * containing only valid Sql characters. + * + * @param source The string that has to be transformed into a valid Sql + * string. + * @return The encoded <code>String</code> object. + * @see #encodeClassname(String) + * @see #encodeUrl(String) + * @see #encodeUrlValue(String) + * @see #encodeHtml(String) + * @see #encodeXml(String) + * @see #encodeString(String) + * @see #encodeLatex(String) + * @see #encodeRegexp(String) + * @since 1.0 + */ + public static String encodeSql(String source) + { + return encode(source, null, SQL_ENCODE_MAP); + } - int strip_length = stringToStrip.length(); - int new_index = 0; - int last_index = 0; + /** + * Transforms a provided <code>String</code> object into a new string, + * containing only valid LaTeX characters. + * + * @param source The string that has to be transformed into a valid LaTeX + * string. + * @return The encoded <code>String</code> object. + * @see #encodeClassname(String) + * @see #encodeUrl(String) + * @see #encodeUrlValue(String) + * @see #encodeHtml(String) + * @see #encodeXml(String) + * @see #encodeSql(String) + * @see #encodeString(String) + * @see #encodeRegexp(String) + * @since 1.0 + */ + public static String encodeLatex(String source) + { + if (null == source) + { + return null; + } - String source_lookup_reference = null; - if (!matchCase) - { - source_lookup_reference = source.toLowerCase(); - stringToStrip = stringToStrip.toLowerCase(); - } - else - { - source_lookup_reference = source; - } + source = encode(source, null, LATEX_ENCODE_MAP); + source = StringUtils.replace(source, "latex", "\\LaTeX", false); - new_index = source_lookup_reference.lastIndexOf(stringToStrip); - if (new_index != -1 && - source.length() == new_index+strip_length) - { - do - { - last_index = new_index; - new_index = source_lookup_reference.lastIndexOf(stringToStrip, last_index-1); - } - while (new_index != -1 && - new_index == last_index-strip_length); + return source; + } - return source.substring(0, last_index); - } - else - { - return source; - } - } + /** + * Transforms a provided <code>String</code> object into a new string, + * using the mapping that are provided through the supplied encoding + * table. + * + * @param source The string that has to be transformed into a valid + * string, using the mappings that are provided through the supplied + * encoding table. + * @param encodingTables A <code>Map</code> object containing the mappings + * to transform characters into valid entities. The keys of this map + * should be <code>Character</code> objects and the values + * <code>String</code> objects. + * @return The encoded <code>String</code> object. + * @since 1.0 + */ + private static String encode(String source, EncoderFallbackHandler fallbackHandler, Map<Character, String>... encodingTables) + { + if (null == source) + { + return null; + } - /** - * Searches for a string within a specified string in a case-sensitive - * manner and replaces every match with another string. - * - * @param source The string in which the matching parts will be replaced. - * @param stringToReplace The string that will be searched for. - * @param replacementString The string that will replace each matching - * part. - * @return A new <code>String</code> object containing the replacement - * result. - * @since 1.0 - */ - public static String replace(String source, String stringToReplace, String replacementString) - { - return replace(source, stringToReplace, replacementString, true); - } + if (null == encodingTables || + 0 == encodingTables.length) + { + return source; + } - /** - * Searches for a string within a specified string and replaces every - * match with another string. - * - * @param source The string in which the matching parts will be replaced. - * @param stringToReplace The string that will be searched for. - * @param replacementString The string that will replace each matching - * part. - * @param matchCase A <code>boolean</code> indicating if the match is - * going to be performed in a case-sensitive manner or not. - * @return A new <code>String</code> object containing the replacement - * result. - * @since 1.0 - */ - public static String replace(String source, String stringToReplace, String replacementString, boolean matchCase) - { - if (null == source) - { - return null; - } + StringBuilder encoded_string = null; + char[] string_to_encode_array = source.toCharArray(); + int last_match = -1; - if (null == stringToReplace) - { - return source; - } + for (int i = 0; i < string_to_encode_array.length; i++) + { + char char_to_encode = string_to_encode_array[i]; + for (Map<Character, String> encoding_table : encodingTables) + { + if (encoding_table.containsKey(char_to_encode)) + { + encoded_string = prepareEncodedString(source, encoded_string, i, last_match, string_to_encode_array); - if (null == replacementString) - { - return source; - } + encoded_string.append(encoding_table.get(char_to_encode)); + last_match = i; + } + } - Iterator<String> string_parts = split(source, stringToReplace, matchCase).iterator(); - StringBuilder new_string = new StringBuilder(); + if (fallbackHandler != null && + last_match < i && + fallbackHandler.hasFallback(char_to_encode)) + { + encoded_string = prepareEncodedString(source, encoded_string, i, last_match, string_to_encode_array); - while (string_parts.hasNext()) - { - String string_part = string_parts.next(); - new_string.append(string_part); - if (string_parts.hasNext()) - { - new_string.append(replacementString); - } - } + fallbackHandler.appendFallback(encoded_string, char_to_encode); + last_match = i; + } + } - return new_string.toString(); - } + if (null == encoded_string) + { + return source; + } else + { + int difference = string_to_encode_array.length - (last_match + 1); + if (difference > 0) + { + encoded_string.append(string_to_encode_array, last_match + 1, difference); + } + return encoded_string.toString(); + } + } - /** - * Creates a new string that contains the provided string a number of - * times. - * - * @param source The string that will be repeated. - * @param count The number of times that the string will be repeated. - * @return A new <code>String</code> object containing the repeated - * concatenation result. - * @since 1.0 - */ - public static String repeat(String source, int count) - { - if (null == source) - { - return null; - } + private static StringBuilder prepareEncodedString(String source, StringBuilder encodedString, int i, int lastMatch, char[] stringToEncodeArray) + { + if (null == encodedString) + { + encodedString = new StringBuilder(source.length()); + } - StringBuilder new_string = new StringBuilder(); - while (count > 0) - { - new_string.append(source); - count --; - } + int difference = i - (lastMatch + 1); + if (difference > 0) + { + encodedString.append(stringToEncodeArray, lastMatch + 1, difference); + } - return new_string.toString(); - } + return encodedString; + } - /** - * Creates a new array of <code>String</code> objects, containing the - * elements of a supplied <code>Iterator</code>. - * - * @param iterator The iterator containing the elements to create the - * array with. - * @return The new <code>String</code> array. - * @since 1.0 - */ - public static String[] toStringArray(Iterator<String> iterator) - { - if (null == iterator) - { - return new String[0]; - } + private static interface EncoderFallbackHandler + { + abstract boolean hasFallback(char character); - ArrayList<String> strings = new ArrayList<String>(); + abstract void appendFallback(StringBuilder encodedBuffer, char character); + } - while (iterator.hasNext()) - { - strings.add(iterator.next()); - } + private static class HtmlEncoderFallbackHandler implements EncoderFallbackHandler + { + private final static String PREFIX = "&#"; + private final static String SUFFIX = ";"; - String[] string_array = new String[strings.size()]; - strings.toArray(string_array); + public boolean hasFallback(char character) + { + if (character < '\u00A0') + { + return false; + } - return string_array; - } + return true; + } - /** - * Creates a new <code>ArrayList</code>, containing the elements of a - * supplied array of <code>String</code> objects. - * - * @param stringArray The array of <code>String</code> objects that have - * to be converted. - * @return The new <code>ArrayList</code> with the elements of the - * <code>String</code> array. - * @since 1.0 - */ - public static ArrayList<String> toArrayList(String[] stringArray) - { - ArrayList<String> strings = new ArrayList<String>(); + public void appendFallback(StringBuilder encodedBuffer, char character) + { + encodedBuffer.append(PREFIX); + encodedBuffer.append((int) character); + encodedBuffer.append(SUFFIX); + } + } - if (null == stringArray) - { - return strings; - } + /** + * Transforms a provided <code>String</code> object into a literal that can + * be included into a regular expression {@link Pattern} as-is. None of the + * regular expression escapes in the string will be functional anymore. + * + * @param source The string that has to be escaped as a literal + * @return The encoded <code>String</code> object. + * @see #encodeClassname(String) + * @see #encodeUrl(String) + * @see #encodeUrlValue(String) + * @see #encodeHtml(String) + * @see #encodeXml(String) + * @see #encodeSql(String) + * @see #encodeString(String) + * @see #encodeLatex(String) + * @since 1.3 + */ + public static String encodeRegexp(String source) + { + int regexp_quote_start = source.indexOf("\\E"); + if (-1 == regexp_quote_start) + { + return "\\Q" + source + "\\E"; + } - for (String element : stringArray) - { - strings.add(element); - } + StringBuilder buffer = new StringBuilder(source.length() * 2); + buffer.append("\\Q"); - return strings; - } + regexp_quote_start = 0; - /** - * Creates a new <code>String</code> object, containing the elements of a - * supplied <code>Collection</code> of <code>String</code> objects joined - * by a given seperator. - * - * @param collection The <code>Collection</code> containing the elements - * to join. - * @param seperator The seperator used to join the string elements. - * @return A new <code>String</code> with the join result. - * @since 1.0 - */ - public static String join(Collection collection, String seperator) - { - if (null == collection) - { - return null; - } + int current = 0; + while (-1 == (regexp_quote_start = source.indexOf("\\E", current))) + { + buffer.append(source.substring(current, regexp_quote_start)); + current = regexp_quote_start + 2; + buffer.append("\\E\\\\E\\Q"); + } - if (null == seperator) - { - seperator = ""; - } + buffer.append(source.substring(current, source.length())); + buffer.append("\\E"); - if (0 == collection.size()) - { - return ""; - } - else - { - StringBuilder result = new StringBuilder(); - for (Object element : collection) - { - result.append(String.valueOf(element)); - result.append(seperator); - } + return buffer.toString(); + } + + /** + * Counts the number of times a substring occures in a provided string in + * a case-sensitive manner. + * + * @param source The <code>String</code> object that will be searched in. + * @param substring The string whose occurances will we counted. + * @return An <code>int</code> value containing the number of occurances + * of the substring. + * @since 1.0 + */ + public static int count(String source, String substring) + { + return count(source, substring, true); + } + + /** + * Counts the number of times a substring occures in a provided string. + * + * @param source The <code>String</code> object that will be searched in. + * @param substring The string whose occurances will we counted. + * @param matchCase A <code>boolean</code> indicating if the match is + * going to be performed in a case-sensitive manner or not. + * @return An <code>int</code> value containing the number of occurances + * of the substring. + * @since 1.0 + */ + public static int count(String source, String substring, boolean matchCase) + { + if (null == source) + { + return 0; + } + + if (null == substring) + { + return 0; + } + + int current_index = 0; + int substring_index = 0; + int count = 0; + + if (!matchCase) + { + source = source.toLowerCase(); + substring = substring.toLowerCase(); + } + + while (current_index < source.length() - 1) + { + substring_index = source.indexOf(substring, current_index); + + if (-1 == substring_index) + { + break; + } else + { + current_index = substring_index + substring.length(); + count++; + } + } + + return count; + } + + /** + * Splits a string into different parts, using a seperator string to + * detect the seperation boundaries in a case-sensitive manner. The + * seperator will not be included in the list of parts. + * + * @param source The string that will be split into parts. + * @param seperator The seperator string that will be used to determine + * the parts. + * @return An <code>ArrayList</code> containing the parts as + * <code>String</code> objects. + * @since 1.0 + */ + public static ArrayList<String> split(String source, String seperator) + { + return split(source, seperator, true); + } + + /** + * Splits a string into different parts, using a seperator string to + * detect the seperation boundaries. The seperator will not be included in + * the list of parts. + * + * @param source The string that will be split into parts. + * @param seperator The seperator string that will be used to determine + * the parts. + * @param matchCase A <code>boolean</code> indicating if the match is + * going to be performed in a case-sensitive manner or not. + * @return An <code>ArrayList</code> containing the parts as + * <code>String</code> objects. + * @since 1.0 + */ + public static ArrayList<String> split(String source, String seperator, boolean matchCase) + { + ArrayList<String> substrings = new ArrayList<String>(); + + if (null == source) + { + return substrings; + } + + if (null == seperator) + { + substrings.add(source); + return substrings; + } + + int current_index = 0; + int delimiter_index = 0; + String element = null; + + String source_lookup_reference = null; + if (!matchCase) + { + source_lookup_reference = source.toLowerCase(); + seperator = seperator.toLowerCase(); + } else + { + source_lookup_reference = source; + } + + while (current_index <= source_lookup_reference.length()) + { + delimiter_index = source_lookup_reference.indexOf(seperator, current_index); + + if (-1 == delimiter_index) + { + element = new String(source.substring(current_index, source.length())); + substrings.add(element); + current_index = source.length() + 1; + } else + { + element = new String(source.substring(current_index, delimiter_index)); + substrings.add(element); + current_index = delimiter_index + seperator.length(); + } + } + + return substrings; + } + + /** + * Splits a string into different parts, using a seperator string to + * detect the seperation boundaries in a case-sensitive manner. The + * seperator will not be included in the parts array. + * + * @param source The string that will be split into parts. + * @param seperator The seperator string that will be used to determine + * the parts. + * @return A <code>String[]</code> array containing the seperated parts. + * @since 1.0 + */ + public static String[] splitToArray(String source, String seperator) + { + return splitToArray(source, seperator, true); + } + + /** + * Splits a string into different parts, using a seperator string to + * detect the seperation boundaries. The seperator will not be included in + * the parts array. + * + * @param source The string that will be split into parts. + * @param seperator The seperator string that will be used to determine + * the parts. + * @param matchCase A <code>boolean</code> indicating if the match is + * going to be performed in a case-sensitive manner or not. + * @return A <code>String[]</code> array containing the seperated parts. + * @since 1.0 + */ + public static String[] splitToArray(String source, String seperator, boolean matchCase) + { + ArrayList<String> substrings = split(source, seperator, matchCase); + String[] substrings_array = new String[substrings.size()]; + substrings_array = substrings.toArray(substrings_array); + + return substrings_array; + } + + /** + * Splits a string into integers, using a seperator string to detect the + * seperation boundaries in a case-sensitive manner. If a part couldn't be + * converted to an integer, it will be omitted from the resulting array. + * + * @param source The string that will be split into integers. + * @param seperator The seperator string that will be used to determine + * the parts. + * @return An <code>int[]</code> array containing the seperated parts. + * @since 1.0 + */ + public static int[] splitToIntArray(String source, String seperator) + { + return splitToIntArray(source, seperator, true); + } + + /** + * Splits a string into integers, using a seperator string to detect the + * seperation boundaries. If a part couldn't be converted to an integer, + * it will be omitted from the resulting array. + * + * @param source The string that will be split into integers. + * @param seperator The seperator string that will be used to determine + * the parts. + * @param matchCase A <code>boolean</code> indicating if the match is + * going to be performed in a case-sensitive manner or not. + * @return An <code>int[]</code> array containing the seperated parts. + * @since 1.0 + */ + public static int[] splitToIntArray(String source, String seperator, boolean matchCase) + { + ArrayList<String> string_parts = split(source, seperator, matchCase); + int number_of_valid_parts = 0; + + for (String string_part : string_parts) + { + try + { + Integer.parseInt(string_part); + number_of_valid_parts++; + } + catch (NumberFormatException e) + { + // just continue + } + } + + int[] string_parts_int = (int[]) Array.newInstance(int.class, number_of_valid_parts); + int added_parts = 0; + + for (String string_part : string_parts) + { + try + { + string_parts_int[added_parts] = Integer.parseInt(string_part); + added_parts++; + } + catch (NumberFormatException e) + { + // just continue + } + } + + return string_parts_int; + } + + /** + * Splits a string into bytes, using a seperator string to detect the + * seperation boundaries in a case-sensitive manner. If a part couldn't be + * converted to a <code>byte</code>, it will be omitted from the resulting + * array. + * + * @param source The string that will be split into bytes. + * @param seperator The seperator string that will be used to determine + * the parts. + * @return A <code>byte[]</code> array containing the bytes. + * @since 1.0 + */ + public static byte[] splitToByteArray(String source, String seperator) + { + return splitToByteArray(source, seperator, true); + } + + /** + * Splits a string into bytes, using a seperator string to detect the + * seperation boundaries. If a part couldn't be converted to a + * <code>byte</code>, it will be omitted from the resulting array. + * + * @param source The string that will be split into bytes. + * @param seperator The seperator string that will be used to determine + * the parts. + * @param matchCase A <code>boolean</code> indicating if the match is + * going to be performed in a case-sensitive manner or not. + * @return A <code>byte[]</code> array containing the bytes. + * @since 1.0 + */ + public static byte[] splitToByteArray(String source, String seperator, boolean matchCase) + { + ArrayList<String> string_parts = split(source, seperator, matchCase); + int number_of_valid_parts = 0; + for (String string_part : string_parts) + { + try + { + Byte.parseByte(string_part); + number_of_valid_parts++; + } + catch (NumberFormatException e) + { + // just continue + } + } + + byte[] string_parts_byte = (byte[]) Array.newInstance(byte.class, number_of_valid_parts); + int added_parts = 0; + for (String string_part : string_parts) + { + try + { + string_parts_byte[added_parts] = Byte.parseByte(string_part); + added_parts++; + } + catch (NumberFormatException e) + { + // just continue + } + } + + return string_parts_byte; + } + + /** + * Removes all occurances of a string from the front of another string in + * a case-sensitive manner. + * + * @param source The string in which the matching will be done. + * @param stringToStrip The string that will be stripped from the front. + * @return A new <code>String</code> containing the stripped result. + * @since 1.0 + */ + public static String stripFromFront(String source, String stringToStrip) + { + return stripFromFront(source, stringToStrip, true); + } + + /** + * Removes all occurances of a string from the front of another string. + * + * @param source The string in which the matching will be done. + * @param stringToStrip The string that will be stripped from the front. + * @param matchCase A <code>boolean</code> indicating if the match is + * going to be performed in a case-sensitive manner or not. + * @return A new <code>String</code> containing the stripping result. + * @since 1.0 + */ + public static String stripFromFront(String source, String stringToStrip, boolean matchCase) + { + if (null == source) + { + return null; + } + + if (null == stringToStrip) + { + return source; + } + + int strip_length = stringToStrip.length(); + int new_index = 0; + int last_index = 0; + + String source_lookup_reference = null; + if (!matchCase) + { + source_lookup_reference = source.toLowerCase(); + stringToStrip = stringToStrip.toLowerCase(); + } else + { + source_lookup_reference = source; + } + + new_index = source_lookup_reference.indexOf(stringToStrip); + if (0 == new_index) + { + do + { + last_index = new_index; + new_index = source_lookup_reference.indexOf(stringToStrip, new_index + strip_length); + } + while (new_index != -1 && + new_index == last_index + strip_length); + + return source.substring(last_index + strip_length); + } else + { + return source; + } + } + + /** + * Removes all occurances of a string from the end of another string in a + * case-sensitive manner. + * + * @param source The string in which the matching will be done. + * @param stringToStrip The string that will be stripped from the end. + * @return A new <code>String</code> containing the stripped result. + * @since 1.0 + */ + public static String stripFromEnd(String source, String stringToStrip) + { + return stripFromEnd(source, stringToStrip, true); + } + + /** + * Removes all occurances of a string from the end of another string. + * + * @param source The string in which the matching will be done. + * @param stringToStrip The string that will be stripped from the end. + * @param matchCase A <code>boolean</code> indicating if the match is + * going to be performed in a case-sensitive manner or not. + * @return A new <code>String</code> containing the stripped result. + * @since 1.0 + */ + public static String stripFromEnd(String source, String stringToStrip, boolean matchCase) + { + if (null == source) + { + return null; + } + + if (null == stringToStrip) + { + return source; + } + + int strip_length = stringToStrip.length(); + int new_index = 0; + int last_index = 0; + + String source_lookup_reference = null; + if (!matchCase) + { + source_lookup_reference = source.toLowerCase(); + stringToStrip = stringToStrip.toLowerCase(); + } else + { + source_lookup_reference = source; + } + + new_index = source_lookup_reference.lastIndexOf(stringToStrip); + if (new_index != -1 && + source.length() == new_index + strip_length) + { + do + { + last_index = new_index; + new_index = source_lookup_reference.lastIndexOf(stringToStrip, last_index - 1); + } + while (new_index != -1 && + new_index == last_index - strip_length); + + return source.substring(0, last_index); + } else + { + return source; + } + } + + /** + * Searches for a string within a specified string in a case-sensitive + * manner and replaces every match with another string. + * + * @param source The string in which the matching parts will be replaced. + * @param stringToReplace The string that will be searched for. + * @param replacementString The string that will replace each matching + * part. + * @return A new <code>String</code> object containing the replacement + * result. + * @since 1.0 + */ + public static String replace(String source, String stringToReplace, String replacementString) + { + return replace(source, stringToReplace, replacementString, true); + } + + /** + * Searches for a string within a specified string and replaces every + * match with another string. + * + * @param source The string in which the matching parts will be replaced. + * @param stringToReplace The string that will be searched for. + * @param replacementString The string that will replace each matching + * part. + * @param matchCase A <code>boolean</code> indicating if the match is + * going to be performed in a case-sensitive manner or not. + * @return A new <code>String</code> object containing the replacement + * result. + * @since 1.0 + */ + public static String replace(String source, String stringToReplace, String replacementString, boolean matchCase) + { + if (null == source) + { + return null; + } + + if (null == stringToReplace) + { + return source; + } + + if (null == replacementString) + { + return source; + } + + Iterator<String> string_parts = split(source, stringToReplace, matchCase).iterator(); + StringBuilder new_string = new StringBuilder(); + + while (string_parts.hasNext()) + { + String string_part = string_parts.next(); + new_string.append(string_part); + if (string_parts.hasNext()) + { + new_string.append(replacementString); + } + } + + return new_string.toString(); + } + + /** + * Creates a new string that contains the provided string a number of + * times. + * + * @param source The string that will be repeated. + * @param count The number of times that the string will be repeated. + * @return A new <code>String</code> object containing the repeated + * concatenation result. + * @since 1.0 + */ + public static String repeat(String source, int count) + { + if (null == source) + { + return null; + } + + StringBuilder new_string = new StringBuilder(); + while (count > 0) + { + new_string.append(source); + count--; + } + + return new_string.toString(); + } + + /** + * Creates a new array of <code>String</code> objects, containing the + * elements of a supplied <code>Iterator</code>. + * + * @param iterator The iterator containing the elements to create the + * array with. + * @return The new <code>String</code> array. + * @since 1.0 + */ + public static String[] toStringArray(Iterator<String> iterator) + { + if (null == iterator) + { + return new String[0]; + } + + ArrayList<String> strings = new ArrayList<String>(); + + while (iterator.hasNext()) + { + strings.add(iterator.next()); + } + + String[] string_array = new String[strings.size()]; + strings.toArray(string_array); + + return string_array; + } + + /** + * Creates a new <code>ArrayList</code>, containing the elements of a + * supplied array of <code>String</code> objects. + * + * @param stringArray The array of <code>String</code> objects that have + * to be converted. + * @return The new <code>ArrayList</code> with the elements of the + * <code>String</code> array. + * @since 1.0 + */ + public static ArrayList<String> toArrayList(String[] stringArray) + { + ArrayList<String> strings = new ArrayList<String>(); + + if (null == stringArray) + { + return strings; + } + + for (String element : stringArray) + { + strings.add(element); + } + + return strings; + } + + /** + * Creates a new <code>String</code> object, containing the elements of a + * supplied <code>Collection</code> of <code>String</code> objects joined + * by a given seperator. + * + * @param collection The <code>Collection</code> containing the elements + * to join. + * @param seperator The seperator used to join the string elements. + * @return A new <code>String</code> with the join result. + * @since 1.0 + */ + public static String join(Collection collection, String seperator) + { + if (null == collection) + { + return null; + } + + if (null == seperator) + { + seperator = ""; + } + + if (0 == collection.size()) + { + return ""; + } else + { + StringBuilder result = new StringBuilder(); + for (Object element : collection) + { + result.append(String.valueOf(element)); + result.append(seperator); + } - result.setLength(result.length()-seperator.length()); - return result.toString(); - } - } + result.setLength(result.length() - seperator.length()); + return result.toString(); + } + } - /** - * Creates a new <code>String</code> object, containing the elements of a - * supplied array, joined by a given seperator. - * - * @param array The object array containing the elements to join. - * @param seperator The seperator used to join the string elements. - * @return A new <code>String</code> with the join result. - * @since 1.0 - */ - public static String join(Object[] array, String seperator) - { - return join(array, seperator, null, false); - } + /** + * Creates a new <code>String</code> object, containing the elements of a + * supplied array, joined by a given seperator. + * + * @param array The object array containing the elements to join. + * @param seperator The seperator used to join the string elements. + * @return A new <code>String</code> with the join result. + * @since 1.0 + */ + public static String join(Object[] array, String seperator) + { + return join(array, seperator, null, false); + } - /** - * Creates a new <code>String</code> object, containing the elements of a - * supplied array, joined by a given seperator. - * - * @param array The object array containing the elements to join. - * @param seperator The seperator used to join the string elements. - * @param delimiter The delimiter used to surround the string elements. - * @return A new <code>String</code> with the join result. - * @since 1.0 - */ - public static String join(Object[] array, String seperator, String delimiter) - { - return join(array, seperator, delimiter, false); - } + /** + * Creates a new <code>String</code> object, containing the elements of a + * supplied array, joined by a given seperator. + * + * @param array The object array containing the elements to join. + * @param seperator The seperator used to join the string elements. + * @param delimiter The delimiter used to surround the string elements. + * @return A new <code>String</code> with the join result. + * @since 1.0 + */ + public static String join(Object[] array, String seperator, String delimiter) + { + return join(array, seperator, delimiter, false); + } - /** - * Creates a new <code>String</code> object, containing the elements of a - * supplied array, joined by a given seperator. - * - * @param array The object array containing the elements to join. - * @param seperator The seperator used to join the string elements. - * @param delimiter The delimiter used to surround the string elements. - * @param encodeStrings Indicates whether the characters of the string - * representation of the Array values should be encoded. - * @return A new <code>String</code> with the join result. - * @since 1.0 - */ - public static String join(Object[] array, String seperator, String delimiter, boolean encodeStrings) - { - if (null == array) - { - return null; - } + /** + * Creates a new <code>String</code> object, containing the elements of a + * supplied array, joined by a given seperator. + * + * @param array The object array containing the elements to join. + * @param seperator The seperator used to join the string elements. + * @param delimiter The delimiter used to surround the string elements. + * @param encodeStrings Indicates whether the characters of the string + * representation of the Array values should be encoded. + * @return A new <code>String</code> with the join result. + * @since 1.0 + */ + public static String join(Object[] array, String seperator, String delimiter, boolean encodeStrings) + { + if (null == array) + { + return null; + } - if (null == seperator) - { - seperator = ""; - } + if (null == seperator) + { + seperator = ""; + } - if (null == delimiter) - { - delimiter = ""; - } + if (null == delimiter) + { + delimiter = ""; + } - if (0 == array.length) - { - return ""; - } - else - { - int current_index = 0; - String array_value = null; - StringBuilder result = new StringBuilder(); - while (current_index < array.length - 1) - { - if (null == array[current_index]) - { - result.append("null"); - } - else - { - array_value = String.valueOf(array[current_index]); - if (encodeStrings) - { - array_value = encodeString(array_value); - } - result.append(delimiter); - result.append(array_value); - result.append(delimiter); - } - result.append(seperator); - current_index++; - } + if (0 == array.length) + { + return ""; + } else + { + int current_index = 0; + String array_value = null; + StringBuilder result = new StringBuilder(); + while (current_index < array.length - 1) + { + if (null == array[current_index]) + { + result.append("null"); + } else + { + array_value = String.valueOf(array[current_index]); + if (encodeStrings) + { + array_value = encodeString(array_value); + } + result.append(delimiter); + result.append(array_value); + result.append(delimiter); + } + result.append(seperator); + current_index++; + } - if (null == array[current_index]) - { - result.append("null"); - } - else - { - array_value = String.valueOf(array[current_index]); - if (encodeStrings) - { - array_value = encodeString(array_value); - } - result.append(delimiter); - result.append(array_value); - result.append(delimiter); - } - return result.toString(); - } - } + if (null == array[current_index]) + { + result.append("null"); + } else + { + array_value = String.valueOf(array[current_index]); + if (encodeStrings) + { + array_value = encodeString(array_value); + } + result.append(delimiter); + result.append(array_value); + result.append(delimiter); + } + return result.toString(); + } + } - /** - * Creates a new <code>String</code> object, containing the elements of a - * supplied array, joined by a given seperator. - * - * @param array The boolean array containing the values to join. - * @param seperator The seperator used to join the string elements. - * @return A new <code>String</code> with the join result. - * @since 1.0 - */ - public static String join(boolean[] array, String seperator) - { - if (null == array) - { - return null; - } + /** + * Creates a new <code>String</code> object, containing the elements of a + * supplied array, joined by a given seperator. + * + * @param array The boolean array containing the values to join. + * @param seperator The seperator used to join the string elements. + * @return A new <code>String</code> with the join result. + * @since 1.0 + */ + public static String join(boolean[] array, String seperator) + { + if (null == array) + { + return null; + } - if (null == seperator) - { - seperator = ""; - } + if (null == seperator) + { + seperator = ""; + } - if (0 == array.length) - { - return ""; - } - else - { - int current_index = 0; - String result = ""; - while (current_index < array.length - 1) - { - result = result + array[current_index] + seperator; - current_index++; - } + if (0 == array.length) + { + return ""; + } else + { + int current_index = 0; + String result = ""; + while (current_index < array.length - 1) + { + result = result + array[current_index] + seperator; + current_index++; + } - result = result + array[current_index]; - return result; - } - } + result = result + array[current_index]; + return result; + } + } - /** - * Creates a new <code>String</code> object, containing the elements of a - * supplied array, joined by a given seperator. - * - * @param array The byte array containing the values to join. - * @param seperator The seperator used to join the string elements. - * @return A new <code>String</code> with the join result. - * @since 1.0 - */ - public static String join(byte[] array, String seperator) - { - if (null == array) - { - return null; - } + /** + * Creates a new <code>String</code> object, containing the elements of a + * supplied array, joined by a given seperator. + * + * @param array The byte array containing the values to join. + * @param seperator The seperator used to join the string elements. + * @return A new <code>String</code> with the join result. + * @since 1.0 + */ + public static String join(byte[] array, String seperator) + { + if (null == array) + { + return null; + } - if (null == seperator) - { - seperator = ""; - } + if (null == seperator) + { + seperator = ""; + } - if (0 == array.length) - { - return ""; - } - else - { - int current_index = 0; - String result = ""; - while (current_index < array.length - 1) - { - result = result + array[current_index] + seperator; - current_index++; - } + if (0 == array.length) + { + return ""; + } else + { + int current_index = 0; + String result = ""; + while (current_index < array.length - 1) + { + result = result + array[current_index] + seperator; + current_index++; + } - result = result + array[current_index]; - return result; - } - } + result = result + array[current_index]; + return result; + } + } - /** - * Creates a new <code>String</code> object, containing the elements of a - * supplied array, joined by a given seperator. - * - * @param array The double array containing the values to join. - * @param seperator The seperator used to join the string elements. - * @return A new <code>String</code> with the join result. - * @since 1.0 - */ - public static String join(double[] array, String seperator) - { - if (null == array) - { - return null; - } + /** + * Creates a new <code>String</code> object, containing the elements of a + * supplied array, joined by a given seperator. + * + * @param array The double array containing the values to join. + * @param seperator The seperator used to join the string elements. + * @return A new <code>String</code> with the join result. + * @since 1.0 + */ + public static String join(double[] array, String seperator) + { + if (null == array) + { + return null; + } - if (null == seperator) - { - seperator = ""; - } + if (null == seperator) + { + seperator = ""; + } - if (0 == array.length) - { - return ""; - } - else - { - int current_index = 0; - String result = ""; - while (current_index < array.length - 1) - { - result = result + array[current_index] + seperator; - current_index++; - } + if (0 == array.length) + { + return ""; + } else + { + int current_index = 0; + String result = ""; + while (current_index < array.length - 1) + { + result = result + array[current_index] + seperator; + current_index++; + } - result = result + array[current_index]; - return result; - } - } + result = result + array[current_index]; + return result; + } + } - /** - * Creates a new <code>String</code> object, containing the elements of a - * supplied array, joined by a given seperator. - * - * @param array The float array containing the values to join. - * @param seperator The seperator used to join the string elements. - * @return A new <code>String</code> with the join result. - * @since 1.0 - */ - public static String join(float[] array, String seperator) - { - if (null == array) - { - return null; - } + /** + * Creates a new <code>String</code> object, containing the elements of a + * supplied array, joined by a given seperator. + * + * @param array The float array containing the values to join. + * @param seperator The seperator used to join the string elements. + * @return A new <code>String</code> with the join result. + * @since 1.0 + */ + public static String join(float[] array, String seperator) + { + if (null == array) + { + return null; + } - if (null == seperator) - { - seperator = ""; - } + if (null == seperator) + { + seperator = ""; + } - if (0 == array.length) - { - return ""; - } - else - { - int current_index = 0; - String result = ""; - while (current_index < array.length - 1) - { - result = result + array[current_index] + seperator; - current_index++; - } + if (0 == array.length) + { + return ""; + } else + { + int current_index = 0; + String result = ""; + while (current_index < array.length - 1) + { + result = result + array[current_index] + seperator; + current_index++; + } - result = result + array[current_index]; - return result; - } - } + result = result + array[current_index]; + return result; + } + } - /** - * Creates a new <code>String</code> object, containing the elements of a - * supplied array, joined by a given seperator. - * - * @param array The integer array containing the values to join. - * @param seperator The seperator used to join the string elements. - * @return A new <code>String</code> with the join result. - * @since 1.0 - */ - public static String join(int[] array, String seperator) - { - if (null == array) - { - return null; - } + /** + * Creates a new <code>String</code> object, containing the elements of a + * supplied array, joined by a given seperator. + * + * @param array The integer array containing the values to join. + * @param seperator The seperator used to join the string elements. + * @return A new <code>String</code> with the join result. + * @since 1.0 + */ + public static String join(int[] array, String seperator) + { + if (null == array) + { + return null; + } - if (null == seperator) - { - seperator = ""; - } + if (null == seperator) + { + seperator = ""; + } - if (0 == array.length) - { - return ""; - } - else - { - int current_index = 0; - String result = ""; - while (current_index < array.length - 1) - { - result = result + array[current_index] + seperator; - current_index++; - } + if (0 == array.length) + { + return ""; + } else + { + int current_index = 0; + String result = ""; + while (current_index < array.length - 1) + { + result = result + array[current_index] + seperator; + current_index++; + } - result = result + array[current_index]; - return result; - } - } + result = result + array[current_index]; + return result; + } + } - /** - * Creates a new <code>String</code> object, containing the elements of a - * supplied array, joined by a given seperator. - * - * @param array The long array containing the values to join. - * @param seperator The seperator used to join the string elements. - * @return A new <code>String</code> with the join result. - * @since 1.0 - */ - public static String join(long[] array, String seperator) - { - if (null == array) - { - return null; - } + /** + * Creates a new <code>String</code> object, containing the elements of a + * supplied array, joined by a given seperator. + * + * @param array The long array containing the values to join. + * @param seperator The seperator used to join the string elements. + * @return A new <code>String</code> with the join result. + * @since 1.0 + */ + public static String join(long[] array, String seperator) + { + if (null == array) + { + return null; + } - if (null == seperator) - { - seperator = ""; - } + if (null == seperator) + { + seperator = ""; + } - if (0 == array.length) - { - return ""; - } - else - { - int current_index = 0; - String result = ""; - while (current_index < array.length - 1) - { - result = result + array[current_index] + seperator; - current_index++; - } + if (0 == array.length) + { + return ""; + } else + { + int current_index = 0; + String result = ""; + while (current_index < array.length - 1) + { + result = result + array[current_index] + seperator; + current_index++; + } - result = result + array[current_index]; - return result; - } - } + result = result + array[current_index]; + return result; + } + } - /** - * Creates a new <code>String</code> object, containing the elements of a - * supplied array, joined by a given seperator. - * - * @param array The short array containing the values to join. - * @param seperator The seperator used to join the string elements. - * @return A new <code>String</code> with the join result. - * @since 1.0 - */ - public static String join(short[] array, String seperator) - { - if (null == array) - { - return null; - } + /** + * Creates a new <code>String</code> object, containing the elements of a + * supplied array, joined by a given seperator. + * + * @param array The short array containing the values to join. + * @param seperator The seperator used to join the string elements. + * @return A new <code>String</code> with the join result. + * @since 1.0 + */ + public static String join(short[] array, String seperator) + { + if (null == array) + { + return null; + } - if (null == seperator) - { - seperator = ""; - } + if (null == seperator) + { + seperator = ""; + } - if (0 == array.length) - { - return ""; - } - else - { - int current_index = 0; - String result = ""; - while (current_index < array.length - 1) - { - result = result + array[current_index] + seperator; - current_index++; - } + if (0 == array.length) + { + return ""; + } else + { + int current_index = 0; + String result = ""; + while (current_index < array.length - 1) + { + result = result + array[current_index] + seperator; + current_index++; + } - result = result + array[current_index]; - return result; - } - } + result = result + array[current_index]; + return result; + } + } - /** - * Creates a new <code>String</code> object, containing the elements of a - * supplied array, joined by a given seperator. - * - * @param array The char array containing the values to join. - * @param seperator The seperator used to join the string elements. - * @return A new <code>String</code> with the join result. - * @since 1.0 - */ - public static String join(char[] array, String seperator) - { - return join(array, seperator, null); - } + /** + * Creates a new <code>String</code> object, containing the elements of a + * supplied array, joined by a given seperator. + * + * @param array The char array containing the values to join. + * @param seperator The seperator used to join the string elements. + * @return A new <code>String</code> with the join result. + * @since 1.0 + */ + public static String join(char[] array, String seperator) + { + return join(array, seperator, null); + } - /** - * Creates a new <code>String</code> object, containing the elements of a - * supplied array, joined by a given seperator. - * - * @param array The char array containing the values to join. - * @param seperator The seperator used to join the string elements. - * @param delimiter The delimiter used to surround the string elements. - * @return A new <code>String</code> with the join result. - * @since 1.0 - */ - public static String join(char[] array, String seperator, String delimiter) - { - if (null == array) - { - return null; - } + /** + * Creates a new <code>String</code> object, containing the elements of a + * supplied array, joined by a given seperator. + * + * @param array The char array containing the values to join. + * @param seperator The seperator used to join the string elements. + * @param delimiter The delimiter used to surround the string elements. + * @return A new <code>String</code> with the join result. + * @since 1.0 + */ + public static String join(char[] array, String seperator, String delimiter) + { + if (null == array) + { + return null; + } - if (null == seperator) - { - seperator = ""; - } + if (null == seperator) + { + seperator = ""; + } - if (null == delimiter) - { - delimiter = ""; - } + if (null == delimiter) + { + delimiter = ""; + } - if (0 == array.length) - { - return ""; - } - else - { - int current_index = 0; - StringBuilder result = new StringBuilder(); - while (current_index < array.length - 1) - { - result.append(delimiter); - result.append(array[current_index]); - result.append(delimiter); - result.append(seperator); - current_index++; - } + if (0 == array.length) + { + return ""; + } else + { + int current_index = 0; + StringBuilder result = new StringBuilder(); + while (current_index < array.length - 1) + { + result.append(delimiter); + result.append(array[current_index]); + result.append(delimiter); + result.append(seperator); + current_index++; + } - result.append(delimiter); - result.append(String.valueOf(array[current_index])); - result.append(delimiter); - return result.toString(); - } - } + result.append(delimiter); + result.append(String.valueOf(array[current_index])); + result.append(delimiter); + return result.toString(); + } + } - /** - * Returns an array that contains all the occurances of a substring in a - * string in the correct order. The search will be performed in a - * case-sensitive manner. - * - * @param source The <code>String</code> object that will be searched in. - * @param substring The string whose occurances will we counted. - * @return An <code>int[]</code> array containing the indices of the - * substring. - * @since 1.0 - */ - public static int[] indicesOf(String source, String substring) - { - return indicesOf(source, substring, true); - } + /** + * Returns an array that contains all the occurances of a substring in a + * string in the correct order. The search will be performed in a + * case-sensitive manner. + * + * @param source The <code>String</code> object that will be searched in. + * @param substring The string whose occurances will we counted. + * @return An <code>int[]</code> array containing the indices of the + * substring. + * @since 1.0 + */ + public static int[] indicesOf(String source, String substring) + { + return indicesOf(source, substring, true); + } - /** - * Returns an array that contains all the occurances of a substring in a - * string in the correct order. - * - * @param source The <code>String</code> object that will be searched in. - * @param substring The string whose occurances will we counted. - * @param matchCase A <code>boolean</code> indicating if the match is - * going to be performed in a case-sensitive manner or not. - * @return An <code>int[]</code> array containing the indices of the - * substring. - * @since 1.0 - */ - public static int[] indicesOf(String source, String substring, boolean matchCase) - { - if (null == source || - null == substring) - { - return new int[0]; - } + /** + * Returns an array that contains all the occurances of a substring in a + * string in the correct order. + * + * @param source The <code>String</code> object that will be searched in. + * @param substring The string whose occurances will we counted. + * @param matchCase A <code>boolean</code> indicating if the match is + * going to be performed in a case-sensitive manner or not. + * @return An <code>int[]</code> array containing the indices of the + * substring. + * @since 1.0 + */ + public static int[] indicesOf(String source, String substring, boolean matchCase) + { + if (null == source || + null == substring) + { + return new int[0]; + } - String source_lookup_reference = null; - if (!matchCase) - { - source_lookup_reference = source.toLowerCase(); - substring = substring.toLowerCase(); - } - else - { - source_lookup_reference = source; - } + String source_lookup_reference = null; + if (!matchCase) + { + source_lookup_reference = source.toLowerCase(); + substring = substring.toLowerCase(); + } else + { + source_lookup_reference = source; + } - int current_index = 0; - int substring_index = 0; - int count = count(source_lookup_reference, substring); - int[] indices = new int[count]; - int counter = 0; + int current_index = 0; + int substring_index = 0; + int count = count(source_lookup_reference, substring); + int[] indices = new int[count]; + int counter = 0; - while (current_index < source.length()-1) - { - substring_index = source_lookup_reference.indexOf(substring, current_index); + while (current_index < source.length() - 1) + { + substring_index = source_lookup_reference.indexOf(substring, current_index); - if (-1 == substring_index) - { - break; - } - else - { - current_index = substring_index + substring.length(); - indices[counter] = substring_index; - counter++; - } - } + if (-1 == substring_index) + { + break; + } else + { + current_index = substring_index + substring.length(); + indices[counter] = substring_index; + counter++; + } + } - return indices; - } + return indices; + } - /** - * Matches a collection of regular expressions against a string. - * - * @param value The <code>String</code> that will be checked. - * @param regexps The collection of regular expressions against which the - * match will be performed. - * @return The <code>Matcher</code> instance that corresponds to the - * <code>String</code> that returned a successful match; or - * <p><code>null</code> if no match could be found. - * @since 1.0 - */ - public static Matcher getMatchingRegexp(String value, Collection<Pattern> regexps) - { - if (value != null && - value.length() > 0 && - regexps != null && - regexps.size() > 0) - { - Matcher matcher = null; - for (Pattern regexp : regexps) - { - matcher = regexp.matcher(value); - if (matcher.matches()) - { - return matcher; - } - } - } + /** + * Matches a collection of regular expressions against a string. + * + * @param value The <code>String</code> that will be checked. + * @param regexps The collection of regular expressions against which the + * match will be performed. + * @return The <code>Matcher</code> instance that corresponds to the + * <code>String</code> that returned a successful match; or + * <p><code>null</code> if no match could be found. + * @since 1.0 + */ + public static Matcher getMatchingRegexp(String value, Collection<Pattern> regexps) + { + if (value != null && + value.length() > 0 && + regexps != null && + regexps.size() > 0) + { + Matcher matcher = null; + for (Pattern regexp : regexps) + { + matcher = regexp.matcher(value); + if (matcher.matches()) + { + return matcher; + } + } + } - return null; - } + return null; + } - /** - * Matches a collection of strings against a regular expression. - * - * @param values The <code>Collection</code> of <code>String</code> - * objects that will be checked. - * @param regexp The regular expression <code>Pattern</code> against which - * the matches will be performed. - * @return The <code>Matcher</code> instance that corresponds to the - * <code>String</code> that returned a successful match; or - * <p><code>null</code> if no match could be found. - * @since 1.0 - */ - public static Matcher getRegexpMatch(Collection<String> values, Pattern regexp) - { - if (values != null && - values.size() > 0 && - regexp != null) - { - Matcher matcher = null; - for (String value : values) - { - matcher = regexp.matcher(value); - if (matcher.matches()) - { - return matcher; - } - } - } + /** + * Matches a collection of strings against a regular expression. + * + * @param values The <code>Collection</code> of <code>String</code> + * objects that will be checked. + * @param regexp The regular expression <code>Pattern</code> against which + * the matches will be performed. + * @return The <code>Matcher</code> instance that corresponds to the + * <code>String</code> that returned a successful match; or + * <p><code>null</code> if no match could be found. + * @since 1.0 + */ + public static Matcher getRegexpMatch(Collection<String> values, Pattern regexp) + { + if (values != null && + values.size() > 0 && + regexp != null) + { + Matcher matcher = null; + for (String value : values) + { + matcher = regexp.matcher(value); + if (matcher.matches()) + { + return matcher; + } + } + } - return null; - } + return null; + } - /** - * Checks if the name filters through an including and an excluding - * regular expression. - * - * @param name The <code>String</code> that will be filtered. - * @param included The regular expressions that needs to succeed - * @param excluded The regular expressions that needs to fail - * @return <code>true</code> if the name filtered through correctly; or - * <p><code>false</code> otherwise. - * @since 1.0 - */ - public static boolean filter(String name, Pattern included, Pattern excluded) - { - Pattern[] included_array = null; - if (included != null) - { - included_array = new Pattern[] {included}; - } + /** + * Checks if the name filters through an including and an excluding + * regular expression. + * + * @param name The <code>String</code> that will be filtered. + * @param included The regular expressions that needs to succeed + * @param excluded The regular expressions that needs to fail + * @return <code>true</code> if the name filtered through correctly; or + * <p><code>false</code> otherwise. + * @since 1.0 + */ + public static boolean filter(String name, Pattern included, Pattern excluded) + { + Pattern[] included_array = null; + if (included != null) + { + included_array = new Pattern[]{included}; + } - Pattern[] excluded_array = null; - if (excluded != null) - { - excluded_array = new Pattern[] {excluded}; - } + Pattern[] excluded_array = null; + if (excluded != null) + { + excluded_array = new Pattern[]{excluded}; + } - return filter(name, included_array, excluded_array); - } + return filter(name, included_array, excluded_array); + } - /** - * Checks if the name filters through a series of including and excluding - * regular expressions. - * - * @param name The <code>String</code> that will be filtered. - * @param included An array of regular expressions that need to succeed - * @param excluded An array of regular expressions that need to fail - * @return <code>true</code> if the name filtered through correctly; or - * <p><code>false</code> otherwise. - * @since 1.0 - */ - public static boolean filter(String name, Pattern[] included, Pattern[] excluded) - { - if (null == name) - { - return false; - } + /** + * Checks if the name filters through a series of including and excluding + * regular expressions. + * + * @param name The <code>String</code> that will be filtered. + * @param included An array of regular expressions that need to succeed + * @param excluded An array of regular expressions that need to fail + * @return <code>true</code> if the name filtered through correctly; or + * <p><code>false</code> otherwise. + * @since 1.0 + */ + public static boolean filter(String name, Pattern[] included, Pattern[] excluded) + { + if (null == name) + { + return false; + } - boolean accepted = false; + boolean accepted = false; - // retain only the includes - if (null == included) - { - accepted = true; - } - else - { - for (Pattern pattern : included) - { - if (pattern != null && - pattern.matcher(name).matches()) - { - accepted = true; - break; - } - } - } + // retain only the includes + if (null == included) + { + accepted = true; + } else + { + for (Pattern pattern : included) + { + if (pattern != null && + pattern.matcher(name).matches()) + { + accepted = true; + break; + } + } + } - // remove the excludes - if (accepted && - excluded != null) - { - for (Pattern pattern : excluded) - { - if (pattern != null && - pattern.matcher(name).matches()) - { - accepted = false; - break; - } - } - } + // remove the excludes + if (accepted && + excluded != null) + { + for (Pattern pattern : excluded) + { + if (pattern != null && + pattern.matcher(name).matches()) + { + accepted = false; + break; + } + } + } - return accepted; - } + return accepted; + } - /** - * Ensure that the first character of the provided string is upper case. - * - * @param source The <code>String</code> to capitalize. - * @return The capitalized <code>String</code>. - * @since 1.0 - */ - public static String capitalize(String source) - { - if (source == null || source.length() == 0) - { - return source; - } + /** + * Ensure that the first character of the provided string is upper case. + * + * @param source The <code>String</code> to capitalize. + * @return The capitalized <code>String</code>. + * @since 1.0 + */ + public static String capitalize(String source) + { + if (source == null || source.length() == 0) + { + return source; + } - if (source.length() > 1 && - Character.isUpperCase(source.charAt(0))) - { - return source; - } + if (source.length() > 1 && + Character.isUpperCase(source.charAt(0))) + { + return source; + } - char chars[] = source.toCharArray(); - chars[0] = Character.toUpperCase(chars[0]); - return new String(chars); - } + char chars[] = source.toCharArray(); + chars[0] = Character.toUpperCase(chars[0]); + return new String(chars); + } - /** - * Ensure that the first character of the provided string lower case. - * - * @param source The <code>String</code> to uncapitalize. - * @return The uncapitalized <code>String</code>. - * @since 1.5 - */ - public static String uncapitalize(String source) - { - if (source == null || source.length() == 0) - { - return source; - } + /** + * Ensure that the first character of the provided string lower case. + * + * @param source The <code>String</code> to uncapitalize. + * @return The uncapitalized <code>String</code>. + * @since 1.5 + */ + public static String uncapitalize(String source) + { + if (source == null || source.length() == 0) + { + return source; + } - if (source.length() > 1 && - Character.isLowerCase(source.charAt(0))) - { - return source; - } + if (source.length() > 1 && + Character.isLowerCase(source.charAt(0))) + { + return source; + } - char chars[] = source.toCharArray(); - chars[0] = Character.toLowerCase(chars[0]); - return new String(chars); - } + char chars[] = source.toCharArray(); + chars[0] = Character.toLowerCase(chars[0]); + return new String(chars); + } - private static String convertUrl(String source, Pattern pattern, boolean shorten, boolean sanitize, boolean no_follow) - { - int max_length = 1024; + private static String convertUrl(String source, Pattern pattern, boolean shorten, boolean sanitize, boolean no_follow) + { + int max_length = 1024; - String result = source; + String result = source; - Matcher url_matcher = pattern.matcher(source); - boolean found = url_matcher.find(); - if (found) - { - String visual_url = null; - String actual_url = null; - int last = 0; - StringBuilder sb = new StringBuilder(); - do - { - actual_url = url_matcher.group(1); - if (url_matcher.groupCount() > 1) - { - visual_url = url_matcher.group(2); - } - else - { - visual_url = actual_url; - } + Matcher url_matcher = pattern.matcher(source); + boolean found = url_matcher.find(); + if (found) + { + String visual_url = null; + String actual_url = null; + int last = 0; + StringBuilder sb = new StringBuilder(); + do + { + actual_url = url_matcher.group(1); + if (url_matcher.groupCount() > 1) + { + visual_url = url_matcher.group(2); + } else + { + visual_url = actual_url; + } - if (sanitize) - { - // defang javascript - actual_url = StringUtils.replace(actual_url, "javascript:", ""); + if (sanitize) + { + // defang javascript + actual_url = StringUtils.replace(actual_url, "javascript:", ""); - // fill in http:// for URLs that don't begin with / - if ((actual_url.indexOf("://") == -1) && - (!actual_url.startsWith("/"))) - { - actual_url = "http://"+actual_url; - } - } + // fill in http:// for URLs that don't begin with / + if ((actual_url.indexOf("://") == -1) && + (!actual_url.startsWith("/"))) + { + actual_url = "http://" + actual_url; + } + } - if (pattern.equals(BBCODE_BAREURL)) - { - sb.append(source.substring(last, url_matcher.start(1))); - } - else - { - sb.append(source.substring(last, url_matcher.start(0))); - } - sb.append("<a href=\""); - sb.append(actual_url); - sb.append("\""); - if (actual_url.startsWith("http://") || - actual_url.startsWith("https://")) - { - sb.append(" target=\"_blank\""); - } - if (no_follow) - { - sb.append(" rel=\"nofollow\""); - } - sb.append(">"); - if (visual_url.length() <= max_length || !shorten) - { - sb.append(visual_url); - } - else - { - String ellipsis = "..."; - int query_index = visual_url.indexOf("?"); + if (pattern.equals(BBCODE_BAREURL)) + { + sb.append(source.substring(last, url_matcher.start(1))); + } else + { + sb.append(source.substring(last, url_matcher.start(0))); + } + sb.append("<a href=\""); + sb.append(actual_url); + sb.append("\""); + if (actual_url.startsWith("http://") || + actual_url.startsWith("https://")) + { + sb.append(" target=\"_blank\""); + } + if (no_follow) + { + sb.append(" rel=\"nofollow\""); + } + sb.append(">"); + if (visual_url.length() <= max_length || !shorten) + { + sb.append(visual_url); + } else + { + String ellipsis = "..."; + int query_index = visual_url.indexOf("?"); - // hack query string off - // keep '?' - if (query_index != -1) - { - visual_url = visual_url.substring(0, query_index + 1) + ellipsis; - } + // hack query string off + // keep '?' + if (query_index != -1) + { + visual_url = visual_url.substring(0, query_index + 1) + ellipsis; + } - if (visual_url.length() >= max_length) - { - int last_slash = visual_url.lastIndexOf("/"); - int start_slash = visual_url.indexOf("/", visual_url.indexOf("://")+3); + if (visual_url.length() >= max_length) + { + int last_slash = visual_url.lastIndexOf("/"); + int start_slash = visual_url.indexOf("/", visual_url.indexOf("://") + 3); - if (last_slash != start_slash) - { - visual_url = visual_url.substring(0, start_slash + 1) + ellipsis + visual_url.substring(last_slash); - } - } + if (last_slash != start_slash) + { + visual_url = visual_url.substring(0, start_slash + 1) + ellipsis + visual_url.substring(last_slash); + } + } - sb.append(visual_url); - } - sb.append("</a>"); + sb.append(visual_url); + } + sb.append("</a>"); - if (pattern.equals(BBCODE_BAREURL)) - { - last = url_matcher.end(1); - } - else - { - last = url_matcher.end(0); - } + if (pattern.equals(BBCODE_BAREURL)) + { + last = url_matcher.end(1); + } else + { + last = url_matcher.end(0); + } - found = url_matcher.find(); - } - while (found); + found = url_matcher.find(); + } + while (found); - sb.append(source.substring(last)); - result = sb.toString(); - } + sb.append(source.substring(last)); + result = sb.toString(); + } - return result; - } + return result; + } - private static String parseBBCode(String source, boolean shorten, boolean sanitize, boolean convert_bare, boolean no_follow) - { - String result = source; + private static String parseBBCode(String source, boolean shorten, boolean sanitize, boolean convert_bare, boolean no_follow) + { + String result = source; - result = StringUtils.replace(result, "[b]", "<b>", false); - result = StringUtils.replace(result, "[/b]", "</b>", false); - result = StringUtils.replace(result, "[u]", "<u>", false); - result = StringUtils.replace(result, "[/u]", "</u>", false); - result = StringUtils.replace(result, "[i]", "<i>", false); - result = StringUtils.replace(result, "[/i]", "</i>", false); - result = StringUtils.replace(result, "[pre]", "<pre>", false); - result = StringUtils.replace(result, "[/pre]", "</pre>", false); + result = StringUtils.replace(result, "[b]", "<b>", false); + result = StringUtils.replace(result, "[/b]", "</b>", false); + result = StringUtils.replace(result, "[u]", "<u>", false); + result = StringUtils.replace(result, "[/u]", "</u>", false); + result = StringUtils.replace(result, "[i]", "<i>", false); + result = StringUtils.replace(result, "[/i]", "</i>", false); + result = StringUtils.replace(result, "[pre]", "<pre>", false); + result = StringUtils.replace(result, "[/pre]", "</pre>", false); - String resultCopy = result; - String resultLowerCopy = result.toLowerCase(); - StringBuilder buffer = new StringBuilder(); - int startIndex; - int endIndex; - while (-1 != (startIndex = resultLowerCopy.indexOf("[*]"))) - { - int begin = resultLowerCopy.indexOf("[list]", startIndex + 3); - int end = resultLowerCopy.indexOf("[/list]", startIndex + 3); - int next = resultLowerCopy.indexOf("[*]", startIndex + 3); // 3 == sizeof [*] + String resultCopy = result; + String resultLowerCopy = result.toLowerCase(); + StringBuilder buffer = new StringBuilder(); + int startIndex; + int endIndex; + while (-1 != (startIndex = resultLowerCopy.indexOf("[*]"))) + { + int begin = resultLowerCopy.indexOf("[list]", startIndex + 3); + int end = resultLowerCopy.indexOf("[/list]", startIndex + 3); + int next = resultLowerCopy.indexOf("[*]", startIndex + 3); // 3 == sizeof [*] - if (begin == -1) - { - begin = Integer.MAX_VALUE; - } + if (begin == -1) + { + begin = Integer.MAX_VALUE; + } - if (end == -1) - { - end = Integer.MAX_VALUE; - } + if (end == -1) + { + end = Integer.MAX_VALUE; + } - if (next == -1) - { - next = Integer.MAX_VALUE; - } + if (next == -1) + { + next = Integer.MAX_VALUE; + } - if (next < begin && next < end) - { - endIndex = next; - } - else if (begin < next && begin < end) - { - endIndex = begin; - } - else if (end < next && end < begin) - { - endIndex = end; - } - else - { - endIndex = resultLowerCopy.length(); - } + if (next < begin && next < end) + { + endIndex = next; + } else if (begin < next && begin < end) + { + endIndex = begin; + } else if (end < next && end < begin) + { + endIndex = end; + } else + { + endIndex = resultLowerCopy.length(); + } - buffer - .append(resultCopy.substring(0, startIndex)) - .append("<li>") - .append(resultCopy.substring(startIndex + 3, endIndex)) // 3 == sizeof [*] - .append("</li>"); + buffer + .append(resultCopy.substring(0, startIndex)) + .append("<li>") + .append(resultCopy.substring(startIndex + 3, endIndex)) // 3 == sizeof [*] + .append("</li>"); - resultCopy = resultCopy.substring(endIndex); - resultLowerCopy = resultLowerCopy.substring(endIndex); - } - buffer.append(resultCopy.substring(0)); + resultCopy = resultCopy.substring(endIndex); + resultLowerCopy = resultLowerCopy.substring(endIndex); + } + buffer.append(resultCopy.substring(0)); - result = buffer.toString(); + result = buffer.toString(); - result = StringUtils.replace(result, "[list]", "<ul>", false); - result = StringUtils.replace(result, "[/list]", "</ul>", false); + result = StringUtils.replace(result, "[list]", "<ul>", false); + result = StringUtils.replace(result, "[/list]", "</ul>", false); - Matcher color_matcher = BBCODE_COLOR.matcher(result); - result = color_matcher.replaceAll("<font color=\"$1\">"); - result = StringUtils.replace(result, "[/color]", "</font>", false); + Matcher color_matcher = BBCODE_COLOR.matcher(result); + result = color_matcher.replaceAll("<font color=\"$1\">"); + result = StringUtils.replace(result, "[/color]", "</font>", false); - Matcher size_matcher = BBCODE_SIZE.matcher(result); - result = size_matcher.replaceAll("<font size=\"$1\">"); - result = StringUtils.replace(result, "[/size]", "</font>", false); + Matcher size_matcher = BBCODE_SIZE.matcher(result); + result = size_matcher.replaceAll("<font size=\"$1\">"); + result = StringUtils.replace(result, "[/size]", "</font>", false); - result = convertUrl(result, BBCODE_URL_SHORT, shorten, sanitize, no_follow); - result = convertUrl(result, BBCODE_URL_LONG, shorten, sanitize, no_follow); + result = convertUrl(result, BBCODE_URL_SHORT, shorten, sanitize, no_follow); + result = convertUrl(result, BBCODE_URL_LONG, shorten, sanitize, no_follow); - if (convert_bare) - { - result = convertUrl(result, BBCODE_BAREURL, shorten, sanitize, no_follow); - } + if (convert_bare) + { + result = convertUrl(result, BBCODE_BAREURL, shorten, sanitize, no_follow); + } - Matcher img_matcher = BBCODE_IMG.matcher(result); - result = img_matcher.replaceAll("<div class=\"bbcode_img\"><img src=\"$1\" border=\"0\" alt=\"\" /></div>"); + Matcher img_matcher = BBCODE_IMG.matcher(result); + result = img_matcher.replaceAll("<div class=\"bbcode_img\"><img src=\"$1\" border=\"0\" alt=\"\" /></div>"); - Matcher quote_matcher_long = BBCODE_QUOTE_LONG.matcher(result); - result = quote_matcher_long.replaceAll("<div class=\"quoteaccount\">$1:</div><div class=\"quotebody\">"); - result = StringUtils.replace(result, "[quote]", "<div class=\"quotebody\">", false); - result = StringUtils.replace(result, "[/quote]", "</div>", false); + Matcher quote_matcher_long = BBCODE_QUOTE_LONG.matcher(result); + result = quote_matcher_long.replaceAll("<div class=\"quoteaccount\">$1:</div><div class=\"quotebody\">"); + result = StringUtils.replace(result, "[quote]", "<div class=\"quotebody\">", false); + result = StringUtils.replace(result, "[/quote]", "</div>", false); - result = StringUtils.replace(result, "\r\n", "<br />\r"); - result = StringUtils.replace(result, "\n", "<br />\n"); - result = StringUtils.replace(result, "\r", "\r\n"); + result = StringUtils.replace(result, "\r\n", "<br />\r"); + result = StringUtils.replace(result, "\n", "<br />\n"); + result = StringUtils.replace(result, "\r", "\r\n"); - // remove the BR that could be added due to code formatting ppl - // use to format lists - result = StringUtils.replace(result, "ul><br />\r\n", "ul>\r\n"); - result = StringUtils.replace(result, "ul><br />\n", "ul>\n"); + // remove the BR that could be added due to code formatting ppl + // use to format lists + result = StringUtils.replace(result, "ul><br />\r\n", "ul>\r\n"); + result = StringUtils.replace(result, "ul><br />\n", "ul>\n"); - return result; - } + return result; + } - /** - * Converts a <code>String</code> to a <code>boolean</code> value. - * - * @param value The <code>String</code> to convert. - * @return The corresponding <code>boolean</code> value. - * @since 1.0 - */ - public static boolean convertToBoolean(String value) - { - if (null == value) - { - return false; - } + /** + * Converts a <code>String</code> to a <code>boolean</code> value. + * + * @param value The <code>String</code> to convert. + * @return The corresponding <code>boolean</code> value. + * @since 1.0 + */ + public static boolean convertToBoolean(String value) + { + if (null == value) + { + return false; + } - if (value.equals("1") || - value.equalsIgnoreCase("t") || - value.equalsIgnoreCase("true") || - value.equalsIgnoreCase("y") || - value.equalsIgnoreCase("yes") || - value.equalsIgnoreCase("on")) - { - return true; - } + if (value.equals("1") || + value.equalsIgnoreCase("t") || + value.equalsIgnoreCase("true") || + value.equalsIgnoreCase("y") || + value.equalsIgnoreCase("yes") || + value.equalsIgnoreCase("on")) + { + return true; + } - return false; - } + return false; + } - /** - * Converts all tabs on a line to spaces according to the provided tab - * width. - * - * @param line The line whose tabs have to be converted. - * @param tabWidth The tab width. - * @return A new <code>String</code> object containing the line with the - * replaced tabs. - * @since 1.0 - */ - public static String convertTabsToSpaces(String line, int tabWidth) - { - StringBuilder result = new StringBuilder(); - int tab_index = -1; - int last_tab_index = 0; - int added_chars = 0; - int tab_size; - while ((tab_index = line.indexOf("\t", last_tab_index)) != -1) - { - tab_size = tabWidth-((tab_index+added_chars)%tabWidth); - if (0 == tab_size) - { - tab_size = tabWidth; - } - added_chars += tab_size-1; - result.append(line.substring(last_tab_index, tab_index)); - result.append(StringUtils.repeat(" ", tab_size)); - last_tab_index = tab_index+1; - } - if (0 == last_tab_index) - { - return line; - } - else - { - result.append(line.substring(last_tab_index)); - } + /** + * Converts all tabs on a line to spaces according to the provided tab + * width. + * + * @param line The line whose tabs have to be converted. + * @param tabWidth The tab width. + * @return A new <code>String</code> object containing the line with the + * replaced tabs. + * @since 1.0 + */ + public static String convertTabsToSpaces(String line, int tabWidth) + { + StringBuilder result = new StringBuilder(); + int tab_index = -1; + int last_tab_index = 0; + int added_chars = 0; + int tab_size; + while ((tab_index = line.indexOf("\t", last_tab_index)) != -1) + { + tab_size = tabWidth - ((tab_index + added_chars) % tabWidth); + if (0 == tab_size) + { + tab_size = tabWidth; + } + added_chars += tab_size - 1; + result.append(line.substring(last_tab_index, tab_index)); + result.append(StringUtils.repeat(" ", tab_size)); + last_tab_index = tab_index + 1; + } + if (0 == last_tab_index) + { + return line; + } else + { + result.append(line.substring(last_tab_index)); + } - return result.toString(); - } + return result.toString(); + } - /** - * Ensures that all whitespace is removed from a <code>String</code>. - * <p>It also works with a <code>null</code> argument. - * - * @param source The <code>String</code> to trim. - * @return The trimmed <code>String</code>. - * @since 1.0 - */ - public static String trim(String source) - { - if (source == null || source.length() == 0) - { - return source; - } + /** + * Ensures that all whitespace is removed from a <code>String</code>. + * <p>It also works with a <code>null</code> argument. + * + * @param source The <code>String</code> to trim. + * @return The trimmed <code>String</code>. + * @since 1.0 + */ + public static String trim(String source) + { + if (source == null || source.length() == 0) + { + return source; + } - return source.trim(); - } + return source.trim(); + } /** * Reformats a string where lines that are longer than <tt>width</tt> * are split apart at the earliest wordbreak or at maxLength, whichever is * sooner. If the width specified is less than 5 or greater than the input * Strings length the string will be returned as is. - * <p> + * <p/> * Please note that this method can be lossy - trailing spaces on wrapped * lines may be trimmed. * @@ -2814,12 +2778,10 @@ if (input == null) { return ""; - } - else if (width < 5) + } else if (width < 5) { return input; - } - else if (width >= input.length()) + } else if (width >= input.length()) { return input; } @@ -2831,18 +2793,18 @@ } StringBuilder buffer = new StringBuilder(input.length()); - int current_index = 0; - int delimiter_index = 0; - String seperator = "\n"; - String line; + int current_index = 0; + int delimiter_index = 0; + String seperator = "\n"; + String line; - // go over the input string and jump from line to line - while (current_index <= input.length()) - { - // look for the next linebreak - delimiter_index = input.indexOf(seperator, current_index); + // go over the input string and jump from line to line + while (current_index <= input.length()) + { + // look for the next linebreak + delimiter_index = input.indexOf(seperator, current_index); - // get the line that corresponds to it + // get the line that corresponds to it if (-1 == delimiter_index) { line = new String(input.substring(current_index, input.length())); -- Gitblit v0.0.0-SNAPSHOT