org.wso2.carbon.identity.entitlement.pip.CarbonAttributeFinder.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.identity.entitlement.pip.CarbonAttributeFinder.java

Source

/*
*  Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. licenses this file to you 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.wso2.carbon.identity.entitlement.pip;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.balana.ParsingException;
import org.wso2.balana.attr.AttributeValue;
import org.wso2.balana.attr.BagAttribute;
import org.wso2.balana.cond.EvaluationResult;
import org.wso2.balana.ctx.EvaluationCtx;
import org.wso2.balana.ctx.Status;
import org.wso2.balana.finder.AttributeFinderModule;
import org.wso2.carbon.identity.entitlement.EntitlementUtil;
import org.wso2.carbon.identity.entitlement.PDPConstants;
import org.wso2.carbon.identity.entitlement.cache.PIPAttributeCache;
import org.wso2.carbon.identity.entitlement.internal.EntitlementServiceComponent;
import org.wso2.carbon.identity.entitlement.pdp.EntitlementEngine;

import javax.xml.transform.TransformerException;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * CarbonAttributeFinder registers with sun-xacml engine as an AttributeFinderModule and delegate
 * functionality to the attribute handlers registered with it self.
 * <p/>
 * Whenever the XACML engine finds a missing attribute in the XACML request - it will call the
 * findAttribute() method of this class.
 */
public class CarbonAttributeFinder extends AttributeFinderModule {

    private Map<String, List<PIPAttributeFinder>> attrFinders = new HashMap<String, List<PIPAttributeFinder>>();
    private static Log log = LogFactory.getLog(CarbonAttributeFinder.class);
    private PIPAttributeCache attributeFinderCache = null;
    protected int tenantId;

    public CarbonAttributeFinder(int tenantId) {
        this.tenantId = tenantId;
    }

