Commit 3d9dd958 authored by Matt Tucker's avatar Matt Tucker Committed by matt

Refactored group support.


git-svn-id: http://svn.igniterealtime.org/svn/repos/messenger/trunk@528 b35dd754-fafc-0310-a699-88a17e54d16e
parent c965dd6d
...@@ -72,30 +72,28 @@ CREATE TABLE jiveVCard ( ...@@ -72,30 +72,28 @@ CREATE TABLE jiveVCard (
CREATE TABLE jiveGroup ( CREATE TABLE jiveGroup (
groupID INTEGER NOT NULL,
name VARCHAR(50) NOT NULL, name VARCHAR(50) NOT NULL,
description VARCHAR(255), description VARCHAR(255),
creationDate CHAR(15) NOT NULL, creationDate CHAR(15) NOT NULL,
modificationDate CHAR(15) NOT NULL, modificationDate CHAR(15) NOT NULL,
CONSTRAINT jiveGroup_pk PRIMARY KEY (groupID) CONSTRAINT jiveGroup_pk PRIMARY KEY (name)
); );
CREATE INDEX jiveGrp_cDate_idx ON jiveGroup (creationDate ASC); CREATE INDEX jiveGrp_cDate_idx ON jiveGroup (creationDate ASC);
CREATE INDEX jiveGrp_name_idx ON jiveGroup (name);
CREATE TABLE jiveGroupProp ( CREATE TABLE jiveGroupProp (
groupID INTEGER NOT NULL, groupName VARCHAR(50) NOT NULL,
name VARCHAR(100) NOT NULL, name VARCHAR(100) NOT NULL,
propValue VARCHAR(2000) NOT NULL, propValue VARCHAR(2000) NOT NULL,
CONSTRAINT jiveGrpProp_pk PRIMARY KEY (groupID, name) CONSTRAINT jiveGrpProp_pk PRIMARY KEY (groupName, name)
); );
CREATE TABLE jiveGroupUser ( CREATE TABLE jiveGroupUser (
groupID INTEGER NOT NULL, groupName VARCHAR(50) NOT NULL,
username VARCHAR(32) NOT NULL, username VARCHAR(32) NOT NULL,
administrator INTEGER NOT NULL, administrator INTEGER NOT NULL,
CONSTRAINT jiveGrpUser PRIMARY KEY (groupID, username, administrator) CONSTRAINT jiveGrpUser PRIMARY KEY (groupName, username, administrator)
); );
...@@ -163,8 +161,6 @@ CREATE TABLE mucConversationLog ( ...@@ -163,8 +161,6 @@ CREATE TABLE mucConversationLog (
-- Finally, insert default table values -- Finally, insert default table values
INSERT INTO jiveID (idType, id) VALUES (3, 2);
INSERT INTO jiveID (idType, id) VALUES (4, 1);
INSERT INTO jiveID (idType, id) VALUES (18, 1); INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1); INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1); INSERT INTO jiveID (idType, id) VALUES (23, 1);
......
...@@ -83,30 +83,28 @@ CREATE TABLE jiveDomain ( ...@@ -83,30 +83,28 @@ CREATE TABLE jiveDomain (
CREATE TABLE jiveGroup ( CREATE TABLE jiveGroup (
groupID BIGINT NOT NULL,
name VARCHAR(50) NOT NULL, name VARCHAR(50) NOT NULL,
description VARCHAR(255), description VARCHAR(255),
creationDate VARCHAR(15) NOT NULL, creationDate VARCHAR(15) NOT NULL,
modificationDate VARCHAR(15) NOT NULL, modificationDate VARCHAR(15) NOT NULL,
CONSTRAINT jiveGroup_pk PRIMARY KEY (groupID) CONSTRAINT jiveGroup_pk PRIMARY KEY (name)
); );
CREATE INDEX jiveGroup_cDate_idx ON jiveGroup (creationDate); CREATE INDEX jiveGroup_cDate_idx ON jiveGroup (creationDate);
CREATE INDEX jiveGroup_name_idx ON jiveGroup (name);
CREATE TABLE jiveGroupProp ( CREATE TABLE jiveGroupProp (
groupID BIGINT NOT NULL, groupName VARCHAR(50) NOT NULL,
name VARCHAR(100) NOT NULL, name VARCHAR(100) NOT NULL,
propValue VARCHAR(4000) NOT NULL, propValue VARCHAR(4000) NOT NULL,
CONSTRAINT jiveGroupProp_pk PRIMARY KEY (groupID, name) CONSTRAINT jiveGroupProp_pk PRIMARY KEY (groupName, name)
); );
CREATE TABLE jiveGroupUser ( CREATE TABLE jiveGroupUser (
groupID BIGINT NOT NULL, groupName VARCHAR(50) NOT NULL,
username VARCHAR(32) NOT NULL, username VARCHAR(32) NOT NULL,
administrator INTEGER NOT NULL, administrator INTEGER NOT NULL,
CONSTRAINT jiveGroupUser_pk PRIMARY KEY (groupID, username, administrator) CONSTRAINT jiveGroupUser_pk PRIMARY KEY (groupName, username, administrator)
); );
...@@ -174,14 +172,10 @@ CREATE TABLE mucConversationLog ( ...@@ -174,14 +172,10 @@ CREATE TABLE mucConversationLog (
// Finally, insert default table values. // Finally, insert default table values.
// Unique ID entry for user, group
// The User ID entry starts at 2 (after admin user entry).
INSERT INTO jiveID (idType, id) VALUES (3, 2);
INSERT INTO jiveID (idType, id) VALUES (4, 1);
INSERT INTO jiveID (idType, id) VALUES (18, 1); INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1); INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1); INSERT INTO jiveID (idType, id) VALUES (23, 1);
// Entry for admin user -- password is "admin" // Entry for admin user
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate) INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
VALUES ('admin', 'admin', 'Administrator', 'admin@example.com', '0', '0'); VALUES ('admin', 'admin', 'Administrator', 'admin@example.com', '0', '0');
\ No newline at end of file
...@@ -21,28 +21,26 @@ CREATE TABLE jiveUserProp ( ...@@ -21,28 +21,26 @@ CREATE TABLE jiveUserProp (
); );
CREATE TABLE jiveGroup ( CREATE TABLE jiveGroup (
groupID BIGINT NOT NULL,
name VARCHAR(50) NOT NULL, name VARCHAR(50) NOT NULL,
description VARCHAR(255), description VARCHAR(255),
creationDate CHAR(15) NOT NULL, creationDate CHAR(15) NOT NULL,
modificationDate CHAR(15) NOT NULL, modificationDate CHAR(15) NOT NULL,
PRIMARY KEY (groupID), PRIMARY KEY (name),
INDEX jiveGroup_cDate_idx (creationDate), INDEX jiveGroup_cDate_idx (creationDate)
INDEX jiveGroup_name_idx (name(10))
); );
CREATE TABLE jiveGroupProp ( CREATE TABLE jiveGroupProp (
groupID BIGINT NOT NULL, groupName VARCHAR(50) NOT NULL,
name VARCHAR(100) NOT NULL, name VARCHAR(100) NOT NULL,
propValue TEXT NOT NULL, propValue TEXT NOT NULL,
PRIMARY KEY (groupID, name) PRIMARY KEY (groupName, name)
); );
CREATE TABLE jiveGroupUser ( CREATE TABLE jiveGroupUser (
groupID BIGINT NOT NULL, groupName VARCHAR(50) NOT NULL,
username VARCHAR(32) NOT NULL, username VARCHAR(32) NOT NULL,
administrator TINYINT NOT NULL, administrator TINYINT NOT NULL,
PRIMARY KEY (groupID, username, administrator) PRIMARY KEY (groupName, username, administrator)
); );
CREATE TABLE jivePrivate ( CREATE TABLE jivePrivate (
...@@ -151,10 +149,6 @@ CREATE TABLE mucConversationLog ( ...@@ -151,10 +149,6 @@ CREATE TABLE mucConversationLog (
# Finally, insert default table values. # Finally, insert default table values.
# Unique ID entry for user, group
# The User ID entry starts at 2 (after admin user entry).
INSERT INTO jiveID (idType, id) VALUES (3, 2);
INSERT INTO jiveID (idType, id) VALUES (4, 1);
INSERT INTO jiveID (idType, id) VALUES (18, 1); INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1); INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1); INSERT INTO jiveID (idType, id) VALUES (23, 1);
......
...@@ -72,28 +72,26 @@ CREATE TABLE jiveVCard ( ...@@ -72,28 +72,26 @@ CREATE TABLE jiveVCard (
); );
CREATE TABLE jiveGroup ( CREATE TABLE jiveGroup (
groupID INTEGER NOT NULL,
name VARCHAR2(50) NOT NULL, name VARCHAR2(50) NOT NULL,
description VARCHAR2(255), description VARCHAR2(255),
creationDate CHAR(15) NOT NULL, creationDate CHAR(15) NOT NULL,
modificationDate CHAR(15) NOT NULL, modificationDate CHAR(15) NOT NULL,
CONSTRAINT jiveGroup_pk PRIMARY KEY (groupID) CONSTRAINT jiveGroup_pk PRIMARY KEY (groupName)
); );
CREATE INDEX jiveGroup_cDate_idx ON jiveGroup (creationDate ASC); CREATE INDEX jiveGroup_cDate_idx ON jiveGroup (creationDate ASC);
CREATE INDEX jiveGroup_name_idx ON jiveGroup (name);
CREATE TABLE jiveGroupProp ( CREATE TABLE jiveGroupProp (
groupID INTEGER NOT NULL, groupName VARCHAR(50) NOT NULL,
name VARCHAR2(100) NOT NULL, name VARCHAR2(100) NOT NULL,
propValue VARCHAR2(4000) NOT NULL, propValue VARCHAR2(4000) NOT NULL,
CONSTRAINT jiveGroupProp_pk PRIMARY KEY (groupID, name) CONSTRAINT jiveGroupProp_pk PRIMARY KEY (groupName, name)
); );
CREATE TABLE jiveGroupUser ( CREATE TABLE jiveGroupUser (
groupID INTEGER NOT NULL, groupName VARCHAR(50) NOT NULL,
username VARCHAR2(32) NOT NULL, username VARCHAR2(32) NOT NULL,
administrator INTEGER NOT NULL, administrator INTEGER NOT NULL,
CONSTRAINT jiveGroupUser PRIMARY KEY (groupID, username, administrator) CONSTRAINT jiveGroupUser PRIMARY KEY (groupName, username, administrator)
); );
CREATE TABLE jiveID ( CREATE TABLE jiveID (
...@@ -158,10 +156,6 @@ CREATE TABLE mucConversationLog ( ...@@ -158,10 +156,6 @@ CREATE TABLE mucConversationLog (
REM // Finally, insert default table values. REM // Finally, insert default table values.
REM // Unique ID entry for user, group
REM // The User ID entry starts at 2 (after admin user entry).
INSERT INTO jiveID (idType, id) VALUES (3, 2);
INSERT INTO jiveID (idType, id) VALUES (4, 1);
INSERT INTO jiveID (idType, id) VALUES (18, 1); INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1); INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1); INSERT INTO jiveID (idType, id) VALUES (23, 1);
......
...@@ -75,33 +75,28 @@ CREATE TABLE jiveVCard ( ...@@ -75,33 +75,28 @@ CREATE TABLE jiveVCard (
CREATE TABLE jiveGroup ( CREATE TABLE jiveGroup (
groupID INTEGER NOT NULL,
name VARCHAR(50) NOT NULL, name VARCHAR(50) NOT NULL,
description VARCHAR(255), description VARCHAR(255),
creationDate CHAR(15) NOT NULL, creationDate CHAR(15) NOT NULL,
modificationDate CHAR(15) NOT NULL, modificationDate CHAR(15) NOT NULL,
CONSTRAINT jiveGroup_pk PRIMARY KEY (groupID) CONSTRAINT jiveGroup_pk PRIMARY KEY (name)
); );
CREATE INDEX jiveGroup_cDate_idx ON jiveGroup (creationDate); CREATE INDEX jiveGroup_cDate_idx ON jiveGroup (creationDate);
CREATE INDEX jiveGroup_name_idx ON jiveGroup (name);
CREATE TABLE jiveGroupProp ( CREATE TABLE jiveGroupProp (
groupID INTEGER NOT NULL, groupName VARCHAR(50) NOT NULL,
name VARCHAR(100) NOT NULL, name VARCHAR(100) NOT NULL,
propValue TEXT NOT NULL, propValue TEXT NOT NULL,
CONSTRAINT jiveGroupProp_pk PRIMARY KEY (groupID, name) CONSTRAINT jiveGroupProp_pk PRIMARY KEY (groupName, name)
); );
-- Commented out since this will cause a third party user system to break
-- If you do not use a third part user system, uncomment these constraints
-- ALTER TABLE jiveGroupProp ADD CONSTRAINT jiveGroupProp_groupID_fk FOREIGN KEY (groupID) REFERENCES jiveGroup INITIALLY DEFERRED DEFERRABLE;
CREATE TABLE jiveGroupUser ( CREATE TABLE jiveGroupUser (
groupID INTEGER NOT NULL, groupName VARCHAR(50) NOT NULL,
username VARCHAR(32) NOT NULL, username VARCHAR(32) NOT NULL,
administrator INTEGER NOT NULL, administrator INTEGER NOT NULL,
CONSTRAINT jiveGroupUser_pk PRIMARY KEY (groupID, username, administrator) CONSTRAINT jiveGroupUser_pk PRIMARY KEY (groupName, username, administrator)
); );
...@@ -168,10 +163,6 @@ CREATE TABLE mucConversationLog ( ...@@ -168,10 +163,6 @@ CREATE TABLE mucConversationLog (
-- Finally, insert default table values. -- Finally, insert default table values.
-- Unique ID entry for user, group
-- The User ID entry starts at 2 (after admin user entry).
INSERT INTO jiveID (idType, id) VALUES (3, 2);
INSERT INTO jiveID (idType, id) VALUES (4, 1);
INSERT INTO jiveID (idType, id) VALUES (18, 1); INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1); INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1); INSERT INTO jiveID (idType, id) VALUES (23, 1);
......
...@@ -75,33 +75,28 @@ CREATE TABLE jiveVCard ( ...@@ -75,33 +75,28 @@ CREATE TABLE jiveVCard (
CREATE TABLE jiveGroup ( CREATE TABLE jiveGroup (
groupID INTEGER NOT NULL,
name NVARCHAR(100) NOT NULL, name NVARCHAR(100) NOT NULL,
description NVARCHAR(255), description NVARCHAR(255),
creationDate CHAR(15) NOT NULL, creationDate CHAR(15) NOT NULL,
modificationDate CHAR(15) NOT NULL, modificationDate CHAR(15) NOT NULL,
CONSTRAINT group_pk PRIMARY KEY (groupID) CONSTRAINT group_pk PRIMARY KEY (name)
); );
CREATE INDEX jiveGroup_cDate_idx ON jiveGroup (creationDate); CREATE INDEX jiveGroup_cDate_idx ON jiveGroup (creationDate);
CREATE INDEX jiveGroup_name_idx ON jiveGroup (name);
CREATE TABLE jiveGroupProp ( CREATE TABLE jiveGroupProp (
groupID INTEGER NOT NULL, groupName NVARCHAR(100) NOT NULL,
name NVARCHAR(100) NOT NULL, name NVARCHAR(100) NOT NULL,
propValue NVARCHAR(3900) NOT NULL, propValue NVARCHAR(3900) NOT NULL,
CONSTRAINT jiveGroupProp_pk PRIMARY KEY (groupID, name) CONSTRAINT jiveGroupProp_pk PRIMARY KEY (groupName, name)
); );
/* Commented out since this will cause a third party user system to break */
/* If you do not use a third part user system, uncomment these constraints */
/* ALTER TABLE jiveGroupProp ADD CONSTRAINT jiveGroupProp_groupID_fk FOREIGN KEY (groupID) REFERENCES jiveGroup; */
CREATE TABLE jiveGroupUser ( CREATE TABLE jiveGroupUser (
groupID INTEGER NOT NULL, groupName NVARCHAR(100) NOT NULL,
username NVARCHAR(32) NOT NULL, username NVARCHAR(32) NOT NULL,
administrator INTEGER NOT NULL, administrator INTEGER NOT NULL,
CONSTRAINT jiveGroupUser_pk PRIMARY KEY (groupID, username, administrator) CONSTRAINT jiveGroupUser_pk PRIMARY KEY (groupName, username, administrator)
); );
...@@ -168,10 +163,6 @@ CREATE TABLE mucConversationLog ( ...@@ -168,10 +163,6 @@ CREATE TABLE mucConversationLog (
/* Finally, insert default table values. */ /* Finally, insert default table values. */
/* Unique ID entry for user, group */
/* The User ID entry starts at 2 (after admin user entry). */
INSERT INTO jiveID (idType, id) VALUES (3, 2);
INSERT INTO jiveID (idType, id) VALUES (4, 1);
INSERT INTO jiveID (idType, id) VALUES (18, 1); INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1); INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1); INSERT INTO jiveID (idType, id) VALUES (23, 1);
......
...@@ -55,8 +55,6 @@ public class SequenceManager { ...@@ -55,8 +55,6 @@ public class SequenceManager {
static { static {
managers = new HashMap<Integer,Object>(); managers = new HashMap<Integer,Object>();
new SequenceManager(JiveConstants.USER, 1);
new SequenceManager(JiveConstants.GROUP, 1);
new SequenceManager(JiveConstants.ROSTER, 5); new SequenceManager(JiveConstants.ROSTER, 5);
new SequenceManager(JiveConstants.OFFLINE, 1); new SequenceManager(JiveConstants.OFFLINE, 1);
new SequenceManager(JiveConstants.MUC_ROOM, 1); new SequenceManager(JiveConstants.MUC_ROOM, 1);
......
...@@ -345,6 +345,42 @@ public class JiveGlobals { ...@@ -345,6 +345,42 @@ public class JiveGlobals {
return xmlProperties.getProperty(name); return xmlProperties.getProperty(name);
} }
/**
* Returns a local property. Local properties are stored in the file
* <tt>jive-messenger.xml</tt> that exists in the <tt>jiveMessenger/conf</tt> directory.
* Properties are always specified as "foo.bar.prop", which would map to
* the following entry in the XML file:
* <pre>
* &lt;foo&gt;
* &lt;bar&gt;
* &lt;prop&gt;some value&lt;/prop&gt;
* &lt;/bar&gt;
* &lt;/foo&gt;
* </pre>
*
* If the specified property can't be found, the <tt>defaultValue</tt> will be returned.
*
* @param name the name of the property to return.
* @param defaultValue the default value for the property.
* @return the property value specified by name.
*/
public static String getXMLProperty(String name, String defaultValue) {
if (xmlProperties == null) {
loadSetupProperties();
}
// messengerHome not loaded?
if (xmlProperties == null) {
return null;
}
String value = xmlProperties.getProperty(name);
if (value == null) {
value = defaultValue;
}
return value;
}
/** /**
* Returns an integer value local property. Local properties are stored in the file * Returns an integer value local property. Local properties are stored in the file
* <tt>jive_forums.xml</tt> that exists in the <tt>jiveHome</tt> directory. * <tt>jive_forums.xml</tt> that exists in the <tt>jiveHome</tt> directory.
......
...@@ -37,7 +37,6 @@ public interface SessionManager { ...@@ -37,7 +37,6 @@ public interface SessionManager {
*/ */
public Session createSession(Connection conn) throws UnauthorizedException; public Session createSession(Connection conn) throws UnauthorizedException;
/** /**
* Change the priority of a session associated with the sender. * Change the priority of a session associated with the sender.
* *
...@@ -82,28 +81,27 @@ public interface SessionManager { ...@@ -82,28 +81,27 @@ public interface SessionManager {
throws UnauthorizedException, SessionNotFoundException; throws UnauthorizedException, SessionNotFoundException;
/** /**
* <p>Obtain an iterator of all sessions on the server.</p> * Returns the Collection of all sessions on the server.
* *
* @return An iterator over the sessions (never null) * @return the Collection of all sessions.
*/ */
public Iterator getSessions() throws UnauthorizedException; public Collection<Session> getSessions();
/** /**
* <p>Obtain an iterator of all sessions on the server.</p> * Returns a Collection of all sessions on the server given the
* specified ResultFilter.
* *
* @param filter The result filter to apply to the search * @param filter the result filter to apply to the search.
* @return An iterator over the sessions (never null) * @return the Collection of all sessions.
*/ */
public Iterator getSessions(SessionResultFilter filter) throws UnauthorizedException; public Collection<Session> getSessions(SessionResultFilter filter);
/** /**
* <p>Obtain an iterator of all anonymous sessions on the server.</p> * <p>Obtain an iterator of all anonymous sessions on the server.</p>
* *
* @return An iterator over the anonynmous sessions (never null) * @return An iterator over the anonynmous sessions (never null)
* @throws UnauthorizedException
* @throws UnauthorizedException If caller doesn't have permission to access this method
*/ */
public Iterator getAnonymousSessions() throws UnauthorizedException; public Iterator getAnonymousSessions();
/** /**
* <p>Obtain an iterator of all sessions for a given user on the server.</p> * <p>Obtain an iterator of all sessions for a given user on the server.</p>
......
...@@ -421,7 +421,7 @@ public class SessionResultFilter { ...@@ -421,7 +421,7 @@ public class SessionResultFilter {
* *
* @return A comparator that sorts Sessions matching the sort order for this filter. * @return A comparator that sorts Sessions matching the sort order for this filter.
*/ */
public Comparator getSortComparator() { public Comparator<Session> getSortComparator() {
return new SessionComparator(); return new SessionComparator();
} }
......
...@@ -16,7 +16,6 @@ import org.jivesoftware.messenger.disco.IQDiscoInfoHandler; ...@@ -16,7 +16,6 @@ import org.jivesoftware.messenger.disco.IQDiscoInfoHandler;
import org.jivesoftware.messenger.disco.IQDiscoItemsHandler; import org.jivesoftware.messenger.disco.IQDiscoItemsHandler;
import org.jivesoftware.messenger.muc.spi.MultiUserChatServerImpl; import org.jivesoftware.messenger.muc.spi.MultiUserChatServerImpl;
import org.jivesoftware.messenger.audit.spi.AuditManagerImpl; import org.jivesoftware.messenger.audit.spi.AuditManagerImpl;
import org.jivesoftware.messenger.auth.spi.GroupManagerImpl;
import org.jivesoftware.messenger.handler.*; import org.jivesoftware.messenger.handler.*;
import org.jivesoftware.messenger.spi.*; import org.jivesoftware.messenger.spi.*;
import org.jivesoftware.messenger.transport.TransportHandler; import org.jivesoftware.messenger.transport.TransportHandler;
...@@ -47,7 +46,6 @@ public class XMPPBootContainer extends BootstrapContainer { ...@@ -47,7 +46,6 @@ public class XMPPBootContainer extends BootstrapContainer {
protected String[] getCoreModuleNames() { protected String[] getCoreModuleNames() {
return new String[]{ return new String[]{
GroupManagerImpl.class.getName(),
ConnectionManagerImpl.class.getName(), ConnectionManagerImpl.class.getName(),
PresenceManagerImpl.class.getName(), PresenceManagerImpl.class.getName(),
SessionManagerImpl.class.getName(), SessionManagerImpl.class.getName(),
......
...@@ -52,7 +52,6 @@ public class AuthProviderFactory { ...@@ -52,7 +52,6 @@ public class AuthProviderFactory {
"org.jivesoftware.messenger.auth.spi.DbGroupProvider"; "org.jivesoftware.messenger.auth.spi.DbGroupProvider";
private static AuthProvider authProvider = null; private static AuthProvider authProvider = null;
private static GroupProvider groupProvider = null;
/** /**
* Returns a concrete AuthProvider. By default, the implementation * Returns a concrete AuthProvider. By default, the implementation
...@@ -86,37 +85,4 @@ public class AuthProviderFactory { ...@@ -86,37 +85,4 @@ public class AuthProviderFactory {
} }
return authProvider; return authProvider;
} }
/**
* <p>Obtains a concrete GroupProvider.<p>
* <p/>
* <p>By default, the implementation used will be an instance
* of DbGroupProvider -- the standard database implementation
* that uses the Jive group table. A different GroupProvider can be
* specified by setting the Jive property "GroupProvider.className".
* However, you must restart Jive for any change to take effect.</p>
*/
public static GroupProvider getGroupProvider() {
if (groupProvider == null) {
// Use className as a convenient object to get a lock on.
synchronized (groupClassName) {
if (groupProvider == null) {
//See if the classname has been set as a Jive property.
String classNameProp =
JiveGlobals.getProperty("GroupProvider.className");
if (classNameProp != null) {
groupClassName = classNameProp;
}
try {
Class c = ClassUtils.forName(groupClassName);
groupProvider = (GroupProvider)c.newInstance();
}
catch (Exception e) {
Log.error("Exception loading class: " + groupClassName, e);
}
}
}
}
return groupProvider;
}
} }
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.auth;
import org.jivesoftware.messenger.user.UserAlreadyExistsException;
import org.jivesoftware.messenger.user.User;
import java.util.Date;
import java.util.Iterator;
/**
* Organizes entities into a group for easier permissions management.
* In this way, groups essentially serve the same purpose that
* they do in Unix or Windows.<p>
* <p/>
* For example, CREATE_THREAD permissions can be set per forum. A
* forum administrator may wish to create a "Thread Posters" group
* that has CREATE_THREAD permissions in the forum. Then, users can
* be added to that group and will automatically receive CREATE_THREAD
* permissions in that forum.<p>
* <p/>
* Security for Group objects is provide by GroupProxy protection proxy objects.
*
* @author Iain Shigeoka
*/
public interface Group {
/**
* Returns the id of the group.
*
* @return the id of the group.
*/
public long getID();
/**
* Returns the name of the group. For example, 'XYZ Admins'.
*
* @return the name of the group.
*/
public String getName();
/**
* Sets the name of the group. For example, 'XYZ Admins'. This
* method is restricted to those with group administration permission.
*
* @param name the name for the group.
* @throws UnauthorizedException if does not have group administrator permissions.
*/
public void setName(String name) throws UnauthorizedException;
/**
* Returns the description of the group. The description often
* summarizes a group's function, such as 'Administrators of the XYZ forum'.
*
* @return the description of the group.
*/
public String getDescription();
/**
* Sets the description of the group. The description often
* summarizes a group's function, such as 'Administrators of
* the XYZ forum'. This method is restricted to those with group
* administration permission.
*
* @param description the description of the group.
* @throws UnauthorizedException if does not have group administrator permissions.
*/
public void setDescription(String description) throws UnauthorizedException;
/**
* Returns the date that the group was created.
*
* @return the date the group was created.
*/
public Date getCreationDate();
/**
* Sets the creation date of the group. In most cases, the
* creation date will default to when the group was entered
* into the system. However, the date needs to be set manually when
* importing data. In other words, skin authors should ignore
* this method since it only intended for system maintenance.
*
* @param creationDate the date the group was created.
* @throws UnauthorizedException if does not have administrator permissions.
*/
public void setCreationDate(Date creationDate) throws UnauthorizedException;
/**
* Returns the date that the group was last modified.
*
* @return the date the group record was last modified.
*/
public Date getModificationDate();
/**
* Sets the date the group was last modified. Skin authors
* should ignore this method since it only intended for
* system maintenance.
*
* @param modificationDate the date the group was modified.
* @throws UnauthorizedException if does not have administrator permissions.
*/
public void setModificationDate(Date modificationDate) throws UnauthorizedException;
/**
* Returns an extended property of the group. Each group can
* have an arbitrary number of extended properties. This
* lets particular skins or filters provide enhanced functionality
* that is not part of the base interface.
*
* @param name the name of the property to get.
* @return the value of the property
*/
public String getProperty(String name);
/**
* Sets an extended property of the group. Each group can have
* an arbitrary number of extended properties. This lets
* particular skins or filters provide enhanced functionality that is not
* part of the base interface.
*
* @param name the name of the property to set.
* @param value the new value for the property.
* @throws UnauthorizedException if not allowed to change the group.
*/
public void setProperty(String name, String value) throws UnauthorizedException;
/**
* Deletes an extended property. If the property specified by
* <code>name</code> does not exist, this method will do nothing.
*
* @param name the name of the property to delete.
* @throws UnauthorizedException if not allowed to edit messages.
*/
public void deleteProperty(String name) throws UnauthorizedException;
/**
* Returns an Iterator for all the names of the extended group properties.
*
* @return an Iterator for the property names.
*/
public Iterator getPropertyNames();
/**
* Grants administrator privileges of the group to a user. This
* method is restricted to those with group administration permission.
*
* @param user the User to grant adminstrative privileges to.
* @throws UnauthorizedException if does not have group administrator permissions.
*/
public void addAdministrator(User user) throws UnauthorizedException, UserAlreadyExistsException;
/**
* Revokes administrator privileges of the group to a user.
* This method is restricted to those with group administration permission.
*
* @param user the User to grant adminstrative privileges to.
* @throws UnauthorizedException if does not have group administrator permissions.
*/
public void removeAdministrator(User user) throws UnauthorizedException;
/**
* Adds a member to the group. This method is restricted to
* those with group administration permission.
*
* @param user the User to add to the group.
* @throws UnauthorizedException if does not have group administrator permissions.
*/
public void addMember(User user) throws UnauthorizedException, UserAlreadyExistsException;
/**
* Removes a member from the group. If the User is not
* in the group, this method does nothing. This method
* is restricted to those with group administration permission.
*
* @param user the User to remove from the group.
* @throws UnauthorizedException if does not have group administrator permissions.
*/
public void removeMember(User user) throws UnauthorizedException;
/**
* Returns true if the User has group administrator permissions.
*
* @return true if the User is an administrator of the group.
*/
public boolean isAdministrator(User user);
/**
* Returns true if if the User is a member of the group.
*
* @return true if the User is a member of the group.
*/
public boolean isMember(User user);
/**
* Returns the number of group administrators.
*
* @return the number of group administrators.
*/
public int getAdministratorCount();
/**
* Returns the number of group members.
*
* @return the number of group members.
*/
public int getMemberCount();
/**
* An iterator for all the Entities that are members of the group.
*
* @return an Iterator for all members of the group.
*/
public Iterator members();
/**
* An iterator for all the Entities that are administrators of the group.
*
* @return an Iterator for all administrators of the group.
*/
public Iterator administrators();
/**
* Returns the permissions for the group that correspond to the passed-in AuthToken.
*
* @param authToken the auth token to lookup permissions for.
* @return the permissions for the group that correspond to the passed-in AuthToken.
* @see Permissions
*/
public Permissions getPermissions(AuthToken authToken);
/**
* Returns true if the handle on the object has the
* permission specified. A list of possible
* permissions can be found in the Permissions class.
* Certain methods of this class are restricted to
* certain permissions as specified in the method comments.
*
* @param permissionType a permission type.
* @return true if the specified permission is valid.
* @see Permissions
*/
public boolean isAuthorized(long permissionType);
}
\ No newline at end of file
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.auth;
import org.jivesoftware.util.BasicResultFilter;
import org.jivesoftware.util.LongList;
import org.jivesoftware.messenger.user.UserAlreadyExistsException;
/**
* The group permission interface to implement when creating an
* authentication service plug-in. Implementations of group provider
* handles the persistent storage access for group in Messenger. Groups
* are associated with Entities (users or chatbots) strictly by the long ID
* for the entities. This allows groups to be handled by Jive while the user
* store is in another backend system, or groups can be handled
* separately from a native Jive user table.
*
* @author Iain Shigeoka
*/
public interface GroupProvider {
/**
* <p>Create a group with the given name (optional operation).</p>
* <p/>
* <p>The provider is responsible for setting the creation date and
* modification date to the current date/time and generating a unique
* group ID for the group.</p>
*
* @param name
* @return The created group
* @throws UnauthorizedException If the password is invalid or
* the caller does not have permission to make the change
* @throws UnsupportedOperationException If the provider does not
* support the operation (this is an optional operation)
* @throws GroupAlreadyExistsException if the group name already
* exists in the system.
*/
Group createGroup(String name)
throws UnauthorizedException,
UnsupportedOperationException,
GroupAlreadyExistsException;
/**
* <p>Deletes the group (optional operation).</p>
*
* @param groupID The ID of the group to delete
* @throws UnauthorizedException If the caller does not have permission to
* make the change
*/
void deleteGroup(long groupID) throws UnauthorizedException;
/**
* <p>Obtains a group by it's long ID.</p>
*
* @param groupID The ID of the group
* @return The group with the given ID
* @throws GroupNotFoundException If no group with that ID could be found
*/
Group getGroup(long groupID) throws GroupNotFoundException;
/**
* <p>Obtain a group given it's name.</p>
*
* @param name The name of the group
* @return The the group with the given name
* @throws GroupNotFoundException If no group with that name exists
*/
Group getGroup(String name) throws GroupNotFoundException;
/**
* <p>Updates the backend storage with the group's information.</p>
* <p/>
* <p>The system will adjust the group's properties then call this
* method so the backend storage can update the group information.</p>
*
* @param group The group to update
* @throws UnauthorizedException If the caller does not have permission to
* make the change
* @throws GroupNotFoundException If no existing group could be found to update
*/
void updateGroup(Group group) throws UnauthorizedException, GroupNotFoundException;
/**
* <p>Obtain the number of groups in the system.</p>
*
* @return The number of groups in the system
*/
int getGroupCount();
/**
* <p>Obtain a list of all Group IDs known by the provider.</p>
*
* @return The list of IDs of the groups on the system
*/
LongList getGroups();
/**
* <p>Obtain a list of all Group IDs known by the provider
* restricted by the given resut filter.</p>
*
* @param filter The filter to apply to the results before returning them
* @return The list of IDs of the groups on the system after filtering
*/
LongList getGroups(BasicResultFilter filter);
/**
* <p>Obtain an list of all Group IDs known by the provider
* that a given entity belongs to.</p>
*
* @param username the username.
* @return The list of IDs of the groups that the entity belongs to
*/
LongList getGroups(String username);
/**
* <p>Creates a membership relationship between the
* group and the entity (optional operation).</p>
*
* @param groupID the group to add the member to
* @param username the username to add
* @param administrator True if the member is an administrator of the group
* @throws UnauthorizedException If the password is invalid or
* the caller does not have permission to make the change
* @throws UnsupportedOperationException If the provider does not
* support the operation (this is an optional operation)
* @throws UserAlreadyExistsException If the given entity is already a member
* of the group
*/
void createMember(long groupID, String username, boolean administrator)
throws UnauthorizedException,
UserAlreadyExistsException,
UnsupportedOperationException;
/**
* <p>Updates a membership relationship between the
* group and the entity (optional operation).</p>
*
* @param groupID The group to add the member to
* @param username the username
* @param administrator True if the member is an administrator of the group
* @throws UnauthorizedException If the password is invalid or
* the caller does not have permission to make the change
* @throws UnsupportedOperationException If the provider does not
* support the operation (this is an optional operation)
*/
void updateMember(long groupID, String username, boolean administrator)
throws UnauthorizedException, UnsupportedOperationException;
/**
* Deletes a membership relationship between the group and the user (optional operation).
*
* @param groupID the group.
* @param username the username.
* @throws UnauthorizedException if does not have permission to make the change.
* @throws UnsupportedOperationException if the provider does not
* support the operation (this is an optional operation).
*/
void deleteMember(long groupID, String username)
throws UnauthorizedException, UnsupportedOperationException;
/**
* <p>Obtains a counto f the number of members in the group.</p>
*
* @param groupID The group to add the member to
* @param adminsOnly True if the member count should be restricted to
* administrators only
*/
int getMemberCount(long groupID, boolean adminsOnly);
/**
* <p>Obtain a list of all entity ID's of members of the given group.</p>
*
* @param groupID The ID of the group to locate members for
* @param adminsOnly True if the results should be restricted to administrators only
* @return The list of IDs of the entities that belongs to the group
*/
String [] getMembers(long groupID, boolean adminsOnly);
/**
* <p>Obtain a list of all entity ID's of members of the given group
* restricted by the given filter.</p>
*
* @param groupID The ID of the group to locate members for
* @param filter The filter to restrict the results list
* @param adminsOnly True if the results should be restricted to administrators only
* @return The list of IDs of the entities that belongs to the group
*/
String [] getMembers(long groupID, BasicResultFilter filter, boolean adminsOnly);
/**
* <p>Determine if a given entity is a member of a group.</p>
*
* @param groupID The ID of the group
* @param username the username.
* @param adminsOnly True if the entity must be an administrator of the group
* @return True if the entity is a member of the group
*/
boolean isMember(long groupID, String username, boolean adminsOnly);
/**
* <p>Creates a property on a group (optional operation).</p>
*
* @param groupID The ID of the group
* @param name The name of the property
* @param value The value of the property
* @throws UnauthorizedException If the password is invalid or
* the caller does not have permission to make the change
* @throws UnsupportedOperationException If the provider does not
* support the operation (this is an optional operation)
*/
void createProperty(long groupID, String name, String value)
throws UnauthorizedException, UnsupportedOperationException;
/**
* <p>Updates a property on a group (optional operation).</p>
*
* @param groupID the ID of the group.
* @param name the name of the property.
* @param value the value of the property.
* @throws UnauthorizedException If the password is invalid or
* the caller does not have permission to make the change
* @throws UnsupportedOperationException If the provider does not
* support the operation (this is an optional operation)
*/
void updateProperty(long groupID, String name, String value)
throws UnauthorizedException, UnsupportedOperationException;
/**
* <p>Deletes a property from a group (optional operation).</p>
*
* @param groupID The ID of the group
* @param name The name of the property
* @throws UnauthorizedException If the password is invalid or
* the caller does not have permission to make the change
* @throws UnsupportedOperationException If the provider does not
* support the operation (this is an optional operation)
*/
void deleteProperty(long groupID, String name)
throws UnauthorizedException, UnsupportedOperationException;
}
\ No newline at end of file
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.auth.spi;
import org.jivesoftware.util.CacheManager;
import org.jivesoftware.util.CacheSizes;
import org.jivesoftware.util.Cache;
import org.jivesoftware.util.*;
import org.jivesoftware.messenger.auth.*;
import org.jivesoftware.messenger.user.UserAlreadyExistsException;
import org.jivesoftware.messenger.user.User;
import org.jivesoftware.messenger.user.spi.UserIterator;
import java.util.*;
/**
* Database implementation of the Group interface.
*
* @author Matt Tucker
* @author Bruce Ritchie
* @author Iain Shigeoka
* @see Group
*/
public class GroupImpl implements Group, Cacheable {
private GroupProvider provider = AuthProviderFactory.getGroupProvider();
private long groupID;
private String name = null;
private String description = " ";
private Date creationDate;
private Date modificationDate;
private Map properties;
private String[] memberList;
private String[] adminList;
private Cache groupCache;
private Cache groupMemberCache;
/**
* <p>Creates a group with the given settings.</p>
*
* @param id The unique ID of the group
* @param groupName The name of the group
* @param groupDescription The description of the group
* @param created The date-time the group was created
* @param modified The date-time the group was last modified
*/
GroupImpl(long id, String groupName, String groupDescription, Date created,
Date modified)
{
groupID = id;
name = groupName;
description = groupDescription;
creationDate = created;
modificationDate = modified;
properties = new Hashtable();
groupCache = CacheManager.getCache(GroupManager.GROUP_CACHE_NAME);
groupMemberCache = CacheManager.getCache(GroupManager.GROUP_MEMBER_CACHE_NAME);
}
public long getID() {
return groupID;
}
public String getName() {
return name;
}
public void setName(String groupName) throws UnauthorizedException {
if (groupName == null) {
throw new IllegalArgumentException("Name cannot be null");
}
this.name = groupName;
}
public String getDescription() {
return description;
}
public void setDescription(String desc) throws UnauthorizedException {
if (desc == null) {
throw new IllegalArgumentException("Description cannot be null");
}
this.description = desc;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date created) throws UnauthorizedException {
if (created == null) {
throw new IllegalArgumentException("Creation date cannot be null");
}
this.creationDate.setTime(created.getTime());
}
public Date getModificationDate() {
return modificationDate;
}
public void setModificationDate(Date modified) throws UnauthorizedException {
if (modified == null) {
throw new IllegalArgumentException("Modification date cannot be null");
}
this.modificationDate.setTime(modified.getTime());
}
public String getProperty(String name) {
return (String)properties.get(name);
}
public void setProperty(String name, String value) throws UnauthorizedException {
// Make sure the property name and value aren't null.
if (name == null || value == null || "".equals(name) || "".equals(value)) {
throw new NullPointerException("Cannot set property with empty or null value.");
}
// See if we need to update a property value or insert a new one.
if (properties.containsKey(name)) {
// Only update the value in the database if the property value has changed.
if (!(value.equals(properties.get(name)))) {
String original = (String)properties.get(name);
properties.put(name, value);
provider.updateProperty(groupID, name, value);
// Re-add group to cache.
groupCache.put(new Long(groupID), this);
// fire off an event
Map params = new HashMap();
params.put("Type", "propertyModify");
params.put("PropertyKey", name);
params.put("originalValue", original);
}
}
else {
properties.put(name, value);
provider.createProperty(groupID, name, value);
// Re-add group to cache.
groupCache.put(new Long(groupID), this);
// fire off an event
Map params = new HashMap();
params.put("Type", "propertyAdd");
params.put("PropertyKey", name);
}
}
public void deleteProperty(String name) throws UnauthorizedException {
// Only delete the property if it exists.
if (properties.containsKey(name)) {
// fire off an event
Map params = new HashMap();
params.put("Type", "propertyDelete");
params.put("PropertyKey", name);
properties.remove(name);
provider.deleteProperty(groupID, name);
// Re-add group to cache.
groupCache.put(new Long(groupID), this);
}
}
public Iterator getPropertyNames() {
return Collections.unmodifiableSet(properties.keySet()).iterator();
}
public void addAdministrator(User user)
throws UnauthorizedException, UserAlreadyExistsException {
// If the user is already an administrator, do nothing.
if (isAdministrator(user)) {
throw new UserAlreadyExistsException("User " + user.getUsername() +
" already is a member of the group");
}
String username = user.getUsername();
provider.createMember(groupID, username, true);
try {
provider.updateGroup(this);
}
catch (GroupNotFoundException e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
// Changed admins, so reset admin list
adminList = null;
groupCache.put(new Long(groupID), this);
groupMemberCache.put(groupID + ",admin," + username, Boolean.TRUE);
// Now, clear the permissions cache.
// This is handled via a listener for the GroupEvent.GROUP_ADMINISTRATOR_ADD event
// fire off an event
Map params = new HashMap();
params.put("Administrator", user);
}
public void removeAdministrator(User user) throws UnauthorizedException {
// If the user is not an administrator, do nothing.
if (isAdministrator(user)) {
String username = user.getUsername();
provider.deleteMember(groupID, username);
try {
provider.updateGroup(this);
}
catch (GroupNotFoundException e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
// Changed admins, so reset admin list
adminList = null;
groupCache.put(new Long(groupID), this);
// Remove user from admin cache
groupMemberCache.remove(groupID + ",admin," + username);
// Now, clear the permissions cache.
// This is handled via a listener for the GroupEvent.GROUP_ADMINISTRATOR_DELETE event
}
}
public void addMember(User user)
throws UnauthorizedException, UserAlreadyExistsException {
// Don't do anything if the user is already a member of the group.
if (isMember(user)) {
throw new UserAlreadyExistsException("User " + user.getUsername() +
" is already a member of the group");
}
String username = user.getUsername();
provider.createMember(groupID, username, false);
try {
provider.updateGroup(this);
}
catch (GroupNotFoundException e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
// Changed membership, so reset member list
memberList = null;
groupCache.put(new Long(groupID), this);
// Remove user from member cache
groupMemberCache.remove(groupID + ",member," + username);
// Remove the user's entry for groups they belong in.
groupMemberCache.remove("userGroups-" + username);
// Now, clear the permissions cache.
// This is handled via a listener for the GroupEvent.GROUP_USER_ADD event
}
public void removeMember(User user) throws UnauthorizedException {
// Don't do anything if the user isn't a member of the group.
if (!isMember(user)) {
return;
}
String username = user.getUsername();
provider.deleteMember(groupID, username);
// Changed membership, so reset member list
memberList = null;
groupCache.put(new Long(groupID), this);
// Remove user from member cache
groupMemberCache.remove(groupID + ",member," + username);
// Remove the user's entry for groups they belong in.
groupMemberCache.remove("userGroups-" + username);
// Now, clear the permissions cache.
// This is handled via a listener for the GroupEvent.GROUP_USER_DELETE event
}
public boolean isAdministrator(User user) {
String username = user.getUsername();
Boolean bool = null;
bool = (Boolean)groupMemberCache.get(groupID + ",admin," + username);
if (bool == null) {
bool = new Boolean(provider.isMember(groupID, username, true));
// Add to cache
groupMemberCache.put(groupID + ",admin," + username, bool);
}
return bool.booleanValue();
}
public boolean isMember(User user) {
String username = user.getUsername();
Boolean bool = null;
bool = (Boolean)groupMemberCache.get(groupID + ",member," + username);
if (bool == null) {
bool = new Boolean(provider.isMember(groupID, username, false));
// Add to cache
groupMemberCache.put(groupID + ",member," + username, bool);
}
return bool.booleanValue();
}
public int getAdministratorCount() {
// If the admin list is null, load it.
if (adminList == null) {
administrators();
}
return adminList.length;
}
public int getMemberCount() {
// If the member list is null, load it.
if (memberList == null) {
members();
}
return memberList.length;
}
public Iterator members() {
if (memberList == null) {
memberList = provider.getMembers(groupID, false);
// Re-add group to cache.
groupCache.put(new Long(groupID), this);
}
try {
return new UserIterator(memberList);
}
catch (UnauthorizedException e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
return null;
}
public Iterator administrators() {
if (adminList == null) {
adminList = provider.getMembers(groupID, true);
// Re-add group to cache.
groupCache.put(new Long(groupID), this);
}
try {
return new UserIterator(adminList);
}
catch (UnauthorizedException e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
return null;
}
public Permissions getPermissions(AuthToken auth) {
String username = auth.getUsername();
try {
Boolean bool = null;
bool = (Boolean)groupMemberCache.get(groupID + ",admin," + username);
if (bool == null) {
bool = new Boolean(provider.isMember(groupID, username, true));
// Add to cache
groupMemberCache.put(groupID + ",admin," + username, bool);
}
if (bool.booleanValue()) {
return new Permissions(Permissions.GROUP_ADMIN);
}
}
catch (Exception e) {
}
return new Permissions(Permissions.NONE);
}
public boolean isAuthorized(long permissionType) {
return true;
}
public int getCachedSize() {
// Approximate the size of the object in bytes by calculating the size of each field.
int size = 0;
size += CacheSizes.sizeOfObject(); // overhead of object
size += CacheSizes.sizeOfLong(); // id
size += CacheSizes.sizeOfString(name); // name
size += CacheSizes.sizeOfString(description); // description
size += CacheSizes.sizeOfDate(); // creation date
size += CacheSizes.sizeOfDate(); // modification date
size += CacheSizes.sizeOfMap(properties); // properties
size += CacheSizes.sizeOfObject(); // member list
size += CacheSizes.sizeOfObject(); // admin list
return size;
}
/**
* Returns a String representation of the Group object using the group name.
*
* @return a String representation of the Group object.
*/
public String toString() {
return name;
}
public int hashCode() {
return (int)groupID;
}
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object != null && object instanceof GroupImpl) {
return groupID == ((GroupImpl)object).getID();
}
else {
return false;
}
}
}
\ No newline at end of file
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.auth.spi;
import org.jivesoftware.database.DatabaseObjectFactory;
import org.jivesoftware.messenger.auth.Group;
import org.jivesoftware.messenger.auth.GroupManager;
import org.jivesoftware.messenger.auth.GroupNotFoundException;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* <p>An class that defines the logic to iterate through an array of
* long unique ID's of Jive objects.</p>
* <p/>
* <p>One feature of the class is the ability to recover from underlying
* modifications to the dataset in some cases. Consider the following
* sequence of events:</p>
* <ul>
* <li> Time 00: An Iterator for users in a group is obtained.
* <li> Time 01: 3 of the 8 users in the group are deleted.
* <li> Time 02: Iteration of users begins.
* </ul>
* <p/>
* <p>In the above example, the underlying users in the group were
* changed after the initial iterator was obtained. The logic in
* this class will attempt to automatically compensate for these changes
* by skipping over items that cannot be loaded. In the above example,
* that would translate to the iterator returning 5 users instead of 8.</p>
*
* @author Iain Shigeoka
*/
public class GroupIterator implements Iterator {
private long[] elements;
private int currentIndex = -1;
private Object nextElement = null;
private DatabaseObjectFactory objectFactory;
/**
* Creates a new GroupIterator.
*/
public GroupIterator(GroupManager manager, long[] elements) {
this.elements = elements;
// Create an objectFactory to load users.
this.objectFactory = new GroupDOFactory(manager);
}
private class GroupDOFactory implements DatabaseObjectFactory {
private GroupManager manager;
public GroupDOFactory(GroupManager manager) {
this.manager = manager;
}
public Object loadObject(long id) {
try {
Group group = manager.getGroup(id);
return group;
}
catch (GroupNotFoundException e) { /* ignore */
}
return null;
}
}
/**
* Returns true if there are more elements in the iteration.
*
* @return true if the iterator has more elements.
*/
public boolean hasNext() {
// If we are at the end of the list, there can't be any more elements
// to iterate through.
if (currentIndex + 1 >= elements.length && nextElement == null) {
return false;
}
// Otherwise, see if nextElement is null. If so, try to load the next
// element to make sure it exists.
if (nextElement == null) {
nextElement = getNextElement();
if (nextElement == null) {
return false;
}
}
return true;
}
/**
* Returns the next element.
*
* @return the next element.
* @throws java.util.NoSuchElementException
* if there are no more elements.
*/
public Object next() throws java.util.NoSuchElementException {
Object element = null;
if (nextElement != null) {
element = nextElement;
nextElement = null;
}
else {
element = getNextElement();
if (element == null) {
throw new NoSuchElementException();
}
}
return element;
}
/**
* Not supported for security reasons.
*/
public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* Returns the next available element, or null if there are no more elements to return.
*
* @return the next available element.
*/
public Object getNextElement() {
while (currentIndex + 1 < elements.length) {
currentIndex++;
Object element = objectFactory.loadObject(elements[currentIndex]);
if (element != null) {
return element;
}
}
return null;
}
}
\ No newline at end of file
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.auth.spi;
import org.jivesoftware.util.ProxyFactory;
import org.jivesoftware.messenger.auth.AuthToken;
import org.jivesoftware.messenger.auth.Group;
import org.jivesoftware.messenger.auth.Permissions;
import java.util.Iterator;
/**
* Protection proxy for Iterators of groups.
*
* @author Iain Shigeoka
*/
public class GroupIteratorProxy implements Iterator {
private Iterator iterator;
private Object nextElement = null;
private AuthToken auth;
private Permissions permissions;
private ProxyFactory proxyFactory;
/**
* Creates a new group iterator proxy.
*
* @param iterator the Iterator to create proxies for.
* @param auth the authorization token.
* @param permissions the permissions that the new proxy will inherit.
*/
public GroupIteratorProxy(Iterator iterator, AuthToken auth, Permissions permissions) {
this.iterator = iterator;
this.auth = auth;
this.permissions = permissions;
// Create a class that wraps groups with proxies.
proxyFactory = new ProxyFactory() {
public Object createProxy(Object obj, AuthToken auth, Permissions perms) {
Group group = (Group)obj;
Permissions userPerms = group.getPermissions(auth);
Permissions newPerms = new Permissions(userPerms, perms);
return new GroupProxy(group, auth, newPerms);
}
};
}
/**
* Returns true if there are more elements in the iteration.
*
* @return true if the iterator has more elements.
*/
public boolean hasNext() {
// If we are at the end of the list, there can't be any more elements to iterate through.
if (!iterator.hasNext() && nextElement == null) {
return false;
}
// Otherwise, see if nextElement is null. If so, try to load the next element to make sure
// it exists.
if (nextElement == null) {
nextElement = getNextElement();
if (nextElement == null) {
return false;
}
}
return true;
}
/**
* Returns the next element.
*
* @return the next element.
* @throws java.util.NoSuchElementException
* if there are no more elements.
*/
public Object next() throws java.util.NoSuchElementException {
Object element = null;
if (nextElement != null) {
element = nextElement;
nextElement = null;
}
else {
element = getNextElement();
if (element == null) {
throw new java.util.NoSuchElementException();
}
}
return element;
}
/**
* Not supported for security reasons.
*/
public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* Returns the next available element, or null if there are no more elements.
*
* @return the next available element.
*/
public Object getNextElement() {
while (iterator.hasNext()) {
Object element = proxyFactory.createProxy(iterator.next(), auth, permissions);
if (element != null) {
return element;
}
}
return null;
}
}
\ No newline at end of file
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.auth.spi;
import org.jivesoftware.util.CacheManager;
import org.jivesoftware.messenger.container.BasicModule;
import org.jivesoftware.messenger.container.Container;
import org.jivesoftware.util.Cache;
import org.jivesoftware.util.*;
import org.jivesoftware.messenger.auth.*;
import org.jivesoftware.messenger.user.User;
import java.util.Iterator;
/**
* Database implementation of the GroupManager interface.
*
* @author Iain Shigeoka
*/
public class GroupManagerImpl extends BasicModule implements GroupManager {
private GroupProvider provider = AuthProviderFactory.getGroupProvider();
/**
* A cache for group object.s
*/
private Cache groupCache;
/**
* A cache that maps group names to ID's.
*/
private Cache groupIDCache;
/**
* A cache for the list members of in each group.
*/
private Cache groupMemberCache;
public GroupManagerImpl() {
super("Group Manager (database-backed)");
}
public Group createGroup(String name)
throws UnauthorizedException, GroupAlreadyExistsException {
Group newGroup = null;
try {
getGroup(name);
// The group already exists since now exception, so:
throw new GroupAlreadyExistsException();
}
catch (GroupNotFoundException unfe) {
// The group doesn't already exist so we can create a new group
newGroup = provider.createGroup(name);
groupCache.put(new Long(newGroup.getID()), newGroup);
}
return newGroup;
}
public Group getGroup(long groupID) throws GroupNotFoundException {
Group group = (Group)groupCache.get(new Long(groupID));
if (group == null) {
group = provider.getGroup(groupID);
groupCache.put(new Long(groupID), group);
}
return group;
}
public Group getGroup(String name) throws GroupNotFoundException {
Long groupIDLong = (Long)groupIDCache.get(name);
// If ID wan't found in cache, load it up and put it there.
if (groupIDLong == null) {
Group group = provider.getGroup(name);
groupIDLong = new Long(group.getID());
groupIDCache.put(name, groupIDLong);
}
return getGroup(groupIDLong.longValue());
}
public void deleteGroup(Group group) throws UnauthorizedException {
long groupID = group.getID();
String[] members = new String[group.getMemberCount()];
Iterator iter = group.members();
for (int i = 0; i < members.length; i++) {
User user = (User)iter.next();
members[i] = user.getUsername();
}
provider.deleteGroup(group.getID());
// Finally, expire all relevant caches
groupCache.remove(new Long(groupID));
groupIDCache.remove(group.getName());
// Remove entries in the group membership cache for all members of the group.
for (int i = 0; i < members.length; i++) {
groupMemberCache.remove("userGroups-" + members[i]);
}
// Removing a group can change the permissions of all the users in that
// group. Therefore, expire permissions cache.
}
public int getGroupCount() {
return provider.getGroupCount();
}
public Iterator getGroups() {
LongList groups = provider.getGroups();
return new GroupIterator(this, groups.toArray());
}
public Iterator getGroups(BasicResultFilter filter) {
LongList groups = provider.getGroups(filter);
return new GroupIterator(this, groups.toArray());
}
public Iterator getGroups(User user) {
String username = user.getUsername();
String key = "userGroups-" + username;
// Look in the group membership cache for the value.
long[] groups = (long[])groupMemberCache.get(key);
if (groups == null) {
groups = provider.getGroups(username).toArray();
}
return new GroupIterator(this, groups);
}
// #####################################################################
// Module management
// #####################################################################
public void initialize(Container container) {
super.initialize(container);
CacheManager.initializeCache(GROUP_CACHE_NAME, 128 * 1024);
CacheManager.initializeCache(GROUP_ID_CACHE_NAME, 128 * 1024);
CacheManager.initializeCache(GROUP_MEMBER_CACHE_NAME, 16 * 1024);
groupCache = CacheManager.getCache(GROUP_CACHE_NAME);
groupIDCache = CacheManager.getCache(GROUP_ID_CACHE_NAME);
groupMemberCache = CacheManager.getCache(GROUP_MEMBER_CACHE_NAME);
}
}
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.auth.spi;
import org.jivesoftware.util.BasicResultFilter;
import org.jivesoftware.util.JiveConstants;
import org.jivesoftware.messenger.auth.*;
import org.jivesoftware.messenger.user.spi.UserGroupIteratorProxy;
import org.jivesoftware.messenger.user.User;
import java.util.Iterator;
/**
* Protection proxy for the GroupManager class. It restricts access to
* protected methods by throwing UnauthorizedExceptions when necessary.
*
* @author Iain Shigeoka
* @see org.jivesoftware.messenger.auth.GroupManager
*/
public class GroupManagerProxy implements GroupManager {
private GroupManager groupManager;
private AuthToken auth;
private Permissions permissions;
/**
* Creates a new GroupManagerProxy.
*/
public GroupManagerProxy(GroupManager groupManager, AuthToken auth, Permissions permissions) {
this.groupManager = groupManager;
this.auth = auth;
this.permissions = permissions;
}
public Group createGroup(String name)
throws UnauthorizedException, GroupAlreadyExistsException {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN)) {
Group group = groupManager.createGroup(name);
return new GroupProxy(group, auth, permissions);
}
else {
throw new UnauthorizedException();
}
}
public Group getGroup(long groupID) throws GroupNotFoundException {
Group group = groupManager.getGroup(groupID);
Permissions groupPermissions = group.getPermissions(auth);
Permissions newPermissions = new Permissions(permissions, groupPermissions);
return new GroupProxy(group, auth, newPermissions);
}
public Group getGroup(String name) throws GroupNotFoundException {
Group group = groupManager.getGroup(name);
Permissions groupPermissions = group.getPermissions(auth);
Permissions newPermissions =
new Permissions(permissions, groupPermissions);
return new GroupProxy(group, auth, newPermissions);
}
public void deleteGroup(Group group) throws UnauthorizedException {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN)) {
groupManager.deleteGroup(group);
}
else {
throw new UnauthorizedException();
}
}
public int getGroupCount() {
return groupManager.getGroupCount();
}
public Iterator getGroups() {
Iterator iterator = groupManager.getGroups();
return new UserGroupIteratorProxy(JiveConstants.GROUP, iterator, auth, permissions);
}
public Iterator getGroups(BasicResultFilter filter) {
Iterator iterator = groupManager.getGroups(filter);
return new UserGroupIteratorProxy(JiveConstants.GROUP, iterator, auth, permissions);
}
public Iterator getGroups(User user) {
Iterator iterator = groupManager.getGroups(user);
return new UserGroupIteratorProxy(JiveConstants.GROUP, iterator, auth, permissions);
}
}
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.auth.spi;
import org.jivesoftware.messenger.auth.AuthToken;
import org.jivesoftware.messenger.auth.Group;
import org.jivesoftware.messenger.auth.Permissions;
import org.jivesoftware.messenger.auth.UnauthorizedException;
import org.jivesoftware.messenger.user.UserAlreadyExistsException;
import org.jivesoftware.messenger.user.User;
import org.jivesoftware.messenger.user.spi.UserIteratorProxy;
import java.util.Date;
import java.util.Iterator;
/**
* Protection proxy for the Group interface. It restricts access of certain
* methods to those that have the proper permissions to administer this object.
*
* @author Iain Shigeoka
*/
public class GroupProxy implements Group {
private Group group;
private AuthToken authToken;
private Permissions permissions;
public GroupProxy(Group group, AuthToken authToken, Permissions permissions) {
this.group = group;
this.authToken = authToken;
this.permissions = permissions;
}
public long getID() {
return group.getID();
}
public String getName() {
return group.getName();
}
public void setName(String name) throws UnauthorizedException {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN
| Permissions.GROUP_ADMIN)) {
group.setName(name);
}
else {
throw new UnauthorizedException();
}
}
public String getDescription() {
return group.getDescription();
}
public void setDescription(String description) throws UnauthorizedException {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN
| Permissions.GROUP_ADMIN)) {
group.setDescription(description);
}
else {
throw new UnauthorizedException();
}
}
public Date getCreationDate() {
return group.getCreationDate();
}
public void setCreationDate(Date creationDate)
throws UnauthorizedException {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN)) {
group.setCreationDate(creationDate);
}
else
throw new UnauthorizedException();
}
public Date getModificationDate() {
return group.getModificationDate();
}
public void setModificationDate(Date modificationDate)
throws UnauthorizedException {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN)) {
group.setModificationDate(modificationDate);
}
else
throw new UnauthorizedException();
}
public String getProperty(String name) {
return group.getProperty(name);
}
public void setProperty(String name, String value)
throws UnauthorizedException {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN
| Permissions.GROUP_ADMIN)) {
group.setProperty(name, value);
}
else {
throw new UnauthorizedException();
}
}
public void deleteProperty(String name) throws UnauthorizedException {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN
| Permissions.GROUP_ADMIN)) {
group.deleteProperty(name);
}
else {
throw new UnauthorizedException();
}
}
public Iterator getPropertyNames() {
return group.getPropertyNames();
}
public void addAdministrator(User user)
throws UnauthorizedException, UserAlreadyExistsException {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN
| Permissions.GROUP_ADMIN)) {
group.addAdministrator(user);
}
else {
throw new UnauthorizedException();
}
}
public void removeAdministrator(User user) throws UnauthorizedException {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN
| Permissions.GROUP_ADMIN)) {
group.removeAdministrator(user);
}
else {
throw new UnauthorizedException();
}
}
public void addMember(User user)
throws UnauthorizedException, UserAlreadyExistsException {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN
| Permissions.GROUP_ADMIN)) {
group.addMember(user);
}
else {
throw new UnauthorizedException();
}
}
public void removeMember(User user) throws UnauthorizedException {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN
| Permissions.GROUP_ADMIN)) {
group.removeMember(user);
}
else {
throw new UnauthorizedException();
}
}
public boolean isAdministrator(User user) {
return group.isAdministrator(user);
}
public boolean isMember(User user) {
return group.isMember(user);
}
public int getAdministratorCount() {
return group.getAdministratorCount();
}
public int getMemberCount() {
return group.getMemberCount();
}
public Iterator members() {
return new UserIteratorProxy(group.members(), authToken, permissions);
}
public Iterator administrators() {
return new UserIteratorProxy(group.administrators(), authToken, permissions);
}
public Permissions getPermissions(AuthToken authToken) {
return group.getPermissions(authToken);
}
public boolean isAuthorized(long type) {
return permissions.hasPermission(type);
}
}
\ No newline at end of file
...@@ -69,6 +69,7 @@ public class AdminConsolePlugin implements Plugin { ...@@ -69,6 +69,7 @@ public class AdminConsolePlugin implements Plugin {
log.add(logSink); log.add(logSink);
jetty = new Server(); jetty = new Server();
// Configure HTTP socket listener // Configure HTTP socket listener
port = JiveGlobals.getProperty("embedded-web.port", "9090"); port = JiveGlobals.getProperty("embedded-web.port", "9090");
......
...@@ -9,13 +9,11 @@ ...@@ -9,13 +9,11 @@
* a copy of which is included in this distribution. * a copy of which is included in this distribution.
*/ */
package org.jivesoftware.messenger.auth.spi; package org.jivesoftware.messenger.group;
import org.jivesoftware.database.DbConnectionManager; import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.database.SequenceManager;
import org.jivesoftware.util.*; import org.jivesoftware.util.*;
import org.jivesoftware.messenger.auth.*; import org.jivesoftware.messenger.user.User;
import org.jivesoftware.messenger.user.UserAlreadyExistsException;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
...@@ -24,6 +22,7 @@ import java.sql.SQLException; ...@@ -24,6 +22,7 @@ import java.sql.SQLException;
import java.util.Date; import java.util.Date;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Collection;
/** /**
* Database implementation of the GroupManager interface. * Database implementation of the GroupManager interface.
...@@ -33,75 +32,49 @@ import java.util.List; ...@@ -33,75 +32,49 @@ import java.util.List;
public class DbGroupProvider implements GroupProvider { public class DbGroupProvider implements GroupProvider {
private static final String INSERT_GROUP = private static final String INSERT_GROUP =
"INSERT INTO jiveGroup " + "INSERT INTO jiveGroup (name, description, creationDate, modificationDate) " +
"(name, description, groupID, creationDate, modificationDate) " + "VALUES (?, ?, ?, ?)";
"VALUES (?, ?, ?, ?, ?)";
private static final String LOAD_PROPERTIES =
"SELECT name, propValue FROM jiveGroupProp WHERE groupID=?";
private static final String LOAD_GROUP_BY_ID =
"SELECT name, description, groupID, creationDate, modificationDate " +
"FROM jiveGroup WHERE groupID=?";
private static final String DELETE_PROPERTY =
"DELETE FROM jiveGroupProp WHERE groupID=? AND name=?";
private static final String SAVE_GROUP = private static final String SAVE_GROUP =
"UPDATE jiveGroup SET name=?, description=?, creationDate=?, modificationDate=? " + "UPDATE jiveGroup SET description=?, creationDate=?, modificationDate=? " +
"WHERE groupID=?"; "WHERE name=?";
private static final String SET_GROUP_NAME_1 =
"UPDATE jiveGroup SET name=? WHERE name=?";
private static final String SET_GROUP_NAME_2 =
"UPDATE jiveGroupProp SET groupName=? WHERE groupName=?";
private static final String SET_GROUP_NAME_3 =
"UPDATE jiveGroupUser SET groupName=? WHERE groupName=?";
private static final String DELETE_GROUP_USERS = private static final String DELETE_GROUP_USERS =
"DELETE FROM jiveGroupUser WHERE groupID=?"; "DELETE FROM jiveGroupUser WHERE groupName=?";
private static final String DELETE_GROUP = private static final String DELETE_GROUP =
"DELETE FROM jiveGroup WHERE groupID=?"; "DELETE FROM jiveGroup WHERE name=?";
private static final String GROUP_COUNT = "SELECT count(*) FROM jiveGroup"; private static final String GROUP_COUNT = "SELECT count(*) FROM jiveGroup";
private static final String UPDATE_PROPERTY =
"UPDATE jiveGroupProp SET propValue=? WHERE name=? AND groupID=?";
private static final String INSERT_PROPERTY =
"INSERT INTO jiveGroupProp (groupID, name, propValue) VALUES (?, ?, ?)";
private static final String MEMBER_TEST =
"SELECT username FROM jiveGroupUser " +
"WHERE groupID=? AND username=? AND administrator=0";
private static final String ADMIN_TEST =
"SELECT username FROM jiveGroupUser " +
"WHERE groupID=? AND username=? AND administrator=1";
private static final String LOAD_ADMINS = private static final String LOAD_ADMINS =
"SELECT username FROM jiveGroupUser WHERE administrator=1 AND groupID=?"; "SELECT username FROM jiveGroupUser WHERE administrator=1 AND groupName=?";
private static final String LOAD_MEMBERS = private static final String LOAD_MEMBERS =
"SELECT username FROM jiveGroupUser WHERE administrator=0 AND groupID=?"; "SELECT username FROM jiveGroupUser WHERE administrator=0 AND groupName=?";
private static final String GROUP_MEMBER_COUNT =
"SELECT count(*) FROM jiveGroupUser WHERE administrator=0";
private static final String GROUP_ADMIN_COUNT =
"SELECT count(*) FROM jiveGroupUser WHERE administrator=1";
private static final String SELECT_GROUP_BY_NAME = private static final String SELECT_GROUP_BY_NAME =
"SELECT name, description, groupID, creationDate, modificationDate " + "SELECT description, creationDate, modificationDate FROM jiveGroup WHERE name=?";
"FROM jiveGroup WHERE name=?";
private static final String REMOVE_USER = private static final String REMOVE_USER =
"DELETE FROM jiveGroupUser WHERE groupID=? AND username=?"; "DELETE FROM jiveGroupUser WHERE groupName=? AND username=?";
private static final String UPDATE_USER =
"UPDATE jiveGroupUser SET administrator=? WHERE groupID=? username=?";
private static final String ADD_USER = private static final String ADD_USER =
"INSERT INTO jiveGroupUser (groupID, username, administrator) VALUES (?, ?, ?)"; "INSERT INTO jiveGroupUser (groupName, username, administrator) VALUES (?, ?, ?)";
private static final String USER_GROUPS = private static final String USER_GROUPS =
"SELECT groupID FROM jiveGroupUser WHERE username=? AND administrator=0"; "SELECT groupName FROM jiveGroupUser WHERE username=?";
private static final String ALL_GROUPS = "SELECT groupID FROM jiveGroup"; private static final String ALL_GROUPS = "SELECT name FROM jiveGroup";
public Group createGroup(String name) throws UnauthorizedException, public Group createGroup(String name) throws GroupAlreadyExistsException {
GroupAlreadyExistsException
{
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
Date nowDate = new Date(now); Date nowDate = new Date(now);
long id = SequenceManager.nextID(JiveConstants.GROUP);
Group group = null;
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(INSERT_GROUP); pstmt = con.prepareStatement(INSERT_GROUP);
pstmt.setString(1, name); pstmt.setString(1, name);
pstmt.setString(2, "None"); pstmt.setString(2, "");
pstmt.setLong(3, id); pstmt.setString(3, StringUtils.dateToMillis(nowDate));
pstmt.setString(4, StringUtils.dateToMillis(nowDate)); pstmt.setString(4, StringUtils.dateToMillis(nowDate));
pstmt.setString(5, StringUtils.dateToMillis(nowDate));
pstmt.executeUpdate(); pstmt.executeUpdate();
group = new GroupImpl(id, name, null, nowDate, nowDate);
} }
catch (SQLException e) { catch (SQLException e) {
Log.error(e); Log.error(e);
...@@ -112,51 +85,35 @@ public class DbGroupProvider implements GroupProvider { ...@@ -112,51 +85,35 @@ public class DbGroupProvider implements GroupProvider {
try { if (con != null) con.close(); } try { if (con != null) con.close(); }
catch (Exception e) { Log.error(e); } catch (Exception e) { Log.error(e); }
} }
if (group == null) { Collection<String> members = getMembers(name, false);
throw new GroupAlreadyExistsException(name); Collection<String> administrators = getMembers(name, true);
} return new Group(this, name, "", nowDate, nowDate, members, administrators);
return group;
} }
public Group getGroup(long groupID) throws GroupNotFoundException { public Group getGroup(String name) throws GroupNotFoundException {
Group group = null; String description = null;
Date creationDate = null;
Date modificationDate = null;
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_GROUP_BY_ID); pstmt = con.prepareStatement(SELECT_GROUP_BY_NAME);
pstmt.setLong(1, groupID); pstmt.setString(1, name);
ResultSet rs = pstmt.executeQuery(); ResultSet rs = pstmt.executeQuery();
if (!rs.next()) {
throw new GroupNotFoundException("Group with name "
+ name + " not found.");
}
if (rs.next()) { if (rs.next()) {
group = new GroupImpl(groupID, description = rs.getString(1);
rs.getString(1), creationDate = new java.util.Date(Long.parseLong(rs.getString(2).trim()));
rs.getString(2), modificationDate = new java.util.Date(Long.parseLong(rs.getString(3).trim()));
new java.util.Date(Long.parseLong(rs.getString(4).trim())),
new java.util.Date(Long.parseLong(rs.getString(5).trim())));
// Load any extended properties.
pstmt = con.prepareStatement(LOAD_PROPERTIES);
pstmt.setLong(1, groupID);
rs = pstmt.executeQuery();
while (rs.next()) {
// Add in name, value as a new property.
group.setProperty(rs.getString(1), rs.getString(2));
}
rs.close();
} }
} }
catch (SQLException e) { catch (SQLException e) {
Log.error(e); Log.error(e);
throw new GroupNotFoundException();
}
catch (NumberFormatException nfe) {
Log.error("WARNING: There was an error parsing the dates " +
"returned from the database. Ensure that they're being stored " +
"correctly.");
throw new GroupNotFoundException("Group with id "
+ groupID + " could not be loaded from the database.");
}
catch (UnauthorizedException e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
} }
finally { finally {
try { if (pstmt != null) pstmt.close(); } try { if (pstmt != null) pstmt.close(); }
...@@ -164,42 +121,29 @@ public class DbGroupProvider implements GroupProvider { ...@@ -164,42 +121,29 @@ public class DbGroupProvider implements GroupProvider {
try { if (con != null) con.close(); } try { if (con != null) con.close(); }
catch (Exception e) { Log.error(e); } catch (Exception e) { Log.error(e); }
} }
if (group == null) { Collection<String> members = getMembers(name, false);
throw new GroupNotFoundException("Group with ID " Collection<String> administrators = getMembers(name, true);
+ groupID + " not found."); return new Group(this, name, description, creationDate, modificationDate,
} members, administrators);
return group;
} }
public Group getGroup(String name) throws GroupNotFoundException { public void updateGroup(String name, String description, Date creationDate,
Group group = null; Date modificationDate) throws GroupNotFoundException
{
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(SELECT_GROUP_BY_NAME); pstmt = con.prepareStatement(SAVE_GROUP);
pstmt.setString(1, name); pstmt.setString(1, description);
ResultSet rs = pstmt.executeQuery(); pstmt.setString(2, StringUtils.dateToMillis(creationDate));
if (rs.next()) { pstmt.setString(3, StringUtils.dateToMillis(modificationDate));
group = new GroupImpl(rs.getLong(3), rs.getString(1), rs.getString(2), pstmt.setString(4, name);
new java.util.Date(Long.parseLong(rs.getString(4).trim())), pstmt.executeUpdate();
new java.util.Date(Long.parseLong(rs.getString(5).trim())));
// Load any extended properties.
pstmt = con.prepareStatement(LOAD_PROPERTIES);
pstmt.setLong(1, group.getID());
rs = pstmt.executeQuery();
while (rs.next()) {
// Add in name, value as a new property.
group.setProperty(rs.getString(1), rs.getString(2));
}
rs.close();
}
} }
catch (SQLException e) { catch (SQLException e) {
Log.error(e); Log.error(e);
} throw new GroupNotFoundException();
catch (UnauthorizedException e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
} }
finally { finally {
try { if (pstmt != null) pstmt.close(); } try { if (pstmt != null) pstmt.close(); }
...@@ -207,40 +151,43 @@ public class DbGroupProvider implements GroupProvider { ...@@ -207,40 +151,43 @@ public class DbGroupProvider implements GroupProvider {
try { if (con != null) con.close(); } try { if (con != null) con.close(); }
catch (Exception e) { Log.error(e); } catch (Exception e) { Log.error(e); }
} }
if (group == null) {
throw new GroupNotFoundException("Group with name "
+ name + " not found.");
}
return group;
} }
public void updateGroup(Group group) throws UnauthorizedException, GroupNotFoundException { public void setGroupName(String oldName, String newName) throws UnsupportedOperationException,
group.setModificationDate(new Date()); GroupAlreadyExistsException
{
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
boolean abortTransaction = false;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getTransactionConnection();
pstmt = con.prepareStatement(SAVE_GROUP); pstmt = con.prepareStatement(SET_GROUP_NAME_1);
pstmt.setString(1, group.getName()); pstmt.setString(1, newName);
pstmt.setString(2, group.getDescription()); pstmt.setString(2, oldName);
pstmt.setString(3, StringUtils.dateToMillis(group.getCreationDate())); pstmt.executeUpdate();
pstmt.setString(4, StringUtils.dateToMillis(group.getModificationDate())); pstmt.close();
pstmt.setLong(5, group.getID()); pstmt = con.prepareStatement(SET_GROUP_NAME_2);
pstmt.setString(1, newName);
pstmt.setString(2, oldName);
pstmt.executeUpdate();
pstmt.close();
pstmt = con.prepareStatement(SET_GROUP_NAME_3);
pstmt.setString(1, newName);
pstmt.setString(2, oldName);
pstmt.executeUpdate(); pstmt.executeUpdate();
} }
catch (SQLException e) { catch (SQLException e) {
Log.error(e); Log.error(e);
throw new GroupNotFoundException(); abortTransaction = true;
} }
finally { finally {
try { if (pstmt != null) pstmt.close(); } try { if (pstmt != null) pstmt.close(); }
catch (Exception e) { Log.error(e); } catch (Exception e) { Log.error(e); }
try { if (con != null) con.close(); } DbConnectionManager.closeTransactionConnection(con, abortTransaction);
catch (Exception e) { Log.error(e); }
} }
} }
public void deleteGroup(long groupID) throws UnauthorizedException { public void deleteGroup(String groupName) {
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
boolean abortTransaction = false; boolean abortTransaction = false;
...@@ -248,12 +195,12 @@ public class DbGroupProvider implements GroupProvider { ...@@ -248,12 +195,12 @@ public class DbGroupProvider implements GroupProvider {
con = DbConnectionManager.getTransactionConnection(); con = DbConnectionManager.getTransactionConnection();
// Remove all users in the group. // Remove all users in the group.
pstmt = con.prepareStatement(DELETE_GROUP_USERS); pstmt = con.prepareStatement(DELETE_GROUP_USERS);
pstmt.setLong(1, groupID); pstmt.setString(1, groupName);
pstmt.executeUpdate(); pstmt.executeUpdate();
pstmt.close(); pstmt.close();
// Remove the group entry. // Remove the group entry.
pstmt = con.prepareStatement(DELETE_GROUP); pstmt = con.prepareStatement(DELETE_GROUP);
pstmt.setLong(1, groupID); pstmt.setString(1, groupName);
pstmt.executeUpdate(); pstmt.executeUpdate();
pstmt.close(); pstmt.close();
} }
...@@ -266,8 +213,6 @@ public class DbGroupProvider implements GroupProvider { ...@@ -266,8 +213,6 @@ public class DbGroupProvider implements GroupProvider {
catch (Exception e) { Log.error(e); } catch (Exception e) { Log.error(e); }
DbConnectionManager.closeTransactionConnection(con, abortTransaction); DbConnectionManager.closeTransactionConnection(con, abortTransaction);
} }
// Removing a group can change the permissions of all the users in that
// group. Therefore, expire permissions cache.
} }
public int getGroupCount() { public int getGroupCount() {
...@@ -295,8 +240,8 @@ public class DbGroupProvider implements GroupProvider { ...@@ -295,8 +240,8 @@ public class DbGroupProvider implements GroupProvider {
return count; return count;
} }
public LongList getGroups() { public Collection<Group> getGroups() {
LongList groups = new LongList(); List<String> groupNames = new ArrayList<String>();
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try { try {
...@@ -304,7 +249,7 @@ public class DbGroupProvider implements GroupProvider { ...@@ -304,7 +249,7 @@ public class DbGroupProvider implements GroupProvider {
pstmt = con.prepareStatement(ALL_GROUPS); pstmt = con.prepareStatement(ALL_GROUPS);
ResultSet rs = pstmt.executeQuery(); ResultSet rs = pstmt.executeQuery();
while (rs.next()) { while (rs.next()) {
groups.add(rs.getLong(1)); groupNames.add(rs.getString(1));
} }
rs.close(); rs.close();
} }
...@@ -317,31 +262,32 @@ public class DbGroupProvider implements GroupProvider { ...@@ -317,31 +262,32 @@ public class DbGroupProvider implements GroupProvider {
try { if (con != null) con.close(); } try { if (con != null) con.close(); }
catch (Exception e) { Log.error(e); } catch (Exception e) { Log.error(e); }
} }
List<Group> groups = new ArrayList<Group>(groupNames.size());
GroupManager manager = GroupManager.getInstance();
for (String groupName : groupNames) {
try {
groups.add(manager.getGroup(groupName));
}
catch (GroupNotFoundException e) {
Log.error(e);
}
}
return groups; return groups;
} }
public LongList getGroups(BasicResultFilter filter) { public Collection<Group> getGroups(int startIndex, int numResults) {
LongList groups = new LongList(); List<String> groupNames = new ArrayList<String>();
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(ALL_GROUPS); pstmt = con.prepareStatement(ALL_GROUPS);
ResultSet rs = pstmt.executeQuery(); ResultSet rs = pstmt.executeQuery();
// Move to start of index DbConnectionManager.scrollResultSet(rs, startIndex);
for (int i = 0; i < filter.getStartIndex(); i++) { int count = 0;
if (!rs.next()) { while (rs.next() && count < numResults) {
break; groupNames.add(rs.getString(1));
} count++;
}
// Now read in desired number of results
for (int i = 0; i < filter.getNumResults(); i++) {
if (rs.next()) {
groups.add(rs.getLong(1));
}
else {
break;
}
} }
rs.close(); rs.close();
} }
...@@ -354,20 +300,30 @@ public class DbGroupProvider implements GroupProvider { ...@@ -354,20 +300,30 @@ public class DbGroupProvider implements GroupProvider {
try { if (con != null) con.close(); } try { if (con != null) con.close(); }
catch (Exception e) { Log.error(e); } catch (Exception e) { Log.error(e); }
} }
List<Group> groups = new ArrayList<Group>(groupNames.size());
GroupManager manager = GroupManager.getInstance();
for (String groupName : groupNames) {
try {
groups.add(manager.getGroup(groupName));
}
catch (GroupNotFoundException e) {
Log.error(e);
}
}
return groups; return groups;
} }
public LongList getGroups(String username) { public Collection<Group> getGroups(User user) {
LongList groups = new LongList(); List<String> groupNames = new ArrayList<String>();
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(USER_GROUPS); pstmt = con.prepareStatement(USER_GROUPS);
pstmt.setString(1, username); pstmt.setString(1, user.getUsername());
ResultSet rs = pstmt.executeQuery(); ResultSet rs = pstmt.executeQuery();
while (rs.next()) { while (rs.next()) {
groups.add(rs.getLong(1)); groupNames.add(rs.getString(1));
} }
rs.close(); rs.close();
} }
...@@ -380,25 +336,32 @@ public class DbGroupProvider implements GroupProvider { ...@@ -380,25 +336,32 @@ public class DbGroupProvider implements GroupProvider {
try { if (con != null) con.close(); } try { if (con != null) con.close(); }
catch (Exception e) { Log.error(e); } catch (Exception e) { Log.error(e); }
} }
List<Group> groups = new ArrayList<Group>(groupNames.size());
GroupManager manager = GroupManager.getInstance();
for (String groupName : groupNames) {
try {
groups.add(manager.getGroup(groupName));
}
catch (GroupNotFoundException e) {
Log.error(e);
}
}
return groups; return groups;
} }
public void createMember(long groupID, String username, boolean administrator) public void addMember(String groupName, String username, boolean administrator) {
throws UserAlreadyExistsException
{
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(ADD_USER); pstmt = con.prepareStatement(ADD_USER);
pstmt.setLong(1, groupID); pstmt.setString(1, groupName);
pstmt.setString(2, username); pstmt.setString(2, username);
pstmt.setInt(3, administrator ? 1 : 0); pstmt.setInt(3, administrator ? 1 : 0);
pstmt.executeUpdate(); pstmt.executeUpdate();
} }
catch (SQLException e) { catch (SQLException e) {
Log.error(e); Log.error(e);
throw new UserAlreadyExistsException(e);
} }
finally { finally {
try { if (pstmt != null) pstmt.close(); } try { if (pstmt != null) pstmt.close(); }
...@@ -408,36 +371,13 @@ public class DbGroupProvider implements GroupProvider { ...@@ -408,36 +371,13 @@ public class DbGroupProvider implements GroupProvider {
} }
} }
public void updateMember(long groupID, String username, boolean administrator) { public void deleteMember(String groupName, String username) {
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(UPDATE_USER);
pstmt.setInt(1, administrator ? 1 : 0);
pstmt.setLong(2, groupID);
pstmt.setString(3, username);
pstmt.executeUpdate();
}
catch (SQLException e) {
Log.error(e);
}
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); }
}
}
public void deleteMember(long groupID, String username) {
Connection con = null;
PreparedStatement pstmt = null;
try { try {
con = DbConnectionManager.getConnection(); con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(REMOVE_USER); pstmt = con.prepareStatement(REMOVE_USER);
pstmt.setLong(1, groupID); pstmt.setString(1, groupName);
pstmt.setString(2, username); pstmt.setString(2, username);
pstmt.executeUpdate(); pstmt.executeUpdate();
} }
...@@ -452,37 +392,7 @@ public class DbGroupProvider implements GroupProvider { ...@@ -452,37 +392,7 @@ public class DbGroupProvider implements GroupProvider {
} }
} }
public int getMemberCount(long groupID, boolean adminsOnly) { private Collection<String> getMembers(String groupName, boolean adminsOnly) {
int count = 0;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
if (adminsOnly) {
pstmt = con.prepareStatement(GROUP_MEMBER_COUNT);
}
else {
pstmt = con.prepareStatement(GROUP_ADMIN_COUNT);
}
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
}
catch (SQLException e) {
Log.error(e);
}
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 count;
}
public String [] getMembers(long groupID, boolean adminsOnly) {
List<String> members = new ArrayList<String>(); List<String> members = new ArrayList<String>();
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
...@@ -494,7 +404,7 @@ public class DbGroupProvider implements GroupProvider { ...@@ -494,7 +404,7 @@ public class DbGroupProvider implements GroupProvider {
else { else {
pstmt = con.prepareStatement(LOAD_ADMINS); pstmt = con.prepareStatement(LOAD_ADMINS);
} }
pstmt.setLong(1, groupID); pstmt.setString(1, groupName);
ResultSet rs = pstmt.executeQuery(); ResultSet rs = pstmt.executeQuery();
while (rs.next()) { while (rs.next()) {
members.add(rs.getString(1)); members.add(rs.getString(1));
...@@ -510,145 +420,6 @@ public class DbGroupProvider implements GroupProvider { ...@@ -510,145 +420,6 @@ public class DbGroupProvider implements GroupProvider {
try { if (con != null) con.close(); } try { if (con != null) con.close(); }
catch (Exception e) { Log.error(e); } catch (Exception e) { Log.error(e); }
} }
return (String [])members.toArray(); return members;
}
public String [] getMembers(long groupID, BasicResultFilter filter, boolean adminsOnly) {
List<String> members = new ArrayList<String>();
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
if (adminsOnly) {
pstmt = con.prepareStatement(LOAD_MEMBERS);
}
else {
pstmt = con.prepareStatement(LOAD_ADMINS);
}
pstmt.setLong(1, groupID);
ResultSet rs = pstmt.executeQuery();
// Move to start of index
for (int i = 0; i < filter.getStartIndex(); i++) {
if (!rs.next()) {
break;
}
}
// Now read in desired number of results
for (int i = 0; i < filter.getNumResults(); i++) {
if (rs.next()) {
members.add(rs.getString(1));
}
else {
break;
}
}
rs.close();
}
catch (SQLException e) {
Log.error(e);
}
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 (String [])members.toArray();
}
public boolean isMember(long groupID, String username, boolean adminsOnly) {
boolean member = false;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
if (adminsOnly) {
pstmt = con.prepareStatement(ADMIN_TEST);
}
else {
pstmt = con.prepareStatement(MEMBER_TEST);
}
pstmt.setLong(1, groupID);
pstmt.setString(2, username);
ResultSet rs = pstmt.executeQuery();
// If there is a result, then the user is a member of the group.
member = rs.next();
rs.close();
}
catch (SQLException e) {
Log.error(e);
}
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 member;
}
public void createProperty(long groupID, String name, String value) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(INSERT_PROPERTY);
pstmt.setLong(1, groupID);
pstmt.setString(2, name);
pstmt.setString(3, value);
pstmt.executeUpdate();
}
catch (SQLException e) {
Log.error(e);
}
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); }
}
}
public void updateProperty(long groupID, String name, String value) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(UPDATE_PROPERTY);
pstmt.setString(1, value);
pstmt.setString(2, name);
pstmt.setLong(3, groupID);
pstmt.executeUpdate();
}
catch (SQLException e) {
Log.error(e);
}
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); }
}
}
public void deleteProperty(long groupID, String name) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(DELETE_PROPERTY);
pstmt.setLong(1, groupID);
pstmt.setString(2, name);
pstmt.executeUpdate();
}
catch (SQLException e) {
Log.error(e);
}
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); }
}
} }
} }
\ No newline at end of file
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.group;
import org.jivesoftware.util.Log;
import org.jivesoftware.database.DbConnectionManager;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Groups organize users into a single entity for easier management.
*
* @see GroupManager#createGroup(String)
*
* @author Matt Tucker
*/
public class Group {
private static final String LOAD_PROPERTIES =
"SELECT name, propValue FROM jiveGroupProp WHERE groupID=?";
private static final String DELETE_PROPERTY =
"DELETE FROM jiveGroupProp WHERE groupID=? AND name=?";
private static final String UPDATE_PROPERTY =
"UPDATE jiveGroupProp SET propValue=? WHERE name=? AND groupID=?";
private static final String INSERT_PROPERTY =
"INSERT INTO jiveGroupProp (groupID, name, propValue) VALUES (?, ?, ?)";
private GroupProvider provider;
private GroupManager groupManager;
private String name;
private String description;
private Date creationDate;
private Date modificationDate;
private Map<String, String> properties;
private Collection<String> members;
private Collection<String> administrators;
/**
* Constructs a new group.
*
* @param provider the group provider.
* @param name the name.
* @param description the description.
* @param creationDate the date the group was created.
* @param modificationDate the date the group was latest modified.
* @param members a Collection of the group members (includes administrators).
* @param administrators a Collection of the group administrators.
*/
protected Group(GroupProvider provider, String name, String description, Date creationDate,
Date modificationDate, Collection<String> members, Collection<String> administrators)
{
this.provider = provider;
this.groupManager = GroupManager.getInstance();
this.name = name;
this.description = description;
this.creationDate = creationDate;
this.modificationDate = modificationDate;
this.members = members;
this.administrators = administrators;
}
/**
* Returns the name of the group. For example, 'XYZ Admins'.
*
* @return the name of the group.
*/
public String getName() {
return name;
}
/**
* Sets the name of the group. For example, 'XYZ Admins'. This
* method is restricted to those with group administration permission.
*
* @param name the name for the group.
*/
public void setName(String name) {
try {
provider.setGroupName(this.name, name);
groupManager.groupCache.remove(this.name);
this.name = name;
groupManager.groupCache.put(name, this);
}
catch (Exception e) {
Log.error(e);
}
}
/**
* Returns the description of the group. The description often
* summarizes a group's function, such as 'Administrators of the XYZ forum'.
*
* @return the description of the group.
*/
public String getDescription() {
return description;
}
/**
* Sets the description of the group. The description often
* summarizes a group's function, such as 'Administrators of
* the XYZ forum'. This method is restricted to those with group
* administration permission.
*
* @param description the description of the group.
*/
public void setDescription(String description) {
try {
provider.updateGroup(name, description, creationDate, modificationDate);
this.description = description;
}
catch (Exception e) {
Log.error(e);
}
}
/**
* Returns the date that the group was created.
*
* @return the date the group was created.
*/
public Date getCreationDate() {
return creationDate;
}
/**
* Sets the creation date of the group. In most cases, the
* creation date will default to when the group was entered
* into the system. However, the date needs to be set manually when
* importing data.
*
* @param creationDate the date the group was created.
*/
public void setCreationDate(Date creationDate) {
try {
provider.updateGroup(name, description, creationDate, modificationDate);
this.creationDate = creationDate;
}
catch (Exception e) {
Log.error(e);
}
}
/**
* Returns the date that the group was last modified.
*
* @return the date the group record was last modified.
*/
public Date getModificationDate() {
return modificationDate;
}
/**
* Sets the date the group was last modified. Skin authors
* should ignore this method since it only intended for
* system maintenance.
*
* @param modificationDate the date the group was modified.
*/
public void setModificationDate(Date modificationDate) {
try {
provider.updateGroup(name, description, creationDate, modificationDate);
this.modificationDate = modificationDate;
}
catch (Exception e) {
Log.error(e);
}
}
/**
* Returns all extended properties of the group. Groups
* have an arbitrary number of extended properties.
*
* @return the extended properties.
*/
public Map<String,String> getProperties() {
if (properties == null) {
synchronized (this) {
if (properties == null) {
properties = new ConcurrentHashMap<String, String>();
loadProperties();
}
}
}
// Return a wrapper that will intercept add and remove commands.
return new PropertiesMap();
}
/**
* Returns a Collection of the group members that are administrators.
*
* @return a Collection of the group administrators.
*/
public Collection<String> getAdministrators() {
// Return a wrapper that will intercept add and remove commands.
return new MemberCollection(administrators, true);
}
/**
* Returns a Collection of the group members. Administrators are also
* considered to be members, so are included in the Collection.
*
* @return a Collection of the group members.
*/
public Collection<String> getMembers() {
// Return a wrapper that will intercept add and remove commands.
return new MemberCollection(members, false);
}
/**
* Collection implementation that notifies the GroupProvider of any
* changes to the collection.
*/
private class MemberCollection extends AbstractCollection {
private Collection<String> users;
private boolean adminCollection;
public MemberCollection(Collection<String> users, boolean adminCollection) {
this.users = users;
this.adminCollection = adminCollection;
}
public Iterator iterator() {
return new Iterator() {
Iterator iter = users.iterator();
Object current = null;
public boolean hasNext() {
return iter.hasNext();
}
public Object next() {
current = iter.next();
return current;
}
public void remove() {
if (current == null) {
throw new IllegalStateException();
}
provider.deleteMember(name, (String)current);
iter.remove();
}
};
}
public int size() {
return users.size();
}
public boolean add(Object member) {
provider.addMember(name, (String)member, adminCollection);
return users.add((String)member);
}
}
/**
* Map implementation that updates the database when properties are modified.
*/
private class PropertiesMap extends AbstractMap {
public Object put(Object key, Object value) {
if (properties.containsKey(key)) {
updateProperty((String)key, (String)value);
}
else {
insertProperty((String)key, (String)value);
}
return properties.put((String)key, (String)value);
}
public Set<Entry> entrySet() {
return new PropertiesEntrySet();
}
}
/**
* Set implementation that updates the database when properties are deleted.
*/
private class PropertiesEntrySet extends AbstractSet {
public int size() {
return properties.entrySet().size();
}
public Iterator iterator() {
return new Iterator() {
Iterator iter = properties.entrySet().iterator();
Map.Entry current = null;
public boolean hasNext() {
return iter.hasNext();
}
public Object next() {
current = (Map.Entry)iter.next();
return iter.next();
}
public void remove() {
if (current == null) {
throw new IllegalStateException();
}
deleteProperty((String)current.getKey());
iter.remove();
}
};
}
}
private void loadProperties() {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_PROPERTIES);
pstmt.setString(1, name);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
properties.put(rs.getString(1), rs.getString(2));
}
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); }
}
}
public void insertProperty(String propName, String propValue) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(INSERT_PROPERTY);
pstmt.setString(1, name);
pstmt.setString(2, propName);
pstmt.setString(3, propValue);
pstmt.executeUpdate();
}
catch (SQLException e) {
Log.error(e);
}
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); }
}
}
public void updateProperty(String propName, String propValue) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(UPDATE_PROPERTY);
pstmt.setString(1, propValue);
pstmt.setString(2, propName);
pstmt.setString(3, name);
pstmt.executeUpdate();
}
catch (SQLException e) {
Log.error(e);
}
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); }
}
}
public void deleteProperty(String propName) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(DELETE_PROPERTY);
pstmt.setString(1, name);
pstmt.setString(2, propName);
pstmt.executeUpdate();
}
catch (SQLException e) {
Log.error(e);
}
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); }
}
}
}
\ No newline at end of file
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* a copy of which is included in this distribution. * a copy of which is included in this distribution.
*/ */
package org.jivesoftware.messenger.auth; package org.jivesoftware.messenger.group;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter; import java.io.PrintWriter;
......
...@@ -9,34 +9,52 @@ ...@@ -9,34 +9,52 @@
* a copy of which is included in this distribution. * a copy of which is included in this distribution.
*/ */
package org.jivesoftware.messenger.auth; package org.jivesoftware.messenger.group;
import org.jivesoftware.util.BasicResultFilter; import org.jivesoftware.util.Cache;
import org.jivesoftware.util.CacheManager;
import org.jivesoftware.util.ClassUtils;
import org.jivesoftware.util.Log;
import org.jivesoftware.messenger.user.User; import org.jivesoftware.messenger.user.User;
import org.jivesoftware.messenger.JiveGlobals;
import java.util.Iterator; import java.util.Collection;
import java.util.ArrayList;
/** /**
* <p>Manages groups.</p> * Manages groups
* *
* @author Iain Shigeoka
* @see Group * @see Group
* @author Matt Tucker
*/ */
public interface GroupManager { public class GroupManager {
/** Cache groupCache;
* <p>The name of the group cache mapping long ID to Group object.</p> Cache groupMemberCache;
*/ private GroupProvider provider;
String GROUP_CACHE_NAME = "group";
/** public static GroupManager getInstance() {
* <p>Cache of group names to group Long ID's.</p> return null;
*/ }
String GROUP_ID_CACHE_NAME = "groupID";
/** private GroupManager() {
* <p>Cache of String("userGroups-" + memberID) to long[] // Initialize caches.
* array of group ID's that member belongs to.</p> CacheManager.initializeCache("group", 128 * 1024);
*/ CacheManager.initializeCache("group member", 32 * 1024);
String GROUP_MEMBER_CACHE_NAME = "groupMember"; groupCache = CacheManager.getCache("group");
groupMemberCache = CacheManager.getCache("group member");
// Load a group provider.
String className = JiveGlobals.getXMLProperty("group.provider.className",
"org.jivesoftware.messenger.group.DbGroupProvider");
try {
Class c = ClassUtils.forName(className);
provider = (GroupProvider)c.newInstance();
}
catch (Exception e) {
Log.error("Error loading group provider: " + className, e);
provider = new DbGroupProvider();
}
}
/** /**
* Factory method for creating a new Group. A unique name is the only required field. * Factory method for creating a new Group. A unique name is the only required field.
...@@ -45,48 +63,77 @@ public interface GroupManager { ...@@ -45,48 +63,77 @@ public interface GroupManager {
* @return a new Group. * @return a new Group.
* @throws GroupAlreadyExistsException if the group name already exists in the system. * @throws GroupAlreadyExistsException if the group name already exists in the system.
*/ */
Group createGroup(String name) public Group createGroup(String name) throws GroupAlreadyExistsException {
throws UnauthorizedException, GroupAlreadyExistsException; synchronized (name.intern()) {
Group newGroup = null;
try {
getGroup(name);
// The group already exists since now exception, so:
throw new GroupAlreadyExistsException();
}
catch (GroupNotFoundException unfe) {
// The group doesn't already exist so we can create a new group
newGroup = provider.createGroup(name);
groupCache.put(name, newGroup);
}
return newGroup;
}
}
/** /**
* Gets a Group by ID. * Returns a Group by name.
*
* @param groupID The ID of the group to retrieve
* @return The group corresponding to the given ID
* @throws GroupNotFoundException if the group does not exist.
*/
Group getGroup(long groupID) throws GroupNotFoundException;
/**
* Gets a Group by name.
* *
* @param name The name of the group to retrieve * @param name The name of the group to retrieve
* @return The group corresponding to that name * @return The group corresponding to that name
* @throws GroupNotFoundException if the group does not exist. * @throws GroupNotFoundException if the group does not exist.
*/ */
Group getGroup(String name) throws GroupNotFoundException; public Group getGroup(String name) throws GroupNotFoundException {
Group group = (Group)groupCache.get(name);
// If ID wan't found in cache, load it up and put it there.
if (group == null) {
group = provider.getGroup(name);
groupCache.put(name, group);
}
return group;
}
/** /**
* Deletes a group from the system. * Deletes a group from the system.
* *
* @param group the group to delete. * @param group the group to delete.
* @throws UnauthorizedException if not a system administrator.
*/ */
void deleteGroup(Group group) throws UnauthorizedException; public void deleteGroup(Group group) {
// Make a copy of the group members.
Collection<String> members = new ArrayList<String>(group.getMembers());
// Delete the group.
provider.deleteGroup(group.getName());
// Expire all relevant caches.
groupCache.remove(group.getName());
// Remove entries in the group membership cache for all members of the group.
for (String username : members) {
groupMemberCache.remove("userGroups-" + username);
}
}
/** /**
* Returns the total number of groups in the system. * Returns the total number of groups in the system.
* *
* @return the total number of groups. * @return the total number of groups.
*/ */
int getGroupCount(); public int getGroupCount() {
return provider.getGroupCount();
}
/** /**
* Returns an iterator for all groups in the system. * Returns an unmodifiable Collection of all groups in the system.
* *
* @return an Iterator for all groups. * @return an unmodifiable Collection of all groups.
*/ */
public Iterator getGroups(); public Collection<Group> getGroups() {
return provider.getGroups();
}
/** /**
* Returns an iterator for all groups according to a filter. * Returns an iterator for all groups according to a filter.
...@@ -98,10 +145,13 @@ public interface GroupManager { ...@@ -98,10 +145,13 @@ public interface GroupManager {
* numResults if numResults is greater than the number of records left in * numResults if numResults is greater than the number of records left in
* the system to display. * the system to display.
* *
* @param filter the filter to restrict results with * @param startIndex start index in results.
* @param numResults number of results to return.
* @return an Iterator for all groups in the specified range. * @return an Iterator for all groups in the specified range.
*/ */
public Iterator getGroups(BasicResultFilter filter); public Collection<Group> getGroups(int startIndex, int numResults) {
return provider.getGroups(startIndex, numResults);
}
/** /**
* Returns an iterator for all groups that a user is a member of. * Returns an iterator for all groups that a user is a member of.
...@@ -109,5 +159,7 @@ public interface GroupManager { ...@@ -109,5 +159,7 @@ public interface GroupManager {
* @param user the user to get a list of groups for. * @param user the user to get a list of groups for.
* @return all groups that a user belongs to. * @return all groups that a user belongs to.
*/ */
public Iterator getGroups(User user); public Collection<Group> getGroups(User user) {
return provider.getGroups(user);
}
} }
\ No newline at end of file
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* a copy of which is included in this distribution. * a copy of which is included in this distribution.
*/ */
package org.jivesoftware.messenger.auth; package org.jivesoftware.messenger.group;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter; import java.io.PrintWriter;
......
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.group;
import org.jivesoftware.messenger.user.User;
import java.util.Collection;
import java.util.Date;
/**
* Group providers load and store group information from a back-end store
* such as a database table, LDAP, etc.
*
* @author Matt Tucker
*/
public interface GroupProvider {
/**
* Creates a group with the given name (optional operation).<p>
*
* The provider is responsible for setting the creation date and
* modification date to the current date/time.
*
* @param name name of the group.
* @return the newly created group.
* @throws GroupAlreadyExistsException if a group with the same name already
* exists.
* @throws UnsupportedOperationException if the provider does not
* support the operation.
*/
Group createGroup(String name) throws UnsupportedOperationException,
GroupAlreadyExistsException;
/**
* Deletes the group (optional operation).
*
* @param name the name of the group to delete
* @throws UnsupportedOperationException if the provider does not
* support the operation.
*/
void deleteGroup(String name) throws UnsupportedOperationException;
/**
* Returns a group based on it's name.
*
* @param name the name of the group.
* @return the group with the given name.
* @throws GroupNotFoundException If no group with that ID could be found
*/
Group getGroup(String name) throws GroupNotFoundException;
/**
* Sets the name of a group to a new name.
*
* @param oldName the current name of the group.
* @param newName the desired new name of the group.
* @throws GroupAlreadyExistsException if a group with the same name already
* exists.
* @throws UnsupportedOperationException if the provider does not
* support the operation.
*/
public void setGroupName(String oldName, String newName) throws UnsupportedOperationException,
GroupAlreadyExistsException;
/**
* Updates the backend storage with the group's information.
*
* @param name the group name.
* @param description the group description.
* @param creationDate the date the group was created.
* @param modificationDate the date the group was last modified.
* @throws GroupNotFoundException if no existing group could be found to update.
*/
void updateGroup(String name, String description, Date creationDate, Date modificationDate)
throws GroupNotFoundException;
/**
* Returns the number of groups in the system.
*
* @return the number of groups in the system.
*/
int getGroupCount();
/**
* Returns the Collection of all groups in the system.
*
* @return the Collection of all groups.
*/
Collection<Group> getGroups();
/**
* Returns the Collection of all groups in the system.
*
* @param startIndex start index in results.
* @param numResults number of results to return.
* @return the Collection of all groups given the <tt>startIndex</tt> and <tt>numResults</tt>.
*/
Collection<Group> getGroups(int startIndex, int numResults);
/**
* Returns the Collection of Groups that a user belongs to.
*
* @param user the user.
* @return the Collection of groups that the user belongs to.
*/
Collection<Group> getGroups(User user);
/**
* Adds a user to a group (optional operation).
*
* @param groupName the group to add the member to
* @param username the username to add
* @param administrator True if the member is an administrator of the group
* @throws UnsupportedOperationException if the provider does not
* support the operation.
*/
void addMember(String groupName, String username, boolean administrator)
throws UnsupportedOperationException;
/**
* Deletes a user from a group (optional operation).
*
* @param groupName the group name.
* @param username the username.
* @throws UnsupportedOperationException if the provider does not
* support the operation.
*/
void deleteMember(String groupName, String username) throws UnsupportedOperationException;
}
\ No newline at end of file
...@@ -36,34 +36,15 @@ public class SessionManagerImpl extends BasicModule implements SessionManager, ...@@ -36,34 +36,15 @@ public class SessionManagerImpl extends BasicModule implements SessionManager,
ConnectionCloseListener ConnectionCloseListener
{ {
/**
* Total number of sessions being managed
*/
private int sessionCount = 0; private int sessionCount = 0;
public XMPPServer server; public XMPPServer server;
/**
* Packet deliverer
*/
public PacketRouter router; public PacketRouter router;
/**
* Packet router
*/
public PacketTransporter transporter; public PacketTransporter transporter;
/**
* Name of the local server
*/
private String serverName; private String serverName;
private XMPPAddress serverAddress; private XMPPAddress serverAddress;
public UserManager userManager; public UserManager userManager;
/**
* Sets the conflict limit of the server.
*/
private int conflictLimit; private int conflictLimit;
/**
* Random resource name generation
*/
private Random randomResource = new Random(); private Random randomResource = new Random();
public SessionManagerImpl() { public SessionManagerImpl() {
...@@ -458,20 +439,18 @@ public class SessionManagerImpl extends BasicModule implements SessionManager, ...@@ -458,20 +439,18 @@ public class SessionManagerImpl extends BasicModule implements SessionManager,
return session; return session;
} }
public Iterator getSessions() throws UnauthorizedException { public Collection<Session> getSessions() {
LinkedList allSessions = new LinkedList(); List<Session> allSessions = new ArrayList<Session>();
copyUserSessions(allSessions); copyUserSessions(allSessions);
copyAnonSessions(allSessions); copyAnonSessions(allSessions);
return allSessions.iterator(); return allSessions;
} }
public Iterator getSessions(SessionResultFilter filter) throws UnauthorizedException { public Collection<Session> getSessions(SessionResultFilter filter) {
Iterator resultIterator = null; List<Session> results = new ArrayList<Session>();
if (filter != null) { if (filter != null) {
// Grab all the possible matching sessions by user // Grab all the possible matching sessions by user
LinkedList results = new LinkedList();
if (filter.getUsername() == null) { if (filter.getUsername() == null) {
// No user id filtering // No user id filtering
copyAnonSessions(results); copyAnonSessions(results);
...@@ -479,7 +458,8 @@ public class SessionManagerImpl extends BasicModule implements SessionManager, ...@@ -479,7 +458,8 @@ public class SessionManagerImpl extends BasicModule implements SessionManager,
} }
else { else {
try { try {
copyUserSessions(userManager.getUser(filter.getUsername()).getUsername(), results); copyUserSessions(userManager.getUser(filter.getUsername()).getUsername(),
results);
} }
catch (UserNotFoundException e) { catch (UserNotFoundException e) {
} }
...@@ -490,20 +470,11 @@ public class SessionManagerImpl extends BasicModule implements SessionManager, ...@@ -490,20 +470,11 @@ public class SessionManagerImpl extends BasicModule implements SessionManager,
Date activityMin = filter.getLastActivityDateRangeMin(); Date activityMin = filter.getLastActivityDateRangeMin();
Date activityMax = filter.getLastActivityDateRangeMax(); Date activityMax = filter.getLastActivityDateRangeMax();
// Stores the sorted results of the filtering
// We defer sorting until we have the final list
// I'm not sure if this is faster than just dumping everything into
// the sorted tree set from the beginning...
TreeSet sortedResults = new TreeSet(filter.getSortComparator());
// Now we have a copy of the references so we can spend some time // Now we have a copy of the references so we can spend some time
// doing the rest of the filtering without locking out session access // doing the rest of the filtering without locking out session access
// so let's iterate and filter each session one by one // so let's iterate and filter each session one by one
List<Session> filteredResults = new ArrayList<Session>();
// Should this checking be done in the session class instead? for (Session session : results) {
Iterator resultIter = results.iterator();
while (resultIter.hasNext()) {
Session session = (Session)resultIter.next();
// Now filter on creation date if needed // Now filter on creation date if needed
if (createMin != null || createMax != null) { if (createMin != null || createMax != null) {
if (!isBetweenDates(session.getCreationDate(), createMin, createMax)) { if (!isBetweenDates(session.getCreationDate(), createMin, createMax)) {
...@@ -531,28 +502,32 @@ public class SessionManagerImpl extends BasicModule implements SessionManager, ...@@ -531,28 +502,32 @@ public class SessionManagerImpl extends BasicModule implements SessionManager,
} }
} }
if (session != null) { if (session != null) {
sortedResults.add(session); filteredResults.add(session);
} }
} }
// Sort list.
Collections.sort(filteredResults, filter.getSortComparator());
int maxResults = filter.getNumResults(); int maxResults = filter.getNumResults();
if (maxResults == SessionResultFilter.NO_RESULT_LIMIT) { if (maxResults == SessionResultFilter.NO_RESULT_LIMIT) {
maxResults = sortedResults.size(); maxResults = filteredResults.size();
} }
// Now generate the final list. I believe it's faster to to build up a new // Now generate the final list. I believe it's faster to to build up a new
// list than it is to remove items from head and tail of the sorted tree // list than it is to remove items from head and tail of the sorted tree
LinkedList finalResults = new LinkedList(); List<Session> finalResults = new ArrayList<Session>();
Iterator sortedIter = sortedResults.iterator();
int startIndex = filter.getStartIndex(); int startIndex = filter.getStartIndex();
Iterator<Session> sortedIter = filteredResults.iterator();
for (int i = 0; sortedIter.hasNext() && finalResults.size() < maxResults; i++) { for (int i = 0; sortedIter.hasNext() && finalResults.size() < maxResults; i++) {
Object result = sortedIter.next(); Session result = sortedIter.next();
if (i >= startIndex) { if (i >= startIndex) {
finalResults.add(result); finalResults.add(result);
} }
} }
resultIterator = finalResults.iterator(); return finalResults;
} }
return resultIterator; return results;
} }
/** /**
...@@ -653,7 +628,7 @@ public class SessionManagerImpl extends BasicModule implements SessionManager, ...@@ -653,7 +628,7 @@ public class SessionManagerImpl extends BasicModule implements SessionManager,
} }
} }
public Iterator getAnonymousSessions() throws UnauthorizedException { public Iterator getAnonymousSessions() {
return Arrays.asList(anonymousSessions.values().toArray()).iterator(); return Arrays.asList(anonymousSessions.values().toArray()).iterator();
} }
...@@ -961,9 +936,7 @@ public class SessionManagerImpl extends BasicModule implements SessionManager, ...@@ -961,9 +936,7 @@ public class SessionManagerImpl extends BasicModule implements SessionManager,
sendServerMessage(null, LocaleUtils.getLocalizedString("admin.shutdown.now")); sendServerMessage(null, LocaleUtils.getLocalizedString("admin.shutdown.now"));
super.stop(); super.stop();
try { try {
Iterator sIter = this.getSessions(); for (Session session : getSessions()) {
while (sIter.hasNext()) {
Session session = (Session)sIter.next();
try { try {
session.getConnection().close(); session.getConnection().close();
} }
......
...@@ -70,31 +70,16 @@ public class SessionManagerProxy implements SessionManager { ...@@ -70,31 +70,16 @@ public class SessionManagerProxy implements SessionManager {
} }
} }
public Iterator getSessions() throws UnauthorizedException { public Collection<Session> getSessions() {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN | Permissions.USER_ADMIN)) { return sessionManager.getSessions();
return sessionManager.getSessions();
}
else {
throw new UnauthorizedException();
}
} }
public Iterator getSessions(SessionResultFilter filter) throws UnauthorizedException { public Collection<Session> getSessions(SessionResultFilter filter) {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN | Permissions.USER_ADMIN)) { return sessionManager.getSessions(filter);
return sessionManager.getSessions(filter);
}
else {
throw new UnauthorizedException();
}
} }
public Iterator getAnonymousSessions() throws UnauthorizedException { public Iterator getAnonymousSessions() {
if (permissions.hasPermission(Permissions.SYSTEM_ADMIN | Permissions.USER_ADMIN)) { return sessionManager.getAnonymousSessions();
return sessionManager.getAnonymousSessions();
}
else {
throw new UnauthorizedException();
}
} }
public Collection<Session> getSessions(String username) throws UnauthorizedException { public Collection<Session> getSessions(String username) throws UnauthorizedException {
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
package org.jivesoftware.messenger.user; package org.jivesoftware.messenger.user;
import org.jivesoftware.messenger.auth.AuthToken; import org.jivesoftware.messenger.auth.AuthToken;
import org.jivesoftware.messenger.auth.Group;
import org.jivesoftware.messenger.auth.Permissions; import org.jivesoftware.messenger.auth.Permissions;
import org.jivesoftware.messenger.auth.UnauthorizedException; import org.jivesoftware.messenger.auth.UnauthorizedException;
import java.util.Iterator; import java.util.Iterator;
...@@ -25,8 +24,6 @@ import java.util.Iterator; ...@@ -25,8 +24,6 @@ import java.util.Iterator;
* <p>Security for User objects is provide by UserProxy protection proxy objects.</p> * <p>Security for User objects is provide by UserProxy protection proxy objects.</p>
* *
* @author Iain Shigeoka * @author Iain Shigeoka
*
* @see Group
*/ */
public interface User { public interface User {
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
package org.jivesoftware.messenger.user; package org.jivesoftware.messenger.user;
import org.jivesoftware.messenger.auth.Group;
import org.jivesoftware.messenger.auth.UnauthorizedException; import org.jivesoftware.messenger.auth.UnauthorizedException;
import org.jivesoftware.util.Cacheable; import org.jivesoftware.util.Cacheable;
...@@ -29,7 +28,6 @@ import java.util.Date; ...@@ -29,7 +28,6 @@ import java.util.Date;
* <p>Security for UserInfo objects is provide by UserInfoProxy protection proxy objects.</p> * <p>Security for UserInfo objects is provide by UserInfoProxy protection proxy objects.</p>
* *
* @author Iain Shigeoka * @author Iain Shigeoka
* @see Group
*/ */
public interface UserInfo extends Cacheable { public interface UserInfo extends Cacheable {
......
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.user.spi;
import org.jivesoftware.util.JiveConstants;
import org.jivesoftware.util.ProxyFactory;
import org.jivesoftware.messenger.auth.AuthToken;
import org.jivesoftware.messenger.auth.Group;
import org.jivesoftware.messenger.auth.Permissions;
import org.jivesoftware.messenger.auth.spi.GroupProxy;
import org.jivesoftware.messenger.user.User;
import java.util.Iterator;
/**
* Protection proxy for Iterators of users and groups. The class is also smart enough to skip
* over elements in the Iterator that the user doesn't have permission to read.
*
* @author Iain Shigeoka
*/
public class UserGroupIteratorProxy implements Iterator {
private Iterator iterator;
private Object nextElement = null;
private AuthToken auth;
private Permissions permissions;
private ProxyFactory proxyFactory;
/**
* Creates a new iterator proxy.
*
* @param type the type of object to be proxied. Must be a valid value from JiveConstants.
* @param iterator the Iterator to create proxies for.
* @param auth the authorization token.
* @param permissions the permissions that the new proxy will inherit.
*/
public UserGroupIteratorProxy(int type, Iterator iterator, AuthToken auth,
Permissions permissions) {
this.iterator = iterator;
this.auth = auth;
this.permissions = permissions;
// Load the appropriate proxy factory depending on the type of object that we're iterating
// through. Each proxy factory is responsible for checking that the user has permission to
// view the object, and then wrapping it with an appropriate proxy.
switch (type) {
// USER
case JiveConstants.USER:
// Create a class that wraps users with proxies.
proxyFactory = new ProxyFactory() {
public Object createProxy(Object obj, AuthToken auth, Permissions perms) {
User user = (User)obj;
Permissions userPerms = user.getPermissions(auth);
Permissions newPerms = new Permissions(perms, userPerms);
return new UserProxy(user, auth, newPerms);
}
};
break;
// GROUP
case JiveConstants.GROUP:
// Create a class that wraps groups with proxies.
proxyFactory = new ProxyFactory() {
public Object createProxy(Object obj, AuthToken auth, Permissions perms) {
Group group = (Group)obj;
Permissions groupPerms = group.getPermissions(auth);
Permissions newPerms = new Permissions(perms, groupPerms);
return new GroupProxy(group, auth, newPerms);
}
};
break;
// Otherwise, an invalid value was passed in so throw an exception.
default:
throw new IllegalArgumentException();
}
}
/**
* Returns true if there are more elements in the iteration.
*
* @return true if the iterator has more elements.
*/
public boolean hasNext() {
// If we are at the end of the list, there can't be any more elements to iterate through.
if (!iterator.hasNext() && nextElement == null) {
return false;
}
// Otherwise, see if nextElement is null. If so, try to load the next element to make sure
// it exists.
if (nextElement == null) {
nextElement = getNextElement();
if (nextElement == null) {
return false;
}
}
return true;
}
/**
* Returns the next element.
*
* @return the next element.
* @throws java.util.NoSuchElementException
* if there are no more elements.
*/
public Object next() throws java.util.NoSuchElementException {
Object element = null;
if (nextElement != null) {
element = nextElement;
nextElement = null;
}
else {
element = getNextElement();
if (element == null) {
throw new java.util.NoSuchElementException();
}
}
return element;
}
/**
* Not supported for security reasons.
*/
public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* Returns the next available element, or null if there are no more elements.
*
* @return the next available element.
*/
public Object getNextElement() {
while (iterator.hasNext()) {
Object element = proxyFactory.createProxy(iterator.next(), auth, permissions);
if (element != null) {
return element;
}
}
return null;
}
}
...@@ -71,13 +71,11 @@ public class UserManagerProxy implements UserManager { ...@@ -71,13 +71,11 @@ public class UserManagerProxy implements UserManager {
} }
public Iterator users() throws UnauthorizedException { public Iterator users() throws UnauthorizedException {
Iterator iterator = userManager.users(); return userManager.users();
return new UserGroupIteratorProxy(JiveConstants.USER, iterator, auth, permissions);
} }
public Iterator users(int startIndex, int numResults) throws UnauthorizedException { public Iterator users(int startIndex, int numResults) throws UnauthorizedException {
Iterator iterator = userManager.users(startIndex, numResults); return userManager.users(startIndex, numResults);
return new UserGroupIteratorProxy(JiveConstants.USER, iterator, auth, permissions);
} }
public String getName() { public String getName() {
......
...@@ -16,9 +16,6 @@ package org.jivesoftware.util; ...@@ -16,9 +16,6 @@ package org.jivesoftware.util;
*/ */
public class JiveConstants { public class JiveConstants {
public static final int USER = 3;
public static final int GROUP = 4;
public static final int SYSTEM = 17; public static final int SYSTEM = 17;
public static final int ROSTER = 18; public static final int ROSTER = 18;
public static final int OFFLINE = 19; public static final int OFFLINE = 19;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
--%> --%>
<%@ page import="org.jivesoftware.util.*, <%@ page import="org.jivesoftware.util.*,
java.util.Iterator, java.util.*,
org.jivesoftware.messenger.*, org.jivesoftware.messenger.*,
java.util.Date, java.util.Date,
org.jivesoftware.admin.*, org.jivesoftware.admin.*,
...@@ -129,8 +129,8 @@ Below is a list of sessions on this server. ...@@ -129,8 +129,8 @@ Below is a list of sessions on this server.
SessionResultFilter filter = new SessionResultFilter(); SessionResultFilter filter = new SessionResultFilter();
filter.setStartIndex(start); filter.setStartIndex(start);
filter.setNumResults(range); filter.setNumResults(range);
Iterator sessions = sessionManager.getSessions(filter); Collection<Session> sessions = sessionManager.getSessions(filter);
if (!sessions.hasNext()) { if (sessions.isEmpty()) {
%> %>
<tr> <tr>
<td colspan="8"> <td colspan="8">
...@@ -145,8 +145,7 @@ Below is a list of sessions on this server. ...@@ -145,8 +145,7 @@ Below is a list of sessions on this server.
<% int count = start; <% int count = start;
boolean current = false; // needed in session-row.jspf boolean current = false; // needed in session-row.jspf
String linkURL = "session-details.jsp"; String linkURL = "session-details.jsp";
while (sessions.hasNext()) { for (Session sess : sessions) {
Session sess = (Session)sessions.next();
count++; count++;
%> %>
<%@ include file="session-row.jspf" %> <%@ include file="session-row.jspf" %>
......
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