KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > web > util > HtmlCharacterEntityDecoder


1 /*
2  * Copyright 2002-2005 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.web.util;
18
19 /**
20  * Helper for decoding HTML Strings by replacing character
21  * entity references with the referred character.
22  *
23  * @author Juergen Hoeller
24  * @author Martin Kersten
25  * @since 1.2.1
26  */

27 class HtmlCharacterEntityDecoder {
28
29     private static final int MAX_REFERENCE_SIZE = 10;
30
31
32     private final HtmlCharacterEntityReferences characterEntityReferences;
33
34     private final String JavaDoc originalMessage;
35
36     private final StringBuffer JavaDoc decodedMessage;
37
38     private int currentPosition = 0;
39
40     private int nextPotentialReferencePosition = -1;
41
42     private int nextSemicolonPosition = -2;
43
44
45     public HtmlCharacterEntityDecoder(HtmlCharacterEntityReferences characterEntityReferences, String JavaDoc original) {
46         this.characterEntityReferences = characterEntityReferences;
47         this.originalMessage = original;
48         this.decodedMessage = new StringBuffer JavaDoc(originalMessage.length());
49     }
50
51     public String JavaDoc decode() {
52         while (currentPosition < originalMessage.length()) {
53             findNextPotentialReference(currentPosition);
54             copyCharactersTillPotentialReference();
55             processPossibleReference();
56         }
57         return decodedMessage.toString();
58     }
59
60     private void findNextPotentialReference(int startPosition) {
61         nextPotentialReferencePosition = Math.max(startPosition, nextSemicolonPosition - MAX_REFERENCE_SIZE);
62
63         do {
64             nextPotentialReferencePosition =
65                     originalMessage.indexOf('&', nextPotentialReferencePosition);
66
67             if (nextSemicolonPosition != -1 &&
68                     nextSemicolonPosition < nextPotentialReferencePosition)
69                 nextSemicolonPosition = originalMessage.indexOf(';', nextPotentialReferencePosition + 1);
70
71             boolean isPotentialReference =
72                     nextPotentialReferencePosition != -1
73                     && nextSemicolonPosition != -1
74                     && nextPotentialReferencePosition - nextSemicolonPosition < MAX_REFERENCE_SIZE;
75
76             if (isPotentialReference) {
77                 break;
78             }
79             if (nextPotentialReferencePosition == -1) {
80                 break;
81             }
82             if (nextSemicolonPosition == -1) {
83                 nextPotentialReferencePosition = -1;
84                 break;
85             }
86
87             nextPotentialReferencePosition = nextPotentialReferencePosition + 1;
88         }
89         while (nextPotentialReferencePosition != -1);
90     }
91
92
93     private void copyCharactersTillPotentialReference() {
94         if (nextPotentialReferencePosition != currentPosition) {
95             int skipUntilIndex = nextPotentialReferencePosition != -1 ?
96                     nextPotentialReferencePosition : originalMessage.length();
97             if (skipUntilIndex - currentPosition > 3) {
98                 decodedMessage.append(originalMessage.substring(currentPosition, skipUntilIndex));
99                 currentPosition = skipUntilIndex;
100             }
101             else {
102                 while (currentPosition < skipUntilIndex)
103                     decodedMessage.append(originalMessage.charAt(currentPosition++));
104             }
105         }
106     }
107
108     private void processPossibleReference() {
109         if (nextPotentialReferencePosition != -1) {
110             boolean isNumberedReference = originalMessage.charAt(currentPosition + 1) == '#';
111             boolean wasProcessable = isNumberedReference ? processNumberedReference() : processNamedReference();
112             if (wasProcessable) {
113                 currentPosition = nextSemicolonPosition + 1;
114             }
115             else {
116                 char currentChar = originalMessage.charAt(currentPosition);
117                 decodedMessage.append(currentChar);
118                 currentPosition++;
119             }
120         }
121     }
122
123     private boolean processNumberedReference() {
124         boolean isHexNumberedReference =
125                 originalMessage.charAt(nextPotentialReferencePosition + 2) == 'x' ||
126                 originalMessage.charAt(nextPotentialReferencePosition + 2) == 'X';
127         try {
128             int value = (!isHexNumberedReference) ?
129                     Integer.parseInt(getReferenceSubstring(2)) :
130                     Integer.parseInt(getReferenceSubstring(3), 16);
131             decodedMessage.append((char) value);
132             return true;
133         }
134         catch (NumberFormatException JavaDoc ex) {
135             return false;
136         }
137     }
138
139     private boolean processNamedReference() {
140         String JavaDoc referenceName = getReferenceSubstring(1);
141         char mappedCharacter = characterEntityReferences.convertToCharacter(referenceName);
142         if (mappedCharacter != HtmlCharacterEntityReferences.CHAR_NULL) {
143             decodedMessage.append(mappedCharacter);
144             return true;
145         }
146         return false;
147     }
148
149     private String JavaDoc getReferenceSubstring(int referenceOffset) {
150         return originalMessage.substring(nextPotentialReferencePosition + referenceOffset, nextSemicolonPosition);
151     }
152
153 }
154
Popular Tags