KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > validator > EmailValidator


1 /*
2  * $Id: EmailValidator.java 155434 2005-02-26 13:16:41Z dirkv $
3  * $Rev$
4  * $Date: 2005-02-26 05:16:41 -0800 (Sat, 26 Feb 2005) $
5  *
6  * ====================================================================
7  * Copyright 2001-2005 The Apache Software Foundation
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */

21
22 package org.apache.commons.validator;
23
24 import org.apache.oro.text.perl.Perl5Util;
25
26 /**
27  * <p>Perform email validations.</p>
28  * <p>
29  * This class is a Singleton; you can retrieve the instance via the getInstance() method.
30  * </p>
31  * <p>
32  * Based on a script by <a HREF="mailto:stamhankar@hotmail.com">Sandeep V. Tamhankar</a>
33  * http://javascript.internet.com
34  * </p>
35  * <p>
36  * This implementation is not guaranteed to catch all possible errors in an email address.
37  * For example, an address like nobody@noplace.d- will pass validator, even though there
38  * is no TLD "d-"
39  * </p>.
40  * @since Validator 1.1
41  */

42 public class EmailValidator {
43
44     private static final String JavaDoc SPECIAL_CHARS = "\\(\\)<>@,;:\\\\\\\"\\.\\[\\]";
45     private static final String JavaDoc VALID_CHARS = "[^\\s" + SPECIAL_CHARS + "]";
46     private static final String JavaDoc QUOTED_USER = "(\"[^\"]*\")";
47     private static final String JavaDoc ATOM = VALID_CHARS + '+';
48     private static final String JavaDoc WORD = "(" + ATOM + "|" + QUOTED_USER + ")";
49
50     // Each pattern must be surrounded by /
51
private static final String JavaDoc LEGAL_ASCII_PATTERN = "/^[\\000-\\177]+$/";
52     private static final String JavaDoc EMAIL_PATTERN = "/^(.+)@(.+)$/";
53     private static final String JavaDoc IP_DOMAIN_PATTERN =
54             "/^\\[(\\d{1,3})[.](\\d{1,3})[.](\\d{1,3})[.](\\d{1,3})\\]$/";
55
56     private static final String JavaDoc USER_PATTERN = "/^\\s*" + WORD + "(\\." + WORD + ")*\\s*$/";
57     private static final String JavaDoc DOMAIN_PATTERN = "/^\\s*" + ATOM + "(\\." + ATOM + ")*\\s*$/";
58     private static final String JavaDoc ATOM_PATTERN = "/(" + ATOM + ")/";
59
60     /**
61      * Singleton instance of this class.
62      */

63     private static final EmailValidator instance = new EmailValidator();
64
65     /**
66      * Returns the Singleton instance of this validator.
67      */

68     public static EmailValidator getInstance() {
69         return instance;
70     }
71
72     /**
73      * Protected constructor for subclasses to use.
74      */

75     protected EmailValidator() {
76         super();
77     }
78
79     /**
80      * <p>Checks if a field has a valid e-mail address.</p>
81      *
82      * @param email The value validation is being performed on. A <code>null</code>
83      * value is considered invalid.
84      */

85     public boolean isValid(String JavaDoc email) {
86         if (email == null) {
87             return false;
88         }
89
90         Perl5Util matchAsciiPat = new Perl5Util();
91         if (!matchAsciiPat.match(LEGAL_ASCII_PATTERN, email)) {
92             return false;
93         }
94
95         email = stripComments(email);
96
97         // Check the whole email address structure
98
Perl5Util emailMatcher = new Perl5Util();
99         if (!emailMatcher.match(EMAIL_PATTERN, email)) {
100             return false;
101         }
102
103         if (email.endsWith(".")) {
104             return false;
105         }
106
107         if (!isValidUser(emailMatcher.group(1))) {
108             return false;
109         }
110
111         if (!isValidDomain(emailMatcher.group(2))) {
112             return false;
113         }
114
115         return true;
116     }
117
118     /**
119      * Returns true if the domain component of an email address is valid.
120      * @param domain being validatied.
121      */

122     protected boolean isValidDomain(String JavaDoc domain) {
123         boolean symbolic = false;
124         Perl5Util ipAddressMatcher = new Perl5Util();
125
126         if (ipAddressMatcher.match(IP_DOMAIN_PATTERN, domain)) {
127             if (!isValidIpAddress(ipAddressMatcher)) {
128                 return false;
129             } else {
130                 return true;
131             }
132         } else {
133             // Domain is symbolic name
134
Perl5Util domainMatcher = new Perl5Util();
135             symbolic = domainMatcher.match(DOMAIN_PATTERN, domain);
136         }
137
138         if (symbolic) {
139             if (!isValidSymbolicDomain(domain)) {
140                 return false;
141             }
142         } else {
143             return false;
144         }
145
146         return true;
147     }
148
149     /**
150      * Returns true if the user component of an email address is valid.
151      * @param user being validated
152      */

153     protected boolean isValidUser(String JavaDoc user) {
154         Perl5Util userMatcher = new Perl5Util();
155         return userMatcher.match(USER_PATTERN, user);
156     }
157
158     /**
159      * Validates an IP address. Returns true if valid.
160      * @param ipAddressMatcher Pattren matcher
161      */

162     protected boolean isValidIpAddress(Perl5Util ipAddressMatcher) {
163         for (int i = 1; i <= 4; i++) {
164             String JavaDoc ipSegment = ipAddressMatcher.group(i);
165             if (ipSegment == null || ipSegment.length() <= 0) {
166                 return false;
167             }
168
169             int iIpSegment = 0;
170
171             try {
172                 iIpSegment = Integer.parseInt(ipSegment);
173             } catch(NumberFormatException JavaDoc e) {
174                 return false;
175             }
176
177             if (iIpSegment > 255) {
178                 return false;
179             }
180
181         }
182         return true;
183     }
184
185     /**
186      * Validates a symbolic domain name. Returns true if it's valid.
187      * @param domain symbolic domain name
188      */

189     protected boolean isValidSymbolicDomain(String JavaDoc domain) {
190         String JavaDoc[] domainSegment = new String JavaDoc[10];
191         boolean match = true;
192         int i = 0;
193         Perl5Util atomMatcher = new Perl5Util();
194         while (match) {
195             match = atomMatcher.match(ATOM_PATTERN, domain);
196             if (match) {
197                 domainSegment[i] = atomMatcher.group(1);
198                 int l = domainSegment[i].length() + 1;
199                 domain =
200                         (l >= domain.length())
201                         ? ""
202                         : domain.substring(l);
203
204                 i++;
205             }
206         }
207
208         int len = i;
209         if (domainSegment[len - 1].length() < 2
210                 || domainSegment[len - 1].length() > 4) {
211
212             return false;
213         }
214
215         // Make sure there's a host name preceding the domain.
216
if (len < 2) {
217             return false;
218         }
219
220         return true;
221     }
222     /**
223      * Recursively remove comments, and replace with a single space. The simpler
224      * regexps in the Email Addressing FAQ are imperfect - they will miss escaped
225      * chars in atoms, for example.
226      * Derived From Mail::RFC822::Address
227     */

228     protected String JavaDoc stripComments(String JavaDoc emailStr) {
229      String JavaDoc input = emailStr;
230      String JavaDoc result = emailStr;
231      String JavaDoc commentPat = "s/^((?:[^\"\\\\]|\\\\.)*(?:\"(?:[^\"\\\\]|\\\\.)*\"(?:[^\"\\\\]|\111111\\\\.)*)*)\\((?:[^()\\\\]|\\\\.)*\\)/$1 /osx";
232      Perl5Util commentMatcher = new Perl5Util();
233      result = commentMatcher.substitute(commentPat,input);
234      // This really needs to be =~ or Perl5Matcher comparison
235
while (!result.equals(input)) {
236         input = result;
237         result = commentMatcher.substitute(commentPat,input);
238      }
239      return result;
240
241     }
242 }
243
Popular Tags