1 package groovy.xml.streamingmarkupsupport;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 import java.io.IOException;
48 import java.io.OutputStreamWriter;
49 import java.io.Writer;
50 import java.nio.charset.Charset;
51 import java.nio.charset.CharsetEncoder;
52
53 public class StreamingMarkupWriter extends Writer {
54 protected final Writer writer;
55 protected final String encoding;
56 protected final CharsetEncoder encoder;
57 private final Writer bodyWriter = new Writer() {
58
59
60
61 public void close() throws IOException {
62 StreamingMarkupWriter.this.close();
63 }
64
65
66
67
68 public void flush() throws IOException {
69 StreamingMarkupWriter.this.flush();
70 }
71
72
73
74
75 public void write(final int c) throws IOException {
76 if (!StreamingMarkupWriter.this.encoder.canEncode((char)c)) {
77 StreamingMarkupWriter.this.writer.write("&#x");
78 StreamingMarkupWriter.this.writer.write(Integer.toHexString(c));
79 StreamingMarkupWriter.this.writer.write(';');
80 } else if (c == '<') {
81 StreamingMarkupWriter.this.writer.write("<");
82 } else if (c == '>') {
83 StreamingMarkupWriter.this.writer.write(">");
84 } else if (c == '&') {
85 StreamingMarkupWriter.this.writer.write("&");
86 } else {
87 StreamingMarkupWriter.this.writer.write(c);
88 }
89 }
90
91
92
93
94 public void write(final char[] cbuf, int off, int len) throws IOException {
95 while (len-- > 0){
96 write(cbuf[off++]);
97 }
98 }
99
100 public Writer attributeValue() {
101 return StreamingMarkupWriter.this.attributeWriter;
102 }
103
104 public Writer bodyText() {
105 return bodyWriter;
106 }
107
108 public Writer unescaped() {
109 return StreamingMarkupWriter.this;
110 }
111 };
112
113 private final Writer attributeWriter = new Writer() {
114
115
116
117 public void close() throws IOException {
118 StreamingMarkupWriter.this.close();
119 }
120
121
122
123
124 public void flush() throws IOException {
125 StreamingMarkupWriter.this.flush();
126 }
127
128
129
130
131 public void write(final int c) throws IOException {
132 if (c == '\'') {
133 StreamingMarkupWriter.this.writer.write("'");
134 } else {
135 StreamingMarkupWriter.this.bodyWriter.write(c);
136 }
137 }
138
139
140
141
142 public void write(final char[] cbuf, int off, int len) throws IOException {
143 while (len-- > 0){
144 write(cbuf[off++]);
145 }
146 }
147
148 public Writer attributeValue() {
149 return attributeWriter;
150 }
151
152 public Writer bodyText() {
153 return StreamingMarkupWriter.this.bodyWriter;
154 }
155
156 public Writer unescaped() {
157 return StreamingMarkupWriter.this;
158 }
159 };
160
161 public StreamingMarkupWriter(final Writer writer, final String encoding) {
162 this.writer = writer;
163
164 if (encoding != null) {
165 this.encoding = encoding;
166 } else if (writer instanceof OutputStreamWriter) {
167 this.encoding = ((OutputStreamWriter)writer).getEncoding();
168 } else {
169 this.encoding = "US-ASCII";
170 }
171
172 this.encoder = Charset.forName(this.encoding).newEncoder();
173 }
174
175 public StreamingMarkupWriter(final Writer writer) {
176 this(writer, null);
177 }
178
179
180
181
182 public void close() throws IOException {
183 this.writer.close();
184 }
185
186
187
188
189 public void flush() throws IOException {
190 this.writer.flush();
191 }
192
193
194
195
196 public void write(final char[] cbuf, int off, int len) throws IOException {
197 this.writer.write(cbuf, off, len);
198 }
199
200 public Writer attributeValue() {
201 return this.attributeWriter;
202 }
203
204 public Writer bodyText() {
205 return this.bodyWriter;
206 }
207
208 public Writer unescaped() {
209 return this;
210 }
211 }