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 {
private static boolean transactionsSupported;
// True if the database requires large text fields to be streamed.
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;
// True if the database supports the Statement.setFetchSize() method.
/** True if the database supports the rs.setFetchSize() method. */
private static boolean fetchSizeSupported;
// True if the database supports correlated subqueries.
private static boolean subqueriesSupported;
......@@ -70,6 +70,9 @@ public class DbConnectionManager {
private static boolean scrollResultsSupported;
// True if the database supports batch updates.
private static boolean batchUpdatesSupported;
/** True if the database supports the Statement.setFetchSize()) method. */
static boolean pstmt_fetchSizeSupported = true;
private static DatabaseType databaseType = DatabaseType.unknown;
......@@ -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
* method should be called is if more information about the current
......@@ -881,6 +932,10 @@ public class DbConnectionManager {
return fetchSizeSupported;
}
public static boolean isPstmtFetchSizeSupported() {
return pstmt_fetchSizeSupported;
}
public static boolean isSubqueriesSupported() {
return subqueriesSupported;
}
......
......@@ -24,7 +24,6 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
......@@ -32,7 +31,6 @@ import java.util.List;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.JID;
......@@ -78,6 +76,7 @@ public class DefaultGroupProvider implements GroupProvider {
private static final String USER_GROUPS =
"SELECT groupName FROM ofGroupUser WHERE username=?";
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();
......@@ -95,16 +94,7 @@ public class DefaultGroupProvider implements GroupProvider {
Log.error(e.getMessage(), e);
}
finally {
try {
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); }
DbConnectionManager.closeConnection(pstmt, con);
}
Collection<JID> members = getMembers(name, false);
Collection<JID> administrators = getMembers(name, true);
......@@ -116,11 +106,12 @@ public class DefaultGroupProvider implements GroupProvider {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_GROUP);
pstmt.setString(1, name);
ResultSet rs = pstmt.executeQuery();
rs = pstmt.executeQuery();
if (!rs.next()) {
throw new GroupNotFoundException("Group with name "
+ name + " not found.");
......@@ -131,16 +122,7 @@ public class DefaultGroupProvider implements GroupProvider {
Log.error(e.getMessage(), e);
}
finally {
try {
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); }
DbConnectionManager.closeConnection(rs, pstmt, con);
}
Collection<JID> members = getMembers(name, false);
Collection<JID> administrators = getMembers(name, true);
......@@ -164,16 +146,7 @@ public class DefaultGroupProvider implements GroupProvider {
throw new GroupNotFoundException();
}
finally {
try {
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); }
DbConnectionManager.closeConnection(pstmt, con);
}
}
......@@ -189,12 +162,14 @@ public class DefaultGroupProvider implements GroupProvider {
pstmt.setString(1, newName);
pstmt.setString(2, oldName);
pstmt.executeUpdate();
pstmt.close();
DbConnectionManager.fastcloseStmt(pstmt);
pstmt = con.prepareStatement(SET_GROUP_NAME_2);
pstmt.setString(1, newName);
pstmt.setString(2, oldName);
pstmt.executeUpdate();
pstmt.close();
DbConnectionManager.fastcloseStmt(pstmt);
pstmt = con.prepareStatement(SET_GROUP_NAME_3);
pstmt.setString(1, newName);
pstmt.setString(2, oldName);
......@@ -205,11 +180,7 @@ public class DefaultGroupProvider implements GroupProvider {
abortTransaction = true;
}
finally {
try {
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
DbConnectionManager.closeStatement(pstmt);
DbConnectionManager.closeTransactionConnection(con, abortTransaction);
}
}
......@@ -224,12 +195,14 @@ public class DefaultGroupProvider implements GroupProvider {
pstmt = con.prepareStatement(DELETE_GROUP_USERS);
pstmt.setString(1, groupName);
pstmt.executeUpdate();
pstmt.close();
DbConnectionManager.fastcloseStmt(pstmt);
// Remove all properties of the group.
pstmt = con.prepareStatement(DELETE_PROPERTIES);
pstmt.setString(1, groupName);
pstmt.executeUpdate();
pstmt.close();
DbConnectionManager.fastcloseStmt(pstmt);
// Remove the group entry.
pstmt = con.prepareStatement(DELETE_GROUP);
pstmt.setString(1, groupName);
......@@ -240,11 +213,7 @@ public class DefaultGroupProvider implements GroupProvider {
abortTransaction = true;
}
finally {
try {
if (pstmt != null) {
pstmt.close();
} }
catch (Exception e) { Log.error(e.getMessage(), e); }
DbConnectionManager.closeStatement(pstmt);
DbConnectionManager.closeTransactionConnection(con, abortTransaction);
}
}
......@@ -253,29 +222,20 @@ public class DefaultGroupProvider implements GroupProvider {
int count = 0;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(GROUP_COUNT);
ResultSet rs = pstmt.executeQuery();
rs = pstmt.executeQuery();
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
try {
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); }
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return count;
}
......@@ -289,30 +249,20 @@ public class DefaultGroupProvider implements GroupProvider {
List<String> groupNames = new ArrayList<String>();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(ALL_GROUPS);
ResultSet rs = pstmt.executeQuery();
rs = pstmt.executeQuery();
while (rs.next()) {
groupNames.add(rs.getString(1));
}
rs.close();
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
try {
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); }
}
DbConnectionManager.closeConnection(rs, pstmt, con); }
return groupNames;
}
......@@ -320,32 +270,23 @@ public class DefaultGroupProvider implements GroupProvider {
List<String> groupNames = new ArrayList<String>();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = DbConnectionManager.createScrollablePreparedStatement(con, ALL_GROUPS);
ResultSet rs = pstmt.executeQuery();
rs = pstmt.executeQuery();
DbConnectionManager.scrollResultSet(rs, startIndex);
int count = 0;
while (rs.next() && count < numResults) {
groupNames.add(rs.getString(1));
count++;
}
rs.close();
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
try {
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); }
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return groupNames;
}
......@@ -354,32 +295,21 @@ public class DefaultGroupProvider implements GroupProvider {
List<String> groupNames = new ArrayList<String>();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(USER_GROUPS);
pstmt.setString(1, server.isLocal(user) ? user.getNode() : user.toString());
ResultSet rs = pstmt.executeQuery();
rs = pstmt.executeQuery();
while (rs.next()) {
groupNames.add(rs.getString(1));
}
rs.close();
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
try {
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); }
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return groupNames;
}
......@@ -399,16 +329,7 @@ public class DefaultGroupProvider implements GroupProvider {
Log.error(e.getMessage(), e);
}
finally {
try {
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); }
DbConnectionManager.closeConnection(pstmt, con);
}
}
......@@ -427,16 +348,7 @@ public class DefaultGroupProvider implements GroupProvider {
Log.error(e.getMessage(), e);
}
finally {
try {
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); }
DbConnectionManager.closeConnection(pstmt, con);
}
}
......@@ -454,16 +366,7 @@ public class DefaultGroupProvider implements GroupProvider {
Log.error(e.getMessage(), e);
}
finally {
try {
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); }
DbConnectionManager.closeConnection(pstmt, con);
}
}
......@@ -472,40 +375,7 @@ public class DefaultGroupProvider implements GroupProvider {
}
public Collection<String> search(String query) {
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> 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;
return search(query, 0, Integer.MAX_VALUE);
}
public Collection<String> search(String query, int startIndex, int numResults) {
......@@ -523,16 +393,24 @@ public class DefaultGroupProvider implements GroupProvider {
List<String> groupNames = new ArrayList<String>();
Connection con = null;
Statement stmt = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
stmt = DbConnectionManager.createScrollableStatement(con);
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());
DbConnectionManager.setFetchSize(rs, startIndex + numResults);
if ((startIndex==0) && (numResults==Integer.MAX_VALUE))
{
pstmt = con.prepareStatement(SEARCH_GROUP_NAME);
pstmt.setString(1, query);
rs = pstmt.executeQuery();
while (rs.next()) {
groupNames.add(rs.getString(1));
}
} else {
pstmt = DbConnectionManager.createScrollablePreparedStatement(con, SEARCH_GROUP_NAME);
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) {
......@@ -540,11 +418,12 @@ public class DefaultGroupProvider implements GroupProvider {
count++;
}
}
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
DbConnectionManager.closeConnection(rs, stmt, con);
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return groupNames;
}
......@@ -557,6 +436,7 @@ public class DefaultGroupProvider implements GroupProvider {
List<JID> members = new ArrayList<JID>();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
if (adminsOnly) {
......@@ -566,7 +446,7 @@ public class DefaultGroupProvider implements GroupProvider {
pstmt = con.prepareStatement(LOAD_MEMBERS);
}
pstmt.setString(1, groupName);
ResultSet rs = pstmt.executeQuery();
rs = pstmt.executeQuery();
while (rs.next()) {
String user = rs.getString(1);
JID userJID = null;
......@@ -581,22 +461,12 @@ public class DefaultGroupProvider implements GroupProvider {
}
members.add(userJID);
}
rs.close();
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
try {
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); }
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return members;
}
......
......@@ -24,7 +24,6 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
......@@ -83,6 +82,7 @@ public class DefaultUserProvider implements UserProvider {
"UPDATE ofUser SET creationDate=? WHERE username=?";
private static final String UPDATE_MODIFICATION_DATE =
"UPDATE ofUser SET modificationDate=? WHERE username=?";
private static final boolean IS_READ_ONLY = false;
public User loadUser(String username) throws UserNotFoundException {
if(username.contains("@")) {
......@@ -120,10 +120,6 @@ public class DefaultUserProvider implements UserProvider {
public User createUser(String username, String password, String name, String email)
throws UserAlreadyExistsException
{
if (isReadOnly()) {
// Reject the operation since the provider is read-only
throw new UnsupportedOperationException();
}
try {
loadUser(username);
// The user already exists since no exception, so:
......@@ -193,10 +189,6 @@ public class DefaultUserProvider implements UserProvider {
}
public void deleteUser(String username) {
if (isReadOnly()) {
// Reject the operation since the provider is read-only
throw new UnsupportedOperationException();
}
Connection con = null;
PreparedStatement pstmt = null;
boolean abortTransaction = false;
......@@ -206,7 +198,8 @@ public class DefaultUserProvider implements UserProvider {
pstmt = con.prepareStatement(DELETE_USER_PROPS);
pstmt.setString(1, username);
pstmt.execute();
pstmt.close();
DbConnectionManager.fastcloseStmt(pstmt);
// Delete the actual user entry
pstmt = con.prepareStatement(DELETE_USER);
pstmt.setString(1, username);
......@@ -217,6 +210,7 @@ public class DefaultUserProvider implements UserProvider {
abortTransaction = true;
}
finally {
DbConnectionManager.closeStatement(pstmt);
DbConnectionManager.closeTransactionConnection(pstmt, con, abortTransaction);
}
}
......@@ -244,45 +238,36 @@ public class DefaultUserProvider implements UserProvider {
}
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()]));
}
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);
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
if ((startIndex==0) && (numResults==Integer.MAX_VALUE))
{
pstmt = con.prepareStatement(ALL_USERS);
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);
DbConnectionManager.setFetchSize(pstmt, 500);
rs = pstmt.executeQuery();
while (rs.next()) {
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) {
List<String> usernames = new ArrayList<String>(numResults);
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
else {
pstmt = DbConnectionManager.createScrollablePreparedStatement(con, ALL_USERS);
DbConnectionManager.limitRowsAndFetchSize(pstmt, startIndex, numResults);
rs = pstmt.executeQuery();
DbConnectionManager.setFetchSize(rs, startIndex + numResults);
DbConnectionManager.scrollResultSet(rs, startIndex);
int count = 0;
while (rs.next() && count < numResults) {
......@@ -290,20 +275,26 @@ public class DefaultUserProvider implements UserProvider {
count++;
}
}
if (Log.isDebugEnabled()) {
Log.debug("Results: " + usernames.size());
LogResults(usernames);
}
}
catch (SQLException e) {
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 {
if (isReadOnly()) {
// Reject the operation since the provider is read-only
throw new UnsupportedOperationException();
}
Connection con = null;
PreparedStatement pstmt = null;
try {
......@@ -327,10 +318,6 @@ public class DefaultUserProvider implements UserProvider {
}
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;
PreparedStatement pstmt = null;
try {
......@@ -354,10 +341,6 @@ public class DefaultUserProvider implements UserProvider {
}
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;
PreparedStatement pstmt = null;
try {
......@@ -376,10 +359,6 @@ public class DefaultUserProvider implements UserProvider {
}
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;
PreparedStatement pstmt = null;
try {
......@@ -401,8 +380,12 @@ public class DefaultUserProvider implements UserProvider {
return new LinkedHashSet<String>(Arrays.asList("Username", "Name", "Email"));
}
public Collection<User> findUsers(Set<String> fields, String query)
throws UnsupportedOperationException
public Collection<User> findUsers(Set<String> fields, String query) throws UnsupportedOperationException {
return findUsers(fields, query, 0, Integer.MAX_VALUE);
}
public Collection<User> findUsers(Set<String> fields, String query, int startIndex,
int numResults) throws UnsupportedOperationException
{
if (fields.isEmpty()) {
return Collections.emptyList();
......@@ -424,94 +407,53 @@ public class DefaultUserProvider implements UserProvider {
List<String> usernames = new ArrayList<String>(50);
Connection con = null;
Statement stmt = null;
PreparedStatement pstmt = null;
int queries=0;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
stmt = con.createStatement();
StringBuilder sql = new StringBuilder();
StringBuilder sql = new StringBuilder(90);
sql.append("SELECT username FROM ofUser WHERE");
boolean first = true;
if (fields.contains("Username")) {
sql.append(" username LIKE '").append(StringUtils.escapeForSQL(query)).append("'");
sql.append(" username LIKE ?");
queries++;
first = false;
}
if (fields.contains("Name")) {
if (!first) {
sql.append(" AND");
}
sql.append(" name LIKE '").append(StringUtils.escapeForSQL(query)).append("'");
sql.append(" name LIKE ?");
queries++;
first = false;
}
if (fields.contains("Email")) {
if (!first) {
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();
if ((startIndex==0) && (numResults==Integer.MAX_VALUE))
{
pstmt = con.prepareStatement(sql.toString());
for (int i=1; i<=queries; i++)
{
pstmt.setString(i, query);
}
rs = pstmt.executeQuery();
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,
int numResults) throws UnsupportedOperationException
} else {
pstmt = DbConnectionManager.createScrollablePreparedStatement(con, sql.toString());
DbConnectionManager.limitRowsAndFetchSize(pstmt, startIndex, numResults);
for (int i=1; i<=queries; i++)
{
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;
pstmt.setString(i, query);
}
if (fields.contains("Email")) {
if (!first) {
sql.append(" AND");
}
sql.append(" email LIKE '").append(StringUtils.escapeForSQL(query)).append("'");
}
rs = stmt.executeQuery(sql.toString());
rs = pstmt.executeQuery();
// Scroll to the start index.
DbConnectionManager.scrollResultSet(rs, startIndex);
int count = 0;
......@@ -520,17 +462,23 @@ public class DefaultUserProvider implements UserProvider {
count++;
}
}
if (Log.isDebugEnabled())
{
Log.debug("Results: " + usernames.size());
LogResults(usernames);
}
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
DbConnectionManager.closeConnection(rs, stmt, con);
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return new UserCollection(usernames.toArray(new String[usernames.size()]));
}
public boolean isReadOnly() {
return false;
return IS_READ_ONLY;
}
public boolean isNameRequired() {
......@@ -540,4 +488,28 @@ public class DefaultUserProvider implements UserProvider {
public boolean isEmailRequired() {
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;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
......@@ -37,7 +36,6 @@ import java.util.Set;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.JID;
......@@ -96,6 +94,7 @@ public class JDBCUserProvider implements UserProvider {
private String nameField;
private String emailField;
private boolean useConnectionProvider;
private static final boolean IS_READ_ONLY = true;
/**
* Constructs a new JDBC user provider.
......@@ -168,6 +167,17 @@ 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() {
int count = 0;
Connection con = null;
......@@ -190,79 +200,61 @@ public class JDBCUserProvider implements UserProvider {
return count;
}
private Connection getConnection() throws SQLException {
if (useConnectionProvider)
return DbConnectionManager.getConnection();
return DriverManager.getConnection(connectionString);
}
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()]));
}
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);
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection();
if ((startIndex==0) && (numResults==Integer.MAX_VALUE))
{
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);
DbConnectionManager.setFetchSize(pstmt, 500);
rs = pstmt.executeQuery();
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) {
List<String> usernames = new ArrayList<String>(numResults);
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection();
else {
pstmt = DbConnectionManager.createScrollablePreparedStatement(con, allUsersSQL);
DbConnectionManager.limitRowsAndFetchSize(pstmt, startIndex, numResults);
rs = pstmt.executeQuery();
DbConnectionManager.setFetchSize(rs, startIndex + numResults);
DbConnectionManager.scrollResultSet(rs, startIndex);
int count = 0;
while (rs.next() && count < numResults) {
Log.debug("JDBCUserProvider: "+rs.getString(1));
usernames.add(rs.getString(1));
count++;
}
}
if (Log.isDebugEnabled()) {
Log.debug("Results: " + usernames.size());
LogResults(usernames);
}
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return new UserCollection(usernames.toArray(new String[usernames.size()]));
}
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();
return usernames;
}
public void deleteUser(String username) {
// Reject the operation since the provider is read-only
throw new UnsupportedOperationException();
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 {
......@@ -285,79 +277,15 @@ public class JDBCUserProvider implements UserProvider {
throw new UnsupportedOperationException();
}
public Collection<User> findUsers(Set<String> fields, String query)
throws UnsupportedOperationException
{
public Set<String> getSearchFields() throws UnsupportedOperationException {
if (searchSQL == null) {
throw new UnsupportedOperationException();
}
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);
return new LinkedHashSet<String>(Arrays.asList("Username", "Name", "Email"));
}
List<String> usernames = new ArrayList<String>(50);
Connection con = null;
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) throws UnsupportedOperationException {
return findUsers(fields, query, 0, Integer.MAX_VALUE);
}
public Collection<User> findUsers(Set<String> fields, String query, int startIndex,
......@@ -386,66 +314,78 @@ public class JDBCUserProvider implements UserProvider {
List<String> usernames = new ArrayList<String>(50);
Connection con = null;
Statement stmt = null;
PreparedStatement pstmt = null;
int queries=0;
ResultSet rs = null;
try {
con = getConnection();
stmt = con.createStatement();
StringBuilder sql = new StringBuilder();
sql.append(searchSQL);
StringBuilder sql = new StringBuilder(90);
sql.append("SELECT username FROM ofUser WHERE");
boolean first = true;
if (fields.contains("Username")) {
sql.append(" ")
.append(usernameField)
.append(" LIKE '")
.append(StringUtils.escapeForSQL(query)).append("'");
sql.append(" username LIKE ?");
queries++;
first = false;
}
if (fields.contains("Name")) {
if (!first) {
sql.append(" AND ");
sql.append(" AND");
}
sql.append(" ")
.append(nameField)
.append("LIKE '")
.append(StringUtils.escapeForSQL(query)).append("'");
sql.append(" name LIKE ?");
queries++;
first = false;
}
if (fields.contains("Email")) {
if (!first) {
sql.append(" AND ");
sql.append(" AND");
}
sql.append(" ")
.append(emailField)
.append(" LIKE '")
.append(StringUtils.escapeForSQL(query)).append("'");
sql.append(" email LIKE ?");
queries++;
}
Log.debug("JDBCUserProvider: "+sql.toString());
rs = stmt.executeQuery(sql.toString());
con = getConnection();
if ((startIndex==0) && (numResults==Integer.MAX_VALUE))
{
pstmt = con.prepareStatement(sql.toString());
for (int i=1; i<=queries; i++)
{
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);
while (rs.next()) {
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) {
Log.error(e.getMessage(), e);
}
finally {
DbConnectionManager.closeConnection(rs, stmt, con);
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return new UserCollection(usernames.toArray(new String[usernames.size()]));
}
public Set<String> getSearchFields() throws UnsupportedOperationException {
if (searchSQL == null) {
throw new UnsupportedOperationException();
}
return new LinkedHashSet<String>(Arrays.asList("Username", "Name", "Email"));
}
public boolean isReadOnly() {
return true;
return IS_READ_ONLY;
}
public boolean isNameRequired() {
......@@ -455,4 +395,37 @@ public class JDBCUserProvider implements UserProvider {
public boolean isEmailRequired() {
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