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.util;
20  import java.io.IOException;
21  import java.io.OutputStream;
22  import java.io.OutputStreamWriter;
23  import java.io.Writer;
24  import java.nio.charset.StandardCharsets;
25  import java.util.Arrays;
26  
27  
28  /* ------------------------------------------------------------ */
29  /** Byte Array ISO 8859 writer. 
30   * This class combines the features of a OutputStreamWriter for
31   * ISO8859 encoding with that of a ByteArrayOutputStream.  It avoids
32   * many inefficiencies associated with these standard library classes.
33   * It has been optimized for standard ASCII characters.
34   * 
35   * 
36   */
37  public class ByteArrayISO8859Writer extends Writer
38  {
39      private byte[] _buf;
40      private int _size;
41      private ByteArrayOutputStream2 _bout=null;
42      private OutputStreamWriter _writer=null;
43      private boolean _fixed=false;
44  
45      /* ------------------------------------------------------------ */
46      /** Constructor. 
47       */
48      public ByteArrayISO8859Writer()
49      {
50          _buf=new byte[2048];
51      } 
52      
53      /* ------------------------------------------------------------ */
54      /** Constructor. 
55       * @param capacity Buffer capacity
56       */
57      public ByteArrayISO8859Writer(int capacity)
58      {
59          _buf=new byte[capacity];
60      }
61      
62      /* ------------------------------------------------------------ */
63      public ByteArrayISO8859Writer(byte[] buf)
64      {
65          _buf=buf;
66          _fixed=true;
67      }
68  
69      /* ------------------------------------------------------------ */
70      public Object getLock()
71      {
72          return lock;
73      }
74      
75      /* ------------------------------------------------------------ */
76      public int size()
77      {
78          return _size;
79      }
80      
81      /* ------------------------------------------------------------ */
82      public int capacity()
83      {
84          return _buf.length;
85      }
86  
87      /* ------------------------------------------------------------ */
88      public int spareCapacity()
89      {
90          return _buf.length-_size;
91      }
92      
93      /* ------------------------------------------------------------ */
94      public void setLength(int l)
95      {
96          _size=l;
97      }
98  
99      /* ------------------------------------------------------------ */
100     public byte[] getBuf()
101     {
102         return _buf;
103     }
104     
105     /* ------------------------------------------------------------ */
106     public void writeTo(OutputStream out)
107         throws IOException
108     {
109         out.write(_buf,0,_size);
110     }
111 
112     /* ------------------------------------------------------------ */
113     public void write(char c)
114         throws IOException
115     {
116         ensureSpareCapacity(1);
117         if (c>=0&&c<=0x7f)
118             _buf[_size++]=(byte)c;
119         else
120         {
121             char[] ca ={c};
122             writeEncoded(ca,0,1);
123         }
124     }
125     
126     /* ------------------------------------------------------------ */
127     @Override
128     public void write(char[] ca)
129         throws IOException
130     {
131         ensureSpareCapacity(ca.length);
132         for (int i=0;i<ca.length;i++)
133         {
134             char c=ca[i];
135             if (c>=0&&c<=0x7f)
136                 _buf[_size++]=(byte)c;
137             else
138             {
139                 writeEncoded(ca,i,ca.length-i);
140                 break;
141             }
142         }
143     }
144     
145     /* ------------------------------------------------------------ */
146     @Override
147     public void write(char[] ca,int offset, int length)
148         throws IOException
149     {
150         ensureSpareCapacity(length);
151         for (int i=0;i<length;i++)
152         {
153             char c=ca[offset+i];
154             if (c>=0&&c<=0x7f)
155                 _buf[_size++]=(byte)c;
156             else
157             {
158                 writeEncoded(ca,offset+i,length-i);
159                 break;
160             }
161         }
162     }
163     
164     /* ------------------------------------------------------------ */
165     @Override
166     public void write(String s)
167         throws IOException
168     {
169         if (s==null)
170         {
171             write("null",0,4);
172             return;
173         }
174         
175         int length=s.length();
176         ensureSpareCapacity(length);
177         for (int i=0;i<length;i++)
178         {
179             char c=s.charAt(i);
180             if (c>=0x0&&c<=0x7f)
181                 _buf[_size++]=(byte)c;
182             else
183             {
184                 writeEncoded(s.toCharArray(),i,length-i);
185                 break;
186             }
187         }
188     }
189     
190     /* ------------------------------------------------------------ */
191     @Override
192     public void write(String s,int offset, int length)
193         throws IOException
194     {
195         ensureSpareCapacity(length);
196         for (int i=0;i<length;i++)
197         {
198             char c=s.charAt(offset+i);
199             if (c>=0&&c<=0x7f)
200                 _buf[_size++]=(byte)c;
201             else
202             {
203                 writeEncoded(s.toCharArray(),offset+i,length-i);
204                 break;
205             }
206         }
207     }
208 
209     /* ------------------------------------------------------------ */
210     private void writeEncoded(char[] ca,int offset, int length)
211         throws IOException
212     {
213         if (_bout==null)
214         {
215             _bout = new ByteArrayOutputStream2(2*length);
216             _writer = new OutputStreamWriter(_bout,StandardCharsets.ISO_8859_1);
217         }
218         else
219             _bout.reset();
220         _writer.write(ca,offset,length);
221         _writer.flush();
222         ensureSpareCapacity(_bout.getCount());
223         System.arraycopy(_bout.getBuf(),0,_buf,_size,_bout.getCount());
224         _size+=_bout.getCount();
225     }
226     
227     /* ------------------------------------------------------------ */
228     @Override
229     public void flush()
230     {}
231 
232     /* ------------------------------------------------------------ */
233     public void resetWriter()
234     {
235         _size=0;
236     }
237 
238     /* ------------------------------------------------------------ */
239     @Override
240     public void close()
241     {}
242 
243     /* ------------------------------------------------------------ */
244     public void destroy()
245     {
246         _buf=null;
247     }
248     
249     /* ------------------------------------------------------------ */
250     public void ensureSpareCapacity(int n)
251         throws IOException
252     {
253         if (_size+n>_buf.length)
254         {
255             if (_fixed)
256                 throw new IOException("Buffer overflow: "+_buf.length);
257             _buf=Arrays.copyOf(_buf,(_buf.length+n)*4/3);
258         }
259     }
260 
261     /* ------------------------------------------------------------ */
262     public byte[] getByteArray()
263     {
264         return Arrays.copyOf(_buf,_size);
265     }
266     
267 }
268     
269