KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > excalibur > instrument > manager > http > server > URLCoder


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
14  * implied.
15  *
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */

19
20 package org.apache.excalibur.instrument.manager.http.server;
21
22 import java.io.UnsupportedEncodingException JavaDoc;
23
24 /**
25  * The java.net.URLDecoder and java.net.URLEncoder classes that ship with Java
26  * do not support encoding until Java 1.4. But this tool needs to be able to
27  * be used with Java 1.3. This class makes that possible.
28  */

29 public class URLCoder
30 {
31     /** Not instantiable. */
32     private URLCoder()
33     {
34     }
35     
36     /**
37      * Returns a single upper case hex digit given a 0..15 number.
38      */

39     private static char getDigit( int d )
40     {
41         char c = Character.forDigit( d, 16 );
42         if ( Character.isLetter( c ) )
43         {
44             c = Character.toUpperCase( c );
45         }
46         return c;
47     }
48     
49     /**
50      * Adds a string of characters in %xx encoded form to the specified
51      * StringBuffer.
52      */

53     private static void encodeChars( String JavaDoc value, String JavaDoc encoding, StringBuffer JavaDoc sb )
54         throws UnsupportedEncodingException JavaDoc
55     {
56         byte[] bytes;
57         if ( encoding == null )
58         {
59             bytes = value.getBytes();
60         }
61         else
62         {
63             bytes = value.getBytes( encoding );
64         }
65         
66         for ( int i = 0; i < bytes.length; i++ )
67         {
68             sb.append( '%' );
69             int b = (int)bytes[i];
70             sb.append( getDigit( ( b & 0xf0 ) >> 4 ) );
71             sb.append( getDigit( b & 0xf ) );
72         }
73     }
74     
75     private static String JavaDoc decodeChars( char[] chars, int start, int count, String JavaDoc encoding )
76         throws UnsupportedEncodingException JavaDoc
77     {
78         byte[] bytes = new byte[count / 3];
79         
80         int pos = start;
81         int bPos = 0;
82         boolean bad = false;
83         while ( pos < start + count )
84         {
85             char c = chars[pos];
86             if ( c != '%' )
87             {
88                 bad = true;
89                 break;
90             }
91             pos++;
92             
93             int b = 0;
94             
95             if ( pos >= chars.length )
96             {
97                 bad = true;
98                 break;
99             }
100             c = chars[pos];
101             if ( ( c >= 'A' ) && ( c <= 'F' ) )
102             {
103                 b = b + 10 + ( c - 'A' );
104             }
105             else if ( ( c >= '0' ) && ( c <= '9' ) )
106             {
107                 b = b + c - '0';
108             }
109             else
110             {
111                 bad = true;
112                 break;
113             }
114             b = b << 4;
115             pos++;
116             
117             if ( pos >= chars.length )
118             {
119                 bad = true;
120                 break;
121             }
122             c = chars[pos];
123             if ( ( c >= 'A' ) && ( c <= 'F' ) )
124             {
125                 b = b + 10 + ( c - 'A' );
126             }
127             else if ( ( c >= '0' ) && ( c <= '9' ) )
128             {
129                 b = b + c - '0';
130             }
131             else
132             {
133                 bad = true;
134                 break;
135             }
136             pos++;
137             
138             bytes[bPos++] = (byte)( b & 0xff );
139         }
140         
141         if ( bad )
142         {
143             throw new IllegalArgumentException JavaDoc( "Unexpected character at position " + pos );
144         }
145         
146         if ( encoding == null )
147         {
148             return new String JavaDoc( bytes );
149         }
150         else
151         {
152             return new String JavaDoc( bytes, encoding );
153         }
154     }
155     
156     public static String JavaDoc encode( String JavaDoc value, String JavaDoc encoding )
157         throws UnsupportedEncodingException JavaDoc
158     {
159         boolean changed = false;
160         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
161         
162         char[] chars = value.toCharArray();
163         
164         int firstEncodeIndex = -1;
165         int encodeCount = 0;
166         StringBuffer JavaDoc encodeSb = new StringBuffer JavaDoc();
167         for ( int i = 0; i < chars.length; i++ )
168         {
169             char c = chars[i];
170             boolean encode;
171             if ( c == ' ' )
172             {
173                 // Special character.
174
c = '+';
175                 changed = true;
176                 encode = false;
177             }
178             else if ( ( ( c >= 'a' ) && ( c <= 'z' ) )
179                 || ( ( c >= 'A' ) && ( c <= 'Z' ) )
180                 || ( ( c >= '0' ) && ( c <= '9' ) )
181                 || ( c == '-' ) || ( c == '_' ) || ( c == '.' ) || ( c == '*' ) )
182             {
183                 // No encoding required.
184
encode = false;
185             }
186             else
187             {
188                 // All other characters must be encoded.
189
changed = true;
190                 encode = true;
191             }
192             
193             if ( encode )
194             {
195                 // This character needs to be encoded.
196
if ( firstEncodeIndex < 0 )
197                 {
198                     firstEncodeIndex = i;
199                 }
200                 encodeCount++;
201             }
202             else
203             {
204                 // No encoding needed.
205
if ( firstEncodeIndex >= 0 )
206                 {
207                     // The last run of chars needs to be encoded.
208
encodeChars( new String JavaDoc( chars, firstEncodeIndex, encodeCount ), encoding, sb );
209                     firstEncodeIndex = -1;
210                     encodeCount = 0;
211                 }
212                 
213                 sb.append( c );
214             }
215         }
216         
217         // If we ended in an encoding block then handle it.
218
if ( firstEncodeIndex >= 0 )
219         {
220             // The last run of chars needs to be encoded.
221
encodeChars( new String JavaDoc( chars, firstEncodeIndex, encodeCount ), encoding, sb );
222             firstEncodeIndex = -1;
223             encodeCount = 0;
224         }
225         
226         if ( changed )
227         {
228             return sb.toString();
229         }
230         else
231         {
232             return value;
233         }
234     }
235     
236     public static String JavaDoc decode( String JavaDoc value, String JavaDoc encoding )
237         throws UnsupportedEncodingException JavaDoc
238     {
239         boolean changed = false;
240         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
241         
242         char[] chars = value.toCharArray();
243         
244         int firstDecodeIndex = -1;
245         int decodeCount = 0;
246         for ( int i = 0; i < chars.length; i++ )
247         {
248             char c = chars[i];
249             boolean decode;
250             if ( c == '+' )
251             {
252                 c = ' ';
253                 decode = false;
254                 changed = true;
255             }
256             else if ( c == '%' )
257             {
258                 decode = true;
259                 changed = true;
260             }
261             else
262             {
263                 decode = false;
264             }
265             
266             if ( decode )
267             {
268                 // This is the first character needing to be decoded.
269
if ( firstDecodeIndex < 0 )
270                 {
271                     firstDecodeIndex = i;
272                 }
273                 decodeCount += 3; // Always assume 3 characters for now.
274
i += 2;
275             }
276             else
277             {
278                 // This character needs no decoding.
279
if ( firstDecodeIndex >= 0 )
280                 {
281                     sb.append( decodeChars( chars, firstDecodeIndex, decodeCount, encoding ) );
282                     firstDecodeIndex = -1;
283                     decodeCount = 0;
284                 }
285                 
286                 sb.append( c );
287             }
288         }
289         
290         // If we ended while decoding a block then handle it.
291
if ( firstDecodeIndex >= 0 )
292         {
293             sb.append( decodeChars( chars, firstDecodeIndex, decodeCount, encoding ) );
294             firstDecodeIndex = -1;
295             decodeCount = 0;
296         }
297         
298         if ( changed )
299         {
300             return sb.toString();
301         }
302         else
303         {
304             return value;
305         }
306     }
307 }
Popular Tags