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.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; 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 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); private static final Map AGGRESSIVE_HTML_ENCODE_MAP = new HashMap(); private static final Map DEFENSIVE_HTML_ENCODE_MAP = new HashMap(); private static final Map XML_ENCODE_MAP = new HashMap(); private static final Map STRING_ENCODE_MAP = new HashMap(); private static final Map SQL_ENCODE_MAP = new HashMap(); private static final Map LATEX_ENCODE_MAP = new HashMap(); private static final Map HTML_DECODE_MAP = new HashMap(); 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 // 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',"€"); // 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',"♦"); Set> aggresive_entries = AGGRESSIVE_HTML_ENCODE_MAP.entrySet(); for (Map.Entry entry : aggresive_entries) { HTML_DECODE_MAP.put(entry.getValue(), entry.getKey()); } Set> defensive_entries = DEFENSIVE_HTML_ENCODE_MAP.entrySet(); for (Map.Entry 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',">"); 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('"',"\\\""); 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}"); // 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}"); // 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}"); // 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}"); // 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}"); // todo \u00FE LATEX_ENCODE_MAP.put('\u00FF',"\\\"{y}"); } /** * Transforms a provided String 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 String 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 String 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 String 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 String 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 String 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 String 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 * doesUrlValueNeedDecoding(String) method. * * @param source the value that has been encoded for URL usage in a * RIFE-specific way * @return The decoded String 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 String 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 true if the value is encoded in the RIFE-specific * format; and *

