KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tomcat > util > buf > B2CConverter


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.tomcat.util.buf;
20
21 import java.io.IOException JavaDoc;
22 import java.io.InputStream JavaDoc;
23 import java.io.InputStreamReader JavaDoc;
24 import java.io.UnsupportedEncodingException JavaDoc;
25
26 /** Efficient conversion of bytes to character .
27  *
28  * This uses the standard JDK mechansim - a reader - but provides mechanisms
29  * to recycle all the objects that are used. It is compatible with JDK1.1
30  * and up,
31  * ( nio is better, but it's not available even in 1.2 or 1.3 )
32  *
33  * Not used in the current code, the performance gain is not very big
34  * in the current case ( since String is created anyway ), but it will
35  * be used in a later version or after the remaining optimizations.
36  */

37 public class B2CConverter {
38     
39     
40     private static org.apache.commons.logging.Log log=
41         org.apache.commons.logging.LogFactory.getLog( B2CConverter.class );
42     
43     private IntermediateInputStream iis;
44     private ReadConvertor conv;
45     private String JavaDoc encoding;
46
47     protected B2CConverter() {
48     }
49     
50     /** Create a converter, with bytes going to a byte buffer
51      */

52     public B2CConverter(String JavaDoc encoding)
53     throws IOException JavaDoc
54     {
55     this.encoding=encoding;
56     reset();
57     }
58
59     
60     /** Reset the internal state, empty the buffers.
61      * The encoding remain in effect, the internal buffers remain allocated.
62      */

63     public void recycle() {
64     conv.recycle();
65     }
66
67     static final int BUFFER_SIZE=8192;
68     char result[]=new char[BUFFER_SIZE];
69
70     /** Convert a buffer of bytes into a chars
71      */

72     public void convert( ByteChunk bb, CharChunk cb )
73     throws IOException JavaDoc
74     {
75     // Set the ByteChunk as input to the Intermediate reader
76
iis.setByteChunk( bb );
77     convert(cb);
78     }
79
80     private void convert(CharChunk cb)
81     throws IOException JavaDoc
82     {
83     try {
84         // read from the reader
85
while( true ) { // conv.ready() ) {
86
int cnt=conv.read( result, 0, BUFFER_SIZE );
87         if( cnt <= 0 ) {
88             // End of stream ! - we may be in a bad state
89
if( debug>0)
90             log( "EOF" );
91             // reset();
92
return;
93         }
94         if( debug > 1 )
95             log("Converted: " + new String JavaDoc( result, 0, cnt ));
96
97         // XXX go directly
98
cb.append( result, 0, cnt );
99         }
100     } catch( IOException JavaDoc ex) {
101         if( debug>0)
102         log( "Reseting the converter " + ex.toString() );
103         reset();
104         throw ex;
105     }
106     }
107
108     public void reset()
109     throws IOException JavaDoc
110     {
111     // destroy the reader/iis
112
iis=new IntermediateInputStream();
113     conv=new ReadConvertor( iis, encoding );
114     }
115
116     private final int debug=0;
117     void log( String JavaDoc s ) {
118         if (log.isDebugEnabled())
119             log.debug("B2CConverter: " + s );
120     }
121
122     // -------------------- Not used - the speed improvemnt is quite small
123

124     /*
125     private Hashtable decoders;
126     public static final boolean useNewString=false;
127     public static final boolean useSpecialDecoders=true;
128     private UTF8Decoder utfD;
129     // private char[] conversionBuff;
130     CharChunk conversionBuf;
131
132
133     private static String decodeString(ByteChunk mb, String enc)
134     throws IOException
135     {
136     byte buff=mb.getBuffer();
137     int start=mb.getStart();
138     int end=mb.getEnd();
139     if( useNewString ) {
140         if( enc==null) enc="UTF8";
141         return new String( buff, start, end-start, enc );
142     }
143     B2CConverter b2c=null;
144     if( useSpecialDecoders &&
145         (enc==null || "UTF8".equalsIgnoreCase(enc))) {
146         if( utfD==null ) utfD=new UTF8Decoder();
147         b2c=utfD;
148     }
149     if(decoders == null ) decoders=new Hashtable();
150     if( enc==null ) enc="UTF8";
151     b2c=(B2CConverter)decoders.get( enc );
152     if( b2c==null ) {
153         if( useSpecialDecoders ) {
154         if( "UTF8".equalsIgnoreCase( enc ) ) {
155             b2c=new UTF8Decoder();
156         }
157         }
158         if( b2c==null )
159         b2c=new B2CConverter( enc );
160         decoders.put( enc, b2c );
161     }
162     if( conversionBuf==null ) conversionBuf=new CharChunk(1024);
163
164     try {
165         conversionBuf.recycle();
166         b2c.convert( this, conversionBuf );
167         //System.out.println("XXX 1 " + conversionBuf );
168         return conversionBuf.toString();
169     } catch( IOException ex ) {
170         ex.printStackTrace();
171         return null;
172     }
173     }
174
175     */

176 }
177
178 // -------------------- Private implementation --------------------
179

180
181
182 /**
183  *
184  */

185 final class ReadConvertor extends InputStreamReader JavaDoc {
186     // stream with flush() and close(). overriden.
187
private IntermediateInputStream iis;
188     
189     // Has a private, internal byte[8192]
190

191     /** Create a converter.
192      */

193     public ReadConvertor( IntermediateInputStream in, String JavaDoc enc )
194     throws UnsupportedEncodingException JavaDoc
195     {
196     super( in, enc );
197     iis=in;
198     }
199     
200     /** Overriden - will do nothing but reset internal state.
201      */

202     public final void close() throws IOException JavaDoc {
203     // NOTHING
204
// Calling super.close() would reset out and cb.
205
}
206     
207     public final int read(char cbuf[], int off, int len)
208     throws IOException JavaDoc
209     {
210     // will do the conversion and call write on the output stream
211
return super.read( cbuf, off, len );
212     }
213     
214     /** Reset the buffer
215      */

216     public final void recycle() {
217     }
218 }
219
220
221 /** Special output stream where close() is overriden, so super.close()
222     is never called.
223     
224     This allows recycling. It can also be disabled, so callbacks will
225     not be called if recycling the converter and if data was not flushed.
226 */

227 final class IntermediateInputStream extends InputStream JavaDoc {
228     byte buf[];
229     int pos;
230     int len;
231     int end;
232     
233     public IntermediateInputStream() {
234     }
235     
236     public final void close() throws IOException JavaDoc {
237     // shouldn't be called - we filter it out in writer
238
throw new IOException JavaDoc("close() called - shouldn't happen ");
239     }
240     
241     public final int read(byte cbuf[], int off, int len) throws IOException JavaDoc {
242     if( pos >= end ) return -1;
243     if (pos + len > end) {
244         len = end - pos;
245     }
246     if (len <= 0) {
247         return 0;
248     }
249     System.arraycopy(buf, pos, cbuf, off, len);
250     pos += len;
251     return len;
252     }
253     
254     public final int read() throws IOException JavaDoc {
255     return (pos < end ) ? (buf[pos++] & 0xff) : -1;
256     }
257
258     // -------------------- Internal methods --------------------
259

260     void setBuffer( byte b[], int p, int l ) {
261     buf=b;
262     pos=p;
263     len=l;
264     end=pos+len;
265     }
266
267     void setByteChunk( ByteChunk mb ) {
268     buf=mb.getBytes();
269     pos=mb.getStart();
270     len=mb.getLength();
271     end=pos+len;
272     }
273
274 }
275
Popular Tags