/* Copyright 2004 Apache Software Foundation
*
* 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.jetspeed.security.impl;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jetspeed.i18n.KeyedMessage;
import org.apache.jetspeed.security.AuthenticationProviderProxy;
import org.apache.jetspeed.security.Group;
import org.apache.jetspeed.security.GroupManager;
import org.apache.jetspeed.security.GroupPrincipal;
import org.apache.jetspeed.security.SecurityException;
import org.apache.jetspeed.security.SecurityProvider;
import org.apache.jetspeed.security.spi.GroupSecurityHandler;
import org.apache.jetspeed.security.spi.SecurityMappingHandler;
import org.apache.jetspeed.util.ArgUtil;
/**
* <p>
* Describes the service interface for managing groups.
* </p>
* <p>
* Group hierarchy elements are being returned as a {@link Group}collection.
* The backing implementation must appropriately map the group hierarchy to a
* preferences sub-tree.
* </p>
* <p>
* The convention {principal}.{subprincipal} has been chosen to name groups
* hierachies. Implementation follow the conventions enforced by the
* {@link Preferences}API.
* </p>
*
* @author <a href="mailto:dlestrat@apache.org">David Le Strat </a>
* @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>
*/
public class GroupManagerImpl implements GroupManager
{
/** The logger. */
private static final Log log = LogFactory.getLog(GroupManagerImpl.class);
/** The authentication provider proxy. */
private AuthenticationProviderProxy atnProviderProxy = null;
/** The group security handler. */
private GroupSecurityHandler groupSecurityHandler = null;
/** The security mapping handler. */
private SecurityMappingHandler securityMappingHandler = null;
/**
* @param securityProvider
* The security provider.
*/
public GroupManagerImpl(SecurityProvider securityProvider)
{
this.atnProviderProxy = securityProvider
.getAuthenticationProviderProxy();
this.groupSecurityHandler = securityProvider.getGroupSecurityHandler();
this.securityMappingHandler = securityProvider
.getSecurityMappingHandler();
}
/**
* @see org.apache.jetspeed.security.GroupManager#addGroup(java.lang.String)
*/
public void addGroup(String groupFullPathName) throws SecurityException
{
ArgUtil.notNull(new Object[]
{ groupFullPathName}, new String[]
{ "groupFullPathName"}, "addGroup(java.lang.String)");
// Check if group already exists.
if (groupExists(groupFullPathName)) {
throw new SecurityException(SecurityException.GROUP_ALREADY_EXISTS.create(groupFullPathName));
}
GroupPrincipal groupPrincipal = new GroupPrincipalImpl(
groupFullPathName);
String fullPath = groupPrincipal.getFullPath();
// Add the preferences.
Preferences preferences = Preferences.userRoot().node(fullPath);
if (log.isDebugEnabled())
{
log.debug("Added group preferences node: " + fullPath);
}
try
{
if ((null != preferences)
&& preferences.absolutePath().equals(fullPath))
{
// Add role principal.
groupSecurityHandler.setGroupPrincipal(groupPrincipal);
if (log.isDebugEnabled())
{
log.debug("Added group: " + fullPath);
}
}
} catch (SecurityException se)
{
String msg = "Unable to create the role.";
log.error(msg, se);
// Remove the preferences node.
try
{
preferences.removeNode();
} catch (BackingStoreException bse)
{
bse.printStackTrace();
}
throw se;
}
}
/**
* @see org.apache.jetspeed.security.GroupManager#removeGroup(java.lang.String)
*/
public void removeGroup(String groupFullPathName) throws SecurityException
{
ArgUtil.notNull(new Object[]
{ groupFullPathName}, new String[]
{ "groupFullPathName"}, "removeGroup(java.lang.String)");
// Resolve the group hierarchy.
Preferences prefs = Preferences.userRoot().node(
GroupPrincipalImpl
.getFullPathFromPrincipalName(groupFullPathName));
String[] groups = securityMappingHandler.getGroupHierarchyResolver()
.resolveChildren(prefs);
for (int i = 0; i < groups.length; i++)
{
try
{
groupSecurityHandler
.removeGroupPrincipal(new GroupPrincipalImpl(
GroupPrincipalImpl
.getPrincipalNameFromFullPath((String) groups[i])));
} catch (SecurityException se)
{
throw se;
} catch (Exception e)
{
KeyedMessage msg =
SecurityException.UNEXPECTED.create("GroupManager.removeGroup",
"GroupSecurityHandler.removeGroupPrincipal("+
GroupPrincipalImpl.getPrincipalNameFromFullPath((String) groups[i])+")",
e.getMessage());
log.error(msg, e);
throw new SecurityException(msg, e);
}
// Remove preferences
Preferences groupPref = Preferences.userRoot().node(
(String) groups[i]);
try
{
groupPref.removeNode();
} catch (BackingStoreException bse)
{
KeyedMessage msg =
SecurityException.UNEXPECTED.create("Preferences.removeNode("+groups[i]+")",
bse.getMessage());
log.error(msg, bse);
throw new SecurityException(msg, bse);
}
}
}
/**
* @see org.apache.jetspeed.security.GroupManager#groupExists(java.lang.String)
*/
public boolean groupExists(String groupFullPathName)
{
ArgUtil.notNull(new Object[]
{ groupFullPathName}, new String[]
{ "groupFullPathName"}, "groupExists(java.lang.String)");
Principal principal = groupSecurityHandler
.getGroupPrincipal(groupFullPathName);
boolean groupExists = (null != principal);
if (log.isDebugEnabled())
{
log.debug("Role exists: " + groupExists);
log.debug("Role: " + groupFullPathName);
}
return groupExists;
}
/**
* @see org.apache.jetspeed.security.GroupManager#getGroup(java.lang.String)
*/
public Group getGroup(String groupFullPathName) throws SecurityException
{
ArgUtil.notNull(new Object[]
{ groupFullPathName}, new String[]
{ "groupFullPathName"}, "getGroup(java.lang.String)");
String fullPath = GroupPrincipalImpl
.getFullPathFromPrincipalName(groupFullPathName);
Principal groupPrincipal = groupSecurityHandler
.getGroupPrincipal(groupFullPathName);
if (null == groupPrincipal) {
throw new SecurityException(
SecurityException.GROUP_DOES_NOT_EXIST.create(groupFullPathName));
}
Preferences preferences = Preferences.userRoot().node(fullPath);
Group group = new GroupImpl(groupPrincipal, preferences);
return group;
}
/**
* @see org.apache.jetspeed.security.GroupManager#getGroupsForUser(java.lang.String)
*/
public Collection getGroupsForUser(String username)
throws SecurityException
{
ArgUtil.notNull(new Object[]
{ username}, new String[]
{ "username"}, "getGroupsForUser(java.lang.String)");
Collection groups = new ArrayList();
Set groupPrincipals = securityMappingHandler
.getGroupPrincipals(username);
Iterator groupPrincipalsIter = groupPrincipals.iterator();
while (groupPrincipalsIter.hasNext())
{
Principal groupPrincipal = (Principal) groupPrincipalsIter.next();
Preferences preferences = Preferences.userRoot().node(
GroupPrincipalImpl
.getFullPathFromPrincipalName(groupPrincipal
.getName()));
groups.add(new GroupImpl(groupPrincipal, preferences));
}
return groups;
}
/**
* @see org.apache.jetspeed.security.GroupManager#getGroupsInRole(java.lang.String)
*/
public Collection getGroupsInRole(String roleFullPathName)
throws SecurityException
{
ArgUtil.notNull(new Object[]
{ roleFullPathName}, new String[]
{ "roleFullPathName"}, "getGroupsInRole(java.lang.String)");
Collection groups = new ArrayList();
Set groupPrincipals = securityMappingHandler
.getGroupPrincipalsInRole(roleFullPathName);
Iterator groupPrincipalsIter = groupPrincipals.iterator();
while (groupPrincipalsIter.hasNext())
{
Principal groupPrincipal = (Principal) groupPrincipalsIter.next();
Preferences preferences = Preferences.userRoot().node(
GroupPrincipalImpl
.getFullPathFromPrincipalName(groupPrincipal
.getName()));
groups.add(new GroupImpl(groupPrincipal, preferences));
}
return groups;
}
/**
* @see org.apache.jetspeed.security.GroupManager#addUserToGroup(java.lang.String,
* java.lang.String)
*/
public void addUserToGroup(String username, String groupFullPathName)
throws SecurityException
{
ArgUtil.notNull(new Object[]
{ username, groupFullPathName}, new String[]
{ "username", "groupFullPathName"},
"addUserToGroup(java.lang.String, java.lang.String)");
// Get the group principal to add to user.
Principal groupPrincipal = groupSecurityHandler
.getGroupPrincipal(groupFullPathName);
if (null == groupPrincipal) {
throw new SecurityException(SecurityException.GROUP_DOES_NOT_EXIST.create(groupFullPathName));
}
// Check that user exists.
Principal userPrincipal = atnProviderProxy.getUserPrincipal(username);
if (null == userPrincipal) {
throw new SecurityException(SecurityException.USER_DOES_NOT_EXIST.create(username));
}
// Get the user groups.
Set groupPrincipals = securityMappingHandler
.getGroupPrincipals(username);
// Add group to user.
if (!groupPrincipals.contains(groupPrincipal))
{
securityMappingHandler.setUserPrincipalInGroup(username,
groupFullPathName);
}
}
/**
* @see org.apache.jetspeed.security.GroupManager#removeUserFromGroup(java.lang.String,
* java.lang.String)
*/
public void removeUserFromGroup(String username, String groupFullPathName)
throws SecurityException
{
ArgUtil.notNull(new Object[]
{ username, groupFullPathName}, new String[]
{ "username", "groupFullPathName"},
"removeUserFromGroup(java.lang.String, java.lang.String)");
// Check that user exists.
Principal userPrincipal = atnProviderProxy.getUserPrincipal(username);
if (null == userPrincipal) {
throw new SecurityException(SecurityException.USER_DOES_NOT_EXIST.create(username));
}
// Get the group principal to remove.
Principal groupPrincipal = groupSecurityHandler
.getGroupPrincipal(groupFullPathName);
if (null != groupPrincipal)
{
securityMappingHandler.removeUserPrincipalInGroup(username,
groupFullPathName);
}
}
/**
* @see org.apache.jetspeed.security.GroupManager#isUserInGroup(java.lang.String,
* java.lang.String)
*/
public boolean isUserInGroup(String username, String groupFullPathName)
throws SecurityException
{
ArgUtil.notNull(new Object[]
{ username, groupFullPathName}, new String[]
{ "username", "groupFullPathName"},
"isUserInGroup(java.lang.String, java.lang.String)");
boolean isUserInGroup = false;
Set groupPrincipals = securityMappingHandler
.getGroupPrincipals(username);
Principal groupPrincipal = new GroupPrincipalImpl(groupFullPathName);
if (groupPrincipals.contains(groupPrincipal))
{
isUserInGroup = true;
}
return isUserInGroup;
}
/**
* @see org.apache.jetspeed.security.GroupManager#getGroups(java.lang.String)
*/
public Iterator getGroups(String filter) throws SecurityException
{
List groups = new LinkedList();
Iterator groupPrincipals = groupSecurityHandler.getGroupPrincipals(filter).iterator();
while (groupPrincipals.hasNext())
{
String groupName = ((Principal) groupPrincipals.next()).getName();
Group group = getGroup(groupName);
groups.add(group);
}
return groups.iterator();
}
}