Source code: com/clra/web/ValidateMemberAccountName.java
1 /*
2 * Copyright (c) Carnegie Lake Rowing Association 2002. All rights reserved.
3 * Distributed under the GPL license. See doc/COPYING.
4 * $RCSfile: ValidateMemberAccountName.java,v $
5 * $Date: 2003/02/26 03:38:46 $
6 * $Revision: 1.3 $
7 */
8
9 package com.clra.web;
10
11 import com.clra.member.MemberDBRead;
12 import com.clra.member.MemberSnapshot;
13 import com.clra.util.DBConfiguration;
14 import java.sql.Connection;
15 import java.sql.PreparedStatement;
16 import java.sql.ResultSet;
17 import java.sql.SQLException;
18 import org.apache.struts.action.ActionError;
19 import org.apache.struts.action.ActionErrors;
20
21 /**
22 * Checks whether a member's account name is valid and unique.
23 *
24 * @version $Id: ValidateMemberAccountName.java,v 1.3 2003/02/26 03:38:46 rphall Exp $
25 * @author <a href="mailto:rphall@pluto.njcc.com">Rick Hall</a>
26 */
27 class ValidateMemberAccountName extends ValidateMember {
28
29 public final static String PROPERTY_ACCOUNTNAME = "accountname";
30
31 ValidateMemberAccountName( MemberInfoForm f ) {
32 super( f );
33 }
34
35 /**
36 * Checks whether a member's account name is valid and unique.
37 */
38 void validate( ActionErrors errors ) {
39
40 if ( errors == null ) {
41 throw new IllegalArgumentException( "null action errors" );
42 }
43
44 String messageKey = "validate.member.accountName.missing";
45 String accountName = this.form.getAccountName();
46 validateRequiredValue(PROPERTY_ACCOUNTNAME,messageKey,accountName,errors);
47
48 if ( accountName != null && accountName.trim().length() > 0 ) {
49
50 boolean isAvailable = false;
51 try {
52 Integer memberId = this.form.getId();
53 if ( memberId != null ) {
54 // Member should already exist in DB, so exclude matches
55 // on accountName if the memberId also matches.
56 int intMemberId = memberId.intValue();
57 isAvailable = isAccountNameAvailable(accountName,intMemberId);
58 }
59 else {
60 // Member should not exist in DB, so any match on accountName
61 // indicates a duplicate
62 isAvailable = isAccountNameAvailable(accountName);
63 }
64 }
65 catch ( Throwable t ) {
66 messageKey = "validate.member.accountName.unexpected";
67 ActionError ae = new ActionError(
68 messageKey, t.getClass().getName(), t.getMessage() );
69 errors.add( ActionErrors.GLOBAL_ERROR, ae );
70 } // end catch
71
72 if ( !isAvailable ) {
73 messageKey = "validate.member.accountName.duplicate";
74 ActionError ae = new ActionError( messageKey, accountName );
75 errors.add( PROPERTY_ACCOUNTNAME, ae );
76 }
77 else {
78 messageKey = "validate.member.accountName.ascii";
79 validateRestrictedAscii(
80 PROPERTY_ACCOUNTNAME, messageKey, accountName, errors );
81 }
82
83 } // end accountName not missing
84
85 return;
86 } // validate(ActionErrors)
87
88 protected final void validateRestrictedAscii( String PROPERTY,
89 String messageKey, String value, ActionErrors errors ) {
90
91 if ( value == null ) {
92 throw new IllegalArgumentException( "null value" );
93 }
94
95 boolean isValid = true;
96 for ( int i=0; isValid && i<value.length(); i++ ) {
97 char c = value.charAt(i);
98 isValid = ( 'a' <= c && c <= 'z' )
99 || ( 'A' <= c && c <= 'Z' )
100 || ( '0' <= c && c <= '9' )
101 || c == '-' || c == '_' || c == '.' ;
102 }
103
104 if ( !isValid ) {
105 ActionError ae = new ActionError(messageKey,value);
106 errors.add( PROPERTY, ae );
107 }
108
109 return;
110 } // validateRequiredValue(String,String,ActionErrors)
111
112 /**
113 * Checks whether any member uses the given account name. If no
114 * such member is found, returns true.</p>
115 * <p>
116 * Implementation note: Unlike MemberDBRead.findMemberByAccountName(String),
117 * this method does not throw an exception when a match is not found.
118 * Throwing and then catching an exception is inefficient, and should
119 * be used only when exceptions are NOT expected. Here, no-match exceptions
120 * are expected, which is why the MemberDBRead method is not used.
121 */
122 private static boolean isAccountNameAvailable(
123 String accountName, int intMemberId ) throws SQLException {
124
125 Connection conn = null;
126 PreparedStatement stmt = null;
127
128 boolean retVal = false;
129 try {
130 conn = DBConfiguration.getConnection();
131 stmt = conn.prepareStatement(
132 com.clra.member.Configuration.SQL_18,
133 ResultSet.TYPE_FORWARD_ONLY,
134 ResultSet.CONCUR_READ_ONLY);
135 stmt.setString( 1, accountName );
136 stmt.setInt( 2, intMemberId );
137 retVal = isAccountNameAvailable(stmt);
138 }
139 finally {
140 DBConfiguration.closeSQLStatement( stmt );
141 stmt = null;
142 DBConfiguration.closeSQLConnection( conn );
143 conn = null;
144 }
145
146 return retVal;
147 } // isAccountNameAvailable(String,int)
148
149 private static boolean isAccountNameAvailable( String accountName )
150 throws SQLException {
151
152 Connection conn = null;
153 PreparedStatement stmt = null;
154
155 boolean retVal = false;
156 try {
157 conn = DBConfiguration.getConnection();
158 stmt = conn.prepareStatement(
159 com.clra.member.Configuration.SQL_05,
160 ResultSet.TYPE_FORWARD_ONLY,
161 ResultSet.CONCUR_READ_ONLY);
162 stmt.setString( 1, accountName );
163 retVal = isAccountNameAvailable(stmt);
164 }
165 finally {
166 DBConfiguration.closeSQLStatement( stmt );
167 stmt = null;
168 DBConfiguration.closeSQLConnection( conn );
169 conn = null;
170 }
171
172 return retVal;
173 } // isAccountNameAvailable(String)
174
175 private static boolean isAccountNameAvailable( PreparedStatement stmt )
176 throws SQLException {
177
178 ResultSet rs = null;
179
180 boolean retVal = true;
181 try {
182 rs = stmt.executeQuery();
183 while ( rs.next() && retVal ) {
184 retVal = false;
185 }
186 }
187 finally {
188 DBConfiguration.closeSQLResultSet( rs );
189 rs = null;
190 }
191
192 return retVal;
193 } // isAccountNameAvailable(String)
194
195 } // ValidateMemberAccountName
196
197 /*
198 * $Log: ValidateMemberAccountName.java,v $
199 * Revision 1.3 2003/02/26 03:38:46 rphall
200 * Added copyright and GPL license
201 *
202 * Revision 1.2 2003/02/21 19:18:42 rphall
203 * Added SQL for checking duplicate user names during editing
204 *
205 * Revision 1.1 2003/02/21 05:08:43 rphall
206 * Moved ValidateMemberUserName to ValidateMemberAccountName
207 *
208 * Revision 1.1 2003/02/11 21:13:15 rphall
209 * Separate class for specific validation task; stubbed implementation
210 *
211 */
212