View Javadoc

1   package org.seasar.cubby.validator.validators;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   import java.util.regex.Matcher;
6   import java.util.regex.Pattern;
7   
8   import org.seasar.cubby.validator.BaseValidator;
9   import org.seasar.cubby.validator.ValidationContext;
10  import org.seasar.framework.util.StringUtil;
11  
12  /**
13   * Eメールアドレスに対する検証を行います。
14   * @author agata
15   *
16   */
17  public class EmailValidator extends BaseValidator {
18  
19      private static final String SPECIAL_CHARS = "\\(\\)<>@,;:\\\\\\\"\\.\\[\\]";
20      private static final String VALID_CHARS = "[^\\s" + SPECIAL_CHARS + "]";
21      private static final String QUOTED_USER = "(\"[^\"]*\")";
22      private static final String ATOM = VALID_CHARS + '+';
23      private static final String WORD = "(" + ATOM + "|" + QUOTED_USER + ")";
24  
25      private static final String LEGAL_ASCII_PATTERN = "^[\\x00-\\x7F]+$";
26      private static final String EMAIL_PATTERN = "^(.+)@(.+)$";
27      private static final String IP_DOMAIN_PATTERN =
28              "^(\\d{1,3})[.](\\d{1,3})[.](\\d{1,3})[.](\\d{1,3})$";
29  
30      private static final String USER_PATTERN = "^" + WORD + "(\\." + WORD + ")*$";
31      private static final String DOMAIN_PATTERN = "^" + ATOM + "(\\." + ATOM + ")*$";
32      private static final String ATOM_PATTERN = "(" + ATOM + ")";
33  
34      /**
35       * コンストラクタ
36       */
37  	public EmailValidator() {
38  		this("valid.email");
39  	}
40  
41  	/**
42  	 * メッセージキーを指定するコンストラクタ
43  	 * @param messageKey
44  	 */
45  	public EmailValidator(final String messageKey) {
46  		this.setMessageKey(messageKey);
47  	}
48  	
49  	public String validate(final ValidationContext ctx) {
50  		final Object value = ctx.getValue();
51  		if (value == null) {
52  			return null;
53  		}
54  		if (value instanceof String) {
55  			final String email = (String) value;
56  			if (StringUtil.isEmpty(email)) {
57  				return null;
58  			}
59  			
60  			boolean match = !email.endsWith(".");
61  			if(match){
62  				Pattern pattern = Pattern.compile(LEGAL_ASCII_PATTERN);
63  				Matcher matchAsciiPat = pattern.matcher(email);
64  				match = matchAsciiPat.matches();
65  			}
66  			
67  			if(match){
68  				Pattern pattern = Pattern.compile(EMAIL_PATTERN);
69  				Matcher matcher = pattern.matcher(email);
70  				match = matcher.find();
71  	        	if(match){
72  			        if (isValidUser(matcher.group(1)) && 
73  			        	isValidDomain(matcher.group(2))) {
74  			            return null;
75  			        }
76  	        	}
77  			}
78  		}
79  		return getMessage(getPropertyMessage(ctx.getName()));
80      }
81  
82      private boolean isValidDomain(String domain) {
83          Pattern pattern = Pattern.compile(IP_DOMAIN_PATTERN);
84  		Matcher ipAddressMatcher = pattern.matcher(domain);
85  
86          if (ipAddressMatcher.find()) {
87              if (isValidIpAddress(ipAddressMatcher)) {
88                  return true;
89              }
90          } else {
91              pattern = Pattern.compile(DOMAIN_PATTERN);
92      		Matcher domainMatcher = pattern.matcher(domain);
93              if (domainMatcher.matches()) {
94                  if (isValidSymbolicDomain(domain)) {
95                      return true;
96                  }
97              }
98          }
99          return false;
100     }
101 
102     private boolean isValidUser(String user) {
103     	Pattern pattern = Pattern.compile(USER_PATTERN);
104 		Matcher userMatcher = pattern.matcher(user);
105         return userMatcher.matches();
106     }
107 
108     private boolean isValidIpAddress(Matcher ipAddressMatcher) {
109         for (int i = 1; i <= 4; i++) {
110             String ipSegment = ipAddressMatcher.group(i);
111             if (ipSegment == null || ipSegment.length() <= 0) {
112                 return false;
113             }
114 
115             int iIpSegment = 0;
116 
117             try {
118                 iIpSegment = Integer.parseInt(ipSegment);
119             } catch(NumberFormatException e) {
120                 return false;
121             }
122 
123             if (iIpSegment > 255) {
124                 return false;
125             }
126 
127         }
128         return true;
129     }
130 
131     private boolean isValidSymbolicDomain(String domain) {
132         List<String> domainSegments = new ArrayList<String>();
133         boolean match = true;
134         int i = 0;
135         
136         Pattern pattern = Pattern.compile(ATOM_PATTERN);
137 		Matcher atomMatcher;
138 		String ds;
139         while (match) {
140         	atomMatcher = pattern.matcher(domain);
141             match = atomMatcher.find();
142             if (match) {
143             	ds = atomMatcher.group(1);
144             	domainSegments.add(ds);
145                 int l = ds.length() + 1;
146                 domain =
147                         (l >= domain.length())
148                         ? ""
149                         : domain.substring(l);
150 
151                 i++;
152             }
153         }
154 
155         int size = domainSegments.size();
156         if( size > 0){
157 	        String end = domainSegments.get(size-1);
158 	        if (end.length() < 2 || end.length() > 4) {
159 	            return false;
160 	        }
161         }
162 
163         if (domainSegments.size() < 2) {
164             return false;
165         }
166 
167         return true;
168     }
169 }