/*
* Copyright (c) Members of the EGEE Collaboration. 2006-2010.
* See http://www.eu-egee.org/partners/ for details on the copyright holders.
*
* 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.glite.authz.pep.obligation.dfpmap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import javax.security.auth.x500.X500Principal;
import org.glite.authz.common.fqan.FQAN;
import org.glite.authz.pep.obligation.ObligationProcessingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** A strategy for mapping a subject's primary and secondary FQANs to primary and secondary groups. */
public class FQANGroupNameMappingStrategy implements GroupNameMappingStrategy {
/** Class logger. */
private final Logger log = LoggerFactory.getLogger(FQANGroupNameMappingStrategy.class);
/** DN/FQAN to POSIX group name mappings. */
private DFPM groupNameMapping;
/** Strategy to see if a {@link DFPM} key matches a given {@link FQAN}. */
private DFPMMatchStrategy<FQAN> fqanMatchStrategy;
/**
* Constructor.
*
* @param mappings DN/FQAN to POSIX group name mappings, may not be null
* @param fqanMatching strategy to see if a {@link DFPM} key matches a given {@link FQAN}, may not be null
*/
public FQANGroupNameMappingStrategy(DFPM mappings, DFPMMatchStrategy<FQAN> fqanMatching) {
if (mappings == null) {
throw new IllegalArgumentException("DN/FQAN to POSIX mapping may not be null");
}
groupNameMapping = mappings;
if (fqanMatching == null) {
throw new IllegalArgumentException("FQAN matching strategy may not be null");
}
fqanMatchStrategy = fqanMatching;
}
/** {@inheritDoc} */
public List<String> mapToGroupNames(X500Principal subjectDN, FQAN primaryFQAN, List<FQAN> secondaryFQANs)
throws ObligationProcessingException {
log.debug("Starting to map subject {} with primary FQAN {} and second FQANs {} to group names", new Object[] {
subjectDN.getName(X500Principal.RFC2253), primaryFQAN, secondaryFQANs });
if(primaryFQAN == null){
log.error("Primary FQAN for subject " + subjectDN.getName() + " is null, group mapping can not be performed");
throw new ObligationProcessingException("Primary FQAN is null, group mapping can not be performed");
}
ArrayList<String> groups = new ArrayList<String>();
String firstGroupFromFQAN = null;
for (String mapKey : groupNameMapping.keySet()) {
if (groupNameMapping.isFQANMapEntry(mapKey)) {
if (firstGroupFromFQAN == null && fqanMatchStrategy.isMatch(mapKey, primaryFQAN)) {
firstGroupFromFQAN = groupNameMapping.get(mapKey).get(0);
}
if (secondaryFQANs != null) {
for (FQAN secondaryFQAN : secondaryFQANs) {
if (fqanMatchStrategy.isMatch(mapKey, secondaryFQAN)) {
groups.addAll(groupNameMapping.get(mapKey));
}
}
}
}
}
if (firstGroupFromFQAN == null) {
throw new ObligationProcessingException("Subject " + subjectDN.getName(X500Principal.RFC2253)
+ " could not be mapped to a primary group");
}
groups.add(0, firstGroupFromFQAN);
removeDuplicates(groups);
log.debug("Subject {} with primary FQAN {} and second FQANs {} mapped to group names {}",
new Object[] { subjectDN.getName(X500Principal.RFC2253), primaryFQAN, secondaryFQANs, groups });
return groups;
}
/**
* Removes duplicates names from the list. The first occurrence is retained.
*
* @param groupNames list of names from which duplicates should be removed.
*/
private void removeDuplicates(List<String> groupNames) {
HashSet<String> alreadySeen = new HashSet<String>();
String name;
Iterator<String> nameItr = groupNames.iterator();
while (nameItr.hasNext()) {
name = nameItr.next();
if (alreadySeen.contains(name)) {
nameItr.remove();
} else {
alreadySeen.add(name);
}
}
}
}