Source Code Cross Referenced for Util.java in  » Net » SkunkDAV » HTTPClient » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » SkunkDAV » HTTPClient 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * @(#)Util.java					0.3-2 18/06/1999
003:         *
004:         *  This file is part of the HTTPClient package
005:         *  Copyright (C) 1996-1999  Ronald Tschalär
006:         *
007:         *  This library is free software; you can redistribute it and/or
008:         *  modify it under the terms of the GNU Lesser General Public
009:         *  License as published by the Free Software Foundation; either
010:         *  version 2 of the License, or (at your option) any later version.
011:         *
012:         *  This library is distributed in the hope that it will be useful,
013:         *  but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015:         *  Lesser General Public License for more details.
016:         *
017:         *  You should have received a copy of the GNU Lesser General Public
018:         *  License along with this library; if not, write to the Free
019:         *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
020:         *  MA 02111-1307, USA
021:         *
022:         *  For questions, suggestions, bug-reports, enhancement-requests etc.
023:         *  I may be contacted at:
024:         *
025:         *  ronald@innovation.ch
026:         *
027:         */
028:
029:        package HTTPClient;
030:
031:        import java.net.URL;
032:        import java.util.Date;
033:        import java.util.BitSet;
034:        import java.util.Vector;
035:        import java.util.Hashtable;
036:        import java.util.SimpleTimeZone;
037:        import java.util.StringTokenizer;
038:        import java.text.SimpleDateFormat;
039:        import java.util.Locale;
040:
041:        /**
042:         * This class holds various utility methods.
043:         *
044:         * @version	0.3-2  18/06/1999
045:         * @author	Ronald Tschalär
046:         */
047:
048:        public class Util {
049:            private static final BitSet Separators = new BitSet(128);
050:            private static final BitSet TokenChar = new BitSet(128);
051:            private static final BitSet UnsafeChar = new BitSet(128);
052:            private static SimpleDateFormat http_format;
053:
054:            static {
055:                // rfc-2068 tspecial
056:                Separators.set('(');
057:                Separators.set(')');
058:                Separators.set('<');
059:                Separators.set('>');
060:                Separators.set('@');
061:                Separators.set(',');
062:                Separators.set(';');
063:                Separators.set(':');
064:                Separators.set('\\');
065:                Separators.set('"');
066:                Separators.set('/');
067:                Separators.set('[');
068:                Separators.set(']');
069:                Separators.set('?');
070:                Separators.set('=');
071:                Separators.set('{');
072:                Separators.set('}');
073:                Separators.set(' ');
074:                Separators.set('\t');
075:
076:                // rfc-2068 token
077:                for (int ch = 32; ch < 127; ch++)
078:                    TokenChar.set(ch);
079:                TokenChar.xor(Separators);
080:
081:                // rfc-1738 unsafe characters, including CTL and SP, and excluding
082:                // "#" and "%"
083:                for (int ch = 0; ch < 32; ch++)
084:                    UnsafeChar.set(ch);
085:                UnsafeChar.set(' ');
086:                UnsafeChar.set('<');
087:                UnsafeChar.set('>');
088:                UnsafeChar.set('"');
089:                UnsafeChar.set('{');
090:                UnsafeChar.set('}');
091:                UnsafeChar.set('|');
092:                UnsafeChar.set('\\');
093:                UnsafeChar.set('^');
094:                UnsafeChar.set('~');
095:                UnsafeChar.set('[');
096:                UnsafeChar.set(']');
097:                UnsafeChar.set('`');
098:                UnsafeChar.set(127);
099:
100:                // rfc-1123 date format (restricted to GMT, as per rfc-2068)
101:                /* This initialization has been moved to httpDate() because it
102:                 * takes an awfully long time and is often not needed
103:                 *
104:                http_format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'",
105:                				   Locale.US);
106:                http_format.setTimeZone(new SimpleTimeZone(0, "GMT"));
107:                 */
108:            }
109:
110:            // Constructors
111:
112:            /**
113:             * This class isn't meant to be instantiated.
114:             */
115:            private Util() {
116:            }
117:
118:            // Methods
119:
120:            // this doesn't work!!! Aaaaarrgghhh!
121:            final static Object[] resizeArray(Object[] src, int new_size) {
122:                Object tmp[] = new Object[new_size];
123:                System.arraycopy(src, 0, tmp, 0,
124:                        (src.length < new_size ? src.length : new_size));
125:                return tmp;
126:            }
127:
128:            final static NVPair[] resizeArray(NVPair[] src, int new_size) {
129:                NVPair tmp[] = new NVPair[new_size];
130:                System.arraycopy(src, 0, tmp, 0,
131:                        (src.length < new_size ? src.length : new_size));
132:                return tmp;
133:            }
134:
135:            final static AuthorizationInfo[] resizeArray(
136:                    AuthorizationInfo[] src, int new_size) {
137:                AuthorizationInfo tmp[] = new AuthorizationInfo[new_size];
138:                System.arraycopy(src, 0, tmp, 0,
139:                        (src.length < new_size ? src.length : new_size));
140:                return tmp;
141:            }
142:
143:            final static Cookie[] resizeArray(Cookie[] src, int new_size) {
144:                Cookie tmp[] = new Cookie[new_size];
145:                System.arraycopy(src, 0, tmp, 0,
146:                        (src.length < new_size ? src.length : new_size));
147:                return tmp;
148:            }
149:
150:            final static String[] resizeArray(String[] src, int new_size) {
151:                String tmp[] = new String[new_size];
152:                System.arraycopy(src, 0, tmp, 0,
153:                        (src.length < new_size ? src.length : new_size));
154:                return tmp;
155:            }
156:
157:            final static boolean[] resizeArray(boolean[] src, int new_size) {
158:                boolean tmp[] = new boolean[new_size];
159:                System.arraycopy(src, 0, tmp, 0,
160:                        (src.length < new_size ? src.length : new_size));
161:                return tmp;
162:            }
163:
164:            final static byte[] resizeArray(byte[] src, int new_size) {
165:                byte tmp[] = new byte[new_size];
166:                System.arraycopy(src, 0, tmp, 0,
167:                        (src.length < new_size ? src.length : new_size));
168:                return tmp;
169:            }
170:
171:            final static char[] resizeArray(char[] src, int new_size) {
172:                char tmp[] = new char[new_size];
173:                System.arraycopy(src, 0, tmp, 0,
174:                        (src.length < new_size ? src.length : new_size));
175:                return tmp;
176:            }
177:
178:            final static int[] resizeArray(int[] src, int new_size) {
179:                int tmp[] = new int[new_size];
180:                System.arraycopy(src, 0, tmp, 0,
181:                        (src.length < new_size ? src.length : new_size));
182:                return tmp;
183:            }
184:
185:            /**
186:             * Split a property into an array of Strings, using "|" as the
187:             * separator.
188:             */
189:            static String[] splitProperty(String prop) {
190:                if (prop == null)
191:                    return new String[0];
192:
193:                StringTokenizer tok = new StringTokenizer(prop, "|");
194:                String[] list = new String[tok.countTokens()];
195:                for (int idx = 0; idx < list.length; idx++)
196:                    list[idx] = tok.nextToken().trim();
197:
198:                return list;
199:            }
200:
201:            /**
202:             * Helper method for context lists used by modules. Returns the
203:             * list associated with the context if it exists; otherwise it creates
204:             * a new list and adds it to the context list.
205:             *
206:             * @param cntxt_list the list of lists indexed by context
207:             * @param cntxt the context
208:             */
209:            final static Hashtable getList(Hashtable cntxt_list, Object cntxt) {
210:                Hashtable list = (Hashtable) cntxt_list.get(cntxt);
211:                if (list == null) {
212:                    synchronized (cntxt_list) // only synch if necessary
213:                    {
214:                        list = (Hashtable) cntxt_list.get(cntxt);
215:                        if (list == null) // verify nobody else beat us to it
216:                        {
217:                            list = new Hashtable();
218:                            cntxt_list.put(cntxt, list);
219:                        }
220:                    }
221:                }
222:
223:                return list;
224:            }
225:
226:            /**
227:             * Creates an array of distances to speed up the search in findStr().
228:             * The returned array should be passed as the second argument to
229:             * findStr().
230:             *
231:             * @param search the search string (same as the first argument to
232:             *               findStr()).
233:             * @return an array of distances (to be passed as the second argument to
234:             *         findStr()).
235:             */
236:            final static int[] compile_search(byte[] search) {
237:                int[] cmp = { 0, 1, 0, 1, 0, 1 };
238:                int end;
239:
240:                for (int idx = 0; idx < search.length; idx++) {
241:                    for (end = idx + 1; end < search.length; end++) {
242:                        if (search[idx] == search[end])
243:                            break;
244:                    }
245:                    if (end < search.length) {
246:                        if ((end - idx) > cmp[1]) {
247:                            cmp[4] = cmp[2];
248:                            cmp[5] = cmp[3];
249:                            cmp[2] = cmp[0];
250:                            cmp[3] = cmp[1];
251:                            cmp[0] = idx;
252:                            cmp[1] = end - idx;
253:                        } else if ((end - idx) > cmp[3]) {
254:                            cmp[4] = cmp[2];
255:                            cmp[5] = cmp[3];
256:                            cmp[2] = idx;
257:                            cmp[3] = end - idx;
258:                        } else if ((end - idx) > cmp[3]) {
259:                            cmp[4] = idx;
260:                            cmp[5] = end - idx;
261:                        }
262:                    }
263:                }
264:
265:                cmp[1] += cmp[0];
266:                cmp[3] += cmp[2];
267:                cmp[5] += cmp[4];
268:                return cmp;
269:            }
270:
271:            /**
272:             * Search for a string. Use compile_search() to first generate the second
273:             * argument. This uses a Knuth-Morris-Pratt like algorithm.
274:             *
275:             * @param search  the string to search for.
276:             * @param cmp     the the array returned by compile_search.
277:             * @param str     the string in which to look for <var>search</var>.
278:             * @param beg     the position at which to start the search in
279:             *                <var>str</var>.
280:             * @param end     the position at which to end the search in <var>str</var>,
281:             *                noninclusive.
282:             * @return the position in <var>str</var> where <var>search</var> was
283:             *         found, or -1 if not found.
284:             */
285:            final static int findStr(byte[] search, int[] cmp, byte[] str,
286:                    int beg, int end) {
287:                int c1f = cmp[0], c1l = cmp[1], d1 = c1l - c1f, c2f = cmp[2], c2l = cmp[3], d2 = c2l
288:                        - c2f, c3f = cmp[4], c3l = cmp[5], d3 = c3l - c3f;
289:
290:                Find: while (beg + search.length <= end) {
291:                    if (search[c1l] == str[beg + c1l]) {
292:                        /* This is correct, but Visual J++ can't cope with it...
293:                        Comp: if (search[c1f] == str[beg+c1f])
294:                        {
295:                            for (int idx=0; idx<search.length; idx++)
296:                        	if (search[idx] != str[beg+idx])  break Comp;
297:
298:                            break Find;		// we found it
299:                        }
300:                         *  so here is the replacement: */
301:                        if (search[c1f] == str[beg + c1f]) {
302:                            boolean same = true;
303:
304:                            for (int idx = 0; idx < search.length; idx++)
305:                                if (search[idx] != str[beg + idx]) {
306:                                    same = false;
307:                                    break;
308:                                }
309:
310:                            if (same)
311:                                break Find; // we found it
312:                        }
313:
314:                        beg += d1;
315:                    } else if (search[c2l] == str[beg + c2l])
316:                        beg += d2;
317:                    else if (search[c3l] == str[beg + c3l])
318:                        beg += d3;
319:                    else
320:                        beg++;
321:                }
322:
323:                if (beg + search.length > end)
324:                    return -1;
325:                else
326:                    return beg;
327:            }
328:
329:            /**
330:             * Replace quoted characters by their unquoted version. Quoted characters
331:             * are characters preceded by a slash. E.g. "\c" would be replaced by "c".
332:             * This is used in parsing http headers where quoted-characters are
333:             * allowed in quoted-strings and often used to quote the quote character
334:             * &lt;"&gt;.
335:             *
336:             * @param str the string do dequote
337:             * @return the string do with all quoted characters replaced by their
338:             *         true value.
339:             */
340:            public final static String dequoteString(String str) {
341:                if (str.indexOf('\\') == -1)
342:                    return str;
343:
344:                char[] buf = str.toCharArray();
345:                int pos = 0, num_deq = 0;
346:                while (pos < buf.length) {
347:                    if (buf[pos] == '\\' && pos + 1 < buf.length) {
348:                        System.arraycopy(buf, pos + 1, buf, pos, buf.length
349:                                - pos - 1);
350:                        num_deq++;
351:                    }
352:                    pos++;
353:                }
354:
355:                return new String(buf, 0, buf.length - num_deq);
356:            }
357:
358:            /**
359:             * Replace given characters by their quoted version. Quoted characters
360:             * are characters preceded by a slash. E.g. "c" would be replaced by "\c".
361:             * This is used in generating http headers where certain characters need
362:             * to be quoted, such as the quote character &lt;"&gt;.
363:             *
364:             * @param str   the string do quote
365:             * @param qlist the list of characters to quote
366:             * @return the string do with all characters replaced by their
367:             *         quoted version.
368:             */
369:            public final static String quoteString(String str, String qlist) {
370:                char[] list = qlist.toCharArray();
371:                int idx;
372:                for (idx = 0; idx < list.length; idx++)
373:                    if (str.indexOf(list[idx]) != -1)
374:                        break;
375:                if (idx == list.length)
376:                    return str;
377:
378:                int len = str.length();
379:                char[] buf = new char[len * 2];
380:                str.getChars(0, len, buf, 0);
381:                int pos = 0;
382:                while (pos < len) {
383:                    if (qlist.indexOf(buf[pos], 0) != -1) {
384:                        if (len == buf.length)
385:                            buf = Util.resizeArray(buf, len + str.length());
386:
387:                        System.arraycopy(buf, pos, buf, pos + 1, len - pos);
388:                        len++;
389:                        buf[pos++] = '\\';
390:                    }
391:                    pos++;
392:                }
393:
394:                return new String(buf, 0, len);
395:            }
396:
397:            /**
398:             * This parses the value part of a header. All quoted strings are
399:             * dequoted.
400:             *
401:             * @see #parseHeader(java.lang.String, boolean)
402:             * @param header  the value part of the header.
403:             * @return a Vector containing all the elements; each entry is an
404:             *         instance of <var>HttpHeaderElement</var>.
405:             * @exception ParseException if the syntax rules are violated.
406:             */
407:            public final static Vector parseHeader(String header)
408:                    throws ParseException {
409:                return parseHeader(header, true);
410:            }
411:
412:            /**
413:             * This parses the value part of a header. The result is a Vector of
414:             * HttpHeaderElement's. The syntax the header must conform to is:
415:             *
416:             * <PRE>
417:             * header  = [ element ] *( "," [ element ] )
418:             * element = name [ "=" [ value ] ] *( ";" [ param ] )
419:             * param   = name [ "=" [ value ] ]
420:             * 
421:             * name    = token
422:             * value   = ( token | quoted-string )
423:             * 
424:             * token         = 1*&lt;any char except "=", ",", ";", &lt;"&gt; and
425:             *                       white space&gt;
426:             * quoted-string = &lt;"&gt; *( text | quoted-char ) &lt;"&gt;
427:             * text          = any char except &lt;"&gt;
428:             * quoted-char   = "\" char
429:             * </PRE>
430:             *
431:             * Any amount of white space is allowed between any part of the header,
432:             * element or param and is ignored. A missing value in any element or
433:             * param will be stored as the empty string; if the "=" is also missing
434:             * <var>null</var> will be stored instead.
435:             *
436:             * @param header  the value part of the header.
437:             * @param dequote if true all quoted strings are dequoted.
438:             * @return a Vector containing all the elements; each entry is an
439:             *         instance of <var>HttpHeaderElement</var>.
440:             * @exception ParseException if the above syntax rules are violated.
441:             * @see HTTPClient.HttpHeaderElement
442:             */
443:            public final static Vector parseHeader(String header,
444:                    boolean dequote) throws ParseException {
445:                if (header == null)
446:                    return null;
447:                char[] buf = header.toCharArray();
448:                Vector elems = new Vector();
449:                boolean first = true;
450:                int beg = -1, end = 0, len = buf.length, abeg[] = new int[1];
451:                String elem_name, elem_value;
452:
453:                elements: while (true) {
454:                    if (!first) // find required ","
455:                    {
456:                        beg = skipSpace(buf, end);
457:                        if (beg == len)
458:                            break;
459:                        if (buf[beg] != ',')
460:                            throw new ParseException("Bad header format: '"
461:                                    + header + "'\nExpected \",\" at position "
462:                                    + beg);
463:                    }
464:                    first = false;
465:
466:                    beg = skipSpace(buf, beg + 1);
467:                    if (beg == len)
468:                        break elements;
469:                    if (buf[beg] == ',') // skip empty elements
470:                    {
471:                        end = beg;
472:                        continue elements;
473:                    }
474:
475:                    if (buf[beg] == '=' || buf[beg] == ';' || buf[beg] == '"')
476:                        throw new ParseException("Bad header format: '"
477:                                + header + "'\nEmpty element name at position "
478:                                + beg);
479:
480:                    end = beg + 1; // extract element name
481:                    while (end < len && !Character.isSpace(buf[end])
482:                            && buf[end] != '=' && buf[end] != ','
483:                            && buf[end] != ';')
484:                        end++;
485:                    elem_name = new String(buf, beg, end - beg);
486:
487:                    beg = skipSpace(buf, end);
488:                    if (beg < len && buf[beg] == '=') // element value
489:                    {
490:                        abeg[0] = beg + 1;
491:                        elem_value = parseValue(buf, abeg, header, dequote);
492:                        end = abeg[0];
493:                    } else {
494:                        elem_value = null;
495:                        end = beg;
496:                    }
497:
498:                    NVPair[] params = new NVPair[0];
499:                    params: while (true) {
500:                        String param_name, param_value;
501:
502:                        beg = skipSpace(buf, end); // expect ";"
503:                        if (beg == len || buf[beg] != ';')
504:                            break params;
505:
506:                        beg = skipSpace(buf, beg + 1);
507:                        if (beg == len || buf[beg] == ',') {
508:                            end = beg;
509:                            break params;
510:                        }
511:                        if (buf[beg] == ';') // skip empty parameters
512:                        {
513:                            end = beg;
514:                            continue params;
515:                        }
516:
517:                        if (buf[beg] == '=' || buf[beg] == '"')
518:                            throw new ParseException("Bad header format: '"
519:                                    + header
520:                                    + "'\nEmpty parameter name at position "
521:                                    + beg);
522:
523:                        end = beg + 1; // extract param name
524:                        while (end < len && !Character.isSpace(buf[end])
525:                                && buf[end] != '=' && buf[end] != ','
526:                                && buf[end] != ';')
527:                            end++;
528:                        param_name = new String(buf, beg, end - beg);
529:
530:                        beg = skipSpace(buf, end);
531:                        if (beg < len && buf[beg] == '=') // element value
532:                        {
533:                            abeg[0] = beg + 1;
534:                            param_value = parseValue(buf, abeg, header, dequote);
535:                            end = abeg[0];
536:                        } else {
537:                            param_value = null;
538:                            end = beg;
539:                        }
540:
541:                        params = Util.resizeArray(params, params.length + 1);
542:                        params[params.length - 1] = new NVPair(param_name,
543:                                param_value);
544:                    }
545:
546:                    elems.addElement(new HttpHeaderElement(elem_name,
547:                            elem_value, params));
548:                }
549:
550:                return elems;
551:            }
552:
553:            /**
554:             * Parse the value part. Accepts either token or quoted string.
555:             */
556:            private static String parseValue(char[] buf, int[] abeg,
557:                    String header, boolean dequote) throws ParseException {
558:                int beg = abeg[0], end = beg, len = buf.length;
559:                String value;
560:
561:                beg = skipSpace(buf, beg);
562:
563:                if (beg < len && buf[beg] == '"') // it's a quoted-string
564:                {
565:                    beg++;
566:                    end = beg;
567:                    char[] deq_buf = null;
568:                    int deq_pos = 0, lst_pos = beg;
569:
570:                    while (end < len && buf[end] != '"') {
571:                        if (buf[end] == '\\') {
572:                            if (dequote) // dequote char
573:                            {
574:                                if (deq_buf == null)
575:                                    deq_buf = new char[buf.length];
576:                                System.arraycopy(buf, lst_pos, deq_buf,
577:                                        deq_pos, end - lst_pos);
578:                                deq_pos += end - lst_pos;
579:                                lst_pos = ++end;
580:                            } else
581:                                end++; // skip quoted char
582:                        }
583:
584:                        end++;
585:                    }
586:                    if (end == len)
587:                        throw new ParseException("Bad header format: '"
588:                                + header + "'\nClosing <\"> for quoted-string"
589:                                + " starting at position " + (beg - 1)
590:                                + " not found");
591:                    if (deq_buf != null) {
592:                        System.arraycopy(buf, lst_pos, deq_buf, deq_pos, end
593:                                - lst_pos);
594:                        deq_pos += end - lst_pos;
595:                        value = new String(deq_buf, 0, deq_pos);
596:                    } else
597:                        value = new String(buf, beg, end - beg);
598:                    end++;
599:                } else // it's a simple token value
600:                {
601:                    end = beg;
602:                    while (end < len && !Character.isSpace(buf[end])
603:                            && buf[end] != ',' && buf[end] != ';')
604:                        end++;
605:
606:                    value = new String(buf, beg, end - beg);
607:                }
608:
609:                abeg[0] = end;
610:                return value;
611:            }
612:
613:            /**
614:             * Determines if the given header contains a certain token. The header
615:             * must conform to the rules outlined in parseHeader().
616:             *
617:             * @see #parseHeader(java.lang.String)
618:             * @param header the header value.
619:             * @param token  the token to find; the match is case-insensitive.
620:             * @return true if the token is present, false otherwise.
621:             * @exception ParseException if this is thrown parseHeader().
622:             */
623:            public final static boolean hasToken(String header, String token)
624:                    throws ParseException {
625:                if (header == null)
626:                    return false;
627:                else
628:                    return parseHeader(header).contains(
629:                            new HttpHeaderElement(token));
630:            }
631:
632:            /**
633:             * Get the HttpHeaderElement with the name <var>name</var>.
634:             *
635:             * @param header a vector of HttpHeaderElement's, such as is returned
636:             *               from <code>parseHeader()</code>
637:             * @param name   the name of element to retrieve; matching is
638:             *               case-insensitive
639:             * @return the request element, or null if none found.
640:             * @see #parseHeader(java.lang.String)
641:             */
642:            public final static HttpHeaderElement getElement(Vector header,
643:                    String name) {
644:                int idx = header.indexOf(new HttpHeaderElement(name));
645:                if (idx == -1)
646:                    return null;
647:                else
648:                    return (HttpHeaderElement) header.elementAt(idx);
649:            }
650:
651:            /**
652:             * retrieves the value associated with the parameter <var>param</var> in
653:             * a given header string. It parses the header using
654:             * <code>parseHeader()</code> and then searches the first element for the
655:             * given parameter. This is used especially in headers like
656:             * 'Content-type' and 'Content-Disposition'.
657:             *
658:             * <P>quoted characters ("\x") in a quoted string are dequoted.
659:             *
660:             * @see #parseHeader(java.lang.String)
661:             * @param  param  the parameter name
662:             * @param  hdr    the header value
663:             * @return the value for this parameter, or null if not found.
664:             * @exception ParseException if the above syntax rules are violated.
665:             */
666:            public final static String getParameter(String param, String hdr)
667:                    throws ParseException {
668:                NVPair[] params = ((HttpHeaderElement) parseHeader(hdr)
669:                        .firstElement()).getParams();
670:
671:                for (int idx = 0; idx < params.length; idx++) {
672:                    if (params[idx].getName().equalsIgnoreCase(param))
673:                        return params[idx].getValue();
674:                }
675:
676:                return null;
677:            }
678:
679:            /**
680:             * Assembles a Vector of HttpHeaderElements into a full header string.
681:             * The individual header elements are seperated by a ", ".
682:             *
683:             * @param the parsed header
684:             * @return a string containing the assembled header
685:             */
686:            public final static String assembleHeader(Vector pheader) {
687:                StringBuffer hdr = new StringBuffer(200);
688:                int len = pheader.size();
689:
690:                for (int idx = 0; idx < len; idx++) {
691:                    ((HttpHeaderElement) pheader.elementAt(idx)).appendTo(hdr);
692:                    hdr.append(", ");
693:                }
694:                hdr.setLength(hdr.length() - 2);
695:
696:                return hdr.toString();
697:            }
698:
699:            /**
700:             * returns the position of the first non-space character in a char array
701:             * starting a position pos.
702:             *
703:             * @param str the char array
704:             * @param pos the position to start looking
705:             * @return the position of the first non-space character
706:             */
707:            final static int skipSpace(char[] str, int pos) {
708:                int len = str.length;
709:                while (pos < len && Character.isSpace(str[pos]))
710:                    pos++;
711:                return pos;
712:            }
713:
714:            /**
715:             * returns the position of the first space character in a char array
716:             * starting a position pos.
717:             *
718:             * @param str the char array
719:             * @param pos the position to start looking
720:             * @return the position of the first space character, or the length of
721:             *         the string if not found
722:             */
723:            final static int findSpace(char[] str, int pos) {
724:                int len = str.length;
725:                while (pos < len && !Character.isSpace(str[pos]))
726:                    pos++;
727:                return pos;
728:            }
729:
730:            /**
731:             * returns the position of the first non-token character in a char array
732:             * starting a position pos.
733:             *
734:             * @param str the char array
735:             * @param pos the position to start looking
736:             * @return the position of the first non-token character, or the length
737:             *         of the string if not found
738:             */
739:            final static int skipToken(char[] str, int pos) {
740:                int len = str.length;
741:                while (pos < len && TokenChar.get(str[pos]))
742:                    pos++;
743:                return pos;
744:            }
745:
746:            /**
747:             * Does the string need to be quoted when sent in a header? I.e. does
748:             * it contain non-token characters?
749:             *
750:             * @param str the string
751:             * @return true if it needs quoting (i.e. it contains non-token chars)
752:             */
753:            final static boolean needsQuoting(String str) {
754:                int len = str.length(), pos = 0;
755:
756:                while (pos < len && TokenChar.get(str.charAt(pos)))
757:                    pos++;
758:                return (pos < len);
759:            }
760:
761:            /**
762:             * Compares two http urls for equality. This exists because the method
763:             * <code>java.net.URL.sameFile()</code> is broken (an explicit port 80
764:             * doesn't compare equal to an implicit port, and it doesn't take
765:             * escapes into account).
766:             *
767:             * <P>Two http urls are considered equal if they have the same protocol
768:             * (case-insensitive match), the same host (case-insensitive), the
769:             * same port and the same file (after decoding escaped characters).
770:             *
771:             * @param url1 the first url
772:             * @param url1 the second url
773:             * @return true if <var>url1</var> and <var>url2</var> compare equal
774:             */
775:            public final static boolean sameHttpURL(URL url1, URL url2) {
776:                if (!url1.getProtocol().equalsIgnoreCase(url2.getProtocol()))
777:                    return false;
778:
779:                if (!url1.getHost().equalsIgnoreCase(url2.getHost()))
780:                    return false;
781:
782:                int port1 = url1.getPort(), port2 = url2.getPort();
783:                if (port1 == -1)
784:                    port1 = URI.defaultPort(url1.getProtocol());
785:                if (port2 == -1)
786:                    port2 = URI.defaultPort(url1.getProtocol());
787:                if (port1 != port2)
788:                    return false;
789:
790:                try {
791:                    return URI.unescape(url1.getFile()).equals(
792:                            URI.unescape(url2.getFile()));
793:                } catch (ParseException pe) {
794:                    return url1.getFile().equals(url2.getFile());
795:                }
796:            }
797:
798:            /**
799:             * Return the default port used by a given protocol.
800:             *
801:             * @param protocol the protocol
802:             * @return the port number, or 0 if unknown
803:             * @deprecated use URI.defaultPort() instead
804:             * @see HTTPClient.URI#defaultPort(java.lang.String)
805:             */
806:            public final static int defaultPort(String protocol) {
807:                return URI.defaultPort(protocol);
808:            }
809:
810:            /**
811:             * This returns a string containing the date and time in <var>date</var>
812:             * formatted according to a subset of RFC-1123. The format is defined in
813:             * the HTTP/1.0 spec (RFC-1945), section 3.3, and the HTTP/1.1 spec
814:             * (RFC-2068), section 3.3.1. Note that Date.toGMTString() is close, but
815:             * is missing the weekday and supresses the leading zero if the day is
816:             * less than the 10th. Instead we use the SimpleDateFormat class.
817:             *
818:             * <P>Some versions of JDK 1.1.x are bugged in that their GMT uses
819:             * daylight savings time... Therefore we use our own timezone
820:             * definitions.
821:             *
822:             * @param date the date and time to be converted
823:             * @return a string containg the date and time as used in http
824:             */
825:            public final static String httpDate(Date date) {
826:                if (http_format == null) {
827:                    synchronized (HTTPClient.Util.class) {
828:                        if (http_format == null) {
829:                            http_format = new SimpleDateFormat(
830:                                    "EEE, dd MMM yyyy HH:mm:ss 'GMT'",
831:                                    Locale.US);
832:                            http_format
833:                                    .setTimeZone(new SimpleTimeZone(0, "GMT"));
834:                        }
835:                    }
836:                }
837:
838:                return http_format.format(date);
839:            }
840:
841:            /**
842:             * Escape unsafe characters in a path.
843:             *
844:             * @param path the original path
845:             * @return the path with all unsafe characters escaped
846:             */
847:            final static String escapeUnsafeChars(String path) {
848:                int len = path.length();
849:                char[] buf = new char[3 * len];
850:
851:                int dst = 0;
852:                for (int src = 0; src < len; src++) {
853:                    char ch = path.charAt(src);
854:                    if (ch >= 128 || UnsafeChar.get(ch)) {
855:                        buf[dst++] = '%';
856:                        buf[dst++] = hex_map[(ch & 0xf0) >>> 4];
857:                        buf[dst++] = hex_map[ch & 0x0f];
858:                    } else
859:                        buf[dst++] = ch;
860:                }
861:
862:                if (dst > len)
863:                    return new String(buf, 0, dst);
864:                else
865:                    return path;
866:            }
867:
868:            static final char[] hex_map = { '0', '1', '2', '3', '4', '5', '6',
869:                    '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
870:
871:            /**
872:             * Extract the path from an http resource.
873:             *
874:             * <P>The "resource" part of an HTTP URI can contain a number of parts,
875:             * some of which are not always of interest. These methods here will
876:             * extract the various parts, assuming the following syntanx (taken from
877:             * RFC-2068):
878:             *
879:             * <PRE>
880:             * resource = [ "/" ] [ path ] [ ";" params ] [ "?" query ] [ "#" fragment ]
881:             * </PRE>
882:             *
883:             * @param the resource to split
884:             * @return the path, including any leading "/"
885:             * @see #getParams
886:             * @see #getQuery
887:             * @see #getFragment
888:             */
889:            public final static String getPath(String resource) {
890:                int p, end = resource.length();
891:                if ((p = resource.indexOf('#')) != -1) // find fragment
892:                    end = p;
893:                if ((p = resource.indexOf('?')) != -1 && p < end) // find query
894:                    end = p;
895:                if ((p = resource.indexOf(';')) != -1 && p < end) // find params
896:                    end = p;
897:                return resource.substring(0, end);
898:            }
899:
900:            /**
901:             * Extract the params part from an http resource.
902:             *
903:             * @param the resource to split
904:             * @return the params, or null if there are none
905:             * @see #getPath
906:             */
907:            public final static String getParams(String resource) {
908:                int beg, f, q;
909:                if ((beg = resource.indexOf(';')) == -1) // find params
910:                    return null;
911:                if ((f = resource.indexOf('#')) != -1 && f < beg) // find fragment
912:                    return null;
913:                if ((q = resource.indexOf('?')) != -1 && q < beg) // find query
914:                    return null;
915:                if (q == -1 && f == -1)
916:                    return resource.substring(beg + 1);
917:                if (f == -1 || (q != -1 && q < f))
918:                    return resource.substring(beg + 1, q);
919:                else
920:                    return resource.substring(beg + 1, f);
921:            }
922:
923:            /**
924:             * Extract the query string from an http resource.
925:             *
926:             * @param the resource to split
927:             * @return the query, or null if there was none
928:             * @see #getPath
929:             */
930:            public final static String getQuery(String resource) {
931:                int beg, f;
932:                if ((beg = resource.indexOf('?')) == -1) // find query
933:                    return null;
934:                if ((f = resource.indexOf('#')) != -1 && f < beg) // find fragment
935:                    return null; // '?' is in fragment
936:                if (f == -1)
937:                    return resource.substring(beg + 1); // no fragment
938:                else
939:                    return resource.substring(beg + 1, f); // strip fragment
940:            }
941:
942:            /**
943:             * Extract the fragment part from an http resource.
944:             *
945:             * @param the resource to split
946:             * @return the fragment, or null if there was none
947:             * @see #getPath
948:             */
949:            public final static String getFragment(String resource) {
950:                int beg;
951:                if ((beg = resource.indexOf('#')) == -1) // find fragment
952:                    return null;
953:                else
954:                    return resource.substring(beg + 1);
955:            }
956:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.