1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.web.util;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.util.Enumeration;
22 import java.util.HashMap;
23 import java.util.Map;
24 import java.util.Properties;
25
26 import org.springframework.util.Assert;
27
28
29
30
31
32
33
34
35
36
37
38
39
40 class HtmlCharacterEntityReferences {
41
42 private static final String PROPERTIES_FILE = "HtmlCharacterEntityReferences.properties";
43
44 static final char REFERENCE_START = '&';
45
46 static final String DECIMAL_REFERENCE_START = "&#";
47
48 static final String HEX_REFERENCE_START = "&#x";
49
50 static final char REFERENCE_END = ';';
51
52 static final char CHAR_NULL = (char) -1;
53
54
55 private final String[] characterToEntityReferenceMap = new String[3000];
56
57 private final Map<String, Character> entityReferenceToCharacterMap = new HashMap<String, Character>(252);
58
59
60
61
62
63 public HtmlCharacterEntityReferences() {
64 Properties entityReferences = new Properties();
65
66
67 InputStream is = HtmlCharacterEntityReferences.class.getResourceAsStream(PROPERTIES_FILE);
68 if (is == null) {
69 throw new IllegalStateException(
70 "Cannot find reference definition file [HtmlCharacterEntityReferences.properties] as class path resource");
71 }
72 try {
73 try {
74 entityReferences.load(is);
75 }
76 finally {
77 is.close();
78 }
79 }
80 catch (IOException ex) {
81 throw new IllegalStateException(
82 "Failed to parse reference definition file [HtmlCharacterEntityReferences.properties]: " + ex.getMessage());
83 }
84
85
86 Enumeration<?> keys = entityReferences.propertyNames();
87 while (keys.hasMoreElements()) {
88 String key = (String) keys.nextElement();
89 int referredChar = Integer.parseInt(key);
90 Assert.isTrue((referredChar < 1000 || (referredChar >= 8000 && referredChar < 10000)),
91 "Invalid reference to special HTML entity: " + referredChar);
92 int index = (referredChar < 1000 ? referredChar : referredChar - 7000);
93 String reference = entityReferences.getProperty(key);
94 this.characterToEntityReferenceMap[index] = REFERENCE_START + reference + REFERENCE_END;
95 this.entityReferenceToCharacterMap.put(reference, (char) referredChar);
96 }
97 }
98
99
100
101
102
103 public int getSupportedReferenceCount() {
104 return this.entityReferenceToCharacterMap.size();
105 }
106
107
108
109
110 public boolean isMappedToReference(char character) {
111 return isMappedToReference(character, WebUtils.DEFAULT_CHARACTER_ENCODING);
112 }
113
114
115
116
117 public boolean isMappedToReference(char character, String encoding) {
118 return (convertToReference(character, encoding) != null);
119 }
120
121
122
123
124 public String convertToReference(char character) {
125 return convertToReference(character, WebUtils.DEFAULT_CHARACTER_ENCODING);
126 }
127
128
129
130
131
132 public String convertToReference(char character, String encoding) {
133 if (encoding.startsWith("UTF-")){
134 switch (character){
135 case '<':
136 return "<";
137 case '>':
138 return ">";
139 case '"':
140 return """;
141 case '&':
142 return "&";
143 case '\'':
144 return "'";
145 }
146 }
147 else if (character < 1000 || (character >= 8000 && character < 10000)) {
148 int index = (character < 1000 ? character : character - 7000);
149 String entityReference = this.characterToEntityReferenceMap[index];
150 if (entityReference != null) {
151 return entityReference;
152 }
153 }
154 return null;
155 }
156
157
158
159
160 public char convertToCharacter(String entityReference) {
161 Character referredCharacter = this.entityReferenceToCharacterMap.get(entityReference);
162 if (referredCharacter != null) {
163 return referredCharacter;
164 }
165 return CHAR_NULL;
166 }
167
168 }