View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.server;
20  
21  import java.io.IOException;
22  
23  /** OutputWriter.
24   * A writer that can wrap a {@link HttpOutput} stream and provide
25   * character encodings.
26   *
27   * The UTF-8 encoding is done by this class and no additional
28   * buffers or Writers are used.
29   * The UTF-8 code was inspired by http://javolution.org
30   */
31  public class Utf8HttpWriter extends HttpWriter
32  {
33      int _surrogate=0;
34  
35      /* ------------------------------------------------------------ */
36      public Utf8HttpWriter(HttpOutput out)
37      {
38          super(out);
39      }
40  
41      /* ------------------------------------------------------------ */
42      @Override
43      public void write (char[] s,int offset, int length) throws IOException
44      {
45          HttpOutput out = _out;
46          if (length==0 && out.isAllContentWritten())
47          {
48              close();
49              return;
50          }
51          
52          while (length > 0)
53          {
54              _bytes.reset();
55              int chars = length>MAX_OUTPUT_CHARS?MAX_OUTPUT_CHARS:length;
56  
57              byte[] buffer=_bytes.getBuf();
58              int bytes=_bytes.getCount();
59  
60              if (bytes+chars>buffer.length)
61                  chars=buffer.length-bytes;
62  
63              for (int i = 0; i < chars; i++)
64              {
65                  int code = s[offset+i];
66  
67                  // Do we already have a surrogate?
68                  if(_surrogate==0)
69                  {
70                      // No - is this char code a surrogate?
71                      if(Character.isHighSurrogate((char)code))
72                      {
73                          _surrogate=code; // UCS-?
74                          continue;
75                      }
76                  }
77                  // else handle a low surrogate
78                  else if(Character.isLowSurrogate((char)code))
79                  {
80                      code = Character.toCodePoint((char)_surrogate, (char)code); // UCS-4
81                  }
82                  // else UCS-2
83                  else
84                  {
85                      code=_surrogate; // UCS-2
86                      _surrogate=0; // USED
87                      i--;
88                  }
89  
90                  if ((code & 0xffffff80) == 0)
91                  {
92                      // 1b
93                      if (bytes>=buffer.length)
94                      {
95                          chars=i;
96                          break;
97                      }
98                      buffer[bytes++]=(byte)(code);
99                  }
100                 else
101                 {
102                     if((code&0xfffff800)==0)
103                     {
104                         // 2b
105                         if (bytes+2>buffer.length)
106                         {
107                             chars=i;
108                             break;
109                         }
110                         buffer[bytes++]=(byte)(0xc0|(code>>6));
111                         buffer[bytes++]=(byte)(0x80|(code&0x3f));
112                     }
113                     else if((code&0xffff0000)==0)
114                     {
115                         // 3b
116                         if (bytes+3>buffer.length)
117                         {
118                             chars=i;
119                             break;
120                         }
121                         buffer[bytes++]=(byte)(0xe0|(code>>12));
122                         buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
123                         buffer[bytes++]=(byte)(0x80|(code&0x3f));
124                     }
125                     else if((code&0xff200000)==0)
126                     {
127                         // 4b
128                         if (bytes+4>buffer.length)
129                         {
130                             chars=i;
131                             break;
132                         }
133                         buffer[bytes++]=(byte)(0xf0|(code>>18));
134                         buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
135                         buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
136                         buffer[bytes++]=(byte)(0x80|(code&0x3f));
137                     }
138                     else if((code&0xf4000000)==0)
139                     {
140                         // 5b
141                         if (bytes+5>buffer.length)
142                         {
143                             chars=i;
144                             break;
145                         }
146                         buffer[bytes++]=(byte)(0xf8|(code>>24));
147                         buffer[bytes++]=(byte)(0x80|((code>>18)&0x3f));
148                         buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
149                         buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
150                         buffer[bytes++]=(byte)(0x80|(code&0x3f));
151                     }
152                     else if((code&0x80000000)==0)
153                     {
154                         // 6b
155                         if (bytes+6>buffer.length)
156                         {
157                             chars=i;
158                             break;
159                         }
160                         buffer[bytes++]=(byte)(0xfc|(code>>30));
161                         buffer[bytes++]=(byte)(0x80|((code>>24)&0x3f));
162                         buffer[bytes++]=(byte)(0x80|((code>>18)&0x3f));
163                         buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
164                         buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
165                         buffer[bytes++]=(byte)(0x80|(code&0x3f));
166                     }
167                     else
168                     {
169                         buffer[bytes++]=(byte)('?');
170                     }
171 
172                     _surrogate=0; // USED
173 
174                     if (bytes==buffer.length)
175                     {
176                         chars=i+1;
177                         break;
178                     }
179                 }
180             }
181             _bytes.setCount(bytes);
182 
183             _bytes.writeTo(out);
184             length-=chars;
185             offset+=chars;
186         }
187     }
188 }