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 _surrogate=0;
177 }
178
179 else
180 {
181 code=_surrogate;
182 _surrogate=0;
183 i--;
184 }
185
186 if ((code & 0xffffff80) == 0)
187 {
188
189 if (bytes>=buffer.length)
190 {
191 chars=i;
192 break;
193 }
194 buffer[bytes++]=(byte)(code);
195 }
196 else
197 {
198 if((code&0xfffff800)==0)
199 {
200
201 if (bytes+2>buffer.length)
202 {
203 chars=i;
204 break;
205 }
206 buffer[bytes++]=(byte)(0xc0|(code>>6));
207 buffer[bytes++]=(byte)(0x80|(code&0x3f));
208 }
209 else if((code&0xffff0000)==0)
210 {
211
212 if (bytes+3>buffer.length)
213 {
214 chars=i;
215 break;
216 }
217 buffer[bytes++]=(byte)(0xe0|(code>>12));
218 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
219 buffer[bytes++]=(byte)(0x80|(code&0x3f));
220 }
221 else if((code&0xff200000)==0)
222 {
223
224 if (bytes+4>buffer.length)
225 {
226 chars=i;
227 break;
228 }
229 buffer[bytes++]=(byte)(0xf0|(code>>18));
230 buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
231 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
232 buffer[bytes++]=(byte)(0x80|(code&0x3f));
233 }
234 else if((code&0xf4000000)==0)
235 {
236
237 if (bytes+5>buffer.length)
238 {
239 chars=i;
240 break;
241 }
242 buffer[bytes++]=(byte)(0xf8|(code>>24));
243 buffer[bytes++]=(byte)(0x80|((code>>18)&0x3f));
244 buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
245 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
246 buffer[bytes++]=(byte)(0x80|(code&0x3f));
247 }
248 else if((code&0x80000000)==0)
249 {
250
251 if (bytes+6>buffer.length)
252 {
253 chars=i;
254 break;
255 }
256 buffer[bytes++]=(byte)(0xfc|(code>>30));
257 buffer[bytes++]=(byte)(0x80|((code>>24)&0x3f));
258 buffer[bytes++]=(byte)(0x80|((code>>18)&0x3f));
259 buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
260 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
261 buffer[bytes++]=(byte)(0x80|(code&0x3f));
262 }
263 else
264 {
265 buffer[bytes++]=(byte)('?');
266 }
267
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 }