1 10 11 package org.mule.util; 12 13 import java.io.IOException ; 14 import java.io.Writer ; 15 import java.util.HashMap ; 16 import java.util.Map ; 17 18 import org.apache.commons.lang.StringEscapeUtils; 19 20 26 public class XMLEntityCodec 28 { 29 private static final Entities MuleEntities = new Entities(); 30 31 static 32 { 33 MuleEntities.addEntities(Entities.APOS_ARRAY); 34 MuleEntities.addEntities(Entities.BASIC_ARRAY); 35 MuleEntities.addEntities(Entities.ISO8859_1_ARRAY); 36 MuleEntities.addEntities(Entities.HTML40_ARRAY); 37 } 38 39 public static String encodeString(String str) 40 { 41 if (StringUtils.isEmpty(str)) 42 { 43 return str; 44 } 45 46 return MuleEntities.escape(str); 47 } 48 49 public static String decodeString(String str) 50 { 51 if (StringUtils.isEmpty(str)) 52 { 53 return str; 54 } 55 56 return MuleEntities.unescape(str); 57 } 58 59 67 public static String entityName(int value) 68 { 69 return MuleEntities.map.name(value); 70 } 71 72 80 public static int entityValue(String name) 81 { 82 return MuleEntities.map.value(name); 83 } 84 85 86 92 108 109 123 private static class Entities 124 { 125 126 private static final String [][] BASIC_ARRAY = 127 { 128 {"quot", "34"}, {"amp", "38"}, {"lt", "60"}, {"gt", "62"}, }; 133 134 private static final String [][] APOS_ARRAY = 135 { 136 {"apos", "39"}, }; 138 139 static final String [][] ISO8859_1_ARRAY = 141 { 142 {"nbsp", "160"}, {"iexcl", "161"}, {"cent", "162"}, {"pound", "163"}, {"curren", "164"}, {"yen", "165"}, {"brvbar", "166"}, {"sect", "167"}, {"uml", "168"}, {"copy", "169"}, {"ordf", "170"}, {"laquo", "171"}, {"not", "172"}, {"shy", "173"}, {"reg", "174"}, {"macr", "175"}, {"deg", "176"}, {"plusmn", "177"}, {"sup2", "178"}, {"sup3", "179"}, {"acute", "180"}, {"micro", "181"}, {"para", "182"}, {"middot", "183"}, {"cedil", "184"}, {"sup1", "185"}, {"ordm", "186"}, {"raquo", "187"}, {"frac14", "188"}, {"frac12", "189"}, {"frac34", "190"}, {"iquest", "191"}, {"Agrave", "192"}, {"Aacute", "193"}, {"Acirc", "194"}, {"Atilde", "195"}, {"Auml", "196"}, {"Aring", "197"}, {"AElig", "198"}, {"Ccedil", "199"}, {"Egrave", "200"}, {"Eacute", "201"}, {"Ecirc", "202"}, {"Euml", "203"}, {"Igrave", "204"}, {"Iacute", "205"}, {"Icirc", "206"}, {"Iuml", "207"}, {"ETH", "208"}, {"Ntilde", "209"}, {"Ograve", "210"}, {"Oacute", "211"}, {"Ocirc", "212"}, {"Otilde", "213"}, {"Ouml", "214"}, {"times", "215"}, {"Oslash", "216"}, {"Ugrave", "217"}, {"Uacute", "218"}, {"Ucirc", "219"}, {"Uuml", "220"}, {"Yacute", "221"}, {"THORN", "222"}, {"szlig", "223"}, {"agrave", "224"}, {"aacute", "225"}, {"acirc", "226"}, {"atilde", "227"}, {"auml", "228"}, {"aring", "229"}, {"aelig", "230"}, {"ccedil", "231"}, {"egrave", "232"}, {"eacute", "233"}, {"ecirc", "234"}, {"euml", "235"}, {"igrave", "236"}, {"iacute", "237"}, {"icirc", "238"}, {"iuml", "239"}, {"eth", "240"}, {"ntilde", "241"}, {"ograve", "242"}, {"oacute", "243"}, {"ocirc", "244"}, {"otilde", "245"}, {"ouml", "246"}, {"divide", "247"}, {"oslash", "248"}, {"ugrave", "249"}, {"uacute", "250"}, {"ucirc", "251"}, {"uuml", "252"}, {"yacute", "253"}, {"thorn", "254"}, {"yuml", "255"}, }; 239 240 static final String [][] HTML40_ARRAY = 243 { 244 {"fnof", "402"}, {"Alpha", "913"}, {"Beta", "914"}, {"Gamma", "915"}, {"Delta", "916"}, {"Epsilon", "917"}, {"Zeta", "918"}, {"Eta", "919"}, {"Theta", "920"}, {"Iota", "921"}, {"Kappa", "922"}, {"Lambda", "923"}, {"Mu", "924"}, {"Nu", "925"}, {"Xi", "926"}, {"Omicron", "927"}, {"Pi", "928"}, {"Rho", "929"}, {"Sigma", "931"}, {"Tau", "932"}, {"Upsilon", "933"}, {"Phi", "934"}, {"Chi", "935"}, {"Psi", "936"}, {"Omega", "937"}, {"alpha", "945"}, {"beta", "946"}, {"gamma", "947"}, {"delta", "948"}, {"epsilon", "949"}, {"zeta", "950"}, {"eta", "951"}, {"theta", "952"}, {"iota", "953"}, {"kappa", "954"}, {"lambda", "955"}, {"mu", "956"}, {"nu", "957"}, {"xi", "958"}, {"omicron", "959"}, {"pi", "960"}, {"rho", "961"}, {"sigmaf", "962"}, {"sigma", "963"}, {"tau", "964"}, {"upsilon", "965"}, {"phi", "966"}, {"chi", "967"}, {"psi", "968"}, {"omega", "969"}, {"thetasym", "977"}, {"upsih", "978"}, {"piv", "982"}, {"bull", "8226"}, {"hellip", "8230"}, {"prime", "8242"}, {"Prime", "8243"}, {"oline", "8254"}, {"frasl", "8260"}, {"weierp", "8472"}, {"image", "8465"}, {"real", "8476"}, {"trade", "8482"}, {"alefsym", "8501"}, {"larr", "8592"}, {"uarr", "8593"}, {"rarr", "8594"}, {"darr", "8595"}, {"harr", "8596"}, {"crarr", "8629"}, {"lArr", "8656"}, {"uArr", "8657"}, {"rArr", "8658"}, {"dArr", "8659"}, {"hArr", "8660"}, {"forall", "8704"}, {"part", "8706"}, {"exist", "8707"}, {"empty", "8709"}, {"nabla", "8711"}, {"isin", "8712"}, {"notin", "8713"}, {"ni", "8715"}, {"prod", "8719"}, {"sum", "8721"}, {"minus", "8722"}, {"lowast", "8727"}, {"radic", "8730"}, {"prop", "8733"}, {"infin", "8734"}, {"ang", "8736"}, {"and", "8743"}, {"or", "8744"}, {"cap", "8745"}, {"cup", "8746"}, {"int", "8747"}, {"there4", "8756"}, {"sim", "8764"}, {"cong", "8773"}, {"asymp", "8776"}, {"ne", "8800"}, {"equiv", "8801"}, {"le", "8804"}, {"ge", "8805"}, {"sub", "8834"}, {"sup", "8835"}, {"sube", "8838"}, {"supe", "8839"}, {"oplus", "8853"}, {"otimes", "8855"}, {"perp", "8869"}, {"sdot", "8901"}, {"lceil", "8968"}, {"rceil", "8969"}, {"lfloor", "8970"}, {"rfloor", "8971"}, {"lang", "9001"}, {"rang", "9002"}, {"loz", "9674"}, {"spades", "9824"}, {"clubs", "9827"}, {"hearts", "9829"}, {"diams", "9830"}, 403 {"OElig", "338"}, {"oelig", "339"}, {"Scaron", "352"}, {"scaron", "353"}, {"Yuml", "376"}, {"circ", "710"}, {"tilde", "732"}, {"ensp", "8194"}, {"emsp", "8195"}, {"thinsp", "8201"}, {"zwnj", "8204"}, {"zwj", "8205"}, {"lrm", "8206"}, {"rlm", "8207"}, {"ndash", "8211"}, {"mdash", "8212"}, {"lsquo", "8216"}, {"rsquo", "8217"}, {"sbquo", "8218"}, {"ldquo", "8220"}, {"rdquo", "8221"}, {"bdquo", "8222"}, {"dagger", "8224"}, {"Dagger", "8225"}, {"permil", "8240"}, {"lsaquo", "8249"}, {"rsaquo", "8250"}, {"euro", "8364"}, }; 438 439 private EntityMap map = new Entities.LookupEntityMap(); 441 442 449 public void addEntities(String [][] entityArray) 450 { 451 for (int i = 0; i < entityArray.length; ++i) 452 { 453 addEntity(entityArray[i][0], Integer.parseInt(entityArray[i][1])); 454 } 455 } 456 457 465 public void addEntity(String name, int value) 466 { 467 map.add(name, value); 468 } 469 470 478 public String entityName(int value) 479 { 480 return map.name(value); 481 } 482 483 491 public int entityValue(String name) 492 { 493 return map.value(name); 494 } 495 496 508 public String escape(String str) 509 { 510 StringBuffer buf = new StringBuffer (str.length() * 2); 512 for (int i = 0; i < str.length(); ++i) 513 { 514 char ch = str.charAt(i); 515 String entityName = this.entityName(ch); 516 if (entityName == null) 517 { 518 if (ch > 0x7F) 519 { 520 buf.append('&'); 521 buf.append('#'); 522 buf.append((int)ch); 523 buf.append(';'); 524 } 525 else 526 { 527 buf.append(ch); 528 } 529 } 530 else 531 { 532 buf.append('&'); 533 buf.append(entityName); 534 buf.append(';'); 535 } 536 } 537 return buf.toString(); 538 } 539 540 555 public void escape(Writer writer, String str) throws IOException 556 { 557 int len = str.length(); 558 for (int i = 0; i < len; i++) 559 { 560 char c = str.charAt(i); 561 String entityName = this.entityName(c); 562 if (entityName == null) 563 { 564 if (c > 0x7F) 565 { 566 writer.write("&#"); 567 writer.write(Integer.toString(c, 10)); 568 writer.write(';'); 569 } 570 else 571 { 572 writer.write(c); 573 } 574 } 575 else 576 { 577 writer.write('&'); 578 writer.write(entityName); 579 writer.write(';'); 580 } 581 } 582 } 583 584 597 public String unescape(String str) 598 { 599 int firstAmp = str.indexOf('&'); 600 if (firstAmp < 0) 601 { 602 return str; 603 } 604 605 StringBuffer buf = new StringBuffer (str.length()); 606 buf.append(str.substring(0, firstAmp)); 607 for (int i = firstAmp; i < str.length(); ++i) 608 { 609 char ch = str.charAt(i); 610 if (ch == '&') 611 { 612 int semi = str.indexOf(';', i + 1); 613 if (semi == -1) 614 { 615 buf.append(ch); 616 continue; 617 } 618 int amph = str.indexOf('&', i + 1); 619 if (amph != -1 && amph < semi) 620 { 621 buf.append(ch); 623 continue; 624 } 625 String entityName = str.substring(i + 1, semi); 626 int entityValue; 627 if (entityName.length() == 0) 628 { 629 entityValue = -1; 630 } 631 else if (entityName.charAt(0) == '#') 632 { 633 if (entityName.length() == 1) 634 { 635 entityValue = -1; 636 } 637 else 638 { 639 char charAt1 = entityName.charAt(1); 640 try 641 { 642 if (charAt1 == 'x' || charAt1 == 'X') 643 { 644 entityValue = Integer.valueOf(entityName.substring(2), 16).intValue(); 645 } 646 else 647 { 648 entityValue = Integer.parseInt(entityName.substring(1)); 649 } 650 if (entityValue > 0xFFFF) 651 { 652 entityValue = -1; 653 } 654 } 655 catch (NumberFormatException ex) 656 { 657 entityValue = -1; 658 } 659 } 660 } 661 else 662 { 663 entityValue = this.entityValue(entityName); 664 } 665 if (entityValue == -1) 666 { 667 buf.append('&'); 668 buf.append(entityName); 669 buf.append(';'); 670 } 671 else 672 { 673 buf.append((char)(entityValue)); 674 } 675 i = semi; 676 } 677 else 678 { 679 buf.append(ch); 680 } 681 } 682 return buf.toString(); 683 } 684 685 700 public void unescape(Writer writer, String string) throws IOException 701 { 702 int firstAmp = string.indexOf('&'); 703 if (firstAmp < 0) 704 { 705 writer.write(string); 706 return; 707 } 708 709 writer.write(string, 0, firstAmp); 710 int len = string.length(); 711 for (int i = firstAmp; i < len; i++) 712 { 713 char c = string.charAt(i); 714 if (c == '&') 715 { 716 int nextIdx = i + 1; 717 int semiColonIdx = string.indexOf(';', nextIdx); 718 if (semiColonIdx == -1) 719 { 720 writer.write(c); 721 continue; 722 } 723 int amphersandIdx = string.indexOf('&', i + 1); 724 if (amphersandIdx != -1 && amphersandIdx < semiColonIdx) 725 { 726 writer.write(c); 728 continue; 729 } 730 String entityContent = string.substring(nextIdx, semiColonIdx); 731 int entityValue = -1; 732 int entityContentLen = entityContent.length(); 733 if (entityContentLen > 0) 734 { 735 if (entityContent.charAt(0) == '#') 736 { if (entityContentLen > 1) 739 { 740 char isHexChar = entityContent.charAt(1); 741 try 742 { 743 switch (isHexChar) 744 { 745 case 'X' : 746 case 'x' : 747 { 748 entityValue = Integer.parseInt(entityContent.substring(2), 16); 749 break; 750 } 751 default : 752 { 753 entityValue = Integer.parseInt(entityContent.substring(1), 10); 754 } 755 } 756 if (entityValue > 0xFFFF) 757 { 758 entityValue = -1; 759 } 760 } 761 catch (NumberFormatException e) 762 { 763 entityValue = -1; 764 } 765 } 766 } 767 else 768 { entityValue = this.entityValue(entityContent); 770 } 771 } 772 773 if (entityValue == -1) 774 { 775 writer.write('&'); 776 writer.write(entityContent); 777 writer.write(';'); 778 } 779 else 780 { 781 writer.write(entityValue); 782 } 783 i = semiColonIdx; } 785 else 786 { 787 writer.write(c); 788 } 789 } 790 } 791 792 private static interface EntityMap 793 { 794 802 void add(String name, int value); 803 804 812 String name(int value); 813 814 822 int value(String name); 823 } 824 825 private static class PrimitiveEntityMap implements EntityMap 826 { 827 private Map mapNameToValue = new HashMap (); 828 private IntHashMap mapValueToName = new IntHashMap(); 829 830 833 public void add(String name, int value) 834 { 835 mapNameToValue.put(name, new Integer (value)); 836 mapValueToName.put(value, name); 837 } 838 839 842 public String name(int value) 843 { 844 return (String )mapValueToName.get(value); 845 } 846 847 850 public int value(String name) 851 { 852 Object value = mapNameToValue.get(name); 853 if (value == null) 854 { 855 return -1; 856 } 857 return ((Integer )value).intValue(); 858 } 859 } 860 861 private static class LookupEntityMap extends PrimitiveEntityMap 862 { 863 private String [] lookupTable; 864 private int LOOKUP_TABLE_SIZE = 256; 865 866 869 public String name(int value) 870 { 871 if (value < LOOKUP_TABLE_SIZE) 872 { 873 return lookupTable()[value]; 874 } 875 return super.name(value); 876 } 877 878 886 private String [] lookupTable() 887 { 888 if (lookupTable == null) 889 { 890 createLookupTable(); 891 } 892 return lookupTable; 893 } 894 895 901 private void createLookupTable() 902 { 903 lookupTable = new String [LOOKUP_TABLE_SIZE]; 904 for (int i = 0; i < LOOKUP_TABLE_SIZE; ++i) 905 { 906 lookupTable[i] = super.name(i); 907 } 908 } 909 } 910 911 929 private static class IntHashMap 930 { 931 932 935 private transient Entry table[]; 936 937 940 private transient int count; 941 942 948 private int threshold; 949 950 955 private float loadFactor; 956 957 963 private static class Entry 964 { 965 int hash; 966 int key; 967 Object value; 968 Entry next; 969 970 980 protected Entry(int hash, int key, Object value, Entry next) 981 { 982 this.hash = hash; 983 this.key = key; 984 this.value = value; 985 this.next = next; 986 } 987 } 988 989 996 public IntHashMap() 997 { 998 this(20, 0.75f); 999 } 1000 1001 1011 public IntHashMap(int initialCapacity) 1012 { 1013 this(initialCapacity, 0.75f); 1014 } 1015 1016 1027 public IntHashMap(int initialCapacity, float loadFactor) 1028 { 1029 super(); 1030 if (initialCapacity < 0) 1031 { 1032 throw new IllegalArgumentException ("Illegal Capacity: " + initialCapacity); 1033 } 1034 if (loadFactor <= 0) 1035 { 1036 throw new IllegalArgumentException ("Illegal Load: " + loadFactor); 1037 } 1038 if (initialCapacity == 0) 1039 { 1040 initialCapacity = 1; 1041 } 1042 1043 this.loadFactor = loadFactor; 1044 table = new Entry[initialCapacity]; 1045 threshold = (int)(initialCapacity * loadFactor); 1046 } 1047 1048 1055 public int size() 1056 { 1057 return count; 1058 } 1059 1060 1068 public boolean isEmpty() 1069 { 1070 return count == 0; 1071 } 1072 1073 1094 public boolean contains(Object value) 1095 { 1096 if (value == null) 1097 { 1098 throw new NullPointerException (); 1099 } 1100 1101 Entry tab[] = table; 1102 for (int i = tab.length; i-- > 0;) 1103 { 1104 for (Entry e = tab[i]; e != null; e = e.next) 1105 { 1106 if (e.value.equals(value)) 1107 { 1108 return true; 1109 } 1110 } 1111 } 1112 return false; 1113 } 1114 1115 1130 public boolean containsValue(Object value) 1131 { 1132 return contains(value); 1133 } 1134 1135 1146 public boolean containsKey(int key) 1147 { 1148 Entry tab[] = table; 1149 int hash = key; 1150 int index = (hash & 0x7FFFFFFF) % tab.length; 1151 for (Entry e = tab[index]; e != null; e = e.next) 1152 { 1153 if (e.hash == hash) 1154 { 1155 return true; 1156 } 1157 } 1158 return false; 1159 } 1160 1161 1172 public Object get(int key) 1173 { 1174 Entry tab[] = table; 1175 int hash = key; 1176 int index = (hash & 0x7FFFFFFF) % tab.length; 1177 for (Entry e = tab[index]; e != null; e = e.next) 1178 { 1179 if (e.hash == hash) 1180 { 1181 return e.value; 1182 } 1183 } 1184 return null; 1185 } 1186 1187 1197 protected void rehash() 1198 { 1199 int oldCapacity = table.length; 1200 Entry oldMap[] = table; 1201 1202 int newCapacity = oldCapacity * 2 + 1; 1203 Entry newMap[] = new Entry[newCapacity]; 1204 1205 threshold = (int)(newCapacity * loadFactor); 1206 table = newMap; 1207 1208 for (int i = oldCapacity; i-- > 0;) 1209 { 1210 for (Entry old = oldMap[i]; old != null;) 1211 { 1212 Entry e = old; 1213 old = old.next; 1214 1215 int index = (e.hash & 0x7FFFFFFF) % newCapacity; 1216 e.next = newMap[index]; 1217 newMap[index] = e; 1218 } 1219 } 1220 } 1221 1222 1240 public Object put(int key, Object value) 1241 { 1242 Entry tab[] = table; 1244 int hash = key; 1245 int index = (hash & 0x7FFFFFFF) % tab.length; 1246 for (Entry e = tab[index]; e != null; e = e.next) 1247 { 1248 if (e.hash == hash) 1249 { 1250 Object old = e.value; 1251 e.value = value; 1252 return old; 1253 } 1254 } 1255 1256 if (count >= threshold) 1257 { 1258 rehash(); 1260 1261 tab = table; 1262 index = (hash & 0x7FFFFFFF) % tab.length; 1263 } 1264 1265 Entry e = new Entry(hash, key, value, tab[index]); 1267 tab[index] = e; 1268 count++; 1269 return null; 1270 } 1271 1272 1284 public Object remove(int key) 1285 { 1286 Entry tab[] = table; 1287 int hash = key; 1288 int index = (hash & 0x7FFFFFFF) % tab.length; 1289 for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next) 1290 { 1291 if (e.hash == hash) 1292 { 1293 if (prev != null) 1294 { 1295 prev.next = e.next; 1296 } 1297 else 1298 { 1299 tab[index] = e.next; 1300 } 1301 count--; 1302 Object oldValue = e.value; 1303 e.value = null; 1304 return oldValue; 1305 } 1306 } 1307 return null; 1308 } 1309 1310 1313 public synchronized void clear() 1314 { 1315 Entry tab[] = table; 1316 for (int index = tab.length; --index >= 0;) 1317 { 1318 tab[index] = null; 1319 } 1320 count = 0; 1321 } 1322 1323 } 1324 1325 } 1326} 1327 | Popular Tags |