false 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 String 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 String 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 String 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 String 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 String 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 String 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 String object into a new string, * containing only valid String characters. * * @param source The string that has to be transformed into a valid * sequence of String characters. * @return The encoded String 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 String 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 String 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 String 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 String 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 String 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 String 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 String 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 Map object containing the mappings * to transform characters into valid entities. The keys of this map * should be Character objects and the values * String objects. * @return The encoded String object. * @since 1.0 */ private static String encode(String source, EncoderFallbackHandler fallbackHandler, Map... 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 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 String 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 String 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(); } /** * Counts the number of times a substring occures in a provided string in * a case-sensitive manner. * * @param source The String object that will be searched in. * @param substring The string whose occurances will we counted. * @return An int 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 String object that will be searched in. * @param substring The string whose occurances will we counted. * @param matchCase A boolean indicating if the match is * going to be performed in a case-sensitive manner or not. * @return An int 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 ArrayList containing the parts as * String objects. * @since 1.0 */ public static ArrayList 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 boolean indicating if the match is * going to be performed in a case-sensitive manner or not. * @return An ArrayList containing the parts as * String objects. * @since 1.0 */ public static ArrayList split(String source, String seperator, boolean matchCase) { ArrayList substrings = new ArrayList(); 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 String[] 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 boolean indicating if the match is * going to be performed in a case-sensitive manner or not. * @return A String[] array containing the seperated parts. * @since 1.0 */ public static String[] splitToArray(String source, String seperator, boolean matchCase) { ArrayList 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 int[] 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 boolean indicating if the match is * going to be performed in a case-sensitive manner or not. * @return An int[] array containing the seperated parts. * @since 1.0 */ public static int[] splitToIntArray(String source, String seperator, boolean matchCase) { ArrayList 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 byte, 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 byte[] 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 * byte, 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 boolean indicating if the match is * going to be performed in a case-sensitive manner or not. * @return A byte[] array containing the bytes. * @since 1.0 */ public static byte[] splitToByteArray(String source, String seperator, boolean matchCase) { ArrayList 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 String 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 boolean indicating if the match is * going to be performed in a case-sensitive manner or not. * @return A new String 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 String 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 boolean indicating if the match is * going to be performed in a case-sensitive manner or not. * @return A new String 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 String 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 boolean indicating if the match is * going to be performed in a case-sensitive manner or not. * @return A new String 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_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 String 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 String objects, containing the * elements of a supplied Iterator. * * @param iterator The iterator containing the elements to create the * array with. * @return The new String array. * @since 1.0 */ public static String[] toStringArray(Iterator iterator) { if (null == iterator) { return new String[0]; } ArrayList strings = new ArrayList(); while (iterator.hasNext()) { strings.add(iterator.next()); } String[] string_array = new String[strings.size()]; strings.toArray(string_array); return string_array; } /** * Creates a new ArrayList, containing the elements of a * supplied array of String objects. * * @param stringArray The array of String objects that have * to be converted. * @return The new ArrayList with the elements of the * String array. * @since 1.0 */ public static ArrayList toArrayList(String[] stringArray) { ArrayList strings = new ArrayList(); if (null == stringArray) { return strings; } for (String element : stringArray) { strings.add(element); } return strings; } /** * Creates a new String object, containing the elements of a * supplied Collection of String objects joined * by a given seperator. * * @param collection The Collection containing the elements * to join. * @param seperator The seperator used to join the string elements. * @return A new String 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(); } } /** * Creates a new String 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 String with the join result. * @since 1.0 */ public static String join(Object[] array, String seperator) { return join(array, seperator, null, false); } /** * Creates a new String 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 String 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 String 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 String 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 == 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 (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 String 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 String 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 (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; } } /** * Creates a new String 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 String 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 (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; } } /** * Creates a new String 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 String 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 (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; } } /** * Creates a new String 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 String 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 (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; } } /** * Creates a new String 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 String 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 (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; } } /** * Creates a new String 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 String 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 (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; } } /** * Creates a new String 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 String 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 (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; } } /** * Creates a new String 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 String with the join result. * @since 1.0 */ public static String join(char[] array, String seperator) { return join(array, seperator, null); } /** * Creates a new String 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 String 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 == 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++; } 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 String object that will be searched in. * @param substring The string whose occurances will we counted. * @return An int[] 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 String object that will be searched in. * @param substring The string whose occurances will we counted. * @param matchCase A boolean indicating if the match is * going to be performed in a case-sensitive manner or not. * @return An int[] 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; } 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); if (-1 == substring_index) { break; } else { current_index = substring_index + substring.length(); indices[counter] = substring_index; counter++; } } return indices; } /** * Matches a collection of regular expressions against a string. * * @param value The String that will be checked. * @param regexps The collection of regular expressions against which the * match will be performed. * @return The Matcher instance that corresponds to the * String that returned a successful match; or *

null if no match could be found. * @since 1.0 */ public static Matcher getMatchingRegexp(String value, Collection 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; } /** * Matches a collection of strings against a regular expression. * * @param values The Collection of String * objects that will be checked. * @param regexp The regular expression Pattern against which * the matches will be performed. * @return The Matcher instance that corresponds to the * String that returned a successful match; or *

null if no match could be found. * @since 1.0 */ public static Matcher getRegexpMatch(Collection 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; } /** * Checks if the name filters through an including and an excluding * regular expression. * * @param name The String that will be filtered. * @param included The regular expressions that needs to succeed * @param excluded The regular expressions that needs to fail * @return true if the name filtered through correctly; or *

false 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}; } return filter(name, included_array, excluded_array); } /** * Checks if the name filters through a series of including and excluding * regular expressions. * * @param name The String 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 true if the name filtered through correctly; or *

false otherwise. * @since 1.0 */ public static boolean filter(String name, Pattern[] included, Pattern[] excluded) { if (null == name) { return 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; } } } // remove the excludes if (accepted && excluded != null) { for (Pattern pattern : excluded) { if (pattern != null && pattern.matcher(name).matches()) { accepted = false; break; } } } return accepted; } /** * Ensure that the first character of the provided string is upper case. * * @param source The String to capitalize. * @return The capitalized String. * @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; } 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 String to uncapitalize. * @return The uncapitalized String. * @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; } 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; 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; } 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; } } 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(""); 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; } 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); } } sb.append(visual_url); } sb.append(""); if (pattern.equals(BBCODE_BAREURL)) { last = url_matcher.end(1); } else { last = url_matcher.end(0); } found = url_matcher.find(); } while (found); sb.append(source.substring(last)); result = sb.toString(); } return result; } private static String parseBBCode(String source, boolean shorten, boolean sanitize, boolean convert_bare, boolean no_follow) { String result = source; result = StringUtils.replace(result, "[b]", "", false); result = StringUtils.replace(result, "[/b]", "", false); result = StringUtils.replace(result, "[u]", "", false); result = StringUtils.replace(result, "[/u]", "", false); result = StringUtils.replace(result, "[i]", "", false); result = StringUtils.replace(result, "[/i]", "", false); result = StringUtils.replace(result, "[pre]", "

", false);
		result = StringUtils.replace(result, "[/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 [*] if (begin == -1) { begin = Integer.MAX_VALUE; } if (end == -1) { end = 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(); } buffer .append(resultCopy.substring(0, startIndex)) .append("
  • ") .append(resultCopy.substring(startIndex + 3, endIndex)) // 3 == sizeof [*] .append("
  • "); resultCopy = resultCopy.substring(endIndex); resultLowerCopy = resultLowerCopy.substring(endIndex); } buffer.append(resultCopy.substring(0)); result = buffer.toString(); result = StringUtils.replace(result, "[list]", "
      ", false); result = StringUtils.replace(result, "[/list]", "
    ", false); Matcher color_matcher = BBCODE_COLOR.matcher(result); result = color_matcher.replaceAll(""); result = StringUtils.replace(result, "[/color]", "", false); Matcher size_matcher = BBCODE_SIZE.matcher(result); result = size_matcher.replaceAll(""); result = StringUtils.replace(result, "[/size]", "", false); 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); } Matcher img_matcher = BBCODE_IMG.matcher(result); result = img_matcher.replaceAll("
    \"\"
    "); Matcher quote_matcher_long = BBCODE_QUOTE_LONG.matcher(result); result = quote_matcher_long.replaceAll("
    $1:
    "); result = StringUtils.replace(result, "[quote]", "
    ", false); result = StringUtils.replace(result, "[/quote]", "
    ", false); result = StringUtils.replace(result, "\r\n", "
    \r"); result = StringUtils.replace(result, "\n", "
    \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>
    \r\n", "ul>\r\n"); result = StringUtils.replace(result, "ul>
    \n", "ul>\n"); return result; } /** * Converts a String to a boolean value. * * @param value The String to convert. * @return The corresponding boolean 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; } 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 String 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(); } /** * Ensures that all whitespace is removed from a String. *

    It also works with a null argument. * * @param source The String to trim. * @return The trimmed String. * @since 1.0 */ public static String trim(String source) { if (source == null || source.length() == 0) { return source; } return source.trim(); } /** * Reformats a string where lines that are longer than width * 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. *

    * Please note that this method can be lossy - trailing spaces on wrapped * lines may be trimmed. * * @param input the String to reformat. * @param width the maximum length of any one line. * @return a new String with reformatted as needed. */ public static String wordWrap(String input, int width, Locale locale) { // handle invalid input if (input == null) { return ""; } else if (width < 5) { return input; } else if (width >= input.length()) { return input; } // default locale if (locale == null) { locale = Locale.US; } StringBuilder buffer = new StringBuilder(input.length()); 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); // get the line that corresponds to it if (-1 == delimiter_index) { line = new String(input.substring(current_index, input.length())); current_index = input.length() + 1; } else { line = new String(input.substring(current_index, delimiter_index)); current_index = delimiter_index + seperator.length(); } // handle the wrapping of the line BreakIterator breaks = BreakIterator.getLineInstance(locale); breaks.setText(line); int line_start = 0; int start = breaks.first(); int end = breaks.next(); while (end != BreakIterator.DONE) { // check if the width has been exceeded if (end - 1 - line_start >= width) { boolean break_line = true; // first check if the last characters were spaces, // if they were and by removing them the width is not // exceeded, just continue if (Character.isWhitespace(line.charAt(end - 1))) { for (int j = end - 1; j >= 0; j--) { if (!Character.isWhitespace(line.charAt(j))) { if (j - line_start < width) { break_line = false; } break; } } } if (break_line) { String line_breaked = line.substring(line_start, start); // this can happen with trailing whitespace if (line_breaked.length() > width) { line_breaked = line_breaked.substring(0, width); } buffer.append(line_breaked); buffer.append("\n"); line_start = start; } } start = end; end = breaks.next(); } if (line_start < line.length()) { buffer.append(line.substring(line_start)); } if (delimiter_index != -1) { buffer.append("\n"); } } return buffer.toString(); } }