Commit 50c3ce4c authored by God Ly's avatar God Ly Committed by it2000

Replaced (con|pstmt|rs).close() with DBConnectionManager.close...(...).

De-duplicated some code.
Added some optimizations.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@11696 b35dd754-fafc-0310-a699-88a17e54d16e
parent e05ccb91
...@@ -60,9 +60,9 @@ public class DbConnectionManager { ...@@ -60,9 +60,9 @@ public class DbConnectionManager {
private static boolean transactionsSupported; private static boolean transactionsSupported;
// True if the database requires large text fields to be streamed. // True if the database requires large text fields to be streamed.
private static boolean streamTextRequired; private static boolean streamTextRequired;
// True if the database supports the Statement.setMaxRows() method. /** True if the database supports the Statement.setMaxRows() method. */
private static boolean maxRowsSupported; private static boolean maxRowsSupported;
// True if the database supports the Statement.setFetchSize() method. /** True if the database supports the rs.setFetchSize() method. */
private static boolean fetchSizeSupported; private static boolean fetchSizeSupported;
// True if the database supports correlated subqueries. // True if the database supports correlated subqueries.
private static boolean subqueriesSupported; private static boolean subqueriesSupported;
...@@ -70,6 +70,9 @@ public class DbConnectionManager { ...@@ -70,6 +70,9 @@ public class DbConnectionManager {
private static boolean scrollResultsSupported; private static boolean scrollResultsSupported;
// True if the database supports batch updates. // True if the database supports batch updates.
private static boolean batchUpdatesSupported; private static boolean batchUpdatesSupported;
/** True if the database supports the Statement.setFetchSize()) method. */
static boolean pstmt_fetchSizeSupported = true;
private static DatabaseType databaseType = DatabaseType.unknown; private static DatabaseType databaseType = DatabaseType.unknown;
...@@ -534,6 +537,54 @@ public class DbConnectionManager { ...@@ -534,6 +537,54 @@ public class DbConnectionManager {
} }
} }
/**
* Limits the number of the results in a result set (to startIndex + numResults).
* Sets the fetch size depending on the features of the JDBC driver and make
* sure that the size is not bigger than 500.
* @param pstmt the PreparedStatement
* @param startIndex the first row with interesting data
* @param numResults the number of interesting results
*/
public static void limitRowsAndFetchSize(PreparedStatement pstmt, int startIndex, int numResults) {
final int MAX_FETCHRESULTS = 500;
final int maxRows = startIndex + numResults;
setMaxRows(pstmt, maxRows);
if (pstmt_fetchSizeSupported)
{
if (scrollResultsSupported) {
setFetchSize(pstmt, Math.min(MAX_FETCHRESULTS, numResults));
}
else {
setFetchSize(pstmt, Math.min(MAX_FETCHRESULTS, maxRows));
}
}
}
/**
* Sets the number of rows that the JDBC driver should buffer at a time.
* The operation is automatically bypassed if Openfire knows that the
* the JDBC driver or database doesn't support it.
*
* @param pstmt the PreparedStatement to set the fetch size for.
* @param fetchSize the fetchSize.
*/
public static void setFetchSize(PreparedStatement pstmt, int fetchSize) {
if (pstmt_fetchSizeSupported) {
try {
pstmt.setFetchSize(fetchSize);
}
catch (Throwable t) {
// Ignore. Exception may happen if the driver doesn't support
// this operation and we didn't set meta-data correctly.
// However, it is a good idea to update the meta-data so that
// we don't have to incur the cost of catching an exception
// each time.
Log.error("Disabling JDBC method pstmt.setFetchSize(fetchSize).", t);
pstmt_fetchSizeSupported = false;
}
}
}
/** /**
* Returns the current connection provider. The only case in which this * Returns the current connection provider. The only case in which this
* method should be called is if more information about the current * method should be called is if more information about the current
...@@ -880,6 +931,10 @@ public class DbConnectionManager { ...@@ -880,6 +931,10 @@ public class DbConnectionManager {
public static boolean isFetchSizeSupported() { public static boolean isFetchSizeSupported() {
return fetchSizeSupported; return fetchSizeSupported;
} }
public static boolean isPstmtFetchSizeSupported() {
return pstmt_fetchSizeSupported;
}
public static boolean isSubqueriesSupported() { public static boolean isSubqueriesSupported() {
return subqueriesSupported; return subqueriesSupported;
......
...@@ -24,7 +24,6 @@ import java.sql.Connection; ...@@ -24,7 +24,6 @@ import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
...@@ -32,7 +31,6 @@ import java.util.List; ...@@ -32,7 +31,6 @@ import java.util.List;
import org.jivesoftware.database.DbConnectionManager; import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.util.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
...@@ -78,6 +76,7 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -78,6 +76,7 @@ public class DefaultGroupProvider implements GroupProvider {
private static final String USER_GROUPS = private static final String USER_GROUPS =
"SELECT groupName FROM ofGroupUser WHERE username=?"; "SELECT groupName FROM ofGroupUser WHERE username=?";
private static final String ALL_GROUPS = "SELECT groupName FROM ofGroup ORDER BY groupName"; private static final String ALL_GROUPS = "SELECT groupName FROM ofGroup ORDER BY groupName";
private static final String SEARCH_GROUP_NAME = "SELECT groupName FROM ofGroup WHERE groupName LIKE ? ORDER BY groupName";
private XMPPServer server = XMPPServer.getInstance(); private XMPPServer server = XMPPServer.getInstance();
...@@ -95,16 +94,7 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -95,16 +94,7 @@ public class DefaultGroupProvider implements GroupProvider {
Log.error(e.getMessage(), e); Log.error(e.getMessage(), e);
} }
finally { finally {
try { DbConnectionManager.closeConnection(pstmt, con);
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
try {
if (con != null) {
con.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
} }
Collection<JID> members = getMembers(name, false); Collection<JID> members = getMembers(name, false);
Collection<JID> administrators = getMembers(name, true); Collection<JID> administrators = getMembers(name, true);
...@@ -116,11 +106,12 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -116,11 +106,12 @@ public class DefaultGroupProvider implements GroupProvider {
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_GROUP); pstmt = con.prepareStatement(LOAD_GROUP);
pstmt.setString(1, name); pstmt.setString(1, name);
ResultSet rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
if (!rs.next()) { if (!rs.next()) {
throw new GroupNotFoundException("Group with name " throw new GroupNotFoundException("Group with name "
+ name + " not found."); + name + " not found.");
...@@ -131,16 +122,7 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -131,16 +122,7 @@ public class DefaultGroupProvider implements GroupProvider {
Log.error(e.getMessage(), e); Log.error(e.getMessage(), e);
} }
finally { finally {
try { DbConnectionManager.closeConnection(rs, pstmt, con);
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
try {
if (con != null) {
con.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
} }
Collection<JID> members = getMembers(name, false); Collection<JID> members = getMembers(name, false);
Collection<JID> administrators = getMembers(name, true); Collection<JID> administrators = getMembers(name, true);
...@@ -164,16 +146,7 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -164,16 +146,7 @@ public class DefaultGroupProvider implements GroupProvider {
throw new GroupNotFoundException(); throw new GroupNotFoundException();
} }
finally { finally {
try { DbConnectionManager.closeConnection(pstmt, con);
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
try {
if (con != null) {
con.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
} }
} }
...@@ -189,12 +162,14 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -189,12 +162,14 @@ public class DefaultGroupProvider implements GroupProvider {
pstmt.setString(1, newName); pstmt.setString(1, newName);
pstmt.setString(2, oldName); pstmt.setString(2, oldName);
pstmt.executeUpdate(); pstmt.executeUpdate();
pstmt.close(); DbConnectionManager.fastcloseStmt(pstmt);
pstmt = con.prepareStatement(SET_GROUP_NAME_2); pstmt = con.prepareStatement(SET_GROUP_NAME_2);
pstmt.setString(1, newName); pstmt.setString(1, newName);
pstmt.setString(2, oldName); pstmt.setString(2, oldName);
pstmt.executeUpdate(); pstmt.executeUpdate();
pstmt.close(); DbConnectionManager.fastcloseStmt(pstmt);
pstmt = con.prepareStatement(SET_GROUP_NAME_3); pstmt = con.prepareStatement(SET_GROUP_NAME_3);
pstmt.setString(1, newName); pstmt.setString(1, newName);
pstmt.setString(2, oldName); pstmt.setString(2, oldName);
...@@ -205,11 +180,7 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -205,11 +180,7 @@ public class DefaultGroupProvider implements GroupProvider {
abortTransaction = true; abortTransaction = true;
} }
finally { finally {
try { DbConnectionManager.closeStatement(pstmt);
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
DbConnectionManager.closeTransactionConnection(con, abortTransaction); DbConnectionManager.closeTransactionConnection(con, abortTransaction);
} }
} }
...@@ -224,12 +195,14 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -224,12 +195,14 @@ public class DefaultGroupProvider implements GroupProvider {
pstmt = con.prepareStatement(DELETE_GROUP_USERS); pstmt = con.prepareStatement(DELETE_GROUP_USERS);
pstmt.setString(1, groupName); pstmt.setString(1, groupName);
pstmt.executeUpdate(); pstmt.executeUpdate();
pstmt.close(); DbConnectionManager.fastcloseStmt(pstmt);
// Remove all properties of the group. // Remove all properties of the group.
pstmt = con.prepareStatement(DELETE_PROPERTIES); pstmt = con.prepareStatement(DELETE_PROPERTIES);
pstmt.setString(1, groupName); pstmt.setString(1, groupName);
pstmt.executeUpdate(); pstmt.executeUpdate();
pstmt.close(); DbConnectionManager.fastcloseStmt(pstmt);
// Remove the group entry. // Remove the group entry.
pstmt = con.prepareStatement(DELETE_GROUP); pstmt = con.prepareStatement(DELETE_GROUP);
pstmt.setString(1, groupName); pstmt.setString(1, groupName);
...@@ -240,11 +213,7 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -240,11 +213,7 @@ public class DefaultGroupProvider implements GroupProvider {
abortTransaction = true; abortTransaction = true;
} }
finally { finally {
try { DbConnectionManager.closeStatement(pstmt);
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
DbConnectionManager.closeTransactionConnection(con, abortTransaction); DbConnectionManager.closeTransactionConnection(con, abortTransaction);
} }
} }
...@@ -253,29 +222,20 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -253,29 +222,20 @@ public class DefaultGroupProvider implements GroupProvider {
int count = 0; int count = 0;
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(GROUP_COUNT); pstmt = con.prepareStatement(GROUP_COUNT);
ResultSet rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
if (rs.next()) { if (rs.next()) {
count = rs.getInt(1); count = rs.getInt(1);
} }
rs.close();
} }
catch (SQLException e) { catch (SQLException e) {
Log.error(e.getMessage(), e); Log.error(e.getMessage(), e);
} }
finally { finally {
try { DbConnectionManager.closeConnection(rs, pstmt, con);
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
try {
if (con != null) {
con.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
} }
return count; return count;
} }
...@@ -289,30 +249,20 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -289,30 +249,20 @@ public class DefaultGroupProvider implements GroupProvider {
List<String> groupNames = new ArrayList<String>(); List<String> groupNames = new ArrayList<String>();
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(ALL_GROUPS); pstmt = con.prepareStatement(ALL_GROUPS);
ResultSet rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
while (rs.next()) { while (rs.next()) {
groupNames.add(rs.getString(1)); groupNames.add(rs.getString(1));
} }
rs.close();
} }
catch (SQLException e) { catch (SQLException e) {
Log.error(e.getMessage(), e); Log.error(e.getMessage(), e);
} }
finally { finally {
try { DbConnectionManager.closeConnection(rs, pstmt, con); }
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
try {
if (con != null) {
con.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
}
return groupNames; return groupNames;
} }
...@@ -320,32 +270,23 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -320,32 +270,23 @@ public class DefaultGroupProvider implements GroupProvider {
List<String> groupNames = new ArrayList<String>(); List<String> groupNames = new ArrayList<String>();
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = DbConnectionManager.createScrollablePreparedStatement(con, ALL_GROUPS); pstmt = DbConnectionManager.createScrollablePreparedStatement(con, ALL_GROUPS);
ResultSet rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
DbConnectionManager.scrollResultSet(rs, startIndex); DbConnectionManager.scrollResultSet(rs, startIndex);
int count = 0; int count = 0;
while (rs.next() && count < numResults) { while (rs.next() && count < numResults) {
groupNames.add(rs.getString(1)); groupNames.add(rs.getString(1));
count++; count++;
} }
rs.close();
} }
catch (SQLException e) { catch (SQLException e) {
Log.error(e.getMessage(), e); Log.error(e.getMessage(), e);
} }
finally { finally {
try { DbConnectionManager.closeConnection(rs, pstmt, con);
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
try {
if (con != null) {
con.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
} }
return groupNames; return groupNames;
} }
...@@ -354,32 +295,21 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -354,32 +295,21 @@ public class DefaultGroupProvider implements GroupProvider {
List<String> groupNames = new ArrayList<String>(); List<String> groupNames = new ArrayList<String>();
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(USER_GROUPS); pstmt = con.prepareStatement(USER_GROUPS);
pstmt.setString(1, server.isLocal(user) ? user.getNode() : user.toString()); pstmt.setString(1, server.isLocal(user) ? user.getNode() : user.toString());
ResultSet rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
while (rs.next()) { while (rs.next()) {
groupNames.add(rs.getString(1)); groupNames.add(rs.getString(1));
} }
rs.close();
} }
catch (SQLException e) { catch (SQLException e) {
Log.error(e.getMessage(), e); Log.error(e.getMessage(), e);
} }
finally { finally {
try { DbConnectionManager.closeConnection(rs, pstmt, con);
if (pstmt != null) {
pstmt.close();
}
}
catch (Exception e) { Log.error(e.getMessage(), e); }
try {
if (con != null) {
con.close();
}
}
catch (Exception e) { Log.error(e.getMessage(), e); }
} }
return groupNames; return groupNames;
} }
...@@ -399,16 +329,7 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -399,16 +329,7 @@ public class DefaultGroupProvider implements GroupProvider {
Log.error(e.getMessage(), e); Log.error(e.getMessage(), e);
} }
finally { finally {
try { DbConnectionManager.closeConnection(pstmt, con);
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
try {
if (con != null) {
con.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
} }
} }
...@@ -427,16 +348,7 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -427,16 +348,7 @@ public class DefaultGroupProvider implements GroupProvider {
Log.error(e.getMessage(), e); Log.error(e.getMessage(), e);
} }
finally { finally {
try { DbConnectionManager.closeConnection(pstmt, con);
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
try {
if (con != null) {
con.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
} }
} }
...@@ -454,16 +366,7 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -454,16 +366,7 @@ public class DefaultGroupProvider implements GroupProvider {
Log.error(e.getMessage(), e); Log.error(e.getMessage(), e);
} }
finally { finally {
try { DbConnectionManager.closeConnection(pstmt, con);
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
try {
if (con != null) {
con.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
} }
} }
...@@ -472,40 +375,7 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -472,40 +375,7 @@ public class DefaultGroupProvider implements GroupProvider {
} }
public Collection<String> search(String query) { public Collection<String> search(String query) {
if (query == null || "".equals(query)) { return search(query, 0, Integer.MAX_VALUE);
return Collections.emptyList();
}
// SQL LIKE queries don't map directly into a keyword/wildcard search like we want.
// Therefore, we do a best approximiation by replacing '*' with '%' and then
// surrounding the whole query with two '%'. This will return more data than desired,
// but is better than returning less data than desired.
query = "%" + query.replace('*', '%') + "%";
if (query.endsWith("%%")) {
query = query.substring(0, query.length()-1);
}
List<String> groupNames = new ArrayList<String>();
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
stmt = con.createStatement();
StringBuilder sql = new StringBuilder();
sql.append("SELECT groupName FROM ofGroup WHERE groupName LIKE '").append(
StringUtils.escapeForSQL(query)).append("' ORDER BY groupName");
rs = stmt.executeQuery(sql.toString());
while (rs.next()) {
groupNames.add(rs.getString(1));
}
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
DbConnectionManager.closeConnection(rs, stmt, con);
}
return groupNames;
} }
public Collection<String> search(String query, int startIndex, int numResults) { public Collection<String> search(String query, int startIndex, int numResults) {
...@@ -523,28 +393,37 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -523,28 +393,37 @@ public class DefaultGroupProvider implements GroupProvider {
List<String> groupNames = new ArrayList<String>(); List<String> groupNames = new ArrayList<String>();
Connection con = null; Connection con = null;
Statement stmt = null; PreparedStatement pstmt = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
stmt = DbConnectionManager.createScrollableStatement(con); if ((startIndex==0) && (numResults==Integer.MAX_VALUE))
StringBuilder sql = new StringBuilder(); {
sql.append("SELECT groupName FROM ofGroup WHERE groupName LIKE '").append( pstmt = con.prepareStatement(SEARCH_GROUP_NAME);
StringUtils.escapeForSQL(query)).append("' ORDER BY groupName"); pstmt.setString(1, query);
rs = stmt.executeQuery(sql.toString()); rs = pstmt.executeQuery();
DbConnectionManager.setFetchSize(rs, startIndex + numResults); while (rs.next()) {
DbConnectionManager.scrollResultSet(rs, startIndex); groupNames.add(rs.getString(1));
int count = 0; }
while (rs.next() && count < numResults) { } else {
groupNames.add(rs.getString(1)); pstmt = DbConnectionManager.createScrollablePreparedStatement(con, SEARCH_GROUP_NAME);
count++; DbConnectionManager.limitRowsAndFetchSize(pstmt, startIndex, numResults);
pstmt.setString(1, query);
rs = pstmt.executeQuery();
// Scroll to the start index.
DbConnectionManager.scrollResultSet(rs, startIndex);
int count = 0;
while (rs.next() && count < numResults) {
groupNames.add(rs.getString(1));
count++;
}
} }
} }
catch (SQLException e) { catch (SQLException e) {
Log.error(e.getMessage(), e); Log.error(e.getMessage(), e);
} }
finally { finally {
DbConnectionManager.closeConnection(rs, stmt, con); DbConnectionManager.closeConnection(rs, pstmt, con);
} }
return groupNames; return groupNames;
} }
...@@ -557,6 +436,7 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -557,6 +436,7 @@ public class DefaultGroupProvider implements GroupProvider {
List<JID> members = new ArrayList<JID>(); List<JID> members = new ArrayList<JID>();
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
if (adminsOnly) { if (adminsOnly) {
...@@ -566,7 +446,7 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -566,7 +446,7 @@ public class DefaultGroupProvider implements GroupProvider {
pstmt = con.prepareStatement(LOAD_MEMBERS); pstmt = con.prepareStatement(LOAD_MEMBERS);
} }
pstmt.setString(1, groupName); pstmt.setString(1, groupName);
ResultSet rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
while (rs.next()) { while (rs.next()) {
String user = rs.getString(1); String user = rs.getString(1);
JID userJID = null; JID userJID = null;
...@@ -581,22 +461,12 @@ public class DefaultGroupProvider implements GroupProvider { ...@@ -581,22 +461,12 @@ public class DefaultGroupProvider implements GroupProvider {
} }
members.add(userJID); members.add(userJID);
} }
rs.close();
} }
catch (SQLException e) { catch (SQLException e) {
Log.error(e.getMessage(), e); Log.error(e.getMessage(), e);
} }
finally { finally {
try { DbConnectionManager.closeConnection(rs, pstmt, con);
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
try {
if (con != null) {
con.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
} }
return members; return members;
} }
......
...@@ -24,7 +24,6 @@ import java.sql.Connection; ...@@ -24,7 +24,6 @@ import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types; import java.sql.Types;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
...@@ -83,6 +82,7 @@ public class DefaultUserProvider implements UserProvider { ...@@ -83,6 +82,7 @@ public class DefaultUserProvider implements UserProvider {
"UPDATE ofUser SET creationDate=? WHERE username=?"; "UPDATE ofUser SET creationDate=? WHERE username=?";
private static final String UPDATE_MODIFICATION_DATE = private static final String UPDATE_MODIFICATION_DATE =
"UPDATE ofUser SET modificationDate=? WHERE username=?"; "UPDATE ofUser SET modificationDate=? WHERE username=?";
private static final boolean IS_READ_ONLY = false;
public User loadUser(String username) throws UserNotFoundException { public User loadUser(String username) throws UserNotFoundException {
if(username.contains("@")) { if(username.contains("@")) {
...@@ -120,10 +120,6 @@ public class DefaultUserProvider implements UserProvider { ...@@ -120,10 +120,6 @@ public class DefaultUserProvider implements UserProvider {
public User createUser(String username, String password, String name, String email) public User createUser(String username, String password, String name, String email)
throws UserAlreadyExistsException throws UserAlreadyExistsException
{ {
if (isReadOnly()) {
// Reject the operation since the provider is read-only
throw new UnsupportedOperationException();
}
try { try {
loadUser(username); loadUser(username);
// The user already exists since no exception, so: // The user already exists since no exception, so:
...@@ -193,10 +189,6 @@ public class DefaultUserProvider implements UserProvider { ...@@ -193,10 +189,6 @@ public class DefaultUserProvider implements UserProvider {
} }
public void deleteUser(String username) { public void deleteUser(String username) {
if (isReadOnly()) {
// Reject the operation since the provider is read-only
throw new UnsupportedOperationException();
}
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
boolean abortTransaction = false; boolean abortTransaction = false;
...@@ -206,7 +198,8 @@ public class DefaultUserProvider implements UserProvider { ...@@ -206,7 +198,8 @@ public class DefaultUserProvider implements UserProvider {
pstmt = con.prepareStatement(DELETE_USER_PROPS); pstmt = con.prepareStatement(DELETE_USER_PROPS);
pstmt.setString(1, username); pstmt.setString(1, username);
pstmt.execute(); pstmt.execute();
pstmt.close(); DbConnectionManager.fastcloseStmt(pstmt);
// Delete the actual user entry // Delete the actual user entry
pstmt = con.prepareStatement(DELETE_USER); pstmt = con.prepareStatement(DELETE_USER);
pstmt.setString(1, username); pstmt.setString(1, username);
...@@ -217,6 +210,7 @@ public class DefaultUserProvider implements UserProvider { ...@@ -217,6 +210,7 @@ public class DefaultUserProvider implements UserProvider {
abortTransaction = true; abortTransaction = true;
} }
finally { finally {
DbConnectionManager.closeStatement(pstmt);
DbConnectionManager.closeTransactionConnection(pstmt, con, abortTransaction); DbConnectionManager.closeTransactionConnection(pstmt, con, abortTransaction);
} }
} }
...@@ -244,24 +238,46 @@ public class DefaultUserProvider implements UserProvider { ...@@ -244,24 +238,46 @@ public class DefaultUserProvider implements UserProvider {
} }
public Collection<User> getUsers() { public Collection<User> getUsers() {
Collection<String> usernames = getUsernames(); Collection<String> usernames = getUsernames(0, Integer.MAX_VALUE);
return new UserCollection(usernames.toArray(new String[usernames.size()])); return new UserCollection(usernames.toArray(new String[usernames.size()]));
} }
public Collection<String> getUsernames() { public Collection<String> getUsernames() {
return getUsernames(0, Integer.MAX_VALUE);
}
private Collection<String> getUsernames(int startIndex, int numResults) {
List<String> usernames = new ArrayList<String>(500); List<String> usernames = new ArrayList<String>(500);
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(ALL_USERS); if ((startIndex==0) && (numResults==Integer.MAX_VALUE))
rs = pstmt.executeQuery(); {
// Set the fetch size. This will prevent some JDBC drivers from trying pstmt = con.prepareStatement(ALL_USERS);
// to load the entire result set into memory. // Set the fetch size. This will prevent some JDBC drivers from trying
DbConnectionManager.setFetchSize(rs, 500); // to load the entire result set into memory.
while (rs.next()) { DbConnectionManager.setFetchSize(pstmt, 500);
usernames.add(rs.getString(1)); rs = pstmt.executeQuery();
while (rs.next()) {
usernames.add(rs.getString(1));
}
}
else {
pstmt = DbConnectionManager.createScrollablePreparedStatement(con, ALL_USERS);
DbConnectionManager.limitRowsAndFetchSize(pstmt, startIndex, numResults);
rs = pstmt.executeQuery();
DbConnectionManager.scrollResultSet(rs, startIndex);
int count = 0;
while (rs.next() && count < numResults) {
usernames.add(rs.getString(1));
count++;
}
}
if (Log.isDebugEnabled()) {
Log.debug("Results: " + usernames.size());
LogResults(usernames);
} }
} }
catch (SQLException e) { catch (SQLException e) {
...@@ -274,36 +290,11 @@ public class DefaultUserProvider implements UserProvider { ...@@ -274,36 +290,11 @@ public class DefaultUserProvider implements UserProvider {
} }
public Collection<User> getUsers(int startIndex, int numResults) { public Collection<User> getUsers(int startIndex, int numResults) {
List<String> usernames = new ArrayList<String>(numResults); Collection<String> usernames = getUsernames(0, Integer.MAX_VALUE);
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = DbConnectionManager.createScrollablePreparedStatement(con, ALL_USERS);
rs = pstmt.executeQuery();
DbConnectionManager.setFetchSize(rs, startIndex + numResults);
DbConnectionManager.scrollResultSet(rs, startIndex);
int count = 0;
while (rs.next() && count < numResults) {
usernames.add(rs.getString(1));
count++;
}
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return new UserCollection(usernames.toArray(new String[usernames.size()])); return new UserCollection(usernames.toArray(new String[usernames.size()]));
} }
public void setName(String username, String name) throws UserNotFoundException { public void setName(String username, String name) throws UserNotFoundException {
if (isReadOnly()) {
// Reject the operation since the provider is read-only
throw new UnsupportedOperationException();
}
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try { try {
...@@ -327,10 +318,6 @@ public class DefaultUserProvider implements UserProvider { ...@@ -327,10 +318,6 @@ public class DefaultUserProvider implements UserProvider {
} }
public void setEmail(String username, String email) throws UserNotFoundException { public void setEmail(String username, String email) throws UserNotFoundException {
if (isReadOnly()) {
// Reject the operation since the provider is read-only
throw new UnsupportedOperationException();
}
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try { try {
...@@ -354,10 +341,6 @@ public class DefaultUserProvider implements UserProvider { ...@@ -354,10 +341,6 @@ public class DefaultUserProvider implements UserProvider {
} }
public void setCreationDate(String username, Date creationDate) throws UserNotFoundException { public void setCreationDate(String username, Date creationDate) throws UserNotFoundException {
if (isReadOnly()) {
// Reject the operation since the provider is read-only
throw new UnsupportedOperationException();
}
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try { try {
...@@ -376,10 +359,6 @@ public class DefaultUserProvider implements UserProvider { ...@@ -376,10 +359,6 @@ public class DefaultUserProvider implements UserProvider {
} }
public void setModificationDate(String username, Date modificationDate) throws UserNotFoundException { public void setModificationDate(String username, Date modificationDate) throws UserNotFoundException {
if (isReadOnly()) {
// Reject the operation since the provider is read-only
throw new UnsupportedOperationException();
}
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try { try {
...@@ -401,66 +380,8 @@ public class DefaultUserProvider implements UserProvider { ...@@ -401,66 +380,8 @@ public class DefaultUserProvider implements UserProvider {
return new LinkedHashSet<String>(Arrays.asList("Username", "Name", "Email")); return new LinkedHashSet<String>(Arrays.asList("Username", "Name", "Email"));
} }
public Collection<User> findUsers(Set<String> fields, String query) public Collection<User> findUsers(Set<String> fields, String query) throws UnsupportedOperationException {
throws UnsupportedOperationException return findUsers(fields, query, 0, Integer.MAX_VALUE);
{
if (fields.isEmpty()) {
return Collections.emptyList();
}
if (!getSearchFields().containsAll(fields)) {
throw new IllegalArgumentException("Search fields " + fields + " are not valid.");
}
if (query == null || "".equals(query)) {
return Collections.emptyList();
}
// SQL LIKE queries don't map directly into a keyword/wildcard search like we want.
// Therefore, we do a best approximiation by replacing '*' with '%' and then
// surrounding the whole query with two '%'. This will return more data than desired,
// but is better than returning less data than desired.
query = "%" + query.replace('*', '%') + "%";
if (query.endsWith("%%")) {
query = query.substring(0, query.length()-1);
}
List<String> usernames = new ArrayList<String>(50);
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
stmt = con.createStatement();
StringBuilder sql = new StringBuilder();
sql.append("SELECT username FROM ofUser WHERE");
boolean first = true;
if (fields.contains("Username")) {
sql.append(" username LIKE '").append(StringUtils.escapeForSQL(query)).append("'");
first = false;
}
if (fields.contains("Name")) {
if (!first) {
sql.append(" AND");
}
sql.append(" name LIKE '").append(StringUtils.escapeForSQL(query)).append("'");
first = false;
}
if (fields.contains("Email")) {
if (!first) {
sql.append(" AND");
}
sql.append(" email LIKE '").append(StringUtils.escapeForSQL(query)).append("'");
}
rs = stmt.executeQuery(sql.toString());
while (rs.next()) {
usernames.add(rs.getString(1));
}
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
DbConnectionManager.closeConnection(rs, stmt, con);
}
return new UserCollection(usernames.toArray(new String[usernames.size()]));
} }
public Collection<User> findUsers(Set<String> fields, String query, int startIndex, public Collection<User> findUsers(Set<String> fields, String query, int startIndex,
...@@ -486,51 +407,78 @@ public class DefaultUserProvider implements UserProvider { ...@@ -486,51 +407,78 @@ public class DefaultUserProvider implements UserProvider {
List<String> usernames = new ArrayList<String>(50); List<String> usernames = new ArrayList<String>(50);
Connection con = null; Connection con = null;
Statement stmt = null; PreparedStatement pstmt = null;
int queries=0;
ResultSet rs = null; ResultSet rs = null;
try { try {
con = DbConnectionManager.getConnection(); StringBuilder sql = new StringBuilder(90);
stmt = con.createStatement();
StringBuilder sql = new StringBuilder();
sql.append("SELECT username FROM ofUser WHERE"); sql.append("SELECT username FROM ofUser WHERE");
boolean first = true; boolean first = true;
if (fields.contains("Username")) { if (fields.contains("Username")) {
sql.append(" username LIKE '").append(StringUtils.escapeForSQL(query)).append("'"); sql.append(" username LIKE ?");
queries++;
first = false; first = false;
} }
if (fields.contains("Name")) { if (fields.contains("Name")) {
if (!first) { if (!first) {
sql.append(" AND"); sql.append(" AND");
} }
sql.append(" name LIKE '").append(StringUtils.escapeForSQL(query)).append("'"); sql.append(" name LIKE ?");
queries++;
first = false; first = false;
} }
if (fields.contains("Email")) { if (fields.contains("Email")) {
if (!first) { if (!first) {
sql.append(" AND"); sql.append(" AND");
} }
sql.append(" email LIKE '").append(StringUtils.escapeForSQL(query)).append("'"); sql.append(" email LIKE ?");
queries++;
} }
rs = stmt.executeQuery(sql.toString()); con = DbConnectionManager.getConnection();
// Scroll to the start index. if ((startIndex==0) && (numResults==Integer.MAX_VALUE))
DbConnectionManager.scrollResultSet(rs, startIndex); {
int count = 0; pstmt = con.prepareStatement(sql.toString());
while (rs.next() && count < numResults) { for (int i=1; i<=queries; i++)
usernames.add(rs.getString(1)); {
count++; pstmt.setString(i, query);
}
rs = pstmt.executeQuery();
while (rs.next()) {
usernames.add(rs.getString(1));
}
} else {
pstmt = DbConnectionManager.createScrollablePreparedStatement(con, sql.toString());
DbConnectionManager.limitRowsAndFetchSize(pstmt, startIndex, numResults);
for (int i=1; i<=queries; i++)
{
pstmt.setString(i, query);
}
rs = pstmt.executeQuery();
// Scroll to the start index.
DbConnectionManager.scrollResultSet(rs, startIndex);
int count = 0;
while (rs.next() && count < numResults) {
usernames.add(rs.getString(1));
count++;
}
}
if (Log.isDebugEnabled())
{
Log.debug("Results: " + usernames.size());
LogResults(usernames);
} }
} }
catch (SQLException e) { catch (SQLException e) {
Log.error(e.getMessage(), e); Log.error(e.getMessage(), e);
} }
finally { finally {
DbConnectionManager.closeConnection(rs, stmt, con); DbConnectionManager.closeConnection(rs, pstmt, con);
} }
return new UserCollection(usernames.toArray(new String[usernames.size()])); return new UserCollection(usernames.toArray(new String[usernames.size()]));
} }
public boolean isReadOnly() { public boolean isReadOnly() {
return false; return IS_READ_ONLY;
} }
public boolean isNameRequired() { public boolean isNameRequired() {
...@@ -540,4 +488,28 @@ public class DefaultUserProvider implements UserProvider { ...@@ -540,4 +488,28 @@ public class DefaultUserProvider implements UserProvider {
public boolean isEmailRequired() { public boolean isEmailRequired() {
return false; return false;
} }
/**
* Make sure that Log.isDebugEnabled()==true before calling this method.
* Twenty elements will be logged in every log line, so for 81-100 elements
* five log lines will be generated
* @param listElements a list of Strings which will be logged
*/
private void LogResults(List<String> listElements) {
String callingMethod = Thread.currentThread().getStackTrace()[3].getMethodName();
StringBuilder sb = new StringBuilder(256);
int count = 0;
for (String element : listElements)
{
if (count > 20)
{
Log.debug(callingMethod + " results: " + sb.toString());
sb.delete(0, sb.length());
count = 0;
}
sb.append(element).append(",");
count++;
}
sb.append(".");
Log.debug(callingMethod + " results: " + sb.toString());
}
} }
...@@ -24,7 +24,6 @@ import java.sql.DriverManager; ...@@ -24,7 +24,6 @@ import java.sql.DriverManager;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
...@@ -37,7 +36,6 @@ import java.util.Set; ...@@ -37,7 +36,6 @@ import java.util.Set;
import org.jivesoftware.database.DbConnectionManager; import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
...@@ -96,6 +94,7 @@ public class JDBCUserProvider implements UserProvider { ...@@ -96,6 +94,7 @@ public class JDBCUserProvider implements UserProvider {
private String nameField; private String nameField;
private String emailField; private String emailField;
private boolean useConnectionProvider; private boolean useConnectionProvider;
private static final boolean IS_READ_ONLY = true;
/** /**
* Constructs a new JDBC user provider. * Constructs a new JDBC user provider.
...@@ -127,8 +126,8 @@ public class JDBCUserProvider implements UserProvider { ...@@ -127,8 +126,8 @@ public class JDBCUserProvider implements UserProvider {
connectionString = JiveGlobals.getProperty("jdbcProvider.connectionString"); connectionString = JiveGlobals.getProperty("jdbcProvider.connectionString");
} }
// Load database statements for user data. // Load database statements for user data.
loadUserSQL = JiveGlobals.getProperty("jdbcUserProvider.loadUserSQL"); loadUserSQL = JiveGlobals.getProperty("jdbcUserProvider.loadUserSQL");
userCountSQL = JiveGlobals.getProperty("jdbcUserProvider.userCountSQL"); userCountSQL = JiveGlobals.getProperty("jdbcUserProvider.userCountSQL");
allUsersSQL = JiveGlobals.getProperty("jdbcUserProvider.allUsersSQL"); allUsersSQL = JiveGlobals.getProperty("jdbcUserProvider.allUsersSQL");
searchSQL = JiveGlobals.getProperty("jdbcUserProvider.searchSQL"); searchSQL = JiveGlobals.getProperty("jdbcUserProvider.searchSQL");
...@@ -168,12 +167,23 @@ public class JDBCUserProvider implements UserProvider { ...@@ -168,12 +167,23 @@ public class JDBCUserProvider implements UserProvider {
} }
} }
public User createUser(String username, String password, String name, String email)
throws UserAlreadyExistsException {
// Reject the operation since the provider is read-only
throw new UnsupportedOperationException();
}
public void deleteUser(String username) {
// Reject the operation since the provider is read-only
throw new UnsupportedOperationException();
}
public int getUserCount() { public int getUserCount() {
int count = 0; int count = 0;
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
con = getConnection(); con = getConnection();
pstmt = con.prepareStatement(userCountSQL); pstmt = con.prepareStatement(userCountSQL);
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
...@@ -190,81 +200,63 @@ public class JDBCUserProvider implements UserProvider { ...@@ -190,81 +200,63 @@ public class JDBCUserProvider implements UserProvider {
return count; return count;
} }
private Connection getConnection() throws SQLException {
if (useConnectionProvider)
return DbConnectionManager.getConnection();
return DriverManager.getConnection(connectionString);
}
public Collection<User> getUsers() { public Collection<User> getUsers() {
Collection<String> usernames = getUsernames(); Collection<String> usernames = getUsernames(0, Integer.MAX_VALUE);
return new UserCollection(usernames.toArray(new String[usernames.size()])); return new UserCollection(usernames.toArray(new String[usernames.size()]));
} }
public Collection<String> getUsernames() { public Collection<String> getUsernames() {
List<String> usernames = new ArrayList<String>(500); return getUsernames(0, Integer.MAX_VALUE);
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection();
pstmt = con.prepareStatement(allUsersSQL);
rs = pstmt.executeQuery();
// Set the fetch size. This will prevent some JDBC drivers from trying
// to load the entire result set into memory.
DbConnectionManager.setFetchSize(rs, 500);
while (rs.next()) {
Log.debug("JDBCUserProvider: "+rs.getString(1));
usernames.add(rs.getString(1));
}
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return usernames;
} }
public Collection<User> getUsers(int startIndex, int numResults) { private Collection<String> getUsernames(int startIndex, int numResults) {
List<String> usernames = new ArrayList<String>(numResults); List<String> usernames = new ArrayList<String>(500);
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
con = getConnection(); con = getConnection();
pstmt = DbConnectionManager.createScrollablePreparedStatement(con, allUsersSQL); if ((startIndex==0) && (numResults==Integer.MAX_VALUE))
rs = pstmt.executeQuery(); {
DbConnectionManager.setFetchSize(rs, startIndex + numResults); pstmt = con.prepareStatement(allUsersSQL);
DbConnectionManager.scrollResultSet(rs, startIndex); // Set the fetch size. This will prevent some JDBC drivers from trying
int count = 0; // to load the entire result set into memory.
while (rs.next() && count < numResults) { DbConnectionManager.setFetchSize(pstmt, 500);
Log.debug("JDBCUserProvider: "+rs.getString(1)); rs = pstmt.executeQuery();
usernames.add(rs.getString(1)); while (rs.next()) {
count++; usernames.add(rs.getString(1));
} }
} }
catch (SQLException e) { else {
Log.error(e.getMessage(), e); pstmt = DbConnectionManager.createScrollablePreparedStatement(con, allUsersSQL);
} DbConnectionManager.limitRowsAndFetchSize(pstmt, startIndex, numResults);
finally { rs = pstmt.executeQuery();
DbConnectionManager.closeConnection(rs, pstmt, con); DbConnectionManager.scrollResultSet(rs, startIndex);
} int count = 0;
return new UserCollection(usernames.toArray(new String[usernames.size()])); while (rs.next() && count < numResults) {
} usernames.add(rs.getString(1));
count++;
public User createUser(String username, String password, String name, String email) }
throws UserAlreadyExistsException { }
// Reject the operation since the provider is read-only if (Log.isDebugEnabled()) {
throw new UnsupportedOperationException(); Log.debug("Results: " + usernames.size());
} LogResults(usernames);
}
public void deleteUser(String username) { }
// Reject the operation since the provider is read-only catch (SQLException e) {
throw new UnsupportedOperationException(); Log.error(e.getMessage(), e);
} }
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return usernames;
}
public Collection<User> getUsers(int startIndex, int numResults) {
Collection<String> usernames = getUsernames(0, Integer.MAX_VALUE);
return new UserCollection(usernames.toArray(new String[usernames.size()]));
}
public void setName(String username, String name) throws UserNotFoundException { public void setName(String username, String name) throws UserNotFoundException {
// Reject the operation since the provider is read-only // Reject the operation since the provider is read-only
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
...@@ -285,79 +277,15 @@ public class JDBCUserProvider implements UserProvider { ...@@ -285,79 +277,15 @@ public class JDBCUserProvider implements UserProvider {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public Collection<User> findUsers(Set<String> fields, String query) public Set<String> getSearchFields() throws UnsupportedOperationException {
throws UnsupportedOperationException if (searchSQL == null) {
{
if (searchSQL == null) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
if (fields.isEmpty()) { return new LinkedHashSet<String>(Arrays.asList("Username", "Name", "Email"));
return Collections.emptyList(); }
}
if (!getSearchFields().containsAll(fields)) {
throw new IllegalArgumentException("Search fields " + fields + " are not valid.");
}
if (query == null || "".equals(query)) {
return Collections.emptyList();
}
// SQL LIKE queries don't map directly into a keyword/wildcard search like we want.
// Therefore, we do a best approximiation by replacing '*' with '%' and then
// surrounding the whole query with two '%'. This will return more data than desired,
// but is better than returning less data than desired.
query = "%" + query.replace('*', '%') + "%";
if (query.endsWith("%%")) {
query = query.substring(0, query.length() - 1);
}
List<String> usernames = new ArrayList<String>(50); public Collection<User> findUsers(Set<String> fields, String query) throws UnsupportedOperationException {
Connection con = null; return findUsers(fields, query, 0, Integer.MAX_VALUE);
Statement stmt = null;
ResultSet rs = null;
try {
con = getConnection();
stmt = con.createStatement();
StringBuilder sql = new StringBuilder();
sql.append(searchSQL);
boolean first = true;
if (fields.contains("Username")) {
sql.append(" ")
.append(usernameField)
.append(" LIKE '")
.append(StringUtils.escapeForSQL(query)).append("'");
first = false;
}
if (fields.contains("Name")) {
if (!first) {
sql.append(" AND ");
}
sql.append(" ")
.append(nameField)
.append(" LIKE '")
.append(StringUtils.escapeForSQL(query)).append("'");
first = false;
}
if (fields.contains("Email")) {
if (!first) {
sql.append(" AND ");
}
sql.append(" ")
.append(emailField)
.append(" LIKE '")
.append(StringUtils.escapeForSQL(query)).append("'");
}
Log.debug("JDBCUserProvider: "+sql.toString());
rs = stmt.executeQuery(sql.toString());
while (rs.next()) {
usernames.add(rs.getString(1));
}
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
DbConnectionManager.closeConnection(rs, stmt, con);
}
return new UserCollection(usernames.toArray(new String[usernames.size()]));
} }
public Collection<User> findUsers(Set<String> fields, String query, int startIndex, public Collection<User> findUsers(Set<String> fields, String query, int startIndex,
...@@ -384,69 +312,81 @@ public class JDBCUserProvider implements UserProvider { ...@@ -384,69 +312,81 @@ public class JDBCUserProvider implements UserProvider {
query = query.substring(0, query.length() - 1); query = query.substring(0, query.length() - 1);
} }
List<String> usernames = new ArrayList<String>(50); List<String> usernames = new ArrayList<String>(50);
Connection con = null; Connection con = null;
Statement stmt = null; PreparedStatement pstmt = null;
int queries=0;
ResultSet rs = null; ResultSet rs = null;
try { try {
con = getConnection(); StringBuilder sql = new StringBuilder(90);
stmt = con.createStatement(); sql.append("SELECT username FROM ofUser WHERE");
StringBuilder sql = new StringBuilder(); boolean first = true;
sql.append(searchSQL); if (fields.contains("Username")) {
boolean first = true; sql.append(" username LIKE ?");
if (fields.contains("Username")) { queries++;
sql.append(" ") first = false;
.append(usernameField) }
.append(" LIKE '") if (fields.contains("Name")) {
.append(StringUtils.escapeForSQL(query)).append("'"); if (!first) {
first = false; sql.append(" AND");
} }
if (fields.contains("Name")) { sql.append(" name LIKE ?");
if (!first) { queries++;
sql.append(" AND "); first = false;
} }
sql.append(" ") if (fields.contains("Email")) {
.append(nameField) if (!first) {
.append("LIKE '") sql.append(" AND");
.append(StringUtils.escapeForSQL(query)).append("'"); }
first = false; sql.append(" email LIKE ?");
} queries++;
if (fields.contains("Email")) { }
if (!first) { con = getConnection();
sql.append(" AND "); if ((startIndex==0) && (numResults==Integer.MAX_VALUE))
} {
sql.append(" ") pstmt = con.prepareStatement(sql.toString());
.append(emailField) for (int i=1; i<=queries; i++)
.append(" LIKE '") {
.append(StringUtils.escapeForSQL(query)).append("'"); pstmt.setString(i, query);
} }
Log.debug("JDBCUserProvider: "+sql.toString()); rs = pstmt.executeQuery();
rs = stmt.executeQuery(sql.toString()); while (rs.next()) {
// Scroll to the start index. usernames.add(rs.getString(1));
DbConnectionManager.scrollResultSet(rs, startIndex); }
while (rs.next()) { } else {
usernames.add(rs.getString(1)); pstmt = DbConnectionManager.createScrollablePreparedStatement(con, sql.toString());
} DbConnectionManager.limitRowsAndFetchSize(pstmt, startIndex, numResults);
} for (int i=1; i<=queries; i++)
catch (SQLException e) { {
Log.error(e.getMessage(), e); pstmt.setString(i, query);
} }
finally { rs = pstmt.executeQuery();
DbConnectionManager.closeConnection(rs, stmt, con); // Scroll to the start index.
} DbConnectionManager.scrollResultSet(rs, startIndex);
return new UserCollection(usernames.toArray(new String[usernames.size()])); int count = 0;
} while (rs.next() && count < numResults) {
usernames.add(rs.getString(1));
public Set<String> getSearchFields() throws UnsupportedOperationException { count++;
if (searchSQL == null) { }
throw new UnsupportedOperationException(); }
if (Log.isDebugEnabled())
{
Log.debug("Results: " + usernames.size());
LogResults(usernames);
}
} }
return new LinkedHashSet<String>(Arrays.asList("Username", "Name", "Email")); catch (SQLException e) {
} Log.error(e.getMessage(), e);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return new UserCollection(usernames.toArray(new String[usernames.size()]));
}
public boolean isReadOnly() { public boolean isReadOnly() {
return true; return IS_READ_ONLY;
} }
public boolean isNameRequired() { public boolean isNameRequired() {
return false; return false;
...@@ -455,4 +395,37 @@ public class JDBCUserProvider implements UserProvider { ...@@ -455,4 +395,37 @@ public class JDBCUserProvider implements UserProvider {
public boolean isEmailRequired() { public boolean isEmailRequired() {
return false; return false;
} }
/**
* Make sure that Log.isDebugEnabled()==true before calling this method.
* Twenty elements will be logged in every log line, so for 81-100 elements
* five log lines will be generated
* @param listElements a list of Strings which will be logged
*/
private void LogResults(List<String> listElements) {
String callingMethod = Thread.currentThread().getStackTrace()[3].getMethodName();
StringBuilder sb = new StringBuilder(256);
int count = 0;
for (String element : listElements)
{
if (count > 20)
{
Log.debug(callingMethod + " results: " + sb.toString());
sb.delete(0, sb.length());
count = 0;
}
sb.append(element).append(",");
count++;
}
sb.append(".");
Log.debug(callingMethod + " results: " + sb.toString());
}
private Connection getConnection() throws SQLException {
if (useConnectionProvider) {
return DbConnectionManager.getConnection();
} else
{
return DriverManager.getConnection(connectionString);
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment