1 /*
2 * Copyright (c) 2003
3 * Information Desire GmbH
4 * All rights reserved.
5 */
6 package com.infodesire.infobit.external.impl;
7
8 import org.apache.commons.logging.Log;
9 import org.apache.commons.logging.LogFactory;
10
11 import java.io.IOException;
12 import java.io.Writer;
13
14 import java.util.HashMap;
15 import java.util.Map;
16
17 /***
18 * This class resolves predifined general entity references within an assumed
19 * XML document.
20 *
21 * @author peter2
22 * @created 1. September 2003
23 * @version $Revision: 1.1 $
24 */
25 class EntityReferenceDecoder {
26
27 private final static Log _log =
28 LogFactory.getLog(EntityReferenceDecoder.class);
29
30 /***
31 * Maximum length of entities to be resolved
32 */
33 private final static int MAX_ENT_NAME = 10;
34
35 /***
36 * Scanning state: waiting for an entity reference to start
37 */
38 private final static int SS_TEXT = 0;
39
40 /***
41 * Scanning state: scanning a referenced entity name
42 */
43 private final static int SS_ENT_NAME = 1;
44
45 /***
46 * Maps (default) entities to their content
47 */
48 private final static Map DEFAULT_ENTITIES = new HashMap();
49
50 /***
51 * The destination of decoded text
52 */
53 private Writer _destination;
54
55 /***
56 * The current scanning state, either {@link #SS_TEXT or {@link
57 * #SS_ENT_NAME}
58 */
59 private int _state = SS_TEXT;
60
61 /***
62 * Buffer to collect entity references
63 */
64 private StringBuffer _nameBuffer = new StringBuffer();
65
66
67 /***
68 * Initializes an instance ready for setup. The instance is in state waiting
69 * for entity references to occure.
70 */
71 EntityReferenceDecoder() {
72 // null;
73 }
74
75
76 /***
77 * Defines the destination of decoded input. The read methods access the
78 * destination and will block if the input blocks. Single character write
79 * operations on the provided writer should not be expensive (else wrap it
80 * with a <code>BufferedWriter</code>).
81 *
82 * @param dest Where to write decoded data to
83 */
84 void setDestination(Writer dest) {
85 _destination = dest;
86 }
87
88
89 /***
90 * Adds the specified characters to the data to be decoded.
91 *
92 * @param b Contains the character chunk to be decoded
93 * @param offset Index of the first character to be decoded in
94 * <code>b</code>
95 * @param length Number of subsequent characters from <code>b</code>
96 * to be decoded
97 * @exception IOException Description of Exception
98 */
99 void decodeChunk(char[] b, int offset, int length)
100 throws IOException {
101
102 for (int i = offset; i < offset + length; ++i) {
103 char c = b[i];
104
105 switch (_state) {
106 case SS_TEXT:
107 // In unescaped text
108 switch (c) {
109 case '&':
110 _state = SS_ENT_NAME;
111 break;
112 default:
113 _destination.write(c);
114 }
115 break;
116 case SS_ENT_NAME:
117 // In entity name
118 switch (c) {
119 case ';':
120 String name = _nameBuffer.toString();
121 String value = (String) DEFAULT_ENTITIES.get(name);
122 if (value != null) {
123 _destination.write(value);
124 }
125 else {
126 _destination.write('&');
127 _destination.write(name);
128 _destination.write(';');
129 }
130 _nameBuffer.delete(0, _nameBuffer.length());
131 _state = SS_TEXT;
132 break;
133 default:
134 // NOTE: no check for proper entity name
135 // syntax
136 if (_nameBuffer.length() == MAX_ENT_NAME) {
137 _destination.write('&');
138 _destination.write(_nameBuffer.toString());
139 _state = SS_TEXT;
140 }
141 else {
142 _nameBuffer.append(c);
143 }
144 }
145 default:
146 String m = "failed assertion: _state: " + _state;
147 _log.error(m);
148 throw new RuntimeException(m);
149 }
150 }
151
152 }
153
154
155 /***
156 * Signals end-of-text of the input source.
157 *
158 * @exception IOException Description of Exception
159 */
160 void endOfText() throws IOException {
161 switch (_state) {
162 case SS_TEXT:
163 break;
164 case SS_ENT_NAME:
165 _destination.write("&");
166 _destination.write(_nameBuffer.toString());
167 break;
168 }
169
170 _destination.flush();
171 }
172
173 static {
174 Map m = DEFAULT_ENTITIES;
175 m.put("lt", "<");
176 m.put("gl", ">");
177 m.put("amp", "&");
178 m.put("quot", "\"");
179 m.put("apos", "'");
180 }
181
182 }
This page was automatically generated by Maven