/*
* 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.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 DN and primary FQAN to an account indicator. */
public class DNPrimaryFQANAccountIndicatorMappingStrategy implements AccountIndicatorMappingStrategy {
/** Class logger. */
private final Logger log = LoggerFactory.getLogger(DNPrimaryFQANAccountIndicatorMappingStrategy.class);
/** DN/FQAN to POSIX account name indicator mappings. */
private DFPM loginNameMapping;
/** Strategy to see if a {@link DFPM} key matches a given {@link X500Principal}. */
private DFPMMatchStrategy<X500Principal> dnMatchStrategy;
/** Strategy to see if a {@link DFPM} key matches a given {@link FQAN}. */
private DFPMMatchStrategy<FQAN> fqanMatchStrategy;
/** Whether to prefer a DN based mapping for the account indicator. */
private boolean preferDNforAccountIndicator;
/**
* Constructor.
*
* @param accountMappings DN/FQAN to POSIX account name indicator mappings, may not be null
* @param dnMatching strategy to see if a {@link DFPM} key matches a given {@link X500Principal}, may not be null
* @param fqanMatching strategy to see if a {@link DFPM} key matches a given {@link FQAN}, may not be null
* @param preferDNmappings whether to prefer a DN based mapping, over an FQAN based mapping, for the account
* indicator
*/
public DNPrimaryFQANAccountIndicatorMappingStrategy(DFPM accountMappings,
DFPMMatchStrategy<X500Principal> dnMatching, DFPMMatchStrategy<FQAN> fqanMatching, boolean preferDNmappings) {
if (accountMappings == null) {
throw new IllegalArgumentException("DN/FQAN to POSIX account mapping may not be null");
}
loginNameMapping = accountMappings;
if (dnMatching == null) {
throw new IllegalArgumentException("DN matching strategy may not be null");
}
dnMatchStrategy = dnMatching;
if (fqanMatching == null) {
throw new IllegalArgumentException("FQAN matching strategy may not be null");
}
fqanMatchStrategy = fqanMatching;
preferDNforAccountIndicator = preferDNmappings;
}
/** {@inheritDoc} */
public String mapToAccountIndicator(X500Principal subjectDN, FQAN primaryFQAN, List<FQAN> secondaryFQANs)
throws ObligationProcessingException {
log.debug("Mapping account indicator for subject {} with primary FQAN {}", subjectDN, primaryFQAN);
String indicatorFromDN = null;
String indicatorFromFQAN = null;
// Loop over the entries in the login name map file
// if the map key is meant to match a DN check it against the subject DN
// if the map key is meant to match a FQAN check it against the primary FQAN
// we keep track of both the first match against the DN and primary FQAN so that if whichever
// the preferred account indicator does not match any entry we don't have to go loop through
// the list again to see if the other indicator matches
for (String mapKey : loginNameMapping.keySet()) {
if (indicatorFromDN == null && loginNameMapping.isDNMapEntry(mapKey)
&& dnMatchStrategy.isMatch(mapKey, subjectDN)) {
indicatorFromDN = loginNameMapping.get(mapKey).get(0);
if (preferDNforAccountIndicator) {
break;
}
}
if (primaryFQAN != null && indicatorFromFQAN == null && loginNameMapping.isFQANMapEntry(mapKey)
&& fqanMatchStrategy.isMatch(mapKey, primaryFQAN)) {
indicatorFromFQAN = loginNameMapping.get(mapKey).get(0);
if (!preferDNforAccountIndicator) {
break;
}
}
}
// If we get to this point then our preferred account indicator did not yield a match
// so we return the second choice, which may be null if that didn't match either
String accountIndicator;
if (preferDNforAccountIndicator) {
accountIndicator = (indicatorFromDN != null) ? indicatorFromDN : indicatorFromFQAN;
} else {
accountIndicator = (indicatorFromFQAN != null) ? indicatorFromFQAN : indicatorFromDN;
}
log.debug("Subject {} with primary FQAN {} mapped to account indicator {}",
new Object[] { subjectDN, primaryFQAN, accountIndicator });
return accountIndicator;
}
}