Source Code Cross Referenced for MMSAddress.java in  » 6.0-JDK-Modules » j2me » com » sun » tck » wma » mms » 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 » com.sun.tck.wma.mms 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *   
0003:         *
0004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006:         * 
0007:         * This program is free software; you can redistribute it and/or
0008:         * modify it under the terms of the GNU General Public License version
0009:         * 2 only, as published by the Free Software Foundation.
0010:         * 
0011:         * This program is distributed in the hope that it will be useful, but
0012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014:         * General Public License version 2 for more details (a copy is
0015:         * included at /legal/license.txt).
0016:         * 
0017:         * You should have received a copy of the GNU General Public License
0018:         * version 2 along with this work; if not, write to the Free Software
0019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020:         * 02110-1301 USA
0021:         * 
0022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023:         * Clara, CA 95054 or visit www.sun.com if you need additional
0024:         * information or have any questions.
0025:         */
0026:
0027:        package com.sun.tck.wma.mms;
0028:
0029:        /**
0030:         * MMS address parsing and validation.
0031:         * MMS address is validated according to Table D-2 in WMA2.0 specification.
0032:         * In addition address is parsed into the fields of <code>MMSAddress </code>
0033:         * object.
0034:         */
0035:        public class MMSAddress {
0036:
0037:            /**
0038:             * Determines whether a character represents a hexadecimal number.
0039:             * ('0' - '9' and 'A' - 'F')
0040:             * @param c The character to check.
0041:             * @return <code>true </code> if <code>c</code> is a hexadecimal number;
0042:             * <code> false </code> otherwise
0043:             */
0044:            private static boolean hex(char c) {
0045:                return (digit(c) || (c >= 'A' && c <= 'F'));
0046:            }
0047:
0048:            /**
0049:             * Determines whether a character is a letter.
0050:             * @param c The character to check.
0051:             * @return <code>true </code> if <code>c</code> is a letter; 
0052:             * <code> false </code> otherwise
0053:             */
0054:            private static boolean alpha(char c) {
0055:                return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
0056:            }
0057:
0058:            /**
0059:             * Determines whether a character represents a digit.
0060:             * @param c The character to check.
0061:             * @return <code>true </code> if <code>c</code> is a digit; 
0062:             * <code> false </code> otherwise
0063:             */
0064:            private static boolean digit(char c) {
0065:                return (c >= '0' && c <= '9');
0066:            }
0067:
0068:            /**
0069:             * Determines whether a string represents a valid phone number
0070:             * starting from an index. If the address string is a valid
0071:             * phone number representation it is parsed into the fields of 
0072:             * <code>MMSAddress </code>object (address and application id).
0073:             * General phone number syntax is specified in WMA 2.0 spec as :
0074:             * ("+" 1*digit | 1*digit) [applicationId]
0075:             *
0076:             * @param s The string to check.
0077:             * @param mmsAddress The return <code>MMSAddress</code> object which
0078:             * fields are filled with parsed address and
0079:             * application id (which can be null), 
0080:             * its type is set to GLOBAL_PHONE_NUMBER.
0081:             * @param i The index of the string at which to start the check. 
0082:             * <code> 0 <= i <= s.length() </code> 
0083:             *
0084:             * @return <code>true </code> if <code>s</code> represents a valid 
0085:             * phone number starting from index <code>i</code>;
0086:             * <code> false </code> otherwise and if index <code>i</code> is
0087:             * invalide value
0088:             */
0089:            static boolean parsePhoneNumber(String s, int i,
0090:                    MMSAddress mmsAddress) {
0091:
0092:                int len = s.length();
0093:                if (i < 0 || i >= len) {
0094:                    return false;
0095:                }
0096:
0097:                int initI = i;
0098:                char c = s.charAt(i);
0099:
0100:                if (c == '+') {
0101:                    i++;
0102:                    if (len == i) {
0103:                        return false;
0104:                    }
0105:                }
0106:
0107:                int j = 0;
0108:                for (; i < len; j++, i++) {
0109:                    c = s.charAt(i);
0110:                    if (!digit(c)) {
0111:                        break;
0112:                    }
0113:                }
0114:
0115:                if (j == 0) {
0116:                    return false;
0117:                }
0118:
0119:                if (i == len) {
0120:                    mmsAddress.set(s.substring(initI), null,
0121:                            GLOBAL_PHONE_NUMBER);
0122:                    return true;
0123:                }
0124:
0125:                if (c == ':') {
0126:                    mmsAddress.set(s.substring(initI, i), null,
0127:                            GLOBAL_PHONE_NUMBER);
0128:                    return parseApplicationId(s, i, mmsAddress);
0129:                }
0130:
0131:                return false;
0132:            }
0133:
0134:            /**
0135:             * Determines whether a string represents a valid ipv4 address
0136:             * starting from an index. If the address string is a valid
0137:             * ipv4 representation it is parsed into the fields of 
0138:             * <code>MMSAddress </code>object (address and application id).
0139:             * ipv4 syntax is specified in WMA 2.0 spec as :
0140:             * 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit [applicationId]
0141:             *
0142:             * @param s The string to check.
0143:             * @param mmsAddress The return <code>MMSAddress</code> object which
0144:             * fields are filled with parsed address and
0145:             * application id (which can be null), its type is set to IPV4.
0146:             * @param i The index of the string at which to start the check. 
0147:             * <code> 0 <= i <= s.length() </code> 
0148:             *
0149:             * @return <code>true </code> if <code>s</code> represents a valid 
0150:             * ipv4 address starting from index <code>i</code>;
0151:             * <code> false </code> otherwise and if index <code>i</code> is
0152:             * invalide value
0153:             */
0154:            static boolean parseIpv4(String s, int i, MMSAddress mmsAddress) {
0155:                int len = s.length();
0156:                if (i <= 0 || i >= len) {
0157:                    return false;
0158:                }
0159:
0160:                char c;
0161:                int j;
0162:                int initI = i;
0163:
0164:                for (int num = 1; num < 5; num++) {
0165:
0166:                    for (j = 0; j < 3 && i < len; i++, j++) {
0167:
0168:                        c = s.charAt(i);
0169:
0170:                        if (!digit(c)) {
0171:                            break;
0172:                        }
0173:                    }
0174:
0175:                    // there should be at least one digit and 
0176:                    // the number between dots should be less then 256
0177:                    if (j == 0
0178:                            || (j == 3 && (((s.charAt(i - 3) - '0') * 10 + (s
0179:                                    .charAt(i - 2) - '0')) * 10 + (s
0180:                                    .charAt(i - 1) - '0')) > 255)) {
0181:                        return false;
0182:                    }
0183:
0184:                    // check if this is the end of the string
0185:                    if (i == len) {
0186:                        if (num == 4) {
0187:                            mmsAddress.set(s.substring(initI), null, IPV4);
0188:                            return true;
0189:                        }
0190:                        return false;
0191:                    }
0192:
0193:                    c = s.charAt(i);
0194:
0195:                    if (c == ':') {
0196:                        mmsAddress.set(s.substring(initI, i), null, IPV4);
0197:                        return parseApplicationId(s, i, mmsAddress);
0198:                    }
0199:
0200:                    if (c != '.') {
0201:                        return false; // 4th character after beg (or dot)
0202:                        // should be dot;
0203:                        // only dots are allowed as non digit char
0204:                    }
0205:
0206:                    // allowed '.' => continue
0207:                    i++;
0208:                }
0209:
0210:                return false;
0211:            }
0212:
0213:            /**
0214:             * Determines whether a string represents a valid ipv6 address
0215:             * starting from an index. If the address string is a valid
0216:             * ipv6 representation it is parsed into the fields of 
0217:             * <code>MMSAddress </code>object (address and application id).
0218:             * ipv6 syntax is specified in WMA 2.0 spec as :
0219:             * ipv6-atom ":" ipv6-atom ":" ipv6-atom ":" ipv6-atom ":" 
0220:             * ipv6-atom ":" ipv6-atom ":" ipv6-atom ":" ipv6-atom [appId]
0221:             * where ipv6-atom is 1*4(digit | hex-alpha).
0222:             *
0223:             * @param s The string to check.
0224:             * @param mmsAddress The return <code>MMSAddress</code> object which
0225:             * fields are filled with parsed address and
0226:             * application id (which can be null), its type is set to IPV6.
0227:             * @param i The index of the string at which to start the check. 
0228:             * <code> 0 <= i <= s.length() </code> 
0229:             *
0230:             * @return <code>true </code> if <code>s</code> represents a valid 
0231:             * ipv6 address starting from index <code>i</code>;
0232:             * <code> false </code> otherwise and if index <code>i</code> is
0233:             * invalide value
0234:             */
0235:            static boolean parseIpv6(String s, int i, MMSAddress mmsAddress) {
0236:                int len = s.length();
0237:                if (i <= 0 || i >= len) {
0238:                    return false;
0239:                }
0240:
0241:                char c;
0242:                int j;
0243:                int initI = i;
0244:
0245:                for (int num = 1; num < 9; num++) {
0246:
0247:                    for (j = 0; j < 4 && i < len; i++, j++) {
0248:
0249:                        c = s.charAt(i);
0250:
0251:                        if (!hex(c)) {
0252:                            break;
0253:                        }
0254:                    }
0255:
0256:                    // there should be at least one digit 
0257:                    if (j == 0) {
0258:                        return false;
0259:                    }
0260:
0261:                    // check if this is the end of the string
0262:                    if (i == len) {
0263:                        if (num == 8) {
0264:                            mmsAddress.set(s.substring(initI), null, IPV6);
0265:                            return true;
0266:                        }
0267:                        return false;
0268:                    }
0269:
0270:                    c = s.charAt(i);
0271:
0272:                    if (c == ':') {
0273:                        if (num == 8) {
0274:                            mmsAddress.set(s.substring(initI, i), null, IPV6);
0275:                            return parseApplicationId(s, i, mmsAddress);
0276:                        }
0277:                    } else {
0278:                        return false; // 5th character after beg (or :)
0279:                        // should be :
0280:                        // only : are allowed as non digit char
0281:                    }
0282:
0283:                    // allowed ':' => continue
0284:                    i++;
0285:                }
0286:
0287:                return false;
0288:            }
0289:
0290:            /**
0291:             * Determines whether a string represents a valid shortcode
0292:             * starting from an index. If the address string is a valid
0293:             * shortcode representation it is parsed into the fields of 
0294:             * <code>MMSAddress </code>object (address and null for appId).
0295:             * Shortcode syntax is specified in WMA 2.0 spec as :
0296:             * *(digit | alpha)
0297:             *
0298:             * @param s The string to check.
0299:             * @param mmsAddress The return <code>MMSAddress</code> object which
0300:             * fields are filled with parsed address and application id (null in
0301:             * this case), its type is set to SHORTCODE.
0302:             * @param i The index of the string at which to start the check. 
0303:             * <code> 0 <= i <= s.length() </code> 
0304:             *
0305:             * @return <code>true </code> if <code>s</code> represents a valid 
0306:             * shortcode starting from index <code>i</code>;
0307:             * <code> false </code> otherwise and if index <code>i</code> is
0308:             * invalide value
0309:             */
0310:            static boolean parseShortCode(String s, int i, MMSAddress mmsAddress) {
0311:                int len = s.length();
0312:                if (i > len) {
0313:                    return false;
0314:                }
0315:
0316:                if (i == len) {
0317:                    return false; // Even though spec allows "mms://" as a valid 
0318:                    // shortcode, we disallow it here
0319:                }
0320:                int initI = i;
0321:                char c;
0322:
0323:                for (; i < s.length(); i++) {
0324:                    c = s.charAt(i);
0325:
0326:                    if (!digit(c) && !alpha(c)) {
0327:                        return false;
0328:                    }
0329:                }
0330:                mmsAddress.set(s.substring(initI), null, SHORTCODE);
0331:                return true;
0332:            }
0333:
0334:            /**
0335:             * Determines whether a string represents a valid application ID
0336:             * starting from an index.If the address string is a valid
0337:             * application id representation it is parsed into the fields of 
0338:             * <code>MMSAddress </code>object (application id and null for the 
0339:             * address).
0340:             * Application ID syntax is specified in WMA 2.0 spec as :
0341:             * ":"[*(1*(alpha | digit | "." | "_") ".")]1*(alpha | digit | "." | "_").
0342:             * The number of characters in application ID must not exceed 32.
0343:             *
0344:             * @param s The string to check.
0345:             * @param mmsAddress The return <code>MMSAddress</code> object which
0346:             * fields are filled with parsed address (null in this case) and
0347:             * application id, its type is set to APP_ID.
0348:             * @param i The index of the string at which to start the check. 
0349:             * <code> 0 <= i <= s.length() </code> 
0350:             *
0351:             * @return <code>true </code> if <code>s</code> represents a valid 
0352:             * application ID starting from index <code>i</code>;
0353:             * <code> false </code> otherwise and if index <code>i</code> is
0354:             * invalide value
0355:             */
0356:            static boolean parseApplicationId(String s, int i,
0357:                    MMSAddress mmsAddress) {
0358:                int len = s.length();
0359:
0360:                // empty string or string like ":" are not allowed
0361:                // only 32 characters is allowed
0362:                if (i <= 0 || i >= len || (len - i) > 32 || (len - i) < 1
0363:                        || s.charAt(i) != ':') {
0364:                    return false;
0365:                }
0366:
0367:                i++; // to skip ':'
0368:
0369:                char c;
0370:                int initI = i;
0371:
0372:                for (int j = 0; i < len; i++) {
0373:
0374:                    c = s.charAt(i);
0375:
0376:                    for (j = 0; i < len; i++, j++) {
0377:                        c = s.charAt(i);
0378:
0379:                        if ((c != '_') && /* dot is also allowed in the spec ??? */
0380:                        !digit(c) && !alpha(c)) {
0381:                            break;
0382:                        }
0383:                    }
0384:
0385:                    if (i == len) {
0386:                        if (mmsAddress.type == INVALID_ADDRESS) {
0387:                            mmsAddress.set(null, s.substring(initI), APP_ID);
0388:                        } else {
0389:                            mmsAddress.setAppid(s.substring(initI));
0390:                        }
0391:                        return true;
0392:                    }
0393:
0394:                    // there has to be at least one digit or letter and
0395:                    // nondigit and nonalpha char can be only dot (one dot only)
0396:                    if (j == 0 || c != '.') {
0397:                        return false;
0398:                    }
0399:                }
0400:
0401:                return false;
0402:            }
0403:
0404:            // ------------------------------- E-mail validation ----------------
0405:            /**
0406:             * Determines whether a character represents a special e-mail character.
0407:             * @param c The character to check.
0408:             * @return <code>true </code> if <code>c</code> is a special character.
0409:             * <code> false </code> otherwise
0410:             */
0411:            private static boolean specials(char c) {
0412:                if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@'
0413:                        || c == ',' || c == ';' || c == ':' || c == '\\'
0414:                        || c == '"' || c == '.' || c == '[' || c == ']') {
0415:                    return true;
0416:                }
0417:                return false;
0418:            }
0419:
0420:            /**
0421:             * Determines whether a character represents a character.
0422:             * @param c The character to check.
0423:             * @return <code>true </code> if <code>c</code> is a character.
0424:             * <code> false </code> otherwise
0425:             */
0426:            private static boolean isChar(char c) {
0427:                return ((int) c) >= 0 && ((int) c) <= 127;
0428:            }
0429:
0430:            /**
0431:             * Determines whether a character represents an ascii control
0432:             * character.
0433:             * @param c The character to check.
0434:             * @return <code>true </code> if <code>c</code> is a character.
0435:             * <code> false </code> otherwise
0436:             */
0437:            private static boolean asciiControl(char c) {
0438:                return ((int) c >= 0 && (int) c <= 31);
0439:            }
0440:
0441:            /**
0442:             * Determines whether a character represents an atom character.
0443:             * as specified in WMA 2.0 specification.
0444:             * @param c The character to check.
0445:             * @return <code>true </code> if <code>c</code> is a special character.
0446:             * <code> false </code> otherwise
0447:             */
0448:            private static boolean atomChar(char c) {
0449:                return ((int) c <= 127 && (int) c > 32 && !specials(c));
0450:            }
0451:
0452:            /**
0453:             * Determines first not linear white space character 
0454:             * in <code>s</code> after character with index <code>i</code> but
0455:             * before character with index <code>n</code>.
0456:             * 
0457:             * @param s The string to check.
0458:             * @param i The index of the string at which to start the check. 
0459:             * <code> 0 <= i <= s.length() </code>
0460:             * @param n The index of the last character to be checked in 
0461:             *          <code>s</code>.
0462:             * @return The first non linear white character after position 
0463:             *          <code>i</code>, it could the the same as passed in
0464:             *          <code>i</code> value if there are no linear white
0465:             *          space characters.
0466:             */
0467:            private static int linearWhiteSpaceSeq(String s, int i, int n) {
0468:                char c;
0469:                for (; i < n; i++) {
0470:                    c = s.charAt(i);
0471:                    if (c == ' ' || c == '\t') {
0472:                        continue;
0473:                    }
0474:                    if (c == '\r') {
0475:                        // only CR LF one after another are allowed
0476:                        // CR by itself is not allowed
0477:                        if (i == n - 1 || s.charAt(i + 1) != '\n') {
0478:                            return i;
0479:                        }
0480:                        i++;
0481:                    } else {
0482:                        return i;
0483:                    }
0484:                }
0485:
0486:                return i;
0487:            }
0488:
0489:            /**
0490:             * Determines whether a string represents a valid e-mail address
0491:             * starting from an index. If the address string is a valid
0492:             * e-mail address representation it is parsed into the fields of 
0493:             * <code>MMSAddress </code>object (address and null for appId).
0494:             * E-mail syntax is specified in WMA 2.0 spec.
0495:             *
0496:             * @param s The string to check.
0497:             * @param i The index of the string at which to start the check. 
0498:             * <code> 0 <= i <= s.length() </code>
0499:             * @param mmsAddress The return <code>MMSAddress</code> object which
0500:             * fields are filled with parsed address and
0501:             * application id (null in this case),  its type is set to EMAIL.
0502:             *
0503:             * @return <code>true </code> if <code>s</code> represents a valid 
0504:             * e-mail address starting from index <code>i</code>;
0505:             * <code> false </code> otherwise and if index <code>i</code> is
0506:             * invalide value
0507:             */
0508:            static boolean parseEmail(String s, int i, MMSAddress mmsAddress) {
0509:
0510:                int len = s.length();
0511:                if (i <= 0 || i >= len) {
0512:                    return false;
0513:                }
0514:
0515:                int initI = i;
0516:
0517:                // email can be on of the following:
0518:                // emial ::== mailbox | phrase : [#mailbox] ;
0519:
0520:                // if there is a ';' at the end then there should be a phrase
0521:                // at the beginning
0522:                if (s.charAt(len - 1) == ';') {
0523:
0524:                    if ((i = isPhrase(s, i, len - 1)) <= 0) {
0525:                        return false;
0526:                    }
0527:
0528:                    // there was no ":"
0529:                    if (i >= len - 1 || s.charAt(i) != ':') {
0530:                        return false;
0531:                    }
0532:
0533:                    i++; // move after ':'
0534:
0535:                    if (i == len - 1) {
0536:                        mmsAddress.set(s.substring(initI), null, EMAIL);
0537:                        return true; // phrase : ; is allowed string
0538:                    }
0539:
0540:                    if ((i = isMailbox(s, i, len - 1)) <= 0) {
0541:                        return false;
0542:                    }
0543:
0544:                    while (i < len - 1) {
0545:
0546:                        // there has to be a ',' sep
0547:                        if (i >= len - 2 && s.charAt(i) != ',') {
0548:                            return false;
0549:                        }
0550:
0551:                        if ((i = isMailbox(s, i + 1, len - 1)) <= 0) {
0552:                            return false;
0553:                        }
0554:                    }
0555:                    if (i == len - 1) {
0556:                        mmsAddress.set(s.substring(initI), null, EMAIL);
0557:                        return true;
0558:                    }
0559:                    return false;
0560:                }
0561:
0562:                if (isMailbox(s, i, len) == len) {
0563:                    mmsAddress.set(s.substring(initI), null, EMAIL);
0564:                    return true;
0565:                }
0566:                return false;
0567:            }
0568:
0569:            /**
0570:             * Determines whether a string represents a valid mailbox address
0571:             * starting from an index.
0572:             * Mailbox syntax is specified in WMA 2.0 spec as
0573:             * local-part"@"domain  or as
0574:             * [phrase] "<"[("@"domain) [*("," ("@"domain))]] local-part"@"domain">"
0575:             *
0576:             * @param s The string to check.
0577:             * @param i The index of the string at which to start the check. 
0578:             * <code> 0 <= i <= s.length() </code> 
0579:             * @param n The index of the last character to be checked in 
0580:             *          <code>s</code>.
0581:             *
0582:             * @return index till which 
0583:             * <code>s</code> contains valid mailbox specification;
0584:             * <code> -1 </code> if index <code>i</code> is invalid or
0585:             * if characters in <code>s</code> starting from <code>i</code>
0586:             * do not comply with mailbox specification
0587:             */
0588:            private static int isMailbox(String s, int i, int n) {
0589:                if (n > s.length()) {
0590:                    n = s.length();
0591:                }
0592:                if (i >= n) {
0593:                    return -1;
0594:                }
0595:
0596:                int initI = i;
0597:
0598:                if ((i = isLocalAtDomain(s, initI, n)) > 0) {
0599:                    return i;
0600:                }
0601:
0602:                i = initI;
0603:
0604:                // check for  [phrase] <[1#(@ domain):] local @ domain>
0605:                // note phrase is optional
0606:                if ((s.charAt(i) != '<') && (i = isPhrase(s, initI, n)) < 0) {
0607:                    return -1;
0608:                }
0609:
0610:                if (i == n || s.charAt(i) != '<') {
0611:                    return -1;
0612:                }
0613:
0614:                i++;
0615:
0616:                if (i == n) {
0617:                    return -1;
0618:                }
0619:
0620:                // there can be a list of domains: 
0621:                // @ domain, @domain, @domain :
0622:                boolean atLeastOneDomain = false;
0623:                while (s.charAt(i) == '@') {
0624:                    atLeastOneDomain = true;
0625:
0626:                    if ((i = isDomain(s, i + 1, n)) < 0) {
0627:                        return -1;
0628:                    }
0629:
0630:                    if (i == n) {
0631:                        return -1;
0632:                    }
0633:
0634:                    if (s.charAt(i) == ':') {
0635:                        break;
0636:                    }
0637:
0638:                    // @domain,,@domain is allowed
0639:                    while (s.charAt(i) == ',') {
0640:                        i++;
0641:                        if (i == n || s.charAt(i) == ':') {
0642:                            return -1;
0643:                        }
0644:                    }
0645:                }
0646:
0647:                if (atLeastOneDomain) {
0648:                    if (i == n || s.charAt(i) != ':') {
0649:                        return -1;
0650:                    }
0651:                    i++;
0652:                }
0653:
0654:                // local @ domain
0655:                if ((i = isLocalAtDomain(s, i, n)) <= 0) {
0656:                    return -1;
0657:                }
0658:
0659:                if (i < n && s.charAt(i) == '>') {
0660:                    return i + 1;
0661:                }
0662:                return -1;
0663:            }
0664:
0665:            /**
0666:             * Determines whether a string represents a valid "local-part"
0667:             * starting from an index.
0668:             * Local-part syntax is specified in WMA 2.0 spec as
0669:             * (atom | "\"alpha) *("." (atom | "\"alpha)) where 
0670:             * atom is represented by at least one char which is 
0671:             * not a space or a special or control character.
0672:             *
0673:             * @param s The string to check.
0674:             * @param i The index of the string at which to start the check
0675:             * <code> 0 <= i <= s.length() </code> 
0676:             * @param n The index of the last character to be checked in 
0677:             *          <code>s</code>.
0678:             *
0679:             * @return index till which 
0680:             * <code>s</code> contains valid local-part specification;
0681:             * <code> -1 </code> if index <code>i</code> is invalid or
0682:             * if characters in <code>s</code> starting from <code>i</code>
0683:             * do not comply with local-part specification
0684:             */
0685:            private static int isLocalPart(String s, int i, int n) {
0686:                return isSequenceOfAtomAndText(s, i, n, '"', '"', true);
0687:            }
0688:
0689:            /**
0690:             * Determines whether a string represents a valid "phrase"
0691:             * starting from an index.
0692:             * Phrase syntax is specified in WMA 2.0 spec as
0693:             * 1*(atom | """ *(text w/o ",\,\r but with linear space | "\"alpha) """) 
0694:             * where atom is represented by at least one char or more which is 
0695:             * not a space or a special or control character.
0696:             *
0697:             * @param s The string to check.
0698:             * @param i The index of the string at which to start the check
0699:             * <code> 0 <= i <= s.length() </code> 
0700:             * @param n The index of the last character to be checked in 
0701:             *          <code>s</code>.
0702:             *
0703:             * @return index till which 
0704:             * <code>s</code> contains valid phrase specification;
0705:             * <code> -1 </code> if index <code>i</code> is invalid or
0706:             * if characters in <code>s</code> starting from <code>i</code>
0707:             * do not comply with phrase specification
0708:             */
0709:            private static int isPhrase(String s, int i, int n) {
0710:                return isSequenceOfAtomAndText(s, i, n, '"', '"', false);
0711:            }
0712:
0713:            /**
0714:             * Determines whether a string represents a valid "domain"
0715:             * starting from an index.
0716:             * Domain syntax is specified in WMA 2.0 spec as
0717:             * 1*(atom | "[" *(text w/o ",[,],\r but with linear space | "\"alpha) "]")
0718:             * where atom is represented by at least one char or more which is 
0719:             * not a space or a special or control character.
0720:             *
0721:             * @param s The string to check.
0722:             * @param i The index of the string at which to start the check
0723:             * <code> 0 <= i <= s.length() </code> 
0724:             * @param n The index of the last character to be checked in 
0725:             *          <code>s</code>.
0726:             *
0727:             * @return index till which 
0728:             * <code>s</code> contains valid domain specification;
0729:             * <code> -1 </code> if index <code>i</code> is invalid or
0730:             * if characters in <code>s</code> starting from <code>i</code>
0731:             * do not comply with domain specification
0732:             */
0733:            private static int isDomain(String s, int i, int n) {
0734:                return isSequenceOfAtomAndText(s, i, n, '[', ']', true);
0735:            }
0736:
0737:            /**
0738:             * Determines whether a string starting from an index
0739:             * represents a valid sequence that satisfies the following
0740:             * syntax:
0741:             * text ::== <begSep>
0742:             *           *(1*(<any char w/o begSep and eSep incl LWSP>|\ALPHA))
0743:             *           <endSep>
0744:             * sequence ::== 1*(atom | text) | (atom | text) *("." (atom | text))
0745:             * where atom is represented by at least one or more characters that  
0746:             * are not space or special or control characters
0747:             * and begSep/endSep are separators that are placed around text.
0748:             * LWSP is a linear white space (space and tabs and \r\n but not \r).
0749:             *
0750:             * @param s The string to check.
0751:             * @param i The index of the string at which to start the check
0752:             * <code> 0 <= i <= s.length() </code> 
0753:             * @param n The index of the last character to be checked in 
0754:             *          <code>s</code>.
0755:             * @param begSep The character marking beginning of quoted text
0756:             * @param endSep The character marking the end of the text
0757:             * @param dotSeparated If true atom and quoted text should be 
0758:             *        separated by a "." character; ".." is not allowed
0759:             *
0760:             * @return index till which 
0761:             * <code>s</code> contains valid sequence;
0762:             * <code> -1 </code> if index <code>i</code> is invalid or
0763:             * if characters in <code>s</code> starting from <code>i</code>
0764:             * do not comply with the sequence specification.
0765:             */
0766:            private static int isSequenceOfAtomAndText(String s, int i, int n,
0767:                    char begSep, char endSep, boolean dotSeparated) {
0768:                if (i >= s.length()) {
0769:                    return -1;
0770:                }
0771:                if (n > s.length()) {
0772:                    n = s.length();
0773:                }
0774:
0775:                // see if there is at least one word
0776:                boolean withinQuotation = false;
0777:                boolean atLeastOneWord = false;
0778:
0779:                char c;
0780:                int initI = i;
0781:
0782:                for (; i < n; i++) {
0783:                    c = s.charAt(i);
0784:                    if (c == begSep) {
0785:                        if (begSep == endSep) {
0786:                            withinQuotation = !withinQuotation;
0787:                        } else if (withinQuotation) {
0788:                            return -1;
0789:                        } else {
0790:                            withinQuotation = true;
0791:                        }
0792:                        atLeastOneWord = true;
0793:                    } else if (c == endSep) {
0794:                        if (!withinQuotation) {
0795:                            return -1;
0796:                        }
0797:                        withinQuotation = false;
0798:                    } else if (c == '\\') {
0799:                        // chars can be quoated only within separators
0800:                        // and there has to be another char after '\'
0801:                        if (!withinQuotation || i == n - 1) {
0802:                            return -1;
0803:                        }
0804:                        i++;
0805:                        c = s.charAt(i);
0806:                        // only ALPHA character can be quoted
0807:                        if (!alpha(c)) {
0808:                            return -1;
0809:                        }
0810:
0811:                    } else if (dotSeparated && c == '.') {
0812:                        if (i == initI
0813:                                || ((i - initI) > 0 && s.charAt(i - 1) == '.')) {
0814:                            // empty word
0815:                            // string starts with .
0816:                            return -1;
0817:                        }
0818:                    } else if (withinQuotation) {
0819:                        // within quotation \r is not allowed but
0820:                        // \r is allowed as part of linear-white-space
0821:                        if (c == ' ' || c == '\t' || c == '\r') {
0822:                            if ((i = linearWhiteSpaceSeq(s, i, n)) < 0) {
0823:                                return -1;
0824:                            }
0825:                            i--;
0826:                        }
0827:                    } else if (atomChar(c)) {
0828:                        atLeastOneWord = true;
0829:                    } else {
0830:                        // this is supposed to be an atom 
0831:                        break;
0832:                    }
0833:                }
0834:
0835:                // open quotation or no words or
0836:                // dot separator is the last char
0837:                if (withinQuotation
0838:                        || !atLeastOneWord
0839:                        || (dotSeparated && i > initI && s.charAt(i - 1) == '.')) {
0840:                    return -1;
0841:                }
0842:
0843:                return i;
0844:            }
0845:
0846:            /**
0847:             * Determines whether a string starting from an index satisfies the
0848:             * following syntax: local-part"@"domain
0849:             *
0850:             * @param s The string to check.
0851:             * @param i The index of the string at which to start the check. 
0852:             * <code> 0 <= i <= s.length() </code> 
0853:             * @param n The index of the last character to be checked in 
0854:             *          <code>s</code>.
0855:             *
0856:             * @return index till which 
0857:             * <code>s</code> contains valid mailbox specification;
0858:             * <code> -1 </code> if index <code>i</code> is invalid or
0859:             * if characters in <code>s</code> starting from <code>i</code>
0860:             * is not in the form of local-part"@"domain
0861:             */
0862:            private static int isLocalAtDomain(String s, int i, int n) {
0863:                if (n > s.length()) {
0864:                    n = s.length();
0865:                }
0866:                if (i >= n) {
0867:                    return -1;
0868:                }
0869:
0870:                // local
0871:                if ((i = isLocalPart(s, i, n)) <= 0) {
0872:                    return -1;
0873:                }
0874:
0875:                if (i == n || s.charAt(i) != '@') {
0876:                    return -1;
0877:                }
0878:
0879:                i++;
0880:
0881:                // domain
0882:                return isDomain(s, i, n);
0883:            }
0884:
0885:            /**
0886:             * Determines whether a string represents a valid mms address
0887:             * as specified in WMA 2.0 specification and parses the
0888:             * incoming string into address and application id strings.
0889:             *
0890:             * @param addressStr The string to check.
0891:             *
0892:             * @return newly created <code>MMSAddress </code> object 
0893:             * if <code>addressStr</code> is a valid mms address; 
0894:             * <code> null </code> otherwise
0895:             */
0896:            public static MMSAddress getParsedMMSAddress(String addressStr) {
0897:                return getParsedMMSAddress(addressStr, null);
0898:            }
0899:
0900:            /**
0901:             * Determines whether a string represents a valid mms address
0902:             * as specified in WMA 2.0 specification and parses the
0903:             * incoming string into address and application id strings.
0904:             * 
0905:             * @param addressStr The string to check.
0906:             * @param mmsAddress The return <code>MMSAddress</code> object which
0907:             * fields will be filled with parsed address and
0908:             * application id, and correspoinding type (EMAIL, GLOBAL_PHONE_NUMBER,
0909:             * IPV4, IPV6, SHORTCODE, APP_ID).
0910:             *
0911:             * @return <code>MMSAddress </code> object if <code>addressStr</code> 
0912:             * is a valid mms address; <code> null </code> otherwise
0913:             */
0914:            public static MMSAddress getParsedMMSAddress(String addressStr,
0915:                    MMSAddress mmsAddress) {
0916:
0917:                if (addressStr == null || !addressStr.startsWith("mms://")) {
0918:                    return null;
0919:                }
0920:
0921:                if (mmsAddress == null) {
0922:                    mmsAddress = new MMSAddress();
0923:                }
0924:
0925:                if (parsePhoneNumber(addressStr, 6, mmsAddress)
0926:                        || parseIpv4(addressStr, 6, mmsAddress)
0927:                        || parseIpv6(addressStr, 6, mmsAddress)
0928:                        || parseEmail(addressStr, 6, mmsAddress)
0929:                        || parseShortCode(addressStr, 6, mmsAddress)
0930:                        || parseApplicationId(addressStr, 6, mmsAddress)) {
0931:                    return mmsAddress;
0932:                }
0933:
0934:                return null;
0935:            }
0936:
0937:            /** Type corresponding to invalid address. */
0938:            public static final int INVALID_ADDRESS = -1;
0939:
0940:            /** Type corresponding to the e-mail address. */
0941:            public static final int EMAIL = 0;
0942:
0943:            /** Type corresponding to global phone number address. */
0944:            public static final int GLOBAL_PHONE_NUMBER = 1;
0945:
0946:            /** Type corresponding to the ipv4 address. */
0947:            public static final int IPV4 = 2;
0948:
0949:            /** Type corresponding to the ipv6 address. */
0950:            public static final int IPV6 = 3;
0951:
0952:            /** Type corresponding to the shortcode address. */
0953:            public static final int SHORTCODE = 4;
0954:
0955:            /** Type corresponding to the application id address. */
0956:            public static final int APP_ID = 5;
0957:
0958:            /** 
0959:             * Field that holds address part of the mms address 
0960:             * (without "mms://" and ":" separator before app id).
0961:             */
0962:            public String address;
0963:
0964:            /** 
0965:             * Field that holds application id part of the mms address
0966:             * which appears after "mms://:" or 
0967:             * after phone number, ipv4, or ipv6 followed by ":" .
0968:             */
0969:            public String appId;
0970:
0971:            /** 
0972:             * Type of this MMSAddress instance, 
0973:             * <code>INVALID_ADDRESS</code> when uninitialized .
0974:             */
0975:            public int type;
0976:
0977:            /**
0978:             *  MMSAddress constructor to create uninitialized instance.
0979:             */
0980:            MMSAddress() {
0981:                clear();
0982:            }
0983:
0984:            /**
0985:             * MMSAddress constructor to create initialized instance.
0986:             * @param address The address part of the mms address
0987:             * @param appId The application id part of the mms address
0988:             * @param type The type of this mms addreess
0989:             * (EMAIL, GLOBAL_PHONE_NUMBER, IPV4, IPV6, SHORTCODE, APP_ID) 
0990:             */
0991:            MMSAddress(String address, String appId, int type) {
0992:                set(address, appId, type);
0993:            }
0994:
0995:            /**
0996:             * Clears <code>MMSAddress</code> fields.
0997:             * Type is set to INVALID_ADDRESS while
0998:             * address and appId are set to null.
0999:             */
1000:            void clear() {
1001:                address = appId = null;
1002:                type = INVALID_ADDRESS;
1003:            }
1004:
1005:            /**
1006:             * Sets <code>MMSAddress</code> fields to the passed in values.
1007:             * @param address The address part of the mms address
1008:             * @param appId The application id part of the mms address
1009:             * @param type The type of this mms addreess
1010:             * (EMAIL, GLOBAL_PHONE_NUMBER, IPV4, IPV6, SHORTCODE, APP_ID) 
1011:             */
1012:            void set(String address, String appId, int type) {
1013:                this .address = address;
1014:                this .appId = appId;
1015:                this .type = type;
1016:            }
1017:
1018:            /**
1019:             * Sets <code>MMSAddress</code> application id field to 
1020:             * the passed in value.
1021:             * @param appId The application id part of the mms address
1022:             */
1023:            void setAppid(String appId) {
1024:                this .appId = appId;
1025:            }
1026:
1027:            /**
1028:             * Creates a valid mms address corresponding to the values
1029:             * in this <code>MMSAddress</code> object.
1030:             * If the object is not intialized null is returned.
1031:             * @return mms address corresponding to this MMSAddress object.
1032:             */
1033:            String getMMSAddressString() {
1034:
1035:                if (type == INVALID_ADDRESS
1036:                        || (address == null && appId == null)) {
1037:                    return null;
1038:                }
1039:
1040:                StringBuffer mmsAddr = new StringBuffer("mms://");
1041:                if (address != null)
1042:                    mmsAddr.append(address);
1043:                if (appId != null)
1044:                    mmsAddr.append(":").append(appId);
1045:                return mmsAddr.toString();
1046:            }
1047:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.