/*
* Atricore IDBus
*
* Copyright (c) 2009, Atricore Inc.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.atricore.idbus.kernel.main.federation.metadata;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.atricore.idbus.kernel.main.mediation.channel.FederationChannel;
import org.atricore.idbus.kernel.main.mediation.claim.ClaimChannel;
import org.atricore.idbus.kernel.main.mediation.provider.*;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
*
*
* @author <a href="mailto:sgonzalez@atricore.org">Sebastian Gonzalez Oyuela</a>
* @version $Id: CircleOfTrustManagerImpl.java 1359 2009-07-19 16:57:57Z sgonzalez $
*/
public class CircleOfTrustManagerImpl implements CircleOfTrustManager, InitializingBean, DisposableBean {
private static final Log logger = LogFactory.getLog(CircleOfTrustManagerImpl.class);
private CircleOfTrust cot;
private Map<String, MetadataDefinition> definitions = new ConcurrentHashMap<String, MetadataDefinition>();
boolean init = false;
public CircleOfTrust getCot() {
return cot;
}
public void setCot(CircleOfTrust cot) {
this.cot = cot;
}
public void afterPropertiesSet() throws Exception {
// Nothing to do ..
}
public void init() throws CircleOfTrustManagerException {
if (init)
return;
synchronized (this) {
if (init)
return;
logger.info("Initializing Circle Of Trust (COT) " + cot.getName());
try {
for (FederatedProvider provider : cot.getProviders()) {
for (CircleOfTrustMemberDescriptor member : provider.getAllMembers()) {
if (logger.isDebugEnabled())
logger.debug("Initializing Provider Member information " + provider.getName() + ", member " + member.getAlias());
registerMember(member);
}
if (provider instanceof AbstractFederatedProvider) {
AbstractFederatedProvider localProvider = (AbstractFederatedProvider) provider;
localProvider.setCircleOfTrust(cot);
if (localProvider.getChannel() != null && localProvider.getChannel().getClaimProviders() != null) {
// Sort claim providers, the collection MUST be a list ....
if (logger.isTraceEnabled())
logger.trace("Sorting Claims providers ");
Collections.sort((List<ClaimChannel>) localProvider.getChannel().getClaimProviders(), new ClaimChannelPriorityComparator());
if (logger.isTraceEnabled()) {
int order = 0;
for (ClaimChannel c : localProvider.getChannel().getClaimProviders()) {
logger.trace("claim channel priority [" + order + "] for " + c.getName());
order ++;
}
}
}
} else {
logger.debug("Unknown provider type " + provider + ", cannot inject COT");
}
}
init = true;
logger.info("Initializing COT " + cot.getName() + " OK");
} catch (Exception e) {
logger.error("Initializing COT Manager : " + e.getMessage());
throw new CircleOfTrustManagerException(e);
}
}
}
protected void registerMember(CircleOfTrustMemberDescriptor member) throws CircleOfTrustManagerException {
if (logger.isDebugEnabled())
logger.debug("Registering COT Member descriptor " + member);
MetadataDefinition def = null;
// resource-based metadata
if (member instanceof ResourceCircleOfTrustMemberDescriptorImpl) {
// Resolve Metadata Definition
ResourceCircleOfTrustMemberDescriptorImpl m = (ResourceCircleOfTrustMemberDescriptorImpl) member;
if (logger.isDebugEnabled())
logger.debug("Loading resource-based metadata for member " + member.getId() + " [" + member.getAlias() + "]");
if (m.getResource() != null)
def = loadMetadataDefinition(member, m.getResource());
} else { // non-resource-based metadata
if (logger.isDebugEnabled())
logger.debug("Loading non resource-based metadata for member " + member.getId() + " [" + member.getAlias() + "]");
def = loadMetadataDefinition(member);
}
if (def != null) {
MetadataDefinition old = definitions.put(member.getAlias(), def);
MetadataEntry md = findEntityMetadata(member.getAlias());
if (md == null)
logger.warn("No metadata found for COT Member " + member.getAlias());
member.setMetadata(md);
if (old != null)
throw new CircleOfTrustManagerException("Duplicated COT Member descriptor for alias : " +
member.getAlias());
}
}
public void destroy() throws Exception {
}
public void exportCircleOfTrustMetadataDefinition(String memberAlias) {
throw new UnsupportedOperationException("Not implemented");
}
public Collection<CircleOfTrustMemberDescriptor> getMembers() {
List<CircleOfTrustMemberDescriptor> members = new ArrayList<CircleOfTrustMemberDescriptor>();
for (FederatedProvider p : cot.getProviders()) {
members.addAll(p.getAllMembers());
}
return members;
}
/**
* This will look in all registered providers that realize the given role for the channel and targets the source
* provider
* @return the COT Member descriptor for the selected provider
*
*/
public CircleOfTrustMemberDescriptor lookupMemberForProvider(Provider srcProvider, String role) throws CircleOfTrustManagerException {
if (logger.isDebugEnabled())
logger.debug("Looking for COT Member descriptor for source provider " + srcProvider.getName() +
", role " + role);
for (Provider destProvider : cot.getProviders()) {
if (destProvider.getRole().equals(role)) {
if (logger.isDebugEnabled())
logger.debug("Provider " + destProvider .getName() + " has role " + role);
CircleOfTrustMemberDescriptor selectedMember = lookupMemberForProvider(srcProvider, destProvider);
if (selectedMember != null) {
if (logger.isDebugEnabled())
logger.debug("Selected COT Member '" + selectedMember + "' for provider '" + srcProvider.getName() +
"' with role '" + role + "' in COT " + cot.getName());
return selectedMember;
}
}
}
if (logger.isDebugEnabled())
logger.debug("NO COT Member found for provider '" + srcProvider.getName() +
"' with role '" + role + "' in COT " + cot.getName());
return null;
}
/**
* This will look for FederationChannel associated with the source provider, that targets the destination provider and
* return the COT Member descriptor.
*
* @return the COT Member descriptor for the selected provider
*
*/
public CircleOfTrustMemberDescriptor lookupMemberForProvider(Provider srcProvider, Provider destProvider) throws CircleOfTrustManagerException {
CircleOfTrustMemberDescriptor targetingMember = null;
if (destProvider instanceof FederatedLocalProvider) {
FederatedLocalProvider federatedDestProvider = (FederatedLocalProvider) destProvider;
for (FederationChannel channel : federatedDestProvider.getChannels()) {
if (channel.getTargetProvider().equals(srcProvider)) {
targetingMember = channel.getMember();
if (logger.isDebugEnabled())
logger.debug("Selected targeting member : " + targetingMember.getAlias());
}
}
}
if (targetingMember == null) {
logger.debug("No Selected between source " + srcProvider.getName() + " and destination " + destProvider.getName());
}
return targetingMember;
}
public boolean isLocalMember(String alias) throws CircleOfTrustManagerException {
for (FederatedProvider p : cot.getProviders()) {
for (CircleOfTrustMemberDescriptor m : p.getAllMembers()) {
if (m.getAlias().equals(alias)) {
return !(p instanceof FederatedRemoteProvider);
}
}
}
throw new CircleOfTrustManagerException("Unknown entity " + alias);
}
/**
* @param role the role realized by the provider, it's protocol specific: i.e. saml 2.0 sp
*/
public Collection<CircleOfTrustMemberDescriptor> lookupMembersForProvider(Provider provider, String role)
throws CircleOfTrustManagerException {
Set<CircleOfTrustMemberDescriptor> members = new HashSet<CircleOfTrustMemberDescriptor>();
for (Provider targetProvider : cot.getProviders()) {
if (!targetProvider.getRole().equals(role))
continue;
if (logger.isDebugEnabled())
logger.debug("Provider " + targetProvider .getName() + " has role " + role);
// See if this local provider can be used with our provider
if (targetProvider instanceof FederatedLocalProvider) {
// The target provider must trust the received provider
FederatedLocalProvider localTargetProvider = (FederatedLocalProvider) targetProvider;
// First, got through non-default (override) channels:
boolean useOverrideChannel = false;
for (FederationChannel channel : localTargetProvider.getChannels()) {
// The received provider is the target of the the specific channel
if (channel.getTargetProvider().equals(provider)) {
useOverrideChannel = true;
members.add(channel.getMember());
if (logger.isDebugEnabled())
logger.debug("Selected targeting member : " + channel.getMember().getAlias());
}
}
// Use the default channel
if (!useOverrideChannel) {
// Only add it if the provider trust us
for (Provider trusted : localTargetProvider.getChannel().getTrustedProviders()) {
if (trusted.getName().equals(provider.getName()))
members.add(localTargetProvider.getChannel().getMember());
}
}
} else {
FederatedRemoteProvider remoteTargetProvider = (FederatedRemoteProvider) targetProvider;
for(CircleOfTrustMemberDescriptor m : remoteTargetProvider.getAllMembers()) {
if (logger.isDebugEnabled())
logger.debug("Selected member : " + m.getAlias());
// Only add it if we trust this provider:
if (provider instanceof FederatedLocalProvider) {
FederatedLocalProvider localProvider = (FederatedLocalProvider) provider;
for (Provider trusted: localProvider.getChannel().getTrustedProviders()) {
if (trusted.getName().equals(remoteTargetProvider.getName()))
members.add(m);
}
for (FederationChannel channel : localProvider.getChannels()) {
for (Provider trusted : channel.getTrustedProviders()) {
if (trusted.getName().equals(remoteTargetProvider.getName()))
members.add(m);
}
}
} else {
// This is not wright
logger.error("Connecting to non-local providers may produce unexpected results");
members.add(m);
}
}
}
}
if (logger.isDebugEnabled())
logger.debug("Found " + members.size() + " members for " + provider.getName() + " with role " + role);
return members;
}
public CircleOfTrustMemberDescriptor lookupMemberByAlias(String alias) {
for (FederatedProvider provider : cot.getProviders()) {
for (CircleOfTrustMemberDescriptor member : provider.getAllMembers()) {
if (member.getAlias().equals(alias)) {
if (logger.isDebugEnabled())
logger.debug("Specific COT Member found for " + alias + " in provider " + provider.getName());
return member;
}
}
}
if (logger.isDebugEnabled())
logger.debug("No COT Member registered with alias " + alias);
// Not found !?
return null;
}
public CircleOfTrustMemberDescriptor lookupMemberById(String id) {
for (FederatedProvider provider : cot.getProviders()) {
for (CircleOfTrustMemberDescriptor member : provider.getAllMembers()) {
if (member.getId().equals(id)) {
if (logger.isDebugEnabled())
logger.debug("Specific COT Member found for " + id + " in provider " + provider.getName());
return member;
}
}
}
if (logger.isDebugEnabled())
logger.debug("No COT Member registered with ID " + id);
// Not found !?
return null;
}
public FederatedProvider lookupFederatedProviderByAlias(String alias) {
for (FederatedProvider provider : cot.getProviders()) {
for (CircleOfTrustMemberDescriptor member : provider.getAllMembers()) {
if (member.getAlias().equals(alias)) {
if (logger.isDebugEnabled())
logger.debug("Specific Provider found for " + alias + " in provider " + provider.getName());
return provider;
}
}
}
if (logger.isDebugEnabled())
logger.debug("No Provider registered with alias " + alias);
// Not found !?
return null;
}
/**
* The member alias must match a MD Definition ID.
*/
public MetadataEntry findEntityMetadata(String memberAlias) throws CircleOfTrustManagerException {
if (memberAlias == null)
throw new NullPointerException("Member Alias cannot be null");
CircleOfTrustMemberDescriptor member = lookupMemberByAlias(memberAlias);
if (member == null) {
throw new CircleOfTrustManagerException("Entity ID is not a COT member alias : " + memberAlias + " in COT " + cot.getName());
}
MetadataDefinition md = definitions.get(member.getAlias());
return this.searchEntityDefinition(member, md, memberAlias);
}
public MetadataEntry findEntityRoleMetadata(String memberAlias, String entityRole) throws CircleOfTrustManagerException {
if (memberAlias == null)
throw new NullPointerException("Member Alias cannot be null");
if (entityRole == null)
throw new NullPointerException("Entity Role cannot be null");
CircleOfTrustMemberDescriptor member = lookupMemberByAlias(memberAlias);
if (member == null) {
throw new CircleOfTrustManagerException("Entity ID is not a COT member alias : " + memberAlias + " in COT " + cot.getName());
}
MetadataDefinition md = definitions.get(member.getAlias());
if (md == null) {
logger.debug("Entity Role metadata not found for '" + memberAlias + "', role '"+entityRole+"'");
return null;
}
return this.searchEntityRoleDefinition(member, md, memberAlias, entityRole);
}
public MetadataEntry findEndpointMetadata(String memberAlias, String entityRole, EndpointDescriptor endpoint) throws CircleOfTrustManagerException {
if (memberAlias == null)
throw new NullPointerException("Member Alias cannot be null");
if (entityRole == null)
throw new NullPointerException("Entity Role cannot be null");
if (endpoint == null)
throw new NullPointerException("IdentityMediationEndpoint cannot be null");
CircleOfTrustMemberDescriptor member = lookupMemberByAlias(memberAlias);
if (member == null) {
throw new CircleOfTrustManagerException("Entity ID is not a COT member alias : " + memberAlias + " in COT " + cot.getName());
}
MetadataDefinition md = definitions.get(member.getAlias());
if (md == null) {
logger.debug("Identity Mediation Endpoint metadata not found for '" + memberAlias +
"', role '" + entityRole +
"', endpoint='" + endpoint + "'");
return null;
}
return this.searchEndpointDescriptor(member, md, memberAlias, entityRole, endpoint);
}
public Collection<MetadataEntry> findEndpointsMetadata(String memberAlias, String entityRole, EndpointDescriptor endpoint) throws CircleOfTrustManagerException {
if (memberAlias == null)
throw new NullPointerException("Member Alias cannot be null");
if (entityRole == null)
throw new NullPointerException("Entity Role cannot be null");
if (endpoint == null)
throw new NullPointerException("IdentityMediationEndpoint cannot be null");
CircleOfTrustMemberDescriptor member = lookupMemberByAlias(memberAlias);
if (member == null) {
throw new CircleOfTrustManagerException("Entity ID is not a COT member alias : " + memberAlias + " in COT " + cot.getName());
}
MetadataDefinition md = definitions.get(member.getAlias());
if (md == null) {
logger.debug("Endpoints metadata not found for '" + memberAlias +
"', role '" + entityRole +
"', endpoint '" + endpoint + "'");
return null;
}
return this.searchEndpointDescriptors(member, md, memberAlias, entityRole, endpoint);
}
protected MetadataDefinition loadMetadataDefinition(CircleOfTrustMemberDescriptor member)
throws CircleOfTrustManagerException {
if (member.getMetadataIntrospector() != null)
return member.getMetadataIntrospector().load(member);
return null;
}
protected MetadataDefinition loadMetadataDefinition(CircleOfTrustMemberDescriptor member,
Resource resource)
throws CircleOfTrustManagerException {
return member.getMetadataIntrospector().load(member, resource);
}
protected MetadataEntry searchEntityDefinition(CircleOfTrustMemberDescriptor member,
MetadataDefinition metadataDefinition,
String memberAlias)
throws CircleOfTrustManagerException {
return member.getMetadataIntrospector().searchEntityDefinition(metadataDefinition, memberAlias);
}
protected MetadataEntry searchEntityRoleDefinition(CircleOfTrustMemberDescriptor member,
MetadataDefinition metadataDefinition,
String memberAlias,
String roleType)
throws CircleOfTrustManagerException {
return member.getMetadataIntrospector().searchEntityRoleDefinition(metadataDefinition, memberAlias, roleType);
}
protected MetadataEntry searchEndpointDescriptor(CircleOfTrustMemberDescriptor member,
MetadataDefinition metadataDefinition,
String memberAlias,
String roleType,
EndpointDescriptor endpoint)
throws CircleOfTrustManagerException {
return member.getMetadataIntrospector().searchEndpointDescriptor(
metadataDefinition,
memberAlias,
roleType,
endpoint);
}
protected Collection<MetadataEntry> searchEndpointDescriptors(CircleOfTrustMemberDescriptor member,
MetadataDefinition metadataDefinition,
String memberAlias,
String roleType,
EndpointDescriptor endpoint)
throws CircleOfTrustManagerException {
return member.getMetadataIntrospector().searchEndpointDescriptors(
metadataDefinition,
memberAlias,
roleType,
endpoint);
}
protected class ClaimChannelPriorityComparator implements Comparator<ClaimChannel> {
public int compare(ClaimChannel o1, ClaimChannel o2) {
return o1.getPriority() - o2.getPriority();
}
}
}