Author: berndf Date: Tue Jun 20 01:40:03 2006 New Revision: 415565 URL: http://svn.apache.org/viewvc?rev=415565&view=rev Log: - added UserManagement JMX MBean - TODOs: merge common code from RemoteManagerHandler; allow change of repositories
Added: james/server/trunk/src/java/org/apache/james/management/ james/server/trunk/src/java/org/apache/james/management/UserManagement.java james/server/trunk/src/java/org/apache/james/management/UserManagement.xinfo james/server/trunk/src/java/org/apache/james/management/UserManagementException.java james/server/trunk/src/java/org/apache/james/management/UserManagementMBean.java james/server/trunk/src/test/org/apache/james/management/ james/server/trunk/src/test/org/apache/james/management/UserManagementTest.java Modified: james/server/trunk/src/conf/james-assembly.xml james/server/trunk/src/java/org/apache/james/JamesMBean.java Modified: james/server/trunk/src/conf/james-assembly.xml URL: http://svn.apache.org/viewvc/james/server/trunk/src/conf/james-assembly.xml?rev=415565&r1=415564&r2=415565&view=diff ============================================================================== --- james/server/trunk/src/conf/james-assembly.xml (original) +++ james/server/trunk/src/conf/james-assembly.xml Tue Jun 20 01:40:03 2006 @@ -67,6 +67,11 @@ role="org.apache.avalon.cornerstone.services.threads.ThreadManager" /> </block> + <!-- The User Management block --> + <block name="usermanagement" class="org.apache.james.management.UserManagement" > + <provide name="localusersrepository" role="org.apache.james.services.UsersRepository"/> + </block> + <!-- POP3 Server --> <block name="pop3server" class="org.apache.james.pop3server.POP3Server" > <provide name="localusersrepository" role="org.apache.james.services.UsersRepository"/> Modified: james/server/trunk/src/java/org/apache/james/JamesMBean.java URL: http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/JamesMBean.java?rev=415565&r1=415564&r2=415565&view=diff ============================================================================== --- james/server/trunk/src/java/org/apache/james/JamesMBean.java (original) +++ james/server/trunk/src/java/org/apache/james/JamesMBean.java Tue Jun 20 01:40:03 2006 @@ -21,6 +21,7 @@ * An interface to expose James management functionality through JMX. At * the time of this writing, this interface is just an example. * + * @deprecated this MBean will be replaced by UserManagementMBean * @phoenix:mx-topic name="MainJAMESServerManagement" */ public interface JamesMBean { @@ -28,6 +29,8 @@ /** * Adds a user to this mail server. * + * @deprecated moved to UserManagementMBean + * * @phoenix:mx-operation * @phoenix:mx-description Add a new user * Added: james/server/trunk/src/java/org/apache/james/management/UserManagement.java URL: http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/management/UserManagement.java?rev=415565&view=auto ============================================================================== --- james/server/trunk/src/java/org/apache/james/management/UserManagement.java (added) +++ james/server/trunk/src/java/org/apache/james/management/UserManagement.java Tue Jun 20 01:40:03 2006 @@ -0,0 +1,152 @@ +/*********************************************************************** + * Copyright (c) 2006 The Apache Software Foundation. * + * All rights reserved. * + * ------------------------------------------------------------------- * + * Licensed under the Apache License, Version 2.0 (the "License"); you * + * may not use this file except in compliance with the License. You * + * may obtain a copy of the License at: * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * + * implied. See the License for the specific language governing * + * permissions and limitations under the License. * + ***********************************************************************/ + + +package org.apache.james.management; + +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.service.Serviceable; +import org.apache.james.services.UsersRepository; +import org.apache.james.services.User; +import org.apache.james.services.JamesUser; +import org.apache.mailet.MailAddress; + +import javax.mail.internet.ParseException; +import java.util.Iterator; +import java.util.ArrayList; +import java.util.List; + +public class UserManagement implements UserManagementMBean, Serviceable { + + /** + * The administered UsersRepository + */ + private UsersRepository users; + + /** + * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager) + */ + public void service( final ServiceManager componentManager ) + throws ServiceException { + users = (UsersRepository) componentManager.lookup(UsersRepository.ROLE); + if (users == null) { + throw new ServiceException("","The user repository could not be found."); + } + } + + private JamesUser getJamesUser(String userName) throws UserManagementException { + User baseuser = users.getUserByName(userName); + if (baseuser == null) throw new UserManagementException("user not found: " + userName); + if (! (baseuser instanceof JamesUser ) ) throw new UserManagementException("user is not of type JamesUser: " + userName); + + return (JamesUser) baseuser; + } + + public boolean addUser(String userName, String password) { + return users.addUser(userName, password); + } + + public boolean deleteUser(String userName) { + if (!users.contains(userName)) return false; + users.removeUser(userName); + return true; + } + + public boolean verifyExists(String userName) { + return users.contains(userName); + } + + public long countUsers() { + return users.countUsers(); + } + + public String[] listAllUsers() { + List userNames = new ArrayList(); + for (Iterator it = users.list(); it.hasNext();) { + userNames.add(it.next()); + } + return (String[])userNames.toArray(new String[]{}); + } + + public boolean setPassword(String userName, String password) throws UserManagementException { + User user = users.getUserByName(userName); + if (user == null) throw new UserManagementException("user not found: " + userName); + return user.setPassword(password); + } + + public boolean setAlias(String userName, String aliasUserName) throws UserManagementException { + JamesUser user = getJamesUser(userName); + JamesUser aliasUser = getJamesUser(aliasUserName); + if (aliasUser == null) return false; + + boolean success = user.setAlias(aliasUserName); + user.setAliasing(true); + users.updateUser(user); + return success; + } + + public boolean unsetAlias(String userName) throws UserManagementException { + JamesUser user = getJamesUser(userName); + if (!user.getAliasing()) return false; + + user.setAliasing(false); + users.updateUser(user); + return true; + } + + public String getAlias(String userName) throws UserManagementException { + JamesUser user = getJamesUser(userName); + if (!user.getAliasing()) return null; + return user.getAlias(); + } + + public boolean setForwardAddress(String userName, String forwardEmailAddress) throws UserManagementException { + MailAddress forwardAddress; + try { + forwardAddress = new MailAddress(forwardEmailAddress); + } catch(ParseException pe) { + throw new UserManagementException(pe); + } + + JamesUser user = getJamesUser(userName); + boolean success = user.setForwardingDestination(forwardAddress); + if (!success) return false; + + user.setForwarding(true); + users.updateUser(user); + return true; + } + + public boolean unsetForwardAddress(String userName) throws UserManagementException { + JamesUser user = getJamesUser(userName); + + if (!user.getForwarding()) return false; + + user.setForwarding(false); + users.updateUser(user); + return true; + } + + public String getForwardAddress(String userName) throws UserManagementException { + JamesUser user = getJamesUser(userName); + if (!user.getForwarding()) return null; + return user.getForwardingDestination().toString(); + } + + +} Added: james/server/trunk/src/java/org/apache/james/management/UserManagement.xinfo URL: http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/management/UserManagement.xinfo?rev=415565&view=auto ============================================================================== --- james/server/trunk/src/java/org/apache/james/management/UserManagement.xinfo (added) +++ james/server/trunk/src/java/org/apache/james/management/UserManagement.xinfo Tue Jun 20 01:40:03 2006 @@ -0,0 +1,20 @@ +<?xml version="1.0"?> + +<blockinfo> + + <!-- section to describe block --> + <block> + <version>1.0</version> + </block> + + <!-- interfaces that may be exported to manange this block --> + <management-access-points> + <service name="org.apache.james.management.UserManagementMBean"/> + </management-access-points> + + <dependencies> + <dependency> + <service name="org.apache.james.services.UsersRepository" version="1.0"/> + </dependency> + </dependencies> +</blockinfo> Added: james/server/trunk/src/java/org/apache/james/management/UserManagementException.java URL: http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/management/UserManagementException.java?rev=415565&view=auto ============================================================================== --- james/server/trunk/src/java/org/apache/james/management/UserManagementException.java (added) +++ james/server/trunk/src/java/org/apache/james/management/UserManagementException.java Tue Jun 20 01:40:03 2006 @@ -0,0 +1,39 @@ +/*********************************************************************** + * Copyright (c) 2006 The Apache Software Foundation. * + * All rights reserved. * + * ------------------------------------------------------------------- * + * Licensed under the Apache License, Version 2.0 (the "License"); you * + * may not use this file except in compliance with the License. You * + * may obtain a copy of the License at: * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * + * implied. See the License for the specific language governing * + * permissions and limitations under the License. * + ***********************************************************************/ + + +package org.apache.james.management; + +public class UserManagementException extends Exception { + + public UserManagementException() { + super(); + } + + public UserManagementException(String message) { + super(message); + } + + public UserManagementException(Exception e) { + super(e); + } + + public UserManagementException(String message, Exception e) { + super(message, e); + } + +} Added: james/server/trunk/src/java/org/apache/james/management/UserManagementMBean.java URL: http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/management/UserManagementMBean.java?rev=415565&view=auto ============================================================================== --- james/server/trunk/src/java/org/apache/james/management/UserManagementMBean.java (added) +++ james/server/trunk/src/java/org/apache/james/management/UserManagementMBean.java Tue Jun 20 01:40:03 2006 @@ -0,0 +1,159 @@ +/*********************************************************************** + * Copyright (c) 2006 The Apache Software Foundation. * + * All rights reserved. * + * ------------------------------------------------------------------- * + * Licensed under the Apache License, Version 2.0 (the "License"); you * + * may not use this file except in compliance with the License. You * + * may obtain a copy of the License at: * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * + * implied. See the License for the specific language governing * + * permissions and limitations under the License. * + ***********************************************************************/ + +package org.apache.james.management; + +/** + * Expose user account management functionality through JMX. + * + * @phoenix:mx-topic name="UserAdministration" + */ +public interface UserManagementMBean { + + /** + * Adds a user to this mail server. + * + * @phoenix:mx-operation + * @phoenix:mx-description Add a new user + * + * @param userName The name of the user being added + * @param password The password of the user being added + * @return if the operation was successfull + */ + boolean addUser(String userName, String password); + + /** + * Deletes a user from this mail server. + * + * @phoenix:mx-operation + * @phoenix:mx-description Delete an existing user + * + * @param userName The name of the user being deleted + * @return if the operation was successfull + */ + boolean deleteUser(String userName); + + /** + * Check if a user exists with the given name. + * + * @phoenix:mx-operation + * @phoenix:mx-description Check for existing user name + * + * @param userName The name of the user + * @return TRUE, if the user exists + */ + boolean verifyExists(String userName); + + /** + * Total count of existing users + * + * @phoenix:mx-operation + * @phoenix:mx-description Total count of existing users + * + * @return Total count of existing users + */ + long countUsers(); + + /** + * List the names of all users + * + * @phoenix:mx-operation + * @phoenix:mx-description List all existing users + * + * @return List of all user names + */ + String[] listAllUsers(); + + /** + * Set a user's password + * + * @phoenix:mx-operation + * @phoenix:mx-description Set a user's password + * + * @param userName The name of the user whose password will be changed + * @param password The new password + * @return if the user has been found and the password was changed successfully + */ + boolean setPassword(String userName, String password) throws UserManagementException; + + /** + * Set a user's alias to whom all mail is forwarded to + * + * @phoenix:mx-operation + * @phoenix:mx-description Set a user's alias to whom all mail is forwarded to + * + * @param userName The name of the user whose alias is set + * @param aliasUserName The user becoming the new alias + * @return if the user has been found and the password was changed successfully + */ + boolean setAlias(String userName, String aliasUserName) throws UserManagementException; + + /** + * Removes a user's alias which terminates local mail forwarding + * + * @phoenix:mx-operation + * @phoenix:mx-description Removes a user's alias which terminates local mail forwarding + * + * @param userName The name of the user whose alias is unset + * @return if the user has been found and the alias was removed + */ + boolean unsetAlias(String userName) throws UserManagementException; + + /** + * Retrieves the user's alias, if set + * + * @phoenix:mx-operation + * @phoenix:mx-description Retrieves the user's alias, if set + * + * @return User's alias, or NULL, if no alias is set + */ + String getAlias(String userName) throws UserManagementException; + + /** + * Set a user's forward email address to whom all mail is forwarded to + * + * @phoenix:mx-operation + * @phoenix:mx-description Set a user's forward email address to whom all mail is forwarded to + * + * @param userName The name of the user whose forward is set + * @param forwardEmailAddress The new forward email address + * @return if the user has been found and the password was changed successfully + */ + boolean setForwardAddress(String userName, String forwardEmailAddress) throws UserManagementException; + + /** + * Removes a user's forward email address which terminates remote mail forwarding + * + * @phoenix:mx-operation + * @phoenix:mx-description Removes a user's forward email address which terminates remote mail forwarding + * + * @param userName The name of the user whose forward is unset + * @return if the user has been found and the forward was removed + */ + boolean unsetForwardAddress(String userName) throws UserManagementException; + + /** + * Retrieves the user's forward, if set + * + * @phoenix:mx-operation + * @phoenix:mx-description Retrieves the user's forward, if set + * + * @return User's forward email address, or NULL, if no forward is set + */ + String getForwardAddress(String userName) throws UserManagementException; + +} Added: james/server/trunk/src/test/org/apache/james/management/UserManagementTest.java URL: http://svn.apache.org/viewvc/james/server/trunk/src/test/org/apache/james/management/UserManagementTest.java?rev=415565&view=auto ============================================================================== --- james/server/trunk/src/test/org/apache/james/management/UserManagementTest.java (added) +++ james/server/trunk/src/test/org/apache/james/management/UserManagementTest.java Tue Jun 20 01:40:03 2006 @@ -0,0 +1,214 @@ +/*********************************************************************** + * Copyright (c) 2006 The Apache Software Foundation. * + * All rights reserved. * + * ------------------------------------------------------------------- * + * Licensed under the Apache License, Version 2.0 (the "License"); you * + * may not use this file except in compliance with the License. You * + * may obtain a copy of the License at: * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * + * implied. See the License for the specific language governing * + * permissions and limitations under the License. * + ***********************************************************************/ + + +package org.apache.james.management; + +import junit.framework.TestCase; +import org.apache.avalon.framework.container.ContainerUtil; +import org.apache.james.services.UsersRepository; +import org.apache.james.test.mock.avalon.MockLogger; +import org.apache.james.test.mock.avalon.MockServiceManager; +import org.apache.james.userrepository.MockUsersRepository; + +import java.io.IOException; +import java.util.List; +import java.util.Arrays; + +/** + * Tests the UserManagement + */ +public class UserManagementTest extends TestCase { + + private MockUsersRepository m_mockUsersRepository; + private UserManagement m_userManagement; + + protected void setUp() throws Exception { + m_userManagement = new UserManagement(); + ContainerUtil.enableLogging(m_userManagement, new MockLogger()); + ContainerUtil.service(m_userManagement, setUpServiceManager()); + } + + private MockServiceManager setUpServiceManager() { + MockServiceManager serviceManager = new MockServiceManager(); + m_mockUsersRepository = new MockUsersRepository(); + serviceManager.put(UsersRepository.ROLE, m_mockUsersRepository); + return serviceManager; + } + + public void testUserCount() throws IOException { + assertEquals("no user yet", 0, m_userManagement.countUsers()); + m_mockUsersRepository.addUser("testCount1", "testCount"); + assertEquals("1 user", 1, m_userManagement.countUsers()); + m_mockUsersRepository.addUser("testCount2", "testCount"); + assertEquals("2 users", 2, m_userManagement.countUsers()); + m_mockUsersRepository.removeUser("testCount1"); + assertEquals("1 user", 1, m_userManagement.countUsers()); + } + + public void testAddUserAndVerify() throws IOException { + assertTrue("user added", m_mockUsersRepository.addUser("testCount1", "testCount")); + assertFalse("user not there", m_userManagement.verifyExists("testNotAdded")); + assertTrue("user is there", m_userManagement.verifyExists("testCount1")); + m_mockUsersRepository.removeUser("testCount1"); + assertFalse("user not there", m_userManagement.verifyExists("testCount1")); + } + + public void testDelUser() throws IOException { + assertTrue("user added", m_mockUsersRepository.addUser("testDel", "test")); + assertFalse("user not there", m_userManagement.verifyExists("testNotDeletable")); + assertTrue("user is there", m_userManagement.verifyExists("testDel")); + m_mockUsersRepository.removeUser("testDel"); + assertFalse("user no longer there", m_userManagement.verifyExists("testDel")); + } + + public void testListUsers() throws IOException { + + String[] usersArray = new String[] {"ccc", "aaa", "dddd", "bbbbb"}; + List users = Arrays.asList(usersArray); + + for (int i = 0; i < users.size(); i++) { + String user = (String) users.get(i); + assertTrue("user added", m_mockUsersRepository.addUser(user, "test")); + } + + String[] userNames = m_userManagement.listAllUsers(); + assertEquals("user count", users.size(), userNames.length); + + for (int i = 0; i < userNames.length; i++) { + String user = userNames[i]; + if (!users.contains(user)) fail("user not listed"); + } + } + + public void testAlias() throws UserManagementException { + m_mockUsersRepository.setForceUseJamesUser(); + + // do some tests when parameter users don't exist + try { + m_userManagement.setAlias("testNonExist1", "testNonExist2"); + fail("user unknown to server"); + } catch (UserManagementException e) { + // success + } + + assertTrue("user added", m_userManagement.addUser("testAlias1", "test")); + + assertNull("no alias set", m_userManagement.getAlias("testAlias1")); + + try { + m_userManagement.setAlias("testAlias1", "testNonExist2"); + fail("alias unknown to server"); + } catch (UserManagementException e) { + // success + } + + try { + m_userManagement.setAlias("testNonExist1", "testAlias"); + fail("user unknown to server"); + } catch (UserManagementException e) { + // success + } + + assertTrue("user added", m_userManagement.addUser("testAlias2", "test")); + + // regular alias + assertTrue("alias for testAlias1 set to:testAlias2", m_userManagement.setAlias("testAlias1", "testAlias2")); + + //TODO: is this correct? even primitive circular aliasing allowed! + assertTrue("alias for testAlias2 set to:testAlias1", m_userManagement.setAlias("testAlias2", "testAlias1")); + + // did first one persist? + assertEquals("Current alias for testAlias1 is: testAlias2", "testAlias2", m_userManagement.getAlias("testAlias1")); + + //TODO: is this correct? setting self as alias! + assertTrue("alias for testAlias1 set to:testAlias1", m_userManagement.setAlias("testAlias1", "testAlias1")); + + assertTrue("user added", m_userManagement.addUser("testAlias3", "test")); + + // re-set, simply overwrites + assertTrue("alias for testAlias1 set to:testAlias3", m_userManagement.setAlias("testAlias1", "testAlias3")); + + // check overwrite + assertEquals("Current alias for testAlias1 is: testAlias3", "testAlias3", m_userManagement.getAlias("testAlias1")); + + // retreat + assertTrue("alias for testAlias1 unset", m_userManagement.unsetAlias("testAlias1")); + + // check removed alias + //sendCommand("showalias testAlias1"); + assertNull("User testAlias1 does not currently have an alias", m_userManagement.getAlias("testAlias1")); + + } + + public void testForward() throws UserManagementException { + m_mockUsersRepository.setForceUseJamesUser(); + + // do some tests when parameter users don't exist + try { + m_userManagement.setForwardAddress("testNonExist1", "[EMAIL PROTECTED]"); + fail("user unknown to server"); + } catch (UserManagementException e) { + // success + } + + assertTrue("user added", m_userManagement.addUser("testForwardUser", "test")); + + assertNull("no forward set", m_userManagement.getForwardAddress("testForwardUser")); + + assertTrue(m_userManagement.setForwardAddress("testForwardUser", "[EMAIL PROTECTED]")); + + // did it persist? + String forwardAddress = m_userManagement.getForwardAddress("testForwardUser"); + assertEquals("forward for testForwardUser is: [EMAIL PROTECTED]", "[EMAIL PROTECTED]", forwardAddress); + + // re-set, simply overwrites + assertTrue(m_userManagement.setForwardAddress("testForwardUser", "[EMAIL PROTECTED]")); + + // check overwrite + forwardAddress = m_userManagement.getForwardAddress("testForwardUser"); + assertEquals("forward for testForwardUser is: [EMAIL PROTECTED]", "[EMAIL PROTECTED]", forwardAddress); + + // retreat + assertTrue("Forward for testForwardUser unset", m_userManagement.unsetForwardAddress("testForwardUser")); + + // check removed forward + assertNull("no more forward set", m_userManagement.getForwardAddress("testForwardUser")); + + } + + public void testSetPassword() throws IOException, UserManagementException { + + assertTrue("user added", m_userManagement.addUser("testPwdUser", "pwd1")); + + assertTrue("initial password", m_mockUsersRepository.test("testPwdUser", "pwd1")); + + // set empty pwd + assertTrue("changed to empty password", m_userManagement.setPassword("testPwdUser", "")); + assertTrue("password changed to empty", m_mockUsersRepository.test("testPwdUser", "")); + + // change pwd + assertTrue("changed password", m_userManagement.setPassword("testPwdUser", "pwd2")); + assertTrue("password not changed to pwd2", m_mockUsersRepository.test("testPwdUser", "pwd2")); + + // assure case sensitivity + assertTrue("changed password", m_userManagement.setPassword("testPwdUser", "pWD2")); + assertFalse("password no longer pwd2", m_mockUsersRepository.test("testPwdUser", "pwd2")); + assertTrue("password changed to pWD2", m_mockUsersRepository.test("testPwdUser", "pWD2")); + + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]