Commit a9ec7c81 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Optimization work (avoid loading a user when possible). JM-599

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3579 b35dd754-fafc-0310-a699-88a17e54d16e
parent 3076f778
......@@ -7,6 +7,7 @@ import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.jivesoftware.wildfire.disco.ServerFeaturesProvider;
import org.jivesoftware.wildfire.roster.RosterItem;
import org.jivesoftware.wildfire.roster.RosterManager;
import org.jivesoftware.wildfire.user.User;
import org.jivesoftware.wildfire.user.UserManager;
import org.jivesoftware.wildfire.user.UserNotFoundException;
......@@ -28,6 +29,7 @@ public class IQLastActivityHandler extends IQHandler implements ServerFeaturesPr
private IQHandlerInfo info;
private PresenceManager presenceManager;
private RosterManager rosterManager;
public IQLastActivityHandler() {
super("XMPP Last Activity Handler");
......@@ -47,12 +49,12 @@ public class IQLastActivityHandler extends IQHandler implements ServerFeaturesPr
}
try {
User user = UserManager.getInstance().getUser(username);
RosterItem item = user.getRoster().getRosterItem(packet.getFrom());
RosterItem item = rosterManager.getRoster(username).getRosterItem(packet.getFrom());
// Check that the user requesting this information is subscribed to the user's presence
if (item.getSubStatus() == RosterItem.SUB_FROM ||
item.getSubStatus() == RosterItem.SUB_BOTH) {
if (sessionManager.getSessions(username).isEmpty()) {
User user = UserManager.getInstance().getUser(username);
// The user is offline so answer the user's "last available time and the
// status message of the last unavailable presence received from the user"
long lastActivityTime = presenceManager.getLastActivity(user);
......@@ -81,8 +83,8 @@ public class IQLastActivityHandler extends IQHandler implements ServerFeaturesPr
return info;
}
public Iterator getFeatures() {
ArrayList features = new ArrayList();
public Iterator<String> getFeatures() {
ArrayList<String> features = new ArrayList<String>();
features.add("jabber:iq:last");
return features.iterator();
}
......@@ -90,5 +92,6 @@ public class IQLastActivityHandler extends IQHandler implements ServerFeaturesPr
public void initialize(XMPPServer server) {
super.initialize(server);
presenceManager = server.getPresenceManager();
rosterManager = server.getRosterManager();
}
}
\ No newline at end of file
......@@ -11,9 +11,7 @@
package org.jivesoftware.wildfire.handler;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.IQHandlerInfo;
import org.jivesoftware.wildfire.PacketException;
......@@ -62,6 +60,7 @@ import org.xmpp.packet.PacketError;
public class IQvCardHandler extends IQHandler {
private IQHandlerInfo info;
private XMPPServer server;
private UserManager userManager;
public IQvCardHandler() {
......@@ -70,61 +69,60 @@ public class IQvCardHandler extends IQHandler {
}
public IQ handleIQ(IQ packet) throws UnauthorizedException, PacketException {
IQ result = null;
try {
IQ.Type type = packet.getType();
if (type.equals(IQ.Type.set)) {
result = IQ.createResultIQ(packet);
IQ result = IQ.createResultIQ(packet);
IQ.Type type = packet.getType();
if (type.equals(IQ.Type.set)) {
try {
User user = userManager.getUser(packet.getFrom().getNode());
// Proper format
Element vcard = packet.getChildElement();
if (vcard != null) {
try {
VCardManager.getInstance().setVCard(user.getUsername(), vcard);
}
catch (Exception e) {
Log.error(e);
result.setError(PacketError.Condition.internal_server_error);
}
VCardManager.getInstance().setVCard(user.getUsername(), vcard);
}
}
else if (type.equals(IQ.Type.get)) {
JID recipient = packet.getTo();
// If no TO was specified then get the vCard of the sender of the packet
if (recipient == null) {
recipient = packet.getFrom();
}
catch (UserNotFoundException e) {
result = IQ.createResultIQ(packet);
Element vcard = DocumentHelper.createElement(QName.get("vCard", "vcard-temp"));
result.setChildElement(vcard);
// Only try to get the vCard values of non-anonymous users
if (recipient != null && userManager.isRegisteredUser(recipient.getNode())) {
User user = userManager.getUser(recipient.getNode());
result.setChildElement(packet.getChildElement().createCopy());
result.setError(PacketError.Condition.item_not_found);
}
catch (Exception e) {
Log.error(e);
result.setError(PacketError.Condition.internal_server_error);
}
}
else if (type.equals(IQ.Type.get)) {
JID recipient = packet.getTo();
// If no TO was specified then get the vCard of the sender of the packet
if (recipient == null) {
recipient = packet.getFrom();
}
// By default return an empty vCard
result.setChildElement("vCard", "vcard-temp");
// Only try to get the vCard values of non-anonymous users
if (recipient != null) {
if (recipient.getNode() != null && server.isLocal(recipient)) {
VCardManager vManager = VCardManager.getInstance();
Element userVCard = vManager.getVCard(user.getUsername());
Element userVCard = vManager.getVCard(recipient.getNode());
if (userVCard != null) {
result.setChildElement(userVCard);
}
}
}
else {
result = IQ.createResultIQ(packet);
result.setChildElement(packet.getChildElement().createCopy());
result.setError(PacketError.Condition.not_acceptable);
else {
result = IQ.createResultIQ(packet);
result.setChildElement(packet.getChildElement().createCopy());
result.setError(PacketError.Condition.item_not_found);
}
}
}
catch (UserNotFoundException e) {
result = IQ.createResultIQ(packet);
else {
result.setChildElement(packet.getChildElement().createCopy());
result.setError(PacketError.Condition.item_not_found);
result.setError(PacketError.Condition.not_acceptable);
}
return result;
}
public void initialize(XMPPServer server) {
super.initialize(server);
this.server = server;
userManager = server.getUserManager();
}
......
......@@ -391,7 +391,10 @@ public class LdapGroupProvider implements GroupProvider {
// In order to lookup a username from the manager, the username
// must be a properly escaped JID node.
String escapedUsername = JID.escapeNode(username);
userManager.getUser(escapedUsername);
if (!escapedUsername.equals(username)) {
// Check if escaped username is valid
userManager.getUser(escapedUsername);
}
// No exception, so the user must exist. Add the user as a group
// member using the escaped username.
userJID = server.createJID(escapedUsername, null);
......
......@@ -295,9 +295,18 @@ public class Roster implements Cacheable {
// If the item only had shared groups before this update then make it persistent
if (item.isShared() && item.getID() == 0) {
// Do nothing if item is only shared and it is using the default user name
String defaultContactName = UserNameManager.getUserName(item.getJid());
if (item.isOnlyShared() && defaultContactName.equals(item.getNickname())) {
return;
if (item.isOnlyShared()) {
String defaultContactName = null;
try {
defaultContactName = UserNameManager.getUserName(item.getJid());
}
catch (UserNotFoundException e) {
// Cannot update a roster item for a local user that does not exist
defaultContactName = item.getNickname();
}
if (defaultContactName.equals(item.getNickname())) {
return;
}
}
try {
rosterItemProvider.createItem(username, item);
......
......@@ -11,20 +11,20 @@
package org.jivesoftware.wildfire.user;
import org.jivesoftware.wildfire.roster.Roster;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.util.CacheSizes;
import org.jivesoftware.util.Cacheable;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.wildfire.event.UserEventDispatcher;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.Cacheable;
import org.jivesoftware.util.CacheSizes;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.wildfire.roster.Roster;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* Encapsulates information about a user. New users are created using
......@@ -40,6 +40,8 @@ public class User implements Cacheable {
private static final String LOAD_PROPERTIES =
"SELECT name, propValue FROM jiveUserProp WHERE username=?";
private static final String LOAD_PROPERTY =
"SELECT propValue FROM jiveUserProp WHERE username=? AND name=?";
private static final String DELETE_PROPERTY =
"DELETE FROM jiveUserProp WHERE username=? AND name=?";
private static final String UPDATE_PROPERTY =
......@@ -55,6 +57,41 @@ public class User implements Cacheable {
private Map<String,String> properties = null;
/**
* Returns the value of the specified property for the given username. This method is
* an optimization to avoid loading a user to get a specific property.
*
* @param username the username of the user to get a specific property value.
* @param propertyName the name of the property to return its value.
* @return the value of the specified property for the given username.
*/
public static String getPropertyValue(String username, String propertyName) {
String propertyValue = null;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_PROPERTY);
pstmt.setString(1, username);
pstmt.setString(2, propertyName);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
propertyValue = rs.getString(1);
}
rs.close();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) { Log.error(e); }
try { if (con != null) con.close(); }
catch (Exception e) { Log.error(e); }
}
return propertyValue;
}
/**
* Constructs a new user. All arguments can be <tt>null</tt> except the username.
* Typically, User objects should not be constructed by end-users of the API.
......
......@@ -244,6 +244,28 @@ public class UserManager implements IQResultListener {
return provider.findUsers(fields, query);
}
/**
* Returns the value of the specified property for the given username. If the user
* has been loaded into memory then the ask the user to return the value of the
* property. However, if the user is not present in memory then try to get the property
* value directly from the database as a way to optimize the performance.
*
* @param username the username of the user to get a specific property value.
* @param propertyName the name of the property to return its value.
* @return the value of the specified property for the given username.
*/
public String getUserProperty(String username, String propertyName) {
username = username.trim().toLowerCase();
User user = (User) userCache.get(username);
if (user == null) {
return User.getPropertyValue(username, propertyName);
}
else {
// User is in memory so ask the user for the specified property value
return user.getProperties().get(propertyName);
}
}
/**
* Returns true if the specified local username belongs to a registered local user.
*
......
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