1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server;
15
16 import java.io.IOException;
17 import java.io.OutputStreamWriter;
18 import java.io.Writer;
19
20 import org.eclipse.jetty.http.AbstractGenerator;
21 import org.eclipse.jetty.util.ByteArrayOutputStream2;
22 import org.eclipse.jetty.util.StringUtil;
23
24
25
26
27
28
29
30
31
32 public class HttpWriter extends Writer
33 {
34 public static final int MAX_OUTPUT_CHARS = 512;
35
36 private static final int WRITE_CONV = 0;
37 private static final int WRITE_ISO1 = 1;
38 private static final int WRITE_UTF8 = 2;
39
40 final HttpOutput _out;
41 final AbstractGenerator _generator;
42 int _writeMode;
43 int _surrogate;
44
45
46 public HttpWriter(HttpOutput out)
47 {
48 _out=out;
49 _generator=_out._generator;
50 _surrogate=0;
51 }
52
53
54 public void setCharacterEncoding(String encoding)
55 {
56 if (encoding == null || StringUtil.__ISO_8859_1.equalsIgnoreCase(encoding))
57 {
58 _writeMode = WRITE_ISO1;
59 }
60 else if (StringUtil.__UTF8.equalsIgnoreCase(encoding))
61 {
62 _writeMode = WRITE_UTF8;
63 }
64 else
65 {
66 _writeMode = WRITE_CONV;
67 if (_out._characterEncoding == null || !_out._characterEncoding.equalsIgnoreCase(encoding))
68 _out._converter = null;
69 }
70
71 _out._characterEncoding = encoding;
72 if (_out._bytes==null)
73 _out._bytes = new ByteArrayOutputStream2(MAX_OUTPUT_CHARS);
74 }
75
76
77 @Override
78 public void close() throws IOException
79 {
80 _out.close();
81 }
82
83
84 @Override
85 public void flush() throws IOException
86 {
87 _out.flush();
88 }
89
90
91 @Override
92 public void write (String s,int offset, int length) throws IOException
93 {
94 while (length > MAX_OUTPUT_CHARS)
95 {
96 write(s, offset, MAX_OUTPUT_CHARS);
97 offset += MAX_OUTPUT_CHARS;
98 length -= MAX_OUTPUT_CHARS;
99 }
100
101 if (_out._chars==null)
102 {
103 _out._chars = new char[MAX_OUTPUT_CHARS];
104 }
105 char[] chars = _out._chars;
106 s.getChars(offset, offset + length, chars, 0);
107 write(chars, 0, length);
108 }
109
110
111 @Override
112 public void write (char[] s,int offset, int length) throws IOException
113 {
114 HttpOutput out = _out;
115
116 while (length > 0)
117 {
118 out._bytes.reset();
119 int chars = length>MAX_OUTPUT_CHARS?MAX_OUTPUT_CHARS:length;
120
121 switch (_writeMode)
122 {
123 case WRITE_CONV:
124 {
125 Writer converter=getConverter();
126 converter.write(s, offset, chars);
127 converter.flush();
128 }
129 break;
130
131 case WRITE_ISO1:
132 {
133 byte[] buffer=out._bytes.getBuf();
134 int bytes=out._bytes.getCount();
135
136 if (chars>buffer.length-bytes)
137 chars=buffer.length-bytes;
138
139 for (int i = 0; i < chars; i++)
140 {
141 int c = s[offset+i];
142 buffer[bytes++]=(byte)(c<256?c:'?');
143 }
144 if (bytes>=0)
145 out._bytes.setCount(bytes);
146
147 break;
148 }
149
150 case WRITE_UTF8:
151 {
152 byte[] buffer=out._bytes.getBuf();
153 int bytes=out._bytes.getCount();
154
155 if (bytes+chars>buffer.length)
156 chars=buffer.length-bytes;
157
158 for (int i = 0; i < chars; i++)
159 {
160 int code = s[offset+i];
161
162
163 if(_surrogate==0)
164 {
165
166 if(Character.isHighSurrogate((char)code))
167 {
168 _surrogate=code;
169 continue;
170 }
171 }
172
173 else if(Character.isLowSurrogate((char)code))
174 {
175 code = Character.toCodePoint((char)_surrogate, (char)code);
176 }
177
178 else
179 {
180 code=_surrogate;
181 _surrogate=0;
182 i--;
183 }
184
185 if ((code & 0xffffff80) == 0)
186 {
187
188 if (bytes>=buffer.length)
189 {
190 chars=i;
191 break;
192 }
193 buffer[bytes++]=(byte)(code);
194 }
195 else
196 {
197 if((code&0xfffff800)==0)
198 {
199
200 if (bytes+2>buffer.length)
201 {
202 chars=i;
203 break;
204 }
205 buffer[bytes++]=(byte)(0xc0|(code>>6));
206 buffer[bytes++]=(byte)(0x80|(code&0x3f));
207 }
208 else if((code&0xffff0000)==0)
209 {
210
211 if (bytes+3>buffer.length)
212 {
213 chars=i;
214 break;
215 }
216 buffer[bytes++]=(byte)(0xe0|(code>>12));
217 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
218 buffer[bytes++]=(byte)(0x80|(code&0x3f));
219 }
220 else if((code&0xff200000)==0)
221 {
222
223 if (bytes+4>buffer.length)
224 {
225 chars=i;
226 break;
227 }
228 buffer[bytes++]=(byte)(0xf0|(code>>18));
229 buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
230 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
231 buffer[bytes++]=(byte)(0x80|(code&0x3f));
232 }
233 else if((code&0xf4000000)==0)
234 {
235
236 if (bytes+5>buffer.length)
237 {
238 chars=i;
239 break;
240 }
241 buffer[bytes++]=(byte)(0xf8|(code>>24));
242 buffer[bytes++]=(byte)(0x80|((code>>18)&0x3f));
243 buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
244 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
245 buffer[bytes++]=(byte)(0x80|(code&0x3f));
246 }
247 else if((code&0x80000000)==0)
248 {
249
250 if (bytes+6>buffer.length)
251 {
252 chars=i;
253 break;
254 }
255 buffer[bytes++]=(byte)(0xfc|(code>>30));
256 buffer[bytes++]=(byte)(0x80|((code>>24)&0x3f));
257 buffer[bytes++]=(byte)(0x80|((code>>18)&0x3f));
258 buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
259 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
260 buffer[bytes++]=(byte)(0x80|(code&0x3f));
261 }
262 else
263 {
264 buffer[bytes++]=(byte)('?');
265 }
266
267 _surrogate=0;
268
269 if (bytes==buffer.length)
270 {
271 chars=i+1;
272 break;
273 }
274 }
275 }
276 out._bytes.setCount(bytes);
277 break;
278 }
279 default:
280 throw new IllegalStateException();
281 }
282
283 out._bytes.writeTo(out);
284 length-=chars;
285 offset+=chars;
286 }
287 }
288
289
290
291 private Writer getConverter() throws IOException
292 {
293 if (_out._converter == null)
294 _out._converter = new OutputStreamWriter(_out._bytes, _out._characterEncoding);
295 return _out._converter;
296 }
297 }