001: /*
002: * Copyright 2002-2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.web.util;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.util.Enumeration;
022: import java.util.HashMap;
023: import java.util.Map;
024: import java.util.Properties;
025:
026: import org.springframework.util.Assert;
027:
028: /**
029: * Represents a set of character entity references defined by the
030: * HTML 4.0 standard.
031: *
032: * <p>A complete description of the HTML 4.0 character set can be found
033: * at http://www.w3.org/TR/html4/charset.html.
034: *
035: * @author Juergen Hoeller
036: * @author Martin Kersten
037: * @since 1.2.1
038: */
039: class HtmlCharacterEntityReferences {
040:
041: static final char REFERENCE_START = '&';
042:
043: static final String DECIMAL_REFERENCE_START = "&#";
044:
045: static final String HEX_REFERENCE_START = "&#x";
046:
047: static final char REFERENCE_END = ';';
048:
049: static final char CHAR_NULL = (char) -1;
050:
051: private static final String PROPERTIES_FILE = "HtmlCharacterEntityReferences.properties";
052:
053: private final String[] characterToEntityReferenceMap = new String[3000];
054:
055: private final Map entityReferenceToCharacterMap = new HashMap(252);
056:
057: /**
058: * Returns a new set of character entity references reflecting the HTML 4.0 character set.
059: */
060: public HtmlCharacterEntityReferences() {
061: Properties entityReferences = new Properties();
062:
063: // Load refeence definition file.
064: InputStream is = HtmlCharacterEntityReferences.class
065: .getResourceAsStream(PROPERTIES_FILE);
066: if (is == null) {
067: throw new IllegalStateException(
068: "Cannot find reference definition file [HtmlCharacterEntityReferences.properties] as class path resource");
069: }
070: try {
071: try {
072: entityReferences.load(is);
073: } finally {
074: is.close();
075: }
076: } catch (IOException ex) {
077: throw new IllegalStateException(
078: "Failed to parse reference definition file [HtmlCharacterEntityReferences.properties]: "
079: + ex.getMessage());
080: }
081:
082: // Parse reference definition properites.
083: Enumeration keys = entityReferences.propertyNames();
084: while (keys.hasMoreElements()) {
085: String key = (String) keys.nextElement();
086: int referredChar = Integer.parseInt(key);
087: Assert
088: .isTrue(
089: (referredChar < 1000 || (referredChar >= 8000 && referredChar < 10000)),
090: "Invalid reference to special HTML entity: "
091: + referredChar);
092: int index = (referredChar < 1000 ? referredChar
093: : referredChar - 7000);
094: String reference = entityReferences.getProperty(key);
095: this .characterToEntityReferenceMap[index] = REFERENCE_START
096: + reference + REFERENCE_END;
097: this .entityReferenceToCharacterMap.put(reference,
098: new Character((char) referredChar));
099: }
100: }
101:
102: /**
103: * Return the number of supported entity references.
104: */
105: public int getSupportedReferenceCount() {
106: return this .entityReferenceToCharacterMap.size();
107: }
108:
109: /**
110: * Return true if the given character is mapped to a supported entity reference.
111: */
112: public boolean isMappedToReference(char character) {
113: return (convertToReference(character) != null);
114: }
115:
116: /**
117: * Return the reference mapped to the given character or <code>null</code>.
118: */
119: public String convertToReference(char character) {
120: if (character < 1000
121: || (character >= 8000 && character < 10000)) {
122: int index = (character < 1000 ? character
123: : character - 7000);
124: String entityReference = this .characterToEntityReferenceMap[index];
125: if (entityReference != null) {
126: return entityReference;
127: }
128: }
129: return null;
130: }
131:
132: /**
133: * Return the char mapped to the given entityReference or -1.
134: */
135: public char convertToCharacter(String entityReference) {
136: Character referredCharacter = (Character) this.entityReferenceToCharacterMap
137: .get(entityReference);
138: if (referredCharacter != null) {
139: return referredCharacter.charValue();
140: }
141: return CHAR_NULL;
142: }
143:
144: }
|