New file |
| | |
| | | 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<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 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<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()); |
| | | } |
| | | |
| | | 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 <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(); |
| | | } |
| | | |
| | | /** |
| | | * 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(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | * @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 == 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 <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 (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 <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 (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 <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 (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 <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 (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 <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 (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 <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 (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 <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 (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 <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; |
| | | } |
| | | |
| | | 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 <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]; |
| | | } |
| | | |
| | | 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 <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; |
| | | } |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | /** |
| | | * 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}; |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | 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 <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; |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | 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("<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; |
| | | } |
| | | |
| | | 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("</a>"); |
| | | |
| | | 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]", "<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 [*] |
| | | |
| | | 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("<li>") |
| | | .append(resultCopy.substring(startIndex + 3, endIndex)) // 3 == sizeof [*] |
| | | .append("</li>"); |
| | | |
| | | resultCopy = resultCopy.substring(endIndex); |
| | | resultLowerCopy = resultLowerCopy.substring(endIndex); |
| | | } |
| | | buffer.append(resultCopy.substring(0)); |
| | | |
| | | result = buffer.toString(); |
| | | |
| | | 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 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); |
| | | |
| | | 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 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"); |
| | | |
| | | // 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; |
| | | } |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | 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)); |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | 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> |
| | | * 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(); |
| | | } |
| | | } |