📄 poolelement.java
字号:
/**
* Copyright (C) 2003 Manfred Andres
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package freecs.auth.sqlConnectionPool;
import freecs.Server;
import freecs.core.CanceledRequestException;
import freecs.core.User;
import freecs.interfaces.IUserStates;
import freecs.util.HashUtils;
import java.sql.*;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
public class PoolElement {
public static final short INVALID = -1;
public static final short IDLE = 0;
public static final short ACTIVE = 1;
volatile private PreparedStatement select = null,
update = null,
updateLastlogin = null,
insert = null;
volatile private String selStrg = null,
insStrg = null,
updStrg = null,
updLastloginStrg = null;
private DbProperties dbp;
private volatile boolean isValid=true;
ConnectionPool pool;
Connection con = null;
int id;
volatile int sCnt=0;
long validUntil;
volatile boolean isActive = false, hasBeenUsed=false, cleanedUp=false;
ResultSet rs;
PoolElement (ConnectionPool pool, Connection con, DbProperties dbp, int id) throws Exception {
if (con == null)
throw new Exception ("no connection supplied");
this.pool = pool;
this.dbp=dbp;
this.id = id;
this.con = con;
con.setAutoCommit (false);
validUntil = System.currentTimeMillis() + dbp.conTTL;
Server.log ("SqlAuthenticator", "Created new Connetion " + this.toString(), Server.MSG_AUTH, Server.LVL_MAJOR);
if (Server.TRACE_CREATE_AND_FINALIZE)
Server.log (this, "++++++++++++++++++++++++++++++++++++++++CREATE", Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
}
private boolean isValid() {
if (!isValid)
return false;
if (con == null
|| cleanedUp)
return false;
if (!hasBeenUsed)
return true;
if (sCnt > dbp.maxStmtPerCon) {
Server.log(this, "invalid because max-statements/connection has been reached " + dbp.maxStmtPerCon, Server.MSG_AUTH, Server.LVL_VERBOSE);
isValid=false;
return false;
}
if (validUntil <= System.currentTimeMillis()) {
Server.log(this, "invalid because connection ttl has been reached " + dbp.conTTL, Server.MSG_AUTH, Server.LVL_VERBOSE);
isValid=false;
return false;
}
return true;
}
/**
* causes this PoolElement to close all open cursors and the connection to it's jdbc-source
*/
public synchronized void cleanup () {
if (cleanedUp)
return;
try {
if (select != null) {
select.close();
select = null;
}
} catch (SQLException se) {
Server.debug(this, "cleanup: select.close()", se, Server.MSG_ERROR, Server.LVL_MAJOR);
}
try {
if (insert != null) {
insert.close();
insert = null;
}
} catch (SQLException se) {
Server.debug(this, "cleanup: insert.close()", se, Server.MSG_ERROR, Server.LVL_MAJOR);
}
try {
if (update != null) {
update.close();
update = null;
}
} catch (SQLException se) {
Server.debug(this, "cleanup: update.close()", se, Server.MSG_ERROR, Server.LVL_MAJOR);
}
try {
if (con!=null) {
con.close();
con = null;
}
} catch (SQLException se) {
Server.debug(this, "cleanup: connection.close()", se, Server.MSG_ERROR, Server.LVL_MAJOR);
}
this.pool = null;
this.isActive = false;
this.cleanedUp = true;
Server.log ("SqlAuthenticator", "Closed Connetion " + this.toString(), Server.MSG_AUTH, Server.LVL_MAJOR);
}
/**
* Checks the given Statement for SQLWarnings and logs them.
* @param s The statement to check for Warnings
*/
public void checkWarnings(Statement s, String prefix) {
try {
SQLWarning sqlW = s.getWarnings();
while (sqlW != null) {
StringBuffer sb = new StringBuffer(this.toString());
sb.append (" getResultSet: Encountered SQLWarning: ");
sb.append (prefix);
sb.append (": ");
sb.append (sqlW.getErrorCode());
sb.append (": ");
sb.append (sqlW.getCause());
Server.log (Thread.currentThread(), sb.toString (), Server.MSG_ERROR, Server.LVL_MAJOR);
sqlW = sqlW.getNextWarning();
}
} catch (SQLException se) {
this.isValid=false;
Server.debug(this, "checkWarnings caused exception", se, Server.MSG_ERROR, Server.LVL_MAJOR);
}
}
public String toString() {
StringBuffer sb = new StringBuffer("[PoolElement: ");
sb.append (id);
sb.append ("/");
sb.append (sCnt);
sb.append ("/");
sb.append (dbp.url).append ("(").append (dbp.table).append(")");
sb.append ("]");
return sb.toString();
}
/**
* Grabs control over this PoolElement and returns true on success
* @return true if the control over this PoolElement was grabbed successfully
*/
public synchronized short grab() {
if (this.isActive)
return ACTIVE;
if (!isValid())
return INVALID;
this.isActive=true;
this.hasBeenUsed=true;
return IDLE;
}
/**
* Clears all parameters given to the PreparedStatements and all their warnings.
* Afterwards this PoolElement is marked as inactive (isActive = false)
*/
public void release() {
try {
if (select!=null) {
select.clearParameters();
select.clearWarnings();
}
if (update!=null) {
update.clearParameters();
update.clearWarnings();
}
if (insert!=null) {
insert.clearParameters();
insert.clearWarnings();
}
} catch (Exception se) {
Server.debug (this, "catched exception while releasing PoolElement", se, Server.MSG_AUTH, Server.LVL_MAJOR);
}
this.isActive=false;
}
/**
* Checks if a PreparedStatement for selection is already constructed or a
* new PreparedStatement will be constructed and this PreparedStatement will
* be returned
* @return the PreparedStatement for selection
* @throws Exception if an Error occured
*/
private PreparedStatement getSelect() throws Exception {
try {
if (select!=null)
return select;
if (con==null)
throw new Exception ("No connection to retrieve a PreparedStatement from");
StringBuffer sb = new StringBuffer ("SELECT ");
sb.append (dbp.columns[0]);
for (int i = 1; i<dbp.columns.length; i++) {
sb.append (", ");
sb.append (dbp.columns[i]);
}
sb.append (", ");
sb.append (dbp.fc_password);
sb.append (" FROM ");
sb.append (dbp.table);
sb.append (" WHERE ");
sb.append (dbp.fc_username);
sb.append (" = ?");
selStrg = sb.toString();
select = con.prepareStatement(selStrg, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
if (dbp.queryTimeout > 0)
select.setQueryTimeout(dbp.queryTimeout);
return select;
} catch (Exception e) {
isValid=false;
release();
throw e;
}
}
private PreparedStatement getUpdate() throws Exception {
try {
if (update != null)
return update;
if (con==null)
throw new Exception ("No connection to retrieve a PreparedStatement from");
StringBuffer sb = new StringBuffer("UPDATE ");
sb.append (dbp.table);
sb.append (" SET ");
sb.append (dbp.updCols[0]);
sb.append (" = ?");
for (int i = 1; i<dbp.updCols.length; i++) {
sb.append (", ");
sb.append (dbp.updCols[i]);
sb.append (" = ?");
}
sb.append (" WHERE ");
if (dbp.idField != null) {
sb.append (dbp.idField);
sb.append (" = ?");
} else {
sb.append (dbp.fc_username);
sb.append (" = ?");
}
updStrg = sb.toString();
update = con.prepareStatement(updStrg);
if (dbp.queryTimeout > 0)
update.setQueryTimeout(dbp.queryTimeout);
return update;
} catch (Exception e) {
isValid=false;
release();
throw e;
}
}
/**
* Checks if there is already a PreparedStatement for retrieving the user-data and
* constructs it, if it doesn't exist. Afterwards the login will be checked and
* the user-object will be constructed if the credentials are correct. Null will
* be returned, if the credentials did not return a user-record.
* @return User the user which is allowed to log in or null if no match was found
* @throws Exception if technical error occures (connection problems, ...)
*/
public User loginUser (String username, String password, String cookie) throws Exception {
try {
checkThread();
PreparedStatement ps = getSelect();
ps.setString(1, username.toLowerCase().trim());
ResultSet rs = ps.executeQuery();
sCnt++;
Server.log(Thread.currentThread(), this.toString() + "LOGIN user uname=" + username.toLowerCase() + "/pwd=" + password + "/cookie=" + cookie + "\r\n" + selStrg, Server.MSG_AUTH, Server.LVL_VERY_VERBOSE);
dbp.cacheMetaData(rs);
if (!rs.next()) {
Server.log(Thread.currentThread(), this.toString()+ "LOGIN no user mathing username and password " + username + "/" + password, Server.MSG_AUTH, Server.LVL_MINOR);
rs.close();
// return unregistered user (if they are allowed will be checked in auth-manager)
return new User(username, cookie); // return an unregistered user
} else if (!rs.isLast()) {
Server.log(Thread.currentThread(), this.toString() + "LOGIN multible records returned for user " + username, Server.MSG_AUTH, Server.LVL_MAJOR);
rs.close();
// return null to make clear, that there is a problem within the db-table
return null;
}
checkThread();
String dbpwd = rs.getString(dbp.columns.length+1);
if (dbpwd==null || !dbpwd.equals(password))
return null;
User u = new User (username, cookie);
u.isUnregistered = false;
readColumns(u, rs);
checkWarnings(ps, "loginUser (getData)");
checkThread();
// if a lastlogin-property exists, we have to update the data in the db
if (!dbp.readOnly) {
doLoginUpdates(u, rs);
}
checkWarnings(ps, "loginUser (update Data)");
rs.close();
Server.log (Thread.currentThread(), this.toString() + "LOGIN returning " + u, Server.MSG_AUTH, Server.LVL_MAJOR);
u.isUnregistered = false;
return u;
} catch (Exception e) {
Server.debug (this, selStrg, e, Server.MSG_AUTH, Server.LVL_MAJOR);
isValid=false;
release();
throw e;
}
}
public User loginUser (User u, String password) throws Exception {
try {
checkThread();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -