001: /**
002: * Copyright (C) 2003 Manfred Andres
003: *
004: * This program is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU General Public License
006: * as published by the Free Software Foundation; either version 2
007: * of the License, or (at your option) any later version.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: */package freecs.auth.sqlConnectionPool;
018:
019: import freecs.Server;
020: import freecs.core.CanceledRequestException;
021: import freecs.core.User;
022: import freecs.interfaces.IUserStates;
023: import freecs.util.HashUtils;
024:
025: import java.sql.*;
026: import java.util.Enumeration;
027: import java.util.Iterator;
028: import java.util.List;
029:
030: public class PoolElement {
031: public static final short INVALID = -1;
032: public static final short IDLE = 0;
033: public static final short ACTIVE = 1;
034:
035: volatile private PreparedStatement select = null, update = null,
036: updateLastlogin = null, insert = null;
037: volatile private String selStrg = null, insStrg = null,
038: updStrg = null, updLastloginStrg = null;
039: private DbProperties dbp;
040: private volatile boolean isValid = true;
041:
042: ConnectionPool pool;
043: Connection con = null;
044: int id;
045: volatile int sCnt = 0;
046: long validUntil;
047: volatile boolean isActive = false, hasBeenUsed = false,
048: cleanedUp = false;
049: ResultSet rs;
050:
051: PoolElement(ConnectionPool pool, Connection con, DbProperties dbp,
052: int id) throws Exception {
053: if (con == null)
054: throw new Exception("no connection supplied");
055: this .pool = pool;
056: this .dbp = dbp;
057: this .id = id;
058: this .con = con;
059: con.setAutoCommit(false);
060: validUntil = System.currentTimeMillis() + dbp.conTTL;
061: Server.log("SqlAuthenticator", "Created new Connetion "
062: + this .toString(), Server.MSG_AUTH, Server.LVL_MAJOR);
063: if (Server.TRACE_CREATE_AND_FINALIZE)
064: Server.log(this ,
065: "++++++++++++++++++++++++++++++++++++++++CREATE",
066: Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
067: }
068:
069: private boolean isValid() {
070: if (!isValid)
071: return false;
072: if (con == null || cleanedUp)
073: return false;
074: if (!hasBeenUsed)
075: return true;
076: if (sCnt > dbp.maxStmtPerCon) {
077: Server.log(this ,
078: "invalid because max-statements/connection has been reached "
079: + dbp.maxStmtPerCon, Server.MSG_AUTH,
080: Server.LVL_VERBOSE);
081: isValid = false;
082: return false;
083: }
084: if (validUntil <= System.currentTimeMillis()) {
085: Server.log(this ,
086: "invalid because connection ttl has been reached "
087: + dbp.conTTL, Server.MSG_AUTH,
088: Server.LVL_VERBOSE);
089: isValid = false;
090: return false;
091: }
092: return true;
093: }
094:
095: /**
096: * causes this PoolElement to close all open cursors and the connection to it's jdbc-source
097: */
098: public synchronized void cleanup() {
099: if (cleanedUp)
100: return;
101: try {
102: if (select != null) {
103: select.close();
104: select = null;
105: }
106: } catch (SQLException se) {
107: Server.debug(this , "cleanup: select.close()", se,
108: Server.MSG_ERROR, Server.LVL_MAJOR);
109: }
110: try {
111: if (insert != null) {
112: insert.close();
113: insert = null;
114: }
115: } catch (SQLException se) {
116: Server.debug(this , "cleanup: insert.close()", se,
117: Server.MSG_ERROR, Server.LVL_MAJOR);
118: }
119: try {
120: if (update != null) {
121: update.close();
122: update = null;
123: }
124: } catch (SQLException se) {
125: Server.debug(this , "cleanup: update.close()", se,
126: Server.MSG_ERROR, Server.LVL_MAJOR);
127: }
128: try {
129: if (con != null) {
130: con.close();
131: con = null;
132: }
133: } catch (SQLException se) {
134: Server.debug(this , "cleanup: connection.close()", se,
135: Server.MSG_ERROR, Server.LVL_MAJOR);
136: }
137: this .pool = null;
138: this .isActive = false;
139: this .cleanedUp = true;
140: Server.log("SqlAuthenticator", "Closed Connetion "
141: + this .toString(), Server.MSG_AUTH, Server.LVL_MAJOR);
142: }
143:
144: /**
145: * Checks the given Statement for SQLWarnings and logs them.
146: * @param s The statement to check for Warnings
147: */
148: public void checkWarnings(Statement s, String prefix) {
149: try {
150: SQLWarning sqlW = s.getWarnings();
151: while (sqlW != null) {
152: StringBuffer sb = new StringBuffer(this .toString());
153: sb.append(" getResultSet: Encountered SQLWarning: ");
154: sb.append(prefix);
155: sb.append(": ");
156: sb.append(sqlW.getErrorCode());
157: sb.append(": ");
158: sb.append(sqlW.getCause());
159: Server.log(Thread.currentThread(), sb.toString(),
160: Server.MSG_ERROR, Server.LVL_MAJOR);
161: sqlW = sqlW.getNextWarning();
162: }
163: } catch (SQLException se) {
164: this .isValid = false;
165: Server.debug(this , "checkWarnings caused exception", se,
166: Server.MSG_ERROR, Server.LVL_MAJOR);
167: }
168: }
169:
170: public String toString() {
171: StringBuffer sb = new StringBuffer("[PoolElement: ");
172: sb.append(id);
173: sb.append("/");
174: sb.append(sCnt);
175: sb.append("/");
176: sb.append(dbp.url).append("(").append(dbp.table).append(")");
177: sb.append("]");
178: return sb.toString();
179: }
180:
181: /**
182: * Grabs control over this PoolElement and returns true on success
183: * @return true if the control over this PoolElement was grabbed successfully
184: */
185: public synchronized short grab() {
186: if (this .isActive)
187: return ACTIVE;
188: if (!isValid())
189: return INVALID;
190: this .isActive = true;
191: this .hasBeenUsed = true;
192: return IDLE;
193: }
194:
195: /**
196: * Clears all parameters given to the PreparedStatements and all their warnings.
197: * Afterwards this PoolElement is marked as inactive (isActive = false)
198: */
199: public void release() {
200: try {
201: if (select != null) {
202: select.clearParameters();
203: select.clearWarnings();
204: }
205: if (update != null) {
206: update.clearParameters();
207: update.clearWarnings();
208: }
209: if (insert != null) {
210: insert.clearParameters();
211: insert.clearWarnings();
212: }
213: } catch (Exception se) {
214: Server.debug(this ,
215: "catched exception while releasing PoolElement",
216: se, Server.MSG_AUTH, Server.LVL_MAJOR);
217: }
218: this .isActive = false;
219: }
220:
221: /**
222: * Checks if a PreparedStatement for selection is already constructed or a
223: * new PreparedStatement will be constructed and this PreparedStatement will
224: * be returned
225: * @return the PreparedStatement for selection
226: * @throws Exception if an Error occured
227: */
228: private PreparedStatement getSelect() throws Exception {
229: try {
230: if (select != null)
231: return select;
232: if (con == null)
233: throw new Exception(
234: "No connection to retrieve a PreparedStatement from");
235: StringBuffer sb = new StringBuffer("SELECT ");
236: sb.append(dbp.columns[0]);
237: for (int i = 1; i < dbp.columns.length; i++) {
238: sb.append(", ");
239: sb.append(dbp.columns[i]);
240: }
241: sb.append(", ");
242: sb.append(dbp.fc_password);
243: sb.append(" FROM ");
244: sb.append(dbp.table);
245: sb.append(" WHERE ");
246: sb.append(dbp.fc_username);
247: sb.append(" = ?");
248: selStrg = sb.toString();
249: select = con.prepareStatement(selStrg,
250: ResultSet.TYPE_SCROLL_INSENSITIVE,
251: ResultSet.CONCUR_UPDATABLE);
252: if (dbp.queryTimeout > 0)
253: select.setQueryTimeout(dbp.queryTimeout);
254: return select;
255: } catch (Exception e) {
256: isValid = false;
257: release();
258: throw e;
259: }
260: }
261:
262: private PreparedStatement getUpdate() throws Exception {
263: try {
264: if (update != null)
265: return update;
266: if (con == null)
267: throw new Exception(
268: "No connection to retrieve a PreparedStatement from");
269: StringBuffer sb = new StringBuffer("UPDATE ");
270: sb.append(dbp.table);
271: sb.append(" SET ");
272: sb.append(dbp.updCols[0]);
273: sb.append(" = ?");
274: for (int i = 1; i < dbp.updCols.length; i++) {
275: sb.append(", ");
276: sb.append(dbp.updCols[i]);
277: sb.append(" = ?");
278: }
279: sb.append(" WHERE ");
280: if (dbp.idField != null) {
281: sb.append(dbp.idField);
282: sb.append(" = ?");
283: } else {
284: sb.append(dbp.fc_username);
285: sb.append(" = ?");
286: }
287: updStrg = sb.toString();
288: update = con.prepareStatement(updStrg);
289: if (dbp.queryTimeout > 0)
290: update.setQueryTimeout(dbp.queryTimeout);
291: return update;
292: } catch (Exception e) {
293: isValid = false;
294: release();
295: throw e;
296: }
297: }
298:
299: /**
300: * Checks if there is already a PreparedStatement for retrieving the user-data and
301: * constructs it, if it doesn't exist. Afterwards the login will be checked and
302: * the user-object will be constructed if the credentials are correct. Null will
303: * be returned, if the credentials did not return a user-record.
304: * @return User the user which is allowed to log in or null if no match was found
305: * @throws Exception if technical error occures (connection problems, ...)
306: */
307: public User loginUser(String username, String password,
308: String cookie) throws Exception {
309: try {
310: checkThread();
311: PreparedStatement ps = getSelect();
312: ps.setString(1, username.toLowerCase().trim());
313: ResultSet rs = ps.executeQuery();
314: sCnt++;
315: Server
316: .log(Thread.currentThread(), this .toString()
317: + "LOGIN user uname="
318: + username.toLowerCase() + "/pwd="
319: + password + "/cookie=" + cookie + "\r\n"
320: + selStrg, Server.MSG_AUTH,
321: Server.LVL_VERY_VERBOSE);
322: dbp.cacheMetaData(rs);
323: if (!rs.next()) {
324: Server
325: .log(
326: Thread.currentThread(),
327: this .toString()
328: + "LOGIN no user mathing username and password "
329: + username + "/" + password,
330: Server.MSG_AUTH, Server.LVL_MINOR);
331: rs.close();
332: // return unregistered user (if they are allowed will be checked in auth-manager)
333: return new User(username, cookie); // return an unregistered user
334: } else if (!rs.isLast()) {
335: Server.log(Thread.currentThread(), this .toString()
336: + "LOGIN multible records returned for user "
337: + username, Server.MSG_AUTH, Server.LVL_MAJOR);
338: rs.close();
339: // return null to make clear, that there is a problem within the db-table
340: return null;
341: }
342: checkThread();
343: String dbpwd = rs.getString(dbp.columns.length + 1);
344: if (dbpwd == null || !dbpwd.equals(password))
345: return null;
346:
347: User u = new User(username, cookie);
348: u.isUnregistered = false;
349:
350: readColumns(u, rs);
351:
352: checkWarnings(ps, "loginUser (getData)");
353:
354: checkThread();
355: // if a lastlogin-property exists, we have to update the data in the db
356: if (!dbp.readOnly) {
357: doLoginUpdates(u, rs);
358: }
359: checkWarnings(ps, "loginUser (update Data)");
360: rs.close();
361: Server.log(Thread.currentThread(), this .toString()
362: + "LOGIN returning " + u, Server.MSG_AUTH,
363: Server.LVL_MAJOR);
364: u.isUnregistered = false;
365: return u;
366: } catch (Exception e) {
367: Server.debug(this , selStrg, e, Server.MSG_AUTH,
368: Server.LVL_MAJOR);
369: isValid = false;
370: release();
371: throw e;
372: }
373: }
374:
375: public User loginUser(User u, String password) throws Exception {
376: try {
377: checkThread();
378: PreparedStatement ps = getSelect();
379: ps.setString(1, u.getName().toLowerCase().trim());
380: Server.log(Thread.currentThread(), this .toString()
381: + "LOGIN user uname=" + u.getName().toLowerCase()
382: + "\r\n" + selStrg, Server.MSG_AUTH,
383: Server.LVL_VERY_VERBOSE);
384: ResultSet rs = ps.executeQuery();
385: sCnt++;
386: dbp.cacheMetaData(rs);
387: if (!rs.next()) {
388: Server.log(Thread.currentThread(), this .toString()
389: + "LOGIN no user mathing username "
390: + u.getName(), Server.MSG_AUTH,
391: Server.LVL_MINOR);
392: rs.close();
393: return u; // return unchanged user object
394: } else if (!rs.isLast()) {
395: Server.log(Thread.currentThread(), this .toString()
396: + "LOGIN multible records returned for user "
397: + u.getName(), Server.MSG_AUTH,
398: Server.LVL_MAJOR);
399: rs.close();
400: return u; // return unchanged user object
401: }
402:
403: // always check Pwd if the userobject is marked as unregistered
404: // if there is an existing user having the same name but a differen password,
405: // we must return login-failed (done by returning null instead of an user-object)
406: if (u.isUnregistered == true) {
407: String dbpwd = rs.getString(dbp.columns.length + 1);
408: if (dbpwd == null || !dbpwd.equals(password)) {
409: return null;
410: }
411: u.isUnregistered = false;
412: }
413: checkThread();
414:
415: // read all the other properties
416: readColumns(u, rs);
417:
418: checkWarnings(ps, "loginUser (getData)");
419: checkThread();
420: // if a lastlogin-property exists, we have to update the data in the db
421: if (!dbp.readOnly) {
422: doLoginUpdates(u, rs);
423: }
424: checkWarnings(ps, "loginUser (update Data)");
425: rs.close();
426: Server.log(Thread.currentThread(), this .toString()
427: + "LOGIN returning " + u, Server.MSG_AUTH,
428: Server.LVL_MAJOR);
429: return u;
430: } catch (Exception e) {
431: Server
432: .log(this , selStrg, Server.MSG_AUTH,
433: Server.LVL_MAJOR);
434: isValid = false;
435: release();
436: throw e;
437: }
438: }
439:
440: private void readColumns(User u, ResultSet rs) throws SQLException {
441: for (int i = 0; i < dbp.columns.length; i++) {
442: String cname = dbp.names[i];
443: int idx = i + 1;
444: if ("userright".equals(cname)) {
445: String val = rs.getString(idx);
446: if (val == null || val.length() == 0
447: || "null".equalsIgnoreCase(val)) {
448: u.setPermission(IUserStates.ROLE_USER);
449: } else if ("true".equalsIgnoreCase(val)
450: || "yes".equalsIgnoreCase(val)
451: || "vip".equalsIgnoreCase(val)) {
452: u.setPermission(IUserStates.ROLE_VIP);
453: } else if ("admin".equalsIgnoreCase(val)) {
454: u.setPermission(IUserStates.ROLE_GOD);
455: } else if ("moderator".equalsIgnoreCase(val)) {
456: u.setPermission(IUserStates.ROLE_VIP
457: | IUserStates.IS_MODERATOR);
458: } else if ("guest".equalsIgnoreCase(val)) {
459: u.setPermission(IUserStates.IS_GUEST);
460: } else if ("asshole".equalsIgnoreCase(val)) {
461: u.setPermission(IUserStates.ROLE_ASSHOLE);
462: } else {
463: try {
464: u.setPermission(Integer.parseInt(val));
465: } catch (NumberFormatException nfe) {
466: Server
467: .log(
468: Thread.currentThread(),
469: this .toString()
470: + "LOGIN userrights-column contains unknown value, corrected to ROLE_USER\r\n(must be null/true,yes,vip or VIP/admin/moderator/guest/user/assohle) ",
471: Server.MSG_AUTH,
472: Server.LVL_MAJOR);
473: u.setPermission(IUserStates.ROLE_USER);
474: }
475: }
476: } else if ("id".equals(cname)) {
477: u.setID(rs.getString(idx));
478: } else if ("color".equals(cname)) {
479: u.setColCode(rs.getString(idx));
480: } else if ("chattime".equals(cname)) {
481: u.setProperty("chattime", new Long(rs.getLong(idx)));
482: } else if ("lastlogin".equals(cname)) {
483: switch (dbp.types[i]) {
484: case Types.BIGINT:
485: case Types.INTEGER:
486: case Types.NUMERIC:
487: case Types.SMALLINT:
488: u.setProperty("lastlogin", new Timestamp(rs
489: .getLong(idx)));
490: break;
491: case Types.DATE:
492: case Types.TIMESTAMP:
493: Timestamp ts = rs.getTimestamp(idx);
494: u.setProperty("lastlogin", ts);
495: break;
496: default:
497: String s = rs.getString(idx);
498: if (rs.wasNull()) {
499: u.setProperty("lastlogin", new Timestamp(System
500: .currentTimeMillis()));
501: break;
502: }
503: try {
504: long l = Long.parseLong(s);
505: u.setProperty("lastlogin", new Timestamp(l));
506: } catch (NumberFormatException nfe) {
507: try {
508: u.setProperty("lastlogin", Timestamp
509: .valueOf(s));
510: } catch (IllegalArgumentException iae) {
511: Server.log(this ,
512: "LOGIN Unable to retrieve lastlogin-value! "
513: + s, Server.MSG_AUTH,
514: Server.LVL_MAJOR);
515: }
516: }
517: }
518: } else if ("friends".equals(cname)) {
519: List users = pool.authenticator.parseUserList(rs
520: .getString(idx));
521: for (Iterator it = users.iterator(); it.hasNext();) {
522: u.addFriend((String) it.next());
523: }
524: } else if ("ignorelist".equals(cname)) {
525: List ignores = pool.authenticator.parseUserList(rs
526: .getString(idx));
527: for (Iterator it = ignores.iterator(); it.hasNext();) {
528: u.ignoreUser((String) it.next());
529: }
530: } else if ("notifyfriends".equals(cname)) {
531: switch (dbp.types[i]) {
532: case Types.BIGINT:
533: case Types.INTEGER:
534: case Types.NUMERIC:
535: case Types.SMALLINT:
536: u.setFriendsNotification(rs.getShort(idx));
537: break;
538: default:
539: u
540: .setFriendsNotification(pool.authenticator
541: .parseBoolean(rs.getString(idx)) ? Server.srv.FN_DEFAULT_MODE_TRUE
542: : Server.srv.FN_DEFAULT_MODE_FALSE);
543: }
544: // u.setFriendsNotification(pool.authenticator.parseBoolean(rs.getString(idx)));
545: } else if ("customtitle".equals(cname)) {
546: u.setCustomTitle(rs.getString(idx));
547: } else if ("blocked".equals(cname)) {
548: u.blocked = pool.authenticator.parseBoolean(rs
549: .getString(idx));
550: } else if ("activated".equals(cname)) {
551: u.activated = pool.authenticator.parseBoolean(rs
552: .getString(idx));
553: } else {
554: String strg = getEncodedString(rs, idx);
555: u.setProperty(cname, strg);
556: }
557: }
558: }
559:
560: private void doLoginUpdates(User nu, ResultSet rs) throws Exception {
561: boolean updated = false, error = false;
562: long ts = System.currentTimeMillis();
563: int idx = dbp.nameV.indexOf("lastlogin");
564: if (idx > -1) {
565: try {
566: switch (dbp.types[idx]) {
567: case Types.INTEGER:
568: case Types.SMALLINT:
569: rs.updateInt(idx + 1, (int) (ts / 1000));
570: break;
571: case Types.BIGINT:
572: case Types.NUMERIC:
573: case Types.DECIMAL:
574: rs.updateLong(idx + 1, ts / 1000);
575: break;
576: case Types.DATE:
577: case Types.TIMESTAMP:
578: rs.updateTimestamp(idx + 1, new Timestamp(ts));
579: break;
580: default:
581: rs.updateString(idx + 1, String.valueOf(ts / 1000));
582: }
583: updated = true;
584: } catch (SQLException se) {
585: Server.debug(Thread.currentThread(), this .toString()
586: + "LOGIN unable to update lastlogin", se,
587: Server.MSG_AUTH, Server.LVL_MAJOR);
588: error = true;
589: }
590: }
591: // update the cookie too (if set in the db properties)
592: idx = dbp.nameV.indexOf("cookie");
593: if (idx > -1)
594: try {
595: rs.updateString(idx + 1, HashUtils.encodeMD5(nu
596: .getCookie()));
597: } catch (SQLException se) {
598: Server.debug(Thread.currentThread(), this .toString()
599: + "LOGIN unable to update cookie", se,
600: Server.MSG_AUTH, Server.LVL_MAJOR);
601: }
602: try {
603: if (updated) {
604: rs.updateRow();
605: con.commit();
606: } else if (error) {
607: rs.cancelRowUpdates();
608: }
609: } catch (SQLException se) {
610: Server
611: .debug(
612: Thread.currentThread(),
613: this .toString()
614: + "LOGIN exception during updateRow/cancelRowUpdates",
615: se, Server.MSG_AUTH, Server.LVL_MAJOR);
616: }
617: }
618:
619: public void logoutUser(User u) throws Exception {
620: try {
621: if (dbp.readOnly || dbp.updCols == null
622: || dbp.updCols.length < 1)
623: return;
624: PreparedStatement ps = getUpdate();
625: for (int i = 0; i < dbp.updCols.length; i++) {
626: String cname = dbp.updNames[i];
627: if ("chattime".equalsIgnoreCase(cname)) {
628: ps.setLong(i + 1, u.getChattime());
629: } else if ("userrights".equalsIgnoreCase(cname)) {
630: ps.setInt(i + 1, u.getPermissionMap());
631: } else if ("color".equalsIgnoreCase(cname)) {
632: ps.setString(i + 1, u.getColCode());
633: } else if ("friends".equalsIgnoreCase(cname)) {
634: StringBuffer sb = new StringBuffer();
635: for (Enumeration e = u.friends(); e
636: .hasMoreElements();) {
637: String s = (String) e.nextElement();
638: sb.append(s);
639: if (e.hasMoreElements())
640: sb.append(", ");
641: }
642: ps.setString(i + 1, sb.toString());
643: } else if ("notifyfriends".equalsIgnoreCase(cname)) {
644: int idx = dbp.nameV.indexOf("notifyfriends");
645: switch (dbp.types[idx]) {
646: case Types.BIGINT:
647: case Types.BIT:
648: case Types.DECIMAL:
649: case Types.INTEGER:
650: case Types.SMALLINT:
651: ps.setInt(i + 1, u.notifyFriends());
652: break;
653: case Types.BOOLEAN:
654: ps.setBoolean(i + 1,
655: u.notifyFriends() == User.FN_ALL ? true
656: : false);
657: break;
658: default:
659: ps
660: .setString(
661: i + 1,
662: u.notifyFriends() == User.FN_ALL ? "true"
663: : "false");
664: }
665: } else if ("extratitle".equalsIgnoreCase(cname)) {
666: ps.setString(i + 1, u.getCustomTitle());
667: } else if ("cookie".equalsIgnoreCase(cname)) {
668: // and overwrite it with "not_logged_in" when the user loggs out
669: ps.setString(i + 1, "not_logged_in");
670: } else if ("blocked".equalsIgnoreCase(cname)) {
671: int idx = dbp.nameV.indexOf("blocked");
672: switch (dbp.types[idx]) {
673: case Types.BIGINT:
674: case Types.BIT:
675: case Types.DECIMAL:
676: case Types.INTEGER:
677: case Types.SMALLINT:
678: ps.setInt(i + 1, u.blocked ? 1 : 0);
679: break;
680: case Types.BOOLEAN:
681: ps.setBoolean(i + 1, u.blocked);
682: break;
683: default:
684: ps.setString(i + 1, u.blocked ? "1" : "0");
685: }
686: } else if ("activated".equalsIgnoreCase(cname)) {
687: int idx = dbp.nameV.indexOf("activated");
688: switch (dbp.types[idx]) {
689: case Types.BIGINT:
690: case Types.BIT:
691: case Types.DECIMAL:
692: case Types.INTEGER:
693: case Types.SMALLINT:
694: ps.setInt(i + 1, u.activated ? 1 : 0);
695: break;
696: case Types.BOOLEAN:
697: ps.setBoolean(i + 1, u.activated);
698: break;
699: default:
700: ps.setString(i + 1, u.activated ? "1" : "0");
701: }
702: }
703: }
704: if (dbp.idField != null) {
705: if (u.getID() == null) {
706: Server.log(u, "Unable to store logout-data for "
707: + u.getName()
708: + " because of missing id-value",
709: Server.MSG_AUTH, Server.LVL_MAJOR);
710: return;
711: }
712: ps.setString(dbp.updCols.length + 1, u.getID());
713: } else {
714: ps.setString(dbp.updCols.length + 1, u.getName()
715: .toLowerCase());
716: }
717: int rows = ps.executeUpdate();
718: sCnt++;
719: if (rows == 1) {
720: con.commit();
721: } else if (rows < 1) {
722: Server
723: .log(
724: Thread.currentThread(),
725: this .toString()
726: + "LOGOUT unable to update userdata! No record for: "
727: + dbp.idField != null ? dbp.idField
728: + " = " + u.getID()
729: : "username = "
730: + u.getName()
731: .toLowerCase(),
732: Server.MSG_AUTH, Server.LVL_MAJOR);
733: return;
734: } else if (rows > 1) {
735: Server
736: .log(
737: Thread.currentThread(),
738: this .toString()
739: + "LOGOUT unable to update userdata! More than one value would be updated: ("
740: + dbp.idField != null ? dbp.idField
741: + " = " + u.getID()
742: : "username = "
743: + u.getName()
744: .toLowerCase()
745: + ")", Server.MSG_AUTH,
746: Server.LVL_MAJOR);
747: try {
748: con.rollback();
749: Server.log(Thread.currentThread(), this .toString()
750: + "LOGOUT rollback successfully",
751: Server.MSG_AUTH, Server.LVL_VERBOSE);
752: } catch (SQLException se) {
753: Server.log(Thread.currentThread(), this .toString()
754: + "LOGOUT rollback failed!!!",
755: Server.MSG_AUTH, Server.LVL_MAJOR);
756: }
757: }
758: checkWarnings(ps, "logoutUser");
759: } catch (Exception e) {
760: isValid = false;
761: release();
762: throw e;
763: }
764: }
765:
766: /**
767: * replaces every < and every > with an HTML-entity and returns the value
768: * @param rs
769: * @param c
770: * @return String The string having the replaces < and >-characters
771: */
772: private static String getEncodedString(ResultSet rs, int idx) {
773: if (rs == null)
774: return null;
775: try {
776: String result = rs.getString(idx);
777: if (result == null)
778: return null;
779: result = result.replaceAll("[<]", "<");
780: result = result.replaceAll("[>]", ">");
781: return result;
782: } catch (Exception e) {
783: Server.debug("static PoolElement",
784: "getEncodedString: error geting encoded string", e,
785: Server.MSG_ERROR, Server.LVL_MAJOR);
786: }
787: return null;
788: }
789:
790: private void checkThread() throws CanceledRequestException {
791: if (Thread.currentThread().isInterrupted())
792: throw new CanceledRequestException(
793: "ConnectionBuffer has been invalidated");
794: }
795:
796: public void finalize() {
797: if (Server.TRACE_CREATE_AND_FINALIZE)
798: Server
799: .log(
800: this ,
801: "----------------------------------------FINALIZED",
802: Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
803: }
804: }
|