    /**
     * Registers PIP attribute handlers with the PDP against their supported attributes. This PIP
     * attribute handlers are picked from pip-config.xml file - which should be inside
     * [CARBON_HOME]\repository\conf.
     */
    public void init() {
        Map<PIPAttributeFinder, Properties> designators = EntitlementServiceComponent.getEntitlementConfig()
                .getDesignators();
        Properties properties = EntitlementServiceComponent.getEntitlementConfig().getEngineProperties();
        if ("true".equals(properties.getProperty(PDPConstants.ATTRIBUTE_CACHING))) {
            int attributeCachingInterval = -1;
            String cacheInterval = properties.getProperty(PDPConstants.ATTRIBUTE_CACHING_INTERVAL);
            if (cacheInterval != null) {
                try {
                    attributeCachingInterval = Integer.parseInt(cacheInterval.trim());
                } catch (Exception e) {
                    //ignore
                }
            }
            attributeFinderCache = new PIPAttributeCache(attributeCachingInterval);
        }
        // clear decision cache
        if (designators != null && !designators.isEmpty()) {
            Set<PIPAttributeFinder> pipAttributeFinders = designators.keySet();
            for (Iterator iterator = pipAttributeFinders.iterator(); iterator.hasNext();) {
                PIPAttributeFinder pipAttributeFinder = (PIPAttributeFinder) iterator.next();
                Set<String> attrs = pipAttributeFinder.getSupportedAttributes();
                if (attrs != null) {
                    for (Iterator attrsIter = attrs.iterator(); attrsIter.hasNext();) {
                        String attr = (String) attrsIter.next();
                        if (attrFinders.containsKey(attr)) {
                            List<PIPAttributeFinder> finders = attrFinders.get(attr);
                            if (!finders.contains(pipAttributeFinder)) {
                                finders.add(pipAttributeFinder);
                                if (log.isDebugEnabled()) {
                                    log.debug(String.format(
                                            "PIP attribute handler %1$s registered for the "
                                                    + "supported attribute %2$s",
                                            pipAttributeFinder.getClass(), attr));
                                }
                            }
                        } else {
                            List<PIPAttributeFinder> finders = new ArrayList<PIPAttributeFinder>();
                            finders.add(pipAttributeFinder);
                            attrFinders.put(attr, finders);
                            if (log.isDebugEnabled()) {
                                log.debug(String.format("PIP attribute handler %1$s registered for the supported "
                                        + "attribute %2$s", pipAttributeFinder.getClass(), attr));
                            }
                        }
                    }
                }
            }
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.wso2.balana.finder.AttributeFinderModule#findAttribute(java.net.URI, java.net.URI,
     * java.net.URI, java.net.URI, org.wso2.balana.EvaluationCtx, int)
     */
    public EvaluationResult findAttribute(URI attributeType, URI attributeId, String issuer, URI category,
            EvaluationCtx context) {

        List<AttributeValue> attrBag = new ArrayList<AttributeValue>();
        // Get the list of attribute finders who are registered with this particular attribute.
        List<PIPAttributeFinder> finders = attrFinders.get(attributeId.toString());

        if (finders == null || finders.size() == 0) {
            finders = attrFinders.get(attributeId.toString());
            if (finders == null || finders.size() == 0) {
                if (log.isDebugEnabled()) {
                    log.debug("No attribute designators defined for the attribute " + attributeId.toString());
                }
                return new EvaluationResult(BagAttribute.createEmptyBag(attributeType));

            }
        }

        try {

            for (Iterator iterator = finders.iterator(); iterator.hasNext();) {
                PIPAttributeFinder pipAttributeFinder = (PIPAttributeFinder) iterator.next();
                if (log.isDebugEnabled()) {
                    log.debug(String.format("Finding attributes with the PIP attribute handler %1$s",
                            pipAttributeFinder.getClass()));
                }

                Set<String> attrs = null;
                String key = null;

                if (attributeFinderCache != null && !pipAttributeFinder.overrideDefaultCache()) {

                    key = attributeType.toString() + attributeId.toString() + category.toString()
                            + encodeContext(context);

                    if (issuer != null) {
                        key += issuer;
                    }

                    if (key != null) {
                        attrs = attributeFinderCache.getFromCache(tenantId, key);
                    }
                }

                if (attrs == null) {
                    attrs = pipAttributeFinder.getAttributeValues(attributeType, attributeId, category, issuer,
                            context);
                    if (attributeFinderCache != null && key != null && !pipAttributeFinder.overrideDefaultCache()) {
                        attributeFinderCache.addToCache(tenantId, key, attrs);
                    }
                }

                if (attrs != null) {
                    for (Iterator iterAttr = attrs.iterator(); iterAttr.hasNext();) {
                        final String attr = (String) iterAttr.next();
                        AttributeValue attribute = EntitlementUtil.getAttributeValue(attr,
                                attributeType.toString());
                        attrBag.add(attribute);
                    }
                }
            }
        } catch (ParsingException e) {
            log.error("Error while parsing attribute values from EvaluationCtx : " + e);
            ArrayList<String> code = new ArrayList<String>();
            code.add(Status.STATUS_MISSING_ATTRIBUTE);
            Status status = new Status(code,
                    "Error while parsing attribute values from EvaluationCtx : " + e.getMessage());
            return new EvaluationResult(status);
        } catch (ParseException e) {
            e.printStackTrace();
            log.error("Error while parsing attribute values from EvaluationCtx : " + e);
            ArrayList<String> code = new ArrayList<String>();
            code.add(Status.STATUS_MISSING_ATTRIBUTE);
            Status status = new Status(code,
                    "Error while parsing attribute values from EvaluationCtx : " + e.getMessage());
            return new EvaluationResult(status);
        } catch (URISyntaxException e) {
            log.error("Error while parsing attribute values from EvaluationCtx : " + e);
            ArrayList<String> code = new ArrayList<String>();
            code.add(Status.STATUS_MISSING_ATTRIBUTE);
            Status status = new Status(code,
                    "Error while parsing attribute values from EvaluationCtx :" + e.getMessage());
            return new EvaluationResult(status);
        } catch (Exception e) {
            log.error("Error while retrieving attribute values from PIP  attribute finder : " + e);
            ArrayList<String> code = new ArrayList<String>();
            code.add(Status.STATUS_MISSING_ATTRIBUTE);
            Status status = new Status(code,
                    "Error while retrieving attribute values from PIP" + " attribute finder : " + e.getMessage());
            return new EvaluationResult(status);
        }
        return new EvaluationResult(new BagAttribute(attributeType, attrBag));
    }

    /*
     * (non-Javadoc)
     *
     * @see org.wso2.balana.finder.AttributeFinderModule#isDesignatorSupported()
     */
    public boolean isDesignatorSupported() {
        return true;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.wso2.balana.finder.AttributeFinderModule#getSupportedIds()
     */
    public Set getSupportedIds() {
        return null;
    }

    /**
     * Registers PIP attribute handlers are initialized when the server is start-up. This method can
     * be used to refresh all attribute finders internally. refreshSupportedAttribute() method must be
     * implemented within the PIP attribute finder to perform this operation. Also this uses to find newly
     * defined attributes, attribute caches are would not be cleared.
     *
     * @throws Exception throws then initialization of attribute finders are failed
     */
    private void refreshAttributeFindersForNewAttributeId() throws Exception {
        Map<PIPAttributeFinder, Properties> designators = EntitlementServiceComponent.getEntitlementConfig()
                .getDesignators();
        if (designators != null && !designators.isEmpty()) {
            Set<Map.Entry<PIPAttributeFinder, Properties>> attributeFinders = designators.entrySet();
            for (Map.Entry<PIPAttributeFinder, Properties> attributeFinder : attributeFinders) {
                attributeFinder.getKey().init(attributeFinder.getValue());
            }
            init();
        }
    }

    /**
     * Clears attribute cache
     */
    public void clearAttributeCache() {
        if (attributeFinderCache != null) {
            attributeFinderCache.clearCache();
            // clear decision cache
            EntitlementEngine.getInstance().clearDecisionCache();
        }
    }

    /**
     * Converts DOM object to String. This is a helper method for creating cache key
     *
     * @param evaluationCtx EvaluationCtx
     * @return String Object
     * @throws TransformerException Exception throws if fails
     */
    private String encodeContext(EvaluationCtx evaluationCtx) throws TransformerException {
        OutputStream stream = new ByteArrayOutputStream();
        evaluationCtx.getRequestCtx().encode(stream);
        return stream.toString();
    }
}