Source Code Cross Referenced for URLParser.java in  » 6.0-JDK-Modules » j2me » gov » nist » siplite » parser » 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 » 6.0 JDK Modules » j2me » gov.nist.siplite.parser 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Portions Copyright  2000-2007 Sun Microsystems, Inc. All Rights
003:         * Reserved.  Use is subject to license terms.
004:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
005:         * 
006:         * This program is free software; you can redistribute it and/or
007:         * modify it under the terms of the GNU General Public License version
008:         * 2 only, as published by the Free Software Foundation.
009:         * 
010:         * This program is distributed in the hope that it will be useful, but
011:         * WITHOUT ANY WARRANTY; without even the implied warranty of
012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013:         * General Public License version 2 for more details (a copy is
014:         * included at /legal/license.txt).
015:         * 
016:         * You should have received a copy of the GNU General Public License
017:         * version 2 along with this work; if not, write to the Free Software
018:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019:         * 02110-1301 USA
020:         * 
021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
022:         * Clara, CA 95054 or visit www.sun.com if you need additional
023:         * information or have any questions.
024:         */
025:        package gov.nist.siplite.parser;
026:
027:        import gov.nist.siplite.address.*;
028:        import gov.nist.core.*;
029:        import java.util.Vector;
030:
031:        /**
032:         * Parser For SIP and Tel URLs. Other kinds of URL's are handled by the
033:         * J2SE 1.4 URL class.
034:         * @version JAIN-SIP-1.1
035:         *
036:         *
037:         * <a href="{@docRoot}/uncopyright.html">This code is in the public domain.</a>
038:         *
039:         */
040:        public class URLParser extends Parser {
041:
042:            /** Symbols of phone digit (RFC 2806, 2.2) */
043:            private static final String PHONE_DIGIT = "01234567890-.()";
044:
045:            /** Symbols of dtmf digit (RFC 2806, 2.2) */
046:            private static final String DTMF_DIGIT = "*#ABCD";
047:
048:            /** Pause characters (RFC 2806, 2.2) */
049:            private static final String PAUSE_CHAR = "pw";
050:
051:            /**
052:             * Constructor with initial URL string.
053:             * @param url initial URL
054:             */
055:            public URLParser(String url) {
056:                this .lexer = new Lexer("sip_urlLexer", url);
057:
058:            }
059:
060:            /**
061:             * Constructor with initial lexer engine.
062:             * @param lexer initial lexer engine
063:             */
064:            URLParser(Lexer lexer) {
065:                this .lexer = lexer;
066:                this .lexer.selectLexer("sip_urlLexer");
067:            }
068:
069:            /**
070:             * Checks if character is punctuation mark.
071:             * @param next character to be checked
072:             * @return true if character is punctuation mark
073:             */
074:            protected static boolean isMark(char next) {
075:                return next == '-' || next == '_' || next == '.' || next == '!'
076:                        || next == '~' || next == '*' || next == '\''
077:                        || next == '(' || next == ')';
078:            }
079:
080:            /**
081:             * Checks if character is reserved.
082:             * @param next character to be checked
083:             * @return true if reserved character.
084:             */
085:            protected static boolean isUnreserved(char next) {
086:                return Lexer.isAlpha(next) || Lexer.isDigit(next)
087:                        || isMark(next);
088:
089:            }
090:
091:            /**
092:             * Checks if reserved character without a slash.
093:             * @param next character to be checked
094:             * @return true if reserved character without a slash
095:             */
096:            protected static boolean isReservedNoSlash(char next) {
097:                return next == ';' || next == '?' || next == ':' || next == '@'
098:                        || next == '&' || next == '+' || next == '$'
099:                        || next == ',';
100:
101:            }
102:
103:            // Missing '=' CR in character set - discovered by interop testing
104:            // at SIPIT 13 by Bob Johnson and Scott Holben.
105:            // Replace . by; 
106:            /**
107:             * Checks if user is unreserved.
108:             * @param la the character to be checked
109:             * @return true if user is not reserved
110:             */
111:            protected static boolean isUserUnreserved(char la) {
112:                return la == '&' || la == '?' || la == '+' || la == '$'
113:                        || la == '#' || la == '/' || la == ',' || la == ';'
114:                        || la == '=';
115:            }
116:
117:            /**
118:             * Gets the unreserved string of characters.
119:             * @return unreserved characters
120:             */
121:            protected String unreserved() throws ParseException {
122:                char next = lexer.lookAhead(0);
123:                if (isUnreserved(next)) {
124:                    lexer.consume(1);
125:                    return new StringBuffer().append(next).toString();
126:                } else
127:                    throw createParseException("unreserved");
128:
129:            }
130:
131:            /**
132:             * Name or value of a parameter.
133:             * @return parsed name or value
134:             * @exception ParseException if a parsing error occurs
135:             */
136:            protected String paramNameOrValue() throws ParseException {
137:                StringBuffer retval = new StringBuffer();
138:                while (lexer.hasMoreChars()) {
139:                    char next = lexer.lookAhead(0);
140:                    if (next == '[' || next == '[' || next == '/'
141:                            || next == ':' || next == '&' || next == '+'
142:                            || next == '$' || next == '#' || isUnreserved(next)) {
143:                        retval.append(next);
144:                        lexer.consume(1);
145:                    } else if (isEscaped()) {
146:                        String esc = lexer.charAsString(3);
147:                        lexer.consume(3);
148:                        retval.append(esc);
149:                    } else
150:                        break;
151:                }
152:                return retval.toString();
153:            }
154:
155:            /**
156:             * Gets the URI pamaeter.
157:             * @return the parsed URI parameter
158:             * @exception ParseException if a parsin error occurs
159:             */
160:            protected NameValue uriParam() throws ParseException {
161:                if (debug)
162:                    dbg_enter("uriParam");
163:                try {
164:                    String pvalue = null;
165:                    String pname = paramNameOrValue();
166:                    char next = lexer.lookAhead(0);
167:                    if (next == LexerCore.EQUALS) {
168:                        lexer.consume(1);
169:                        next = lexer.lookAhead(0);
170:                        if (next == LexerCore.DOUBLEQUOTE) {
171:                            pvalue = "\"" + lexer.quotedString() + "\""; // quoted param
172:                        } else { // unquoted parameter
173:                            pvalue = paramNameOrValue();
174:                        }
175:                    }
176:                    return new NameValue(pname, (pvalue == null) ? "" : pvalue);
177:                } finally {
178:                    if (debug)
179:                        dbg_leave("uriParam");
180:                }
181:            }
182:
183:            /**
184:             * Checks if character is reserved.
185:             * @param next character to be checked
186:             * @return true if character is reserved
187:             */
188:            protected static boolean isReserved(char next) {
189:                return next == ';' || next == '/' || next == '?' || next == ':'
190:                        || next == '@' || next == '&' || next == '+'
191:                        || next == '$' || next == '=' || next == ',';
192:            }
193:
194:            /**
195:             * Gets the listof reserved characters.
196:             * @return string of reserved characters.
197:             */
198:            protected String reserved() throws ParseException {
199:                char next = lexer.lookAhead(0);
200:                if (isReserved(next)) {
201:                    lexer.consume(1);
202:                    return new StringBuffer().append(next).toString();
203:                } else
204:                    throw createParseException("reserved");
205:            }
206:
207:            /**
208:             * Checks if current character is escaped.
209:             * @return true if processing an escaped sequenec
210:             */
211:            protected boolean isEscaped() {
212:                try {
213:                    char next = lexer.lookAhead(0);
214:                    char next1 = lexer.lookAhead(1);
215:                    char next2 = lexer.lookAhead(2);
216:                    return (next == '%' && Lexer.isHexDigit(next1) && Lexer
217:                            .isHexDigit(next2));
218:                } catch (ParseException ex) {
219:                    return false;
220:                }
221:            }
222:
223:            /**
224:             * Gets the escaped character sequence.
225:             * @return the escaped character sequence
226:             */
227:            protected String escaped() throws ParseException {
228:                if (debug)
229:                    dbg_enter("escaped");
230:                try {
231:                    StringBuffer retval = new StringBuffer();
232:                    char next = lexer.lookAhead(0);
233:                    char next1 = lexer.lookAhead(1);
234:                    char next2 = lexer.lookAhead(2);
235:                    if (next == '%' && Lexer.isHexDigit(next1)
236:                            && Lexer.isHexDigit(next2)) {
237:                        lexer.consume(3);
238:                        retval.append(next);
239:                        retval.append(next1);
240:                        retval.append(next2);
241:                    } else
242:                        throw createParseException("escaped");
243:                    return retval.toString();
244:                } finally {
245:                    if (debug)
246:                        dbg_leave("escaped");
247:                }
248:            }
249:
250:            /**
251:             * Remembers the current stream position.
252:             * @return the current marked position
253:             */
254:            protected String mark() throws ParseException {
255:                if (debug)
256:                    dbg_enter("mark");
257:                try {
258:                    char next = lexer.lookAhead(0);
259:                    if (isMark(next)) {
260:                        lexer.consume(1);
261:                        return new StringBuffer().append(next).toString();
262:                    } else
263:                        throw createParseException("mark");
264:                } finally {
265:                    if (debug)
266:                        dbg_leave("mark");
267:                }
268:            }
269:
270:            /**
271:             * Gets the uric.
272:             * @return the uric
273:             */
274:            protected String uric() {
275:                if (debug)
276:                    dbg_enter("uric");
277:                try {
278:                    try {
279:                        char la = lexer.lookAhead(0);
280:                        if (isUnreserved(la)) {
281:                            lexer.consume(1);
282:                            return Lexer.charAsString(la);
283:                        } else if (isReserved(la)) {
284:                            lexer.consume(1);
285:                            return Lexer.charAsString(la);
286:                        } else if (isEscaped()) {
287:                            String retval = lexer.charAsString(3);
288:                            lexer.consume(3);
289:                            return retval;
290:                        } else
291:                            return null;
292:                    } catch (ParseException ex) {
293:                        return null;
294:                    }
295:                } finally {
296:                    if (debug)
297:                        dbg_leave("uric");
298:                }
299:
300:            }
301:
302:            /**
303:             * Gets the uric without slashes.
304:             * @return the uric string without slashes.
305:             */
306:            protected String uricNoSlash() {
307:                if (debug)
308:                    dbg_enter("uricNoSlash");
309:                try {
310:                    try {
311:                        char la = lexer.lookAhead(0);
312:                        if (isEscaped()) {
313:                            String retval = lexer.charAsString(3);
314:                            lexer.consume(3);
315:                            return retval;
316:                        } else if (isUnreserved(la)) {
317:                            lexer.consume(1);
318:                            return Lexer.charAsString(la);
319:                        } else if (isReservedNoSlash(la)) {
320:                            lexer.consume(1);
321:                            return Lexer.charAsString(la);
322:                        } else
323:                            return null;
324:                    } catch (ParseException ex) {
325:                        return null;
326:                    }
327:                } finally {
328:                    if (debug)
329:                        dbg_leave("uricNoSlash");
330:                }
331:            }
332:
333:            /**
334:             * Gets the uric string.
335:             * @return the uric string
336:             */
337:            protected String uricString() {
338:                StringBuffer retval = new StringBuffer();
339:                while (true) {
340:                    String next = uric();
341:                    if (next == null)
342:                        break;
343:                    retval.append(next);
344:                }
345:                return retval.toString();
346:            }
347:
348:            /**
349:             * Parses and return a structure for a generic URL.
350:             * Note that non SIP URLs are just stored as a string (not parsed).
351:             * @return URI is a URL structure for a SIP url.
352:             * @throws ParsException if there was a problem parsing.
353:             */
354:            public URI uriReference() throws ParseException {
355:                if (debug)
356:                    dbg_enter("uriReference");
357:
358:                URI retval = null;
359:                Vector vect = lexer.peekNextToken(2);
360:                Token t1 = (Token) vect.elementAt(0);
361:                Token t2 = (Token) vect.elementAt(1);
362:
363:                try {
364:                    // System.out.println("token = " + t1.getTokenValue());
365:                    // System.out.println("tokentype = " + t1.getTokenType());
366:
367:                    int type1, type2;
368:                    type1 = t1.getTokenType();
369:
370:                    // Create an URI
371:                    if (t2.getTokenType() == ':') {
372:                        if (type1 == TokenTypes.SIP || type1 == TokenTypes.SIPS) {
373:                            // SIP or SIPS URL
374:                            retval = sipURL(t1);
375:                        } else if (type1 == TokenTypes.TEL) {
376:                            // TEL URL
377:                            retval = telURL();
378:                        } else {
379:                            // Generic URL
380:
381:                            /*
382:                             * We can't throw an exception here because according to
383:                             * RFC 3261, p. 224 the scheme may be different from
384:                             * sip/sips/tel.
385:                             * In Connector.open(scheme) only 'sip' and 'sips'
386:                             * schemes are allowed, but this is not a problem
387:                             * because the package path where VM will try to find
388:                             * Protocol.class contains the scheme's name and an
389:                             * exception will be thrown if it is invalid.
390:                             */
391:                            retval = new URI(lexer.getString('>'));
392:
393:                            int pos = lexer.markInputPosition();
394:                            // It's safe to use 'pos-1' because at least
395:                            // one character ('>') was read from the buffer.
396:                            lexer.rewindInputPosition(pos - 1);
397:                        }
398:                    } else {
399:                        throw createParseException("Expecting \':\'");
400:                    }
401:
402:                } finally {
403:                    if (debug)
404:                        dbg_leave("uriReference");
405:                }
406:
407:                return retval;
408:            }
409:
410:            /**
411:             * Parses for the base phone number.
412:             * @return the base phone number
413:             * @exception ParseException if a parsingerror occurs
414:             */
415:            private String base_phone_number() throws ParseException {
416:                StringBuffer s = new StringBuffer();
417:
418:                if (debug)
419:                    dbg_enter("base_phone_number");
420:                try {
421:                    int lc = 0;
422:                    while (lexer.hasMoreChars()) {
423:                        char w = lexer.lookAhead(0);
424:                        if (LexerCore.isDigit(w) || w == '-' || w == '.'
425:                                || w == '(' || w == ')') {
426:                            lexer.consume(1);
427:                            s.append(w);
428:                            lc++;
429:                        } else if (lc > 0)
430:                            break;
431:                        else
432:                            throw createParseException("unexpected " + w);
433:                    }
434:                    return s.toString();
435:                } finally {
436:                    if (debug)
437:                        dbg_leave("base_phone_number");
438:                }
439:
440:            }
441:
442:            /**
443:             * Parses for the local phone number.
444:             * @return the local phone number
445:             * @exception ParseException if a parsing error occurs
446:             */
447:            private String local_number() throws ParseException {
448:                StringBuffer s = new StringBuffer();
449:                if (debug)
450:                    dbg_enter("local_number");
451:                try {
452:                    int lc = 0;
453:                    while (lexer.hasMoreChars()) {
454:                        char la = lexer.lookAhead(0);
455:                        if (la == '*' || la == '#' || la == '-' || la == '.'
456:                                || la == '(' || la == ')'
457:                                || LexerCore.isDigit(la)) {
458:                            lexer.consume(1);
459:                            s.append(la);
460:                            lc++;
461:                        } else if (lc > 0)
462:                            break;
463:                        else
464:                            throw createParseException("unexepcted " + la);
465:                    }
466:                    return s.toString();
467:                } finally {
468:                    if (debug)
469:                        dbg_leave("local_number");
470:                }
471:
472:            }
473:
474:            /**
475:             * Parses for telephone subscriber.
476:             *
477:             * @return the parsed telephone number.
478:             * @exception ParseException if a parsing error occurs
479:             */
480:            public final TelephoneNumber parseTelephoneNumber()
481:                    throws ParseException {
482:                TelephoneNumber tn;
483:
484:                if (debug)
485:                    dbg_enter("telephone_subscriber");
486:                lexer.selectLexer("charLexer");
487:                try {
488:                    char c = lexer.lookAhead(0);
489:                    if (c == '+')
490:                        tn = global_phone_number();
491:                    else if (LexerCore.isAlpha(c) || LexerCore.isDigit(c)
492:                            || c == '-' || c == '*' || c == '.' || c == '('
493:                            || c == ')' || c == '#') {
494:                        tn = local_phone_number();
495:                    } else
496:                        throw createParseException("unexpected char " + c);
497:                    return tn;
498:                } finally {
499:                    if (debug)
500:                        dbg_leave("telephone_subscriber");
501:                }
502:
503:            }
504:
505:            /**
506:             * Gets the global phone number.
507:             * @return the parsed phone number
508:             * @exception  ParseException ifa parsing error occurs
509:             */
510:            private final TelephoneNumber global_phone_number()
511:                    throws ParseException {
512:                if (debug)
513:                    dbg_enter("global_phone_number");
514:                try {
515:                    TelephoneNumber tn = new TelephoneNumber();
516:                    tn.setGlobal(true);
517:                    NameValueList nv = null;
518:                    this .lexer.match(PLUS);
519:                    String b = base_phone_number();
520:                    tn.setPhoneNumber(b);
521:                    if (lexer.hasMoreChars()) {
522:                        char tok = lexer.lookAhead(0);
523:                        if (tok == ';') {
524:                            nv = tel_parameters();
525:                            tn.setParameters(nv);
526:                        }
527:                    }
528:                    return tn;
529:                } finally {
530:                    if (debug)
531:                        dbg_leave("global_phone_number");
532:                }
533:            }
534:
535:            /**
536:             * Gets the local phone number.
537:             * @return the parsed phone number
538:             * @exception  ParseException ifa parsing error occurs
539:             */
540:            private TelephoneNumber local_phone_number() throws ParseException {
541:                if (debug)
542:                    dbg_enter("local_phone_number");
543:                TelephoneNumber tn = new TelephoneNumber();
544:                tn.setGlobal(false);
545:                NameValueList nv = null;
546:                String b = null;
547:                try {
548:                    b = local_number();
549:                    tn.setPhoneNumber(b);
550:                    if (lexer.hasMoreChars()) {
551:                        Token tok = this .lexer.peekNextToken();
552:                        switch (tok.getTokenType()) {
553:                        case SEMICOLON: {
554:                            nv = tel_parameters();
555:                            tn.setParameters(nv);
556:                            break;
557:                        }
558:                        default: {
559:                            break;
560:                        }
561:                        }
562:                    }
563:                } finally {
564:                    if (debug)
565:                        dbg_leave("local_phone_number");
566:                }
567:                return tn;
568:            }
569:
570:            /**
571:             * Gets the telephone field parameters.
572:             * @return the telephone parameters
573:             * @exception ParseException if a parsing error occurs
574:             */
575:            private NameValueList tel_parameters() throws ParseException {
576:                NameValueList nvList = new NameValueList();
577:                while (lexer.hasMoreChars()) {
578:                    lexer.consume(1);
579:                    NameValue nv = uriParam();
580:                    String nameParam = nv.getName();
581:                    String valueParam = (String) (nv.getValue());
582:                    if (nameParam.equalsIgnoreCase("isub")) {
583:                        // RFC 2806, 2.2
584:                        // isdn-subaddress       = ";isub=" 1*phonedigit
585:                        // phonedigit            = DIGIT / visual-separator
586:                        // visual-separator      = "-" / "." / "(" / ")"
587:                        byte[] valueBytes = valueParam.getBytes();
588:                        for (int i = 0; i < valueBytes.length; i++) {
589:                            if (!isPhoneDigit(valueBytes[i])) {
590:                                throw new IllegalArgumentException(
591:                                        "Wrong isdn-subaddress");
592:                            }
593:                        }
594:                    } else if (nameParam.equalsIgnoreCase("postd")) {
595:                        // RFC 2806, 2.2
596:                        // post-dial             = ";postd=" 1*(phonedigit /
597:                        //                         dtmf-digit / pause-character)
598:                        // dtmf-digit            = "*" / "#" / "A" / "B" / "C" / "D"
599:                        // pause-character       = one-second-pause / wait-for-dial-tone
600:                        // one-second-pause      = "p"
601:                        // wait-for-dial-tone    = "w"
602:                        byte[] valueBytes = valueParam.getBytes();
603:                        for (int i = 0; i < valueBytes.length; i++) {
604:                            int ch = valueBytes[i];
605:                            if (!isPhoneDigit(ch) && !isDtmf_digit(ch)
606:                                    && !isPauseChar(ch)) {
607:                                throw new IllegalArgumentException(
608:                                        "Wrong post-dial");
609:                            }
610:                        }
611:                    }
612:                    nvList.add(nv);
613:                    char tok = lexer.lookAhead(0);
614:                    if (tok == ';')
615:                        continue;
616:                    else
617:                        break;
618:                }
619:                return nvList;
620:            }
621:
622:            /**
623:             * Checks that the given symbol os a phonedigit.
624:             * RFC 2806, 2.2
625:             * phonedigit            = DIGIT / visual-separator
626:             * visual-separator      = "-" / "." / "(" / ")"
627:             * @param ch is a given byte to checking
628:             * @return true if the given char is a phonedigit
629:             */
630:            private boolean isPhoneDigit(int ch) {
631:                return isCharFromString(ch, PHONE_DIGIT);
632:            }
633:
634:            /**
635:             * Checks that the given symbol is a dtmf digit.
636:             * RFC 2806, 2.2
637:             * dtmf-digit            = "*" / "#" / "A" / "B" / "C" / "D"
638:             * @param ch is a given byte to checking
639:             * @return true if the given char is a dtmf digit
640:             */
641:            private boolean isDtmf_digit(int ch) {
642:                return isCharFromString(ch, DTMF_DIGIT);
643:            }
644:
645:            /**
646:             * Checks that the given symbol is a pause character.
647:             * pause-character       = one-second-pause / wait-for-dial-tone
648:             * one-second-pause      = "p"
649:             * wait-for-dial-tone    = "w"
650:             * @param ch is a given byte to checking
651:             * @return true if the given char is a dtmf digit
652:             */
653:            private boolean isPauseChar(int ch) {
654:                return isCharFromString(ch, PAUSE_CHAR);
655:            }
656:
657:            /**
658:             * Checks that the given symbol contains into a string.
659:             * @param ch is a given byte to checking
660:             * @param str is a string for checking
661:             * @return true if the given char can be find in a string
662:             */
663:            private boolean isCharFromString(int ch, String str) {
664:                return (str.indexOf(ch) != -1);
665:            }
666:
667:            /**
668:             * Parses and returns a structure for a Tel URL.
669:             * @return a parsed tel url structure.
670:             * @exception ParseException if a parsing error occurs
671:             */
672:            public TelURL telURL() throws ParseException {
673:                lexer.match(TokenTypes.TEL);
674:                lexer.match(':');
675:                TelephoneNumber tn = this .parseTelephoneNumber();
676:                TelURL telUrl = new TelURL();
677:                telUrl.setTelephoneNumber(tn);
678:                return telUrl;
679:            }
680:
681:            /**
682:             * Parses and returns a structure for a SIP URL.
683:             * @param token the token of scheme (SIP or SIPS)
684:             * @return a URL structure for a SIP url.
685:             * @throws ParsException if there was a problem parsing.
686:             * @throws IllegalArgumentException when parsing error is fatal.
687:             */
688:            public SipURI sipURL(Token token) throws ParseException {
689:                if (debug)
690:                    dbg_enter("sipURL");
691:
692:                char la;
693:                SipURI retval = new SipURI();
694:
695:                try {
696:                    lexer.match(token.getTokenType());
697:                    lexer.match(':');
698:                    retval.setScheme(token.getTokenValue());
699:                    if (!lexer.hasMoreChars()) { // sip: - server dedicated URI
700:                        retval.setServer();
701:                        return retval;
702:                    }
703:                    int m = lexer.markInputPosition();
704:                    // get user part
705:                    String user = user();
706:                    if (!lexer.hasMoreChars()) { // nosymbols after user name  
707:                        lexer.rewindInputPosition(m); // move to start of host
708:                    } else { // check symbols after user name    
709:                        // maybe sip:host
710:                        la = lexer.lookAhead(0);
711:                        // check that user field is not empty
712:                        if (la == ':' || la == '@') { // sip:user@... or sip:user:pass
713:                            if (user.length() == 0) {
714:                                throw new IllegalArgumentException(
715:                                        "User field is missed");
716:                            }
717:                            if (la == ':') {
718:                                // sip:user:passw...
719:                                lexer.consume(1);
720:                                String password = password();
721:                                if (!lexer.hasMoreChars()
722:                                        || lexer.lookAhead(0) != '@') {
723:                                    if (StringTokenizer.isDigitString(password)) {
724:                                        // maybe sip:host:port - move to start of host
725:                                        lexer.rewindInputPosition(m);
726:                                    } else { // sip:user:pass<wrong symbol>
727:                                        throw new IllegalArgumentException(
728:                                                "Expecting \"@\"");
729:                                    }
730:                                } else { // sip:user:pass@...
731:                                    retval.setUser(user);
732:                                    retval.setUserPassword(password);
733:                                    lexer.consume(1);
734:                                }
735:                            } else { // la == '@'
736:                                retval.setUser(user);
737:                                lexer.consume(1);
738:                            }
739:                        } else { // no '@' after user field - maybe sip:host...
740:                            lexer.rewindInputPosition(m); // move to start of host
741:                        }
742:                    }
743:                    // check for sip:*
744:                    la = lexer.lookAhead(0);
745:                    if (la == '*') {
746:                        lexer.consume(1);
747:                        // server shared URI
748:                        retval.setServer();
749:                        retval.setShared();
750:                    } else if (la == ';') { // sip:;...
751:                        retval.setServer();
752:                    } else { // try to read host
753:                        // host parsing
754:                        HostNameParser hnp = new HostNameParser(this .getLexer());
755:                        HostPort hp = hnp.hostPort();
756:                        String host = hp.getHost().getHostname();
757:                        if (host == null) { // maybe sip:5060
758:                            if (hp.hasPort()) { // port only - server URI
759:                                retval.setServer();
760:                            } else { // sip:1234:5678 - wrong format
761:                                throw new IllegalArgumentException(
762:                                        "Illegal URI format");
763:                            }
764:                        }
765:                        retval.setHostPort(hp);
766:                    }
767:
768:                    lexer.selectLexer("charLexer");
769:
770:                    // parse parameters
771:                    while (lexer.hasMoreChars()) {
772:                        if (lexer.lookAhead(0) != ';')
773:                            break;
774:                        lexer.consume(1);
775:                        NameValue parms = uriParam();
776:                        if (retval.hasParameter(parms.getName())) {
777:                            throw new IllegalArgumentException(
778:                                    "Found duplicate of parameter ");
779:                        }
780:                        if (parms.isValueQuoted() && !retval.isServer()) {
781:                            throw new IllegalArgumentException(
782:                                    "Client URI cannot contain quoted parameter ");
783:                        }
784:                        retval.setUriParameter(parms);
785:                    }
786:
787:                    if (lexer.hasMoreChars() && lexer.lookAhead(0) == '?') {
788:                        if (retval.isServer()) {
789:                            throw new IllegalArgumentException(
790:                                    "Server URI cannot contain headers");
791:                        }
792:                        lexer.consume(1);
793:                        while (lexer.hasMoreChars()) {
794:                            NameValue parms = qheader();
795:                            retval.setQHeader(parms);
796:                            if (lexer.hasMoreChars()
797:                                    && lexer.lookAhead(0) != '&')
798:                                break;
799:                            else
800:                                lexer.consume(1);
801:                        }
802:                    }
803:
804:                    return retval;
805:                } finally {
806:                    if (debug)
807:                        dbg_leave("sipURL");
808:                }
809:            }
810:
811:            /**
812:             * Peeks at the scheme field.
813:             * @return the protocol scheme
814:             * @exception ParseException if a parsing error occurs
815:             */
816:            public String peekScheme() throws ParseException {
817:                Vector tokens = lexer.peekNextToken(1);
818:
819:                if (tokens.size() == 0)
820:                    return null;
821:
822:                String scheme = ((Token) tokens.elementAt(0)).getTokenValue();
823:                return scheme;
824:            }
825:
826:            /**
827:             * Gets a name value for a given query header (ie one that comes
828:             * after the ?).
829:             * @return name value pair for q-header
830:             * @exception ParseException if a parsing error occurs
831:             */
832:            protected NameValue qheader() throws ParseException {
833:
834:                String name = lexer.getNextToken('=');
835:                lexer.consume(1);
836:                String value = hvalue();
837:                return new NameValue(name, value);
838:
839:            }
840:
841:            /**
842:             * Gets a header value.
843:             * @return value of current header
844:             * @exception ParseException if a parsing error occurs
845:             */
846:            protected String hvalue() throws ParseException {
847:                StringBuffer retval = new StringBuffer();
848:                while (lexer.hasMoreChars()) {
849:                    char la = lexer.lookAhead(0);
850:                    // Look for a character that can terminate a URL.
851:                    if (la == '+' || la == '?' || la == ':' || la == '@'
852:                            || la == '[' || la == ']' || la == '/' || la == '$'
853:                            || la == '_' || la == '-' || la == '"' || la == '!'
854:                            || la == '~' || la == '*' || la == '.' || la == '('
855:                            || la == ')' || LexerCore.isAlpha(la)
856:                            || LexerCore.isDigit(la)) {
857:                        lexer.consume(1);
858:                        retval.append(la);
859:                    } else if (la == '%') {
860:                        retval.append(escaped());
861:                    } else
862:                        break;
863:                }
864:                return retval.toString();
865:            }
866:
867:            /**
868:             * Scans forward until you hit a terminating character for a URL.
869:             * We do not handle non sip urls in this implementation.
870:             * @return the string that takes us to the end of this URL (i.e. to
871:             * the next delimiter).
872:             * @exception ParseException if a parsing error occurs
873:             */
874:            protected String urlString() throws ParseException {
875:                StringBuffer retval = new StringBuffer();
876:                lexer.selectLexer("charLexer");
877:
878:                while (lexer.hasMoreChars()) {
879:                    char la = lexer.lookAhead(0);
880:                    // Look for a character that can terminate a URL.
881:                    if (la == ' ' || la == '\t' || la == '\n' || la == '>'
882:                            || la == '<')
883:                        break;
884:                    lexer.consume(0);
885:                    retval.append(la);
886:                }
887:                return retval.toString();
888:            }
889:
890:            /**
891:             * Gets the user field from the URI.
892:             * @return ths parsed user field
893:             * @exception ParseException if a parsing error occurs
894:             */
895:            protected String user() throws ParseException {
896:
897:                if (debug)
898:                    dbg_enter("user");
899:                try {
900:                    StringBuffer retval = new StringBuffer();
901:                    while (lexer.hasMoreChars()) {
902:                        char la = lexer.lookAhead(0);
903:                        if (isUnreserved(la) || isUserUnreserved(la)) {
904:                            retval.append(la);
905:                            lexer.consume(1);
906:                        } else if (isEscaped()) {
907:                            String esc = lexer.charAsString(3);
908:                            lexer.consume(3);
909:                            retval.append(esc);
910:                        } else
911:                            break;
912:                    }
913:                    return retval.toString();
914:                } finally {
915:                    if (debug)
916:                        dbg_leave("user");
917:                }
918:
919:            }
920:
921:            /**
922:             * Gets the password field from the URI.
923:             * @return ths parsed password field
924:             * @exception ParseException if a parsing error occurs
925:             */
926:            protected String password() throws ParseException {
927:                StringBuffer retval = new StringBuffer();
928:                while (true) {
929:                    char la = lexer.lookAhead(0);
930:                    if (isUnreserved(la) || la == '&' || la == '=' || la == '+'
931:                            || la == '$' || la == ',') {
932:                        retval.append(la);
933:                        lexer.consume(1);
934:                    } else if (isEscaped()) {
935:                        String esc = lexer.charAsString(3);
936:                        retval.append(esc);
937:                        // CR FIX from Jeff Haynie frm JAIN-SIP
938:                        lexer.consume(3);
939:                    } else
940:                        break;
941:                }
942:                return retval.toString();
943:            }
944:
945:            /**
946:             * Default parse method. This method just calls uriReference.
947:             * @return ths parsed URI
948:             * @exception ParseException if a parsing error occurs
949:             */
950:            public URI parse() throws ParseException {
951:                return uriReference();
952:            }
953:
954:            /**
955:             * Parse method with checking the rest of input URL.
956:             * @return ths parsed URI
957:             * @exception ParseException if a parsing error occurs
958:             */
959:            public URI parseWholeString() throws ParseException {
960:                URI retValue = uriReference();
961:                if (lexer.hasMoreChars()) {
962:                    throw createParseException("redundant symbols");
963:                }
964:                return retValue;
965:            }
966:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.