root/trunk/src/java/org/jcoderz/commons/types/EmailAddress.java

Revision 1404, 9.1 kB (checked in by amandel, 3 years ago)

Whitespace cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Author Date Revision
Line 
1/*
2 * $Id$
3 *
4 * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *    * Redistributions of source code must retain the above copyright
11 *      notice, this list of conditions and the following disclaimer.
12 *    * Redistributions in binary form must reproduce the above
13 *      copyright notice, this list of conditions and the following
14 *      disclaimer in the documentation and/or other materials
15 *      provided with the distribution.
16 *    * Neither the name of the jCoderZ.org Project nor the names of
17 *      its contributors may be used to endorse or promote products
18 *      derived from this software without specific prior written
19 *      permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33package org.jcoderz.commons.types;
34
35import java.io.Serializable;
36import java.util.regex.Matcher;
37import java.util.regex.Pattern;
38
39import org.jcoderz.commons.ArgumentMalformedException;
40import org.jcoderz.commons.util.Assert;
41import org.jcoderz.commons.util.HashCodeUtil;
42import org.jcoderz.commons.util.StringUtil;
43
44/**
45 * This class represents an email addresses compliant to RFC 2822,
46 * chapter 3.4.1. Addr-spec specification.
47 * This class does not support obsolete addressing (see ch. 4.4.
48 * Obsolete Addressing).
49 *
50 * <pre>
51 * atext           =       ALPHA / DIGIT / ; Any character except controls,
52 *                         "!" / "#" /     ;  SP, and specials.
53 *                         "$" / "%" /     ;  Used for atoms
54 *                         "&" / "'" /
55 *                         "*" / "+" /
56 *                         "-" / "/" /
57 *                         "=" / "?" /
58 *                         "^" / "_" /
59 *                         "`" / "{" /
60 *                         "|" / "}" /
61 *                         "~"
62 * atom            =       [CFWS] 1*atext [CFWS]
63 * dot-atom        =       [CFWS] dot-atom-text [CFWS]
64 * dot-atom-text   =       1*atext *("." 1*atext)
65 * addr-spec       = local-part "@" domain
66 * local-part      = dot-atom / quoted-string
67 * qtext           =       NO-WS-CTL /     ; Non white space controls
68 *                         %d33 /          ; The rest of the US-ASCII
69 *                         %d35-91 /       ;  characters not including "\"
70 *                         %d93-126        ;  or the quote character
71 * qcontent        =       qtext / quoted-pair
72 * quoted-string   = [CFWS]
73 *                   DQUOTE *([FWS] qcontent) [FWS] DQUOTE
74 *                   [CFWS]
75 * domain          = dot-atom / domain-literal
76 * domain-literal  = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
77 * dcontent        = dtext / quoted-pair
78 * dtext           = NO-WS-CTL /     ; Non white space controls
79 *                   %d33-90 /       ; The rest of the US-ASCII
80 *                   %d94-126        ;  characters not including "[",
81 *                                   ;  "]", or "\"
82 * FWS             =       ([*WSP CRLF] 1*WSP) /   ; Folding white space
83 *                         obs-FWS
84 * ctext           =       NO-WS-CTL /     ; Non white space controls
85 *                         %d33-39 /       ; The rest of the US-ASCII
86 *                         %d42-91 /       ;  characters not including "(",
87 *                         %d93-126        ;  ")", or "\"
88 * ccontent        =       ctext / quoted-pair / comment
89 * comment         =       "(" *([FWS] ccontent) [FWS] ")"
90 * CFWS            =       *([FWS] comment) (([FWS] comment) / FWS)
91 * </pre>
92 *
93 * <p>The maximum length of an email address is:
94 * 64+1+255 characters (local-part + @ + domain).
95 * The minimum length of an email address is:
96 * 1+1+4 characters (local-part + @ + domain).</p>
97 *
98 * <p>A valid list of top-level domains is defined by the IANA. A top-level
99 * domain which is not part of the
100 * <a href="http://data.iana.org/TLD/tlds-alpha-by-domain.txt">official list</a>
101 * will be rejected.</p>
102 *
103 * @author Michael Rumpf
104 */
105public class EmailAddress
106  implements Serializable
107{
108  private static final long serialVersionUID = 1L;
109
110  private static final int MAX_LENGTH_LOCAL_PART = 64;
111  private static final int MAX_LENGTH_DOMAIN = 255;
112
113  // RFC 2822 token definitions for a valid email
114  private static final String SP = "!#$%&'*+-/=?^_`{|}~";
115  private static final String ATEXT = "[a-zA-Z0-9" + SP + "]";
116  private static final String ATOM = ATEXT + "+";
117
118  // one or more atext chars
119  private static final String DOT_ATOM = "\\." + ATOM;
120  // one atom followed by 0 or more dotAtoms.
121  private static final String LOCAL_PART = ATOM + "(" + DOT_ATOM + ")*";
122
123  // RFC 1035 tokens for domain names:
124  private static final String LETTER = "[a-zA-Z]";
125  private static final String LET_DIG = "[a-zA-Z0-9]";
126  private static final String LET_DIG_HYP = "[a-zA-Z0-9-]";
127  private static final String RFC_LABEL
128      = LET_DIG + LET_DIG_HYP + "{0,61}" + LET_DIG;
129  private static final String DOMAIN
130      = RFC_LABEL + "(\\." + RFC_LABEL + ")*\\." + LETTER + "{2,6}";
131
132  //Combined together, these form the allowed email regexp allowed by RFC 2822:
133  private static final String ADDRESS = "^" + LOCAL_PART + "@" + DOMAIN + "$";
134
135  private static final Pattern ADDRESS_PATTERN = Pattern.compile(ADDRESS);
136
137
138  private final String mLocalPart;
139  private final String mDomain;
140  private final String mTopLevelDomain;
141
142  /**
143   * This is the constructor of the EmailAddress type.
144   *
145   * @param email The email address.
146   */
147  public EmailAddress (String email)
148  {
149    Assert.notNull(email, "email");
150    final String mail = email.trim();
151    final Matcher matcher = ADDRESS_PATTERN.matcher(email);
152    if (!matcher.matches())
153    {
154      throw new ArgumentMalformedException("email", email,
155          "EMail pattern does not match the RFC2822 grammar!");
156    }
157
158    final int at = mail.indexOf('@');
159    if (at > MAX_LENGTH_LOCAL_PART)
160    {
161      throw new ArgumentMalformedException("email", email,
162          "The local part is longer than " + MAX_LENGTH_LOCAL_PART
163          + " characters!");
164    }
165    if (mail.length() - at - 1 > MAX_LENGTH_DOMAIN)
166    {
167      throw new ArgumentMalformedException("email", email,
168          "The domain is longer than " + MAX_LENGTH_DOMAIN
169          + " characters!");
170    }
171    mLocalPart = mail.substring(0, at);
172    mDomain = mail.substring(at + 1);
173
174    final int dot = mail.lastIndexOf('.');
175    mTopLevelDomain = mail.substring(dot + 1);
176  }
177
178  /**
179   * Factory method for converting a String into an instance of type
180   * EmailAddress.
181   *
182   * @param email the email address to parse
183   * @return An instance of type EmailAddress
184   */
185  public static EmailAddress fromString(String email)
186  {
187    return new EmailAddress(email);
188  }
189
190  /**
191   * Returns the local part of the address.
192   * @return the local part of the address.
193   */
194  public String getName ()
195  {
196    return mLocalPart;
197  }
198
199
200  /**
201   * Returns the domain name of the address.
202   * @return the domain name of the address.
203   */
204  public String getDomain ()
205  {
206    return mDomain;
207  }
208
209
210  /**
211   * Returns the top-level domain name of the address.
212   * @return the top-level domain name of the address.
213   */
214  public String getTopLevelDomain ()
215  {
216    return mTopLevelDomain;
217  }
218
219
220  /**
221   * Returns the full email address.
222   * @return the full email address.
223   */
224  public String getAddress ()
225  {
226    return mLocalPart + "@" + mDomain;
227  }
228
229  /**
230   * Returns the full email address.
231   * @return the full email address.
232   */
233  public String toString ()
234  {
235    return mLocalPart + "@" + mDomain;
236  }
237
238  /**
239   * Returns the true if this email address equals the other.
240   * @param obj the object to compare to.
241   * @return the true if this email address equals the other.
242   * @see java.lang.Object#equals(java.lang.Object)
243   */
244  public boolean equals (Object obj)
245  {
246    boolean result = false;
247    if (this == obj)
248    {
249      result = true;
250    }
251    else if (obj instanceof EmailAddress)
252    {
253      final EmailAddress other = (EmailAddress) obj;
254      if (StringUtil.equals(getDomain(), other.getDomain())
255          && StringUtil.equals(getName(), other.getName()))
256      {
257        result = true;
258      }
259    }
260    return result;
261  }
262
263  /**
264   * Returns the hash code for this email.
265   * @return the hash code for this email.
266   */
267  public int hashCode ()
268  {
269    int hashCode = HashCodeUtil.hash(HashCodeUtil.SEED, mLocalPart);
270    return HashCodeUtil.hash(hashCode, mDomain);
271  }
272}
Note: See TracBrowser for help on using the browser.