001/**
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: PolicyEvaluator.java,v 1.19 2010/01/14 23:18:35 dillidorai Exp $
026 *
027 * Portions Copyrighted 2011-2014 ForgeRock AS.
028 */
029package com.sun.identity.policy;
030
031import java.util.Set;
032import java.util.Enumeration;
033import java.util.HashSet;
034import java.util.Map;
035import java.util.HashMap;
036import java.util.Iterator;
037import java.util.Collections;
038import com.iplanet.am.sdk.AMStoreConnection;
039import com.iplanet.am.sdk.AMUser;
040import com.iplanet.am.sdk.AMException;
041import com.iplanet.am.util.Cache;
042import com.iplanet.am.util.SystemProperties;
043import com.sun.identity.shared.debug.Debug;
044import com.sun.identity.shared.stats.Stats;
045import com.iplanet.sso.SSOToken;
046import com.iplanet.sso.SSOTokenListener;
047import com.iplanet.sso.SSOException;
048import com.sun.identity.monitoring.Agent;
049import com.sun.identity.monitoring.SsoServerPolicySvcImpl;
050import com.sun.identity.entitlement.Application;
051import com.sun.identity.entitlement.ApplicationManager;
052import com.sun.identity.entitlement.Entitlement;
053import com.sun.identity.entitlement.EntitlementException;
054import com.sun.identity.entitlement.Evaluator;
055import com.sun.identity.entitlement.PrivilegeManager;
056import com.sun.identity.entitlement.opensso.SubjectUtils;
057import com.sun.identity.monitoring.MonitoringUtil;
058import com.sun.identity.policy.interfaces.Condition;
059import com.sun.identity.policy.interfaces.PolicyListener;
060import com.sun.identity.security.AdminTokenAction;
061import com.sun.identity.sm.AttributeSchema;
062import com.sun.identity.sm.ServiceManager;
063import com.sun.identity.shared.ldap.util.DN;
064import com.sun.identity.sm.DNMapper;
065import java.security.AccessController;
066import java.security.Principal;
067import java.util.List;
068import javax.security.auth.Subject;
069
070import static org.forgerock.openam.utils.CollectionUtils.asSet;
071
072/**
073 * The class <code>PolicyEvaluator</code> evaluates policies
074 * and provides policy decisions.
075 * @supported.api
076 * @deprecated since 12.0.0
077 */
078@Deprecated
079public class PolicyEvaluator {
080
081    /**
082     * Constant used to identity all the resources of a service type. 
083     * The resources include the sub resources of all resource prefixes of 
084     * resource type
085     *
086     * @supported.api
087     */
088    public static final String ALL_RESOURCES 
089            = "---ALL_RESOURCES---";
090
091    public static final String ADVICING_ORGANIZATION 
092            = "AdvicingOrganization";
093
094    /**
095     * Constant used to identity empty resource
096     *
097     * @supported.api
098     */
099    public static final String EMPTY_RESOURCE_NAME = "";
100
101    /**
102     * Constant used for key to pass the requested resource name canonicalized
103     * in the env map, so that Condition(s)/ResponseProvider(s) could use 
104     * the requested resource name, if necessary
105     */
106    public static final String SUN_AM_REQUESTED_RESOURCE 
107            = "sun.am.requestedResource";
108
109    /**
110     * Constant used for key to pass the requested resource name uncanonicalized
111     * in the env map, so that Condition(s)/ResponseProvider(s) could use 
112     * the requested resource name, if necessary
113     */
114    public static final String SUN_AM_ORIGINAL_REQUESTED_RESOURCE 
115            = "sun.am.requestedOriginalResource";
116
117    /**
118     * Constant used for key to pass the requested actions names
119     * in the env map, so that Condition(s)/ResponseProvider(s) could use 
120     *  the requested actions names, if necessary
121     */
122    public static final String SUN_AM_REQUESTED_ACTIONS 
123            = "sun.am.requestedActions";
124
125    /**
126     * Constant used for key to pass the realm DN in the env map, so that Condition(s)
127     * can look up the relevant <code>PolicyConfig</code> config map, if necessary.
128     * <code>LDAPFilterCondition</code> needs to use PolicyConfig config map.
129     */
130    public static final String REALM_DN = "am.policy.realmDN";
131
132    public static final String RESULTS_CACHE_SESSION_CAP 
133            = "com.sun.identity.policy.resultsCacheSessionCap";
134
135    public static int DEFAULT_RESULTS_CACHE_SESSION_CAP = 1000;
136
137    public static int resultsCacheSessionCap = DEFAULT_RESULTS_CACHE_SESSION_CAP;
138
139    public static final String RESULTS_CACHE_RESOURCE_CAP 
140            = "com.sun.identity.policy.resultsCacheResourceCap";
141
142    public static int DEFAULT_RESULTS_CACHE_RESOURCE_CAP = 100;
143
144    public static int resultsCacheResourceCap = DEFAULT_RESULTS_CACHE_RESOURCE_CAP;
145
146    private static final Debug DEBUG = PolicyManager.debug;
147    private static final boolean USE_POLICY_CACHE = true;
148    private static final boolean INCLUDE_SUPER_RESOURCE_POLCIES = true;
149    private static final long DEFAULT_USER_NSROLE_CACHE_TTL = 600000;
150
151    private String orgName;
152    private String realm;
153    private String serviceTypeName;
154    private String applicationName;
155    private ServiceType serviceType;
156    private PolicyCache policyCache;
157    private PolicyManager policyManager;
158    private ResourceIndexManager resourceIndexManager;
159
160    private HashMap booleanActionNameTrueValues; //cache
161    private HashMap booleanActionNameFalseValues; //cache
162    private Set actionNames; //all action names valid for the serviceType
163    private Set orgNames = new HashSet(); // to pass org name in envParameters
164    // used to pass service type name in envParameters
165    private Set serviceTypeNames = new HashSet(); 
166    // listener for policy decision cache
167    private PolicyDecisionCacheListener listener = null; 
168
169    /*
170     * Cache to keep the policy evaluation results
171     * Cache structure layout:
172     * 
173     * cache ----> Servicename1
174     *       ----> servicename2
175     *        ...  
176     *       ----> servicenameN
177     *
178     * servicenameI ----> Resourcename1
179     *              ----> Resourcename2
180     *              ...
181     *              ----> ResourcenameN
182     *
183     * resourcenameI ----> userssotokenidstring1
184     *               ----> userssotokenidstring2
185     *               ...
186     *               ----> userssotokenidstringN
187     *
188     * userssotokenidstringI ----> requestscope1
189     *                       ----> requestscope2
190     *
191     * requestscope1 ----> resourceresult1
192     * requestscope2 ----> resourceresult2
193     */
194    static Map policyResultsCache = new HashMap();
195
196    /*
197     * The sso token listener registry for policy decision cache. 
198     * To avoid adding multiple sso token listeners for the same 
199     * token, we use this registry to make sure the listener is 
200     * registered only once for each token. It will be unregistered 
201     * if token is expired. 
202     *
203     * Key is tokenId and value is policySSOTokenListener
204     * ssoTokenIDString : PolicySSOTokenListener
205     *
206     * Used to clean up cache on ssoToken notifications
207     */
208    public static Map ssoListenerRegistry =
209              Collections.synchronizedMap(new HashMap());
210
211    /*
212     * The policy change listener registry for policy decision cache.
213     * To avoid adding multiple listeners for the same service, we 
214     * use this registry to make sure the listener is registered only 
215     * once for each service. 
216     *
217     * Key is serviceTypeName and value is <code>PolicyDecisionCacheListener
218     * </code>
219     * serviceTypeName : PolicyDecisionCacheListener for service type
220     *
221     * Used to clean up the decision cache on policy change notification
222     */
223    private static Map<String, PolicyDecisionCacheListener> policyListenerRegistry =
224              Collections.synchronizedMap(new HashMap<String, PolicyDecisionCacheListener>());
225
226    /**
227     * The user <code>nsRole</code> attribute cache.
228     * AMSDK cache stops caching a user's nsRole attribute in 6.2
229     * due to notification issue. Adding this cache in policy to 
230     * avoid performance impact caused by the AMSDK change. This 
231     * cache uses a user's token as the key to map to the user's
232     * <code>nsRole</code> attribute values.
233     *
234     * Key is tokenId and value is set of role DN(s)
235     * ssoTokenIDString : set of role DN(s)
236     */
237    static Map userNSRoleCache = 
238              Collections.synchronizedMap(new HashMap());
239
240    // TTL value for entries in the user's nsRole attribute values.
241    private static long userNSRoleCacheTTL = 0;
242
243    /**
244     * listener object to be used in cleaning up the
245     * userNSRoleCache, subjectEvaluationCache , user role
246     * cache in LDAPRoles and policyResultsCache 
247     * upon user token  expiration.
248     */
249    public static SSOTokenListener ssoListener = 
250                                 new PolicySSOTokenListener(); 
251               
252    /*
253     * Cache for sub resources keyed by resource name 
254     * The structure is a Map of
255     * serviceType(String) : resourceNamesCache(Cache)
256     * Key for resourceNamesCache is a root resource name and value is
257     * a <code>Set</code> of sub resource names for the root resource name
258     *
259     * serviceType: resourceName : resourceNames
260     */
261    private static Map resourceNamesMap = new HashMap(); 
262
263    /**
264     * Constant key for passing organization name in the environment map during
265     * policy evaluation. The value for the key would be a <code>Set</code> 
266     * with one element of type String. The string is the name of the 
267     * organization the policy evaluator has been instantiated for.
268     */
269     static final String ORGANIZATION_NAME = "organizationName";
270
271    /**
272     * Constant key for passing service type name in the environment map during
273     * policy evaluation. The value for the key would be a <code>Set</code> 
274     * with one element of type String. The string is the name of the 
275     * <code>ServiceType</code> the  policy evaluator has been instantiated for.
276     */
277     static final String SERVICE_TYPE_NAME = "serviceTypeName";
278
279     static final Object lock = new Object();
280
281    /**
282     * Constructor to create a <code>PolicyEvaluator</code> given the <code>
283     * ServiceType</code> name.
284     *
285     * @param serviceTypeName the name of the <code>ServiceType</code> for 
286     * which this evaluator can be used.
287     * @throws SSOException if <code>SSOToken</code> used by
288     *                      <code>PolicyEvaluator</code> is invalid
289     * @throws NameNotFoundException if the service with name 
290     *                      <code>serviceTypeName</code> is not found
291     * @throws PolicyException for any other abnormal condition
292     *
293     * @supported.api
294     */
295    public PolicyEvaluator(String serviceTypeName)
296        throws SSOException, NameNotFoundException, PolicyException {
297
298        this("", serviceTypeName);
299
300        registerListener();
301    }
302
303    /**
304     * Constructor to create a <code>PolicyEvaluator</code> given organization
305     * name and the <code>ServiceType</code> name.
306     *
307     * @param orgName the name of the organization under which the evaluation
308     * is being done
309     * @param serviceTypeName the name of the <code>ServiceType</code> for 
310     * which this evaluator can be used.
311     */
312    public PolicyEvaluator(String orgName, String serviceTypeName)
313            throws SSOException, PolicyException, NameNotFoundException {
314
315        if ( (orgName == null) || (orgName.equals("/"))
316                    || (orgName.length() == 0) ) {
317            orgName = ServiceManager.getBaseDN();
318        } else {
319            orgName = com.sun.identity.sm.DNMapper.orgNameToDN(orgName);
320        }
321        this.orgName = orgName;
322
323        this.realm = com.sun.identity.sm.DNMapper.orgNameToRealmName(orgName);
324        this.serviceTypeName = serviceTypeName;
325        // Default application to be the service type, this maintains legacy behaviour.
326        this.applicationName = serviceTypeName;
327
328        this.policyCache = PolicyCache.getInstance();
329
330        ServiceTypeManager stm = ServiceTypeManager.getServiceTypeManager();
331        serviceType = stm.getServiceType(serviceTypeName);
332        policyManager = policyCache.getPolicyManager(orgName);
333        this.orgNames.add(policyManager.getOrganizationDN());
334        this.serviceTypeNames.add(serviceTypeName);
335        resourceIndexManager = policyManager.getResourceIndexManager();
336
337        String resultsCacheSessionCapString
338                = SystemProperties.get(RESULTS_CACHE_SESSION_CAP);
339        if (resultsCacheSessionCapString != null) {
340            try {
341                resultsCacheSessionCap
342                        = Integer.parseInt(resultsCacheSessionCapString);
343            } catch (NumberFormatException nfe) {
344                if (PolicyManager.debug.warningEnabled()) {
345                    PolicyManager.debug.warning("PolicyEvaluator:"
346                            + "number format exception: "
347                            + "defaulting resultsCacheSessionCap to "
348                            + DEFAULT_RESULTS_CACHE_SESSION_CAP);
349                }
350                resultsCacheSessionCap = DEFAULT_RESULTS_CACHE_SESSION_CAP;
351            }
352        } else {
353            if (PolicyManager.debug.warningEnabled()) {
354                PolicyManager.debug.warning("PolicyEvaluator:"
355                        + "resultsCacheSessionCap not specified, "
356                        + "defaulting resultsCacheSessionCap to "
357                        + DEFAULT_RESULTS_CACHE_SESSION_CAP);
358            }
359            resultsCacheSessionCap = DEFAULT_RESULTS_CACHE_SESSION_CAP;
360        }
361        if (PolicyManager.debug.messageEnabled()) {
362            PolicyManager.debug.message("PolicyEvaluator:"
363                    + "resultsCacheSessionCap=" + resultsCacheSessionCap);
364        }
365
366        String resultsCacheResourceCapString
367                = SystemProperties.get(RESULTS_CACHE_RESOURCE_CAP);
368        if (resultsCacheResourceCapString != null) {
369            try {
370                resultsCacheResourceCap
371                        = Integer.parseInt(resultsCacheResourceCapString);
372            } catch (NumberFormatException nfe) {
373                if (PolicyManager.debug.warningEnabled()) {
374                    PolicyManager.debug.warning("PolicyEvaluator:"
375                            + "number format exception: "
376                            + "defaulting resultsCacheResourceCap to "
377                            + DEFAULT_RESULTS_CACHE_RESOURCE_CAP);
378                }
379                resultsCacheResourceCap = DEFAULT_RESULTS_CACHE_RESOURCE_CAP;
380            }
381        } else {
382            if (PolicyManager.debug.warningEnabled()) {
383                PolicyManager.debug.warning("PolicyEvaluator:"
384                        + "resultsCacheResourceCap not specified, "
385                        + "defaulting resultsCacheResourceCap to "
386                        + DEFAULT_RESULTS_CACHE_RESOURCE_CAP);
387            }
388            resultsCacheResourceCap = DEFAULT_RESULTS_CACHE_RESOURCE_CAP;
389        }
390        if (PolicyManager.debug.messageEnabled()) {
391            PolicyManager.debug.message("PolicyEvaluator:"
392                    + "resultsCacheResourceCap=" + resultsCacheResourceCap);
393        }
394
395    }
396
397    /**
398     * Creates a new policy evaluator instance.
399     *
400     * @param orgName
401     *         the name of the organization under which the evaluation is being done
402     * @param serviceTypeName
403     *         the name of the <code>ServiceType</code> for which this evaluator can be used
404     * @param applicationName
405     *         the application name containing the policies in question
406     *
407     * @throws PolicyException
408     *         should some error occur constructor the evaluator
409     * @throws SSOException
410     *         should some error occur with regards to any SSO token
411     */
412    public PolicyEvaluator(String orgName, String serviceTypeName, String applicationName)
413            throws PolicyException, SSOException {
414        this(orgName, serviceTypeName);
415        this.applicationName = applicationName;
416
417        registerListener();
418    }
419
420    /**
421     * Register a policy listener for updating policy decision cache if there is none already registered.
422     */
423    private void registerListener() {
424        synchronized (lock) {
425            if (!policyListenerRegistry.containsKey(serviceTypeName)) {
426                listener = new PolicyDecisionCacheListener(serviceTypeName);
427
428                try {
429                    PolicyCache.getInstance().addPolicyListener(listener);
430                } catch (PolicyException pe) {
431                    DEBUG.error("PolicyEvaluator: registering policy decision cache listener failed");
432                }
433
434                policyListenerRegistry.put(serviceTypeName, listener);
435
436                if (DEBUG.messageEnabled()) {
437                    DEBUG.message("PolicyEvaluator:policy listener for service " + serviceTypeName + " added");
438                }
439
440            } else {
441                listener = policyListenerRegistry.get(serviceTypeName);
442            }
443        }
444    }
445
446    /**
447     * Evaluates a simple privilege of boolean type. The privilege indicate
448     * if the user can perform specified action on the specified resource.
449     * Invoking this method would result in <code>PolicyException</code>,
450     * if the syntax for the <code>actionName</code> is not declared to be
451     * boolean, in the service schema.
452     *
453     * @param token single sign on token of the user evaluating policies
454     * @param resourceName name of the resource the user is trying to access
455     * @param actionName name of the action the user is trying to perform on
456     * the resource
457     *
458     * @return the result of the evaluation as a boolean value
459     *
460     * @exception SSOException single-sign-on token invalid or expired
461     * 
462     */
463    public boolean isAllowed(SSOToken token, String resourceName,
464        String actionName) throws PolicyException, SSOException {
465        return (isAllowed(token, resourceName, actionName, 
466                new HashMap()));
467    }
468
469    /**
470     * Evaluates simple privileges of boolean type. The privilege indicate
471     * if the user can perform specified action on the specified resource.
472     * The evaluation depends on user's application environment parameters.
473     * Invoking this method would result in <code>PolicyException</code>,
474     * if the syntax for the <code>actionName</code> is not declared to be
475     * boolean, in the service schema.
476     *
477     * @param token single sign on token of the user evaluating policies
478     * @param resourceName name of the resource the user is trying to access
479     * @param actionName name of the action the user is trying to perform on
480     * the resource
481     * @param envParameters run-time environment parameters
482     *
483     * @return the result of the evaluation as a boolean value
484     *
485     * @throws SSOException single-sign-on token invalid or expired
486     * @throws PolicyException for any other abnormal condition
487     * 
488     * @supported.api
489     */
490    public boolean isAllowed(SSOToken token, String resourceName,
491        String actionName, Map envParameters) throws SSOException,
492        PolicyException {
493        if (PolicyManager.isMigratedToEntitlementService()) {
494            return isAllowedE(token, resourceName, actionName, envParameters);
495        }
496        return isAllowedO(token, resourceName, actionName, envParameters);
497    }
498
499    public boolean isAllowedO(SSOToken token, String resourceName,
500            String actionName, Map envParameters) throws SSOException,
501            PolicyException {
502
503        ActionSchema schema = serviceType.getActionSchema(actionName);
504
505        // Cache the false values for the action names
506        if (booleanActionNameFalseValues == null) {
507            booleanActionNameFalseValues = new HashMap(10);
508        }
509        String falseValue = null;
510        if ((falseValue = (String)
511                booleanActionNameFalseValues.get(actionName)) == null) {
512            falseValue = schema.getFalseValue();
513            // Add it to the cache
514            booleanActionNameFalseValues.put(actionName, falseValue);
515        }
516
517
518        // Cache the true values for the action names
519        if (booleanActionNameTrueValues == null) {
520            booleanActionNameTrueValues = new HashMap(10);
521        }
522
523        String trueValue = null;
524        if ((trueValue = (String)
525                booleanActionNameTrueValues.get(actionName)) == null) {
526            trueValue = schema.getTrueValue();
527            // Add it to the cache
528            booleanActionNameTrueValues.put(actionName, trueValue);
529        }
530
531        if (!AttributeSchema.Syntax.BOOLEAN.equals(schema.getSyntax())) {
532            String objs[] = {actionName};
533            throw new PolicyException(
534                    ResBundleUtils.rbName,
535                    "action_does_not_have_boolean_syntax", objs, null);
536        }
537
538        boolean actionAllowed = false;
539        HashSet actionNames = new HashSet(2);
540        actionNames.add(actionName);
541        PolicyDecision policyDecision = getPolicyDecision(token, resourceName,
542                                   actionNames, envParameters);
543        ActionDecision actionDecision =
544                (ActionDecision) policyDecision.getActionDecisions()
545                .get(actionName);
546
547        if ( actionDecision != null ) {
548            Set set = (Set) actionDecision.getValues();
549            if ( (set != null) ) {
550                if ( set.contains(falseValue) ) {
551                    actionAllowed = false;
552                } else if ( set.contains(trueValue) ) {
553                    actionAllowed = true;
554                }
555            }
556        }
557
558        return actionAllowed;
559    }
560
561    private void padEnvParameters(SSOToken token, String resourceName,
562        String actionName, Map envParameters) throws PolicyException, SSOException {
563        if ((resourceName == null) || (resourceName.trim().length() == 0)) {
564            resourceName = Rule.EMPTY_RESOURCE_NAME;
565        }
566
567        Set originalResourceNames = new HashSet(2);
568        originalResourceNames.add(resourceName);
569
570        String realmName = (DN.isDN(realm)) ?
571            DNMapper.orgNameToRealmName(realm) : realm;
572        try {
573            Application appl = ApplicationManager.getApplication(
574                PrivilegeManager.superAdminSubject,
575                realmName, applicationName);
576            resourceName = appl.getResourceComparator().canonicalize(
577                resourceName);
578        } catch (EntitlementException e) {
579            throw new PolicyException(e);
580        }
581        //Add request resourceName and request actionNames to the envParameters
582        //so that Condition(s)/ResponseProvider(s) can use them if necessary
583        Set resourceNames = new HashSet(2);
584        resourceNames.add(resourceName);
585
586        Set actions = new HashSet();
587        if (actionName != null) {
588            actions.add(actionName);
589        } else {
590            Set actionNames = serviceType.getActionNames();
591            if (actionNames != null) {
592                actions.addAll(actionNames);
593            }
594        }
595
596        envParameters.put(SUN_AM_REQUESTED_RESOURCE, resourceNames);
597        envParameters.put(SUN_AM_ORIGINAL_REQUESTED_RESOURCE,
598                originalResourceNames);
599        envParameters.put(SUN_AM_REQUESTED_ACTIONS, actions);
600        envParameters.put(REALM_DN, asSet(policyManager.getOrganizationDN()));
601
602        // Fix for OPENAM-811
603        String userid = null; 
604        Principal principal = token.getPrincipal();
605        if (principal != null) {
606            userid = principal.getName();
607        }
608        if ((userid != null) && (userid.length() != 0)) {
609           HashSet<String> set = new HashSet<String>();
610           set.add(userid);
611           // Required by the AMIdentityMembershipCondition
612           envParameters.put(Condition.INVOCATOR_PRINCIPAL_UUID, set);
613        } else {
614            if (DEBUG.messageEnabled()) {
615                DEBUG.message("PolicyEvaluator.padEnvParameters() unable to get userid from token.");
616            }
617        }
618    }
619
620    private boolean isAllowedE(SSOToken token, String resourceName,
621        String actionName, Map envParameters) throws SSOException,
622        PolicyException {
623
624        if ((envParameters == null) || envParameters.isEmpty()) {
625            envParameters = new HashMap();
626        }
627
628        padEnvParameters(token, resourceName, actionName, envParameters);
629
630        ActionSchema schema = serviceType.getActionSchema(actionName);
631        
632        if (!AttributeSchema.Syntax.BOOLEAN.equals(schema.getSyntax())) {
633            String objs[] = {actionName};
634            throw new PolicyException(
635                    ResBundleUtils.rbName,
636                    "action_does_not_have_boolean_syntax", objs, null);
637        }
638
639        HashSet actions = new HashSet(2);
640        actions.add(actionName);
641        SSOToken adminSSOToken = (SSOToken) AccessController.doPrivileged(
642            AdminTokenAction.getInstance());
643
644        try {
645            Subject adminSubject =  SubjectUtils.createSubject(token);
646
647            Entitlement entitlement = new Entitlement(serviceTypeName, resourceName, actions);
648            entitlement.canonicalizeResources(adminSubject, realm);
649
650            Evaluator eval = new Evaluator(adminSubject, applicationName);
651            return eval.hasEntitlement(realm, SubjectUtils.createSubject(token), entitlement, envParameters);
652
653        } catch (EntitlementException e) {
654            throw new PolicyException(e);
655        }
656    }
657
658    private String getActionFalseBooleanValue(String actionName)
659        throws InvalidNameException {
660
661        if (serviceType == null) {
662            return Boolean.FALSE.toString();
663        }
664
665        ActionSchema schema = serviceType.getActionSchema(actionName);
666
667        // Cache the false values for the action names
668        if (booleanActionNameFalseValues == null) {
669            booleanActionNameFalseValues = new HashMap(10);
670        }
671        String falseValue = null;
672        if ((falseValue = (String)
673                booleanActionNameFalseValues.get(actionName)) == null) {
674            falseValue = schema.getFalseValue();
675            // Add it to the cache
676            booleanActionNameFalseValues.put(actionName, falseValue);
677        }
678        return falseValue;
679    }
680
681    private String getActionTrueBooleanValue(String actionName)
682        throws InvalidNameException {
683
684        if (serviceType == null) {
685            return Boolean.TRUE.toString();
686        }
687
688        ActionSchema schema = serviceType.getActionSchema(actionName);
689
690        // Cache the true values for the action names
691        if (booleanActionNameTrueValues == null) {
692            booleanActionNameTrueValues = new HashMap(10);
693        }
694
695        String trueValue = null;
696        if ((trueValue = (String)
697            booleanActionNameTrueValues.get(actionName)) == null) {
698            trueValue = schema.getTrueValue();
699            booleanActionNameTrueValues.put(actionName, trueValue);
700        }
701
702        return trueValue;
703    }
704
705    /**
706     * Evaluates privileges of the user to perform the specified actions
707     * on the specified resource.
708     *
709     * @param token single sign on token of the user evaluating policies
710     * @param resourceName name of the resource the user is trying to access
711     * @param actionNames a <code>Set</code> of <code>Sting</code> objects
712     * representing names of the actions the user is trying to perform on
713     * the resource
714     *
715     * @return policy decision
716     *
717     * @exception SSOException single-sign-on token invalid or expired
718     * @exception PolicyException for any other abnormal condition.
719     */
720    public PolicyDecision getPolicyDecision(SSOToken token, String resourceName,
721        Set actionNames) throws PolicyException, SSOException {
722        return getPolicyDecision(token, resourceName, actionNames, null);
723    }
724    
725
726    /**
727     * Evaluates privileges of the user to perform the specified actions
728     * on the specified resource. The evaluation depends on user's
729     * application environment parameters.
730     *
731     * @param token single sign on token of the user evaluating policies
732     * @param resourceName name of the resource the user is trying to access
733     * @param actionNames <code>Set</code> of names(<code>String</code>) of 
734     * the action the user is trying to perform on the resource
735     * @param envParameters <code>Map</code> of run-time environment parameters
736     *
737     * @return policy decision
738     *
739     * @throws SSOException single-sign-on token invalid or expired
740     * @throws PolicyException for any other abnormal condition
741     * 
742     * @supported.api
743     */
744    public PolicyDecision getPolicyDecision(
745            SSOToken token, String resourceName, Set actionNames,
746            Map envParameters)  throws SSOException, PolicyException {
747        if ( (resourceName == null) || (resourceName.length() == 0) ) {
748            resourceName = Rule.EMPTY_RESOURCE_NAME;
749        }
750
751        Set originalResourceNames = new HashSet(2);
752        originalResourceNames.add(resourceName);
753
754        resourceName = serviceType.canonicalize(resourceName);
755
756        //Add request resourceName and request actionNames to the envParameters
757        //so that Condition(s)/ResponseProvider(s) can use them if necessary
758        Set resourceNames = new HashSet(2);
759        resourceNames.add(resourceName);
760
761        /* compute for all action names if passed in actionNames is
762           null or empty */
763        if ( (actionNames == null) || (actionNames.isEmpty()) ) {
764            actionNames = serviceType.getActionNames();
765        }
766
767        Set actions = new HashSet();
768        if (actionNames != null) {
769            actions.addAll(actionNames);
770        }
771
772        /*
773         * We create new HashMap in place of empty map since
774         * Collections.EMPTY_MAP can not be modified
775         */
776        if ((envParameters == null) || envParameters.isEmpty()) {
777            envParameters = new HashMap();
778        }
779
780        envParameters.put(SUN_AM_REQUESTED_RESOURCE, resourceNames);
781        envParameters.put(SUN_AM_ORIGINAL_REQUESTED_RESOURCE, 
782                originalResourceNames);
783        envParameters.put(SUN_AM_REQUESTED_ACTIONS, actions);
784        envParameters.put(REALM_DN, asSet(policyManager.getOrganizationDN()));
785
786        return getPolicyDecision(token, resourceName, actionNames,
787                envParameters, new HashSet());
788    }
789
790    /**
791     * Evaluates privileges of the user to perform the specified actions
792     * on the specified resource. The evaluation depends on user's
793     * application environment parameters.
794     *
795     * @param token single sign on token of the user evaluating policies
796     * @param resourceName name of the resource the user is trying to access
797     * @param actionNames <code>Set</code> of names(<code>String</code>) of the
798     * action the user is trying to perform on the resource.
799     * @param envParameters run-time environment parameters
800     * @param visitedOrgs names of organizations that have been already visited
801     *                    during policy evaluation for this request
802     *
803     * @return policy decision
804     *
805     * @exception SSOException single-sign-on token invalid or expired
806     * @exception PolicyException if any policy evaluation error.
807     */
808    private PolicyDecision getPolicyDecision(
809        SSOToken token, String resourceName, Set actionNames,
810        Map envParameters, Set visitedOrgs)
811        throws PolicyException, SSOException {
812        if (MonitoringUtil.isRunning()) {
813            SsoServerPolicySvcImpl sspsi =
814                Agent.getPolicySvcMBean();
815            sspsi.incPolicyEvalsIn();
816        }
817
818        try {
819            return (PolicyManager.isMigratedToEntitlementService()) ? 
820                getPolicyDecisionE(token, resourceName, actionNames,
821                envParameters) : getPolicyDecisionO(token, resourceName,
822                actionNames,
823                envParameters, visitedOrgs);
824        } finally {
825            if (MonitoringUtil.isRunning()) {
826                SsoServerPolicySvcImpl sspsi =
827                        Agent.getPolicySvcMBean();
828                sspsi.incPolicyEvalsOut();
829            }
830        }
831    }
832
833
834    /**
835     * Evaluates privileges of the user to perform the specified actions
836     * on the specified resource. The evaluation depends on user's
837     * application environment parameters.
838     *
839     * @param token single sign on token of the user evaluating policies
840     * @param resourceName name of the resource the user is trying to access
841     * @param actionNames <code>Set</code> of names(<code>String</code>) of the
842     * action the user is trying to perform on the resource.
843     * @param envParameters run-time environment parameters
844     * @return policy decision
845     *
846     * @exception SSOException single-sign-on token invalid or expired
847     * @exception PolicyException if any policy evaluation error.
848     */
849    private PolicyDecision getPolicyDecisionE(
850        SSOToken token, String resourceName, Set actionNames,
851        Map envParameters)
852        throws PolicyException, SSOException {
853
854        if ( DEBUG.messageEnabled() ) {
855            DEBUG.message("Evaluating policies at org " + orgName);
856        }
857
858        /* compute for all action names if passed in actionNames is
859           null or empty */
860        if ( (actionNames == null) || (actionNames.isEmpty()) ) {
861            actionNames = serviceType.getActionNames();
862        }
863
864        SSOToken adminSSOToken = (SSOToken) AccessController.doPrivileged(
865            AdminTokenAction.getInstance());
866
867        try {
868            Evaluator eval = new Evaluator(
869                SubjectUtils.createSubject(adminSSOToken), applicationName);
870            Subject sbj = (token != null) ? SubjectUtils.createSubject(token) :
871                null;
872            List<Entitlement> entitlements = eval.evaluate(
873                orgName, sbj, resourceName, envParameters, false);
874            if ((entitlements != null) && !entitlements.isEmpty()) {
875                Entitlement e = entitlements.iterator().next();
876                return (entitlementToPolicyDecision(e, actionNames));
877            }
878        } catch (EntitlementException e) {
879            throw new PolicyException(e);
880        }
881        return (new PolicyDecision());
882    }
883
884    private PolicyDecision getPolicyDecisionO(
885            SSOToken token, String resourceName, Set actionNames,
886            Map envParameters, Set visitedOrgs)
887            throws PolicyException, SSOException {
888
889        if ( DEBUG.messageEnabled() ) {
890            DEBUG.message("Evaluating policies at org " + orgName);
891        }
892
893        /* compute for all action names if passed in actionNames is
894           null or empty */
895        if ( (actionNames == null) || (actionNames.isEmpty()) ) {
896            actionNames = serviceType.getActionNames();
897        }
898
899        Set actions = new HashSet();
900        actions.addAll(actionNames);
901
902        PolicyDecision mergedPolicyDecision = null;
903        Set policyNameSet = null;
904        Set toRemovePolicyNameSet = null;
905        policyNameSet = resourceIndexManager.getPolicyNames(
906                serviceType, resourceName, INCLUDE_SUPER_RESOURCE_POLCIES);
907        if ( DEBUG.messageEnabled() ) {
908            String tokenPrincipal =
909                    (token != null) ? token.getPrincipal().getName()
910                    : PolicyUtils.EMPTY_STRING;
911            DEBUG.message(new StringBuffer("at PolicyEvaluator")
912                .append(".getPolicyDecision()")
913                .append(" principal, resource name, ")
914                .append("action names, policy names,")
915                .append(" orgName =")
916                .append(tokenPrincipal) .append(",  ")
917                .append(resourceName) .append(",  ")
918                .append(actionNames) .append(",  ")
919                .append(policyNameSet).append(",  ")
920                .append(orgName).toString());
921        }
922        Iterator policyIter = policyNameSet.iterator();
923        while ( policyIter.hasNext() ) {
924            String policyName = (String) policyIter.next();
925            Policy policy = policyManager.getPolicy(policyName,
926                USE_POLICY_CACHE);
927            if ( policy != null && policy.isActive()) {
928                //policy might have been removed or inactivated
929                PolicyDecision policyDecision = policy.getPolicyDecision(token,
930                       serviceTypeName, resourceName, actions, envParameters);
931                if (!policy.isReferralPolicy() && policyDecision.hasAdvices()) {
932                    addAdvice(policyDecision, ADVICING_ORGANIZATION, orgName);
933                }
934
935                // Let us log all policy evaluation results
936                if (PolicyUtils.logStatus && (token != null)) {
937                    String decision = policyDecision.toString();
938                    if (decision != null && decision.length() != 0) {
939                        String[] objs = { policyName, orgName, serviceTypeName,
940                                        resourceName, actionNames.toString(),
941                                        decision };
942                            PolicyUtils.logAccessMessage("POLICY_EVALUATION",
943                                                objs, token, serviceTypeName);
944                    }
945                }
946                if ( mergedPolicyDecision == null ) {
947                    mergedPolicyDecision = policyDecision;
948                } else {
949                    mergePolicyDecisions(serviceType, policyDecision,
950                           mergedPolicyDecision);
951                }
952
953                if (!PolicyConfig.continueEvaluationOnDenyDecision()) {
954                    actions.removeAll(getFinalizedActions(serviceType,
955                            mergedPolicyDecision));
956                }
957
958                if ( actions.isEmpty() ) {
959                    break;
960                }
961            } else { // add policy names to toRemovePolicyNameSet
962                if (toRemovePolicyNameSet == null) {
963                    toRemovePolicyNameSet = new HashSet();
964                }
965                toRemovePolicyNameSet.add(policyName);
966                if ( DEBUG.messageEnabled() ) {
967                    DEBUG.message("PolicyEvaluator.getPolicyDecision():"
968                        +policyName+ " is inactive or non-existent");
969                }
970            }
971        }
972
973        // remove inactive/missing policies from policyNameSet
974        if (toRemovePolicyNameSet != null) {
975            policyNameSet.removeAll(toRemovePolicyNameSet);
976        }
977
978        Set orgsToVisit = getOrgsToVisit(policyNameSet);
979
980        if (PolicyConfig.orgAliasMappedResourcesEnabled()
981                    && PolicyManager.WEB_AGENT_SERVICE.equalsIgnoreCase(
982                    serviceTypeName)) {
983            String orgAlias = policyManager.getOrgAliasWithResource(
984                    resourceName);
985            if (orgAlias != null) {
986                String orgWithAlias = policyManager.getOrgNameWithAlias(
987                        orgAlias);
988                if (orgWithAlias != null) {
989                    if ( DEBUG.messageEnabled() ) {
990                        DEBUG.message("PolicyEvaluator.getPolicyDecision():"
991                                + "adding orgWithAlias to orgsToVisit="
992                                + orgWithAlias);
993                    }
994                    orgsToVisit.add(orgWithAlias);
995                }
996            }
997        }
998
999        if ( DEBUG.messageEnabled() ) {
1000            DEBUG.message(new StringBuffer("at PolicyEvaluator")
1001                .append(".getPolicyDecision()")
1002                .append(" orgsToVist=").append(orgsToVisit.toString())
1003                .toString());
1004        }
1005        orgsToVisit.removeAll(visitedOrgs);
1006        if ( DEBUG.messageEnabled() ) {
1007            DEBUG.message(new StringBuffer("at PolicyEvaluator")
1008                .append(".getPolicyDecision()")
1009                .append(" orgsToVist(after removing already visited orgs=")
1010                .append(orgsToVisit.toString())
1011                .toString() );
1012        }
1013        while ( !orgsToVisit.isEmpty() && !actions.isEmpty() ) {
1014            String orgToVisit = (String) orgsToVisit.iterator().next();
1015            orgsToVisit.remove(orgToVisit);
1016            visitedOrgs.add(orgToVisit);
1017            try {
1018                // need to use admin sso token here. Need all privileges to
1019                // check for the organzation
1020                policyManager.verifyOrgName(orgToVisit);
1021            } catch (NameNotFoundException nnfe) {
1022                if( DEBUG.warningEnabled()) {
1023                    DEBUG.warning("Organization does not exist - "
1024                            + "skipping referral to " + orgToVisit);
1025                }
1026                continue;
1027            }
1028            PolicyEvaluator pe = new PolicyEvaluator(orgToVisit,
1029                    serviceTypeName);
1030            /**
1031             * save current realm DN before passing control down to sub-realm
1032             */
1033            Set<String> savedRealmDn = (Set<String>) envParameters.get(REALM_DN);
1034            // Update env to point to the realm policy config data.
1035            envParameters.put(REALM_DN, asSet(DNMapper.orgNameToDN(orgToVisit)));
1036            PolicyDecision policyDecision
1037                    = pe.getPolicyDecision(token, resourceName, actionNames,
1038                    envParameters,visitedOrgs);
1039            // restore back the policy config data for the parent realm
1040            envParameters.put(REALM_DN, savedRealmDn);
1041            if ( mergedPolicyDecision == null ) {
1042                mergedPolicyDecision = policyDecision;
1043            } else {
1044                mergePolicyDecisions(serviceType, policyDecision,
1045                       mergedPolicyDecision);
1046            }
1047            if (!PolicyConfig.continueEvaluationOnDenyDecision()) {
1048                actions.removeAll(getFinalizedActions(serviceType,
1049                        mergedPolicyDecision));
1050            }
1051        }
1052
1053        if ( mergedPolicyDecision == null ) {
1054            mergedPolicyDecision = new PolicyDecision();
1055        }
1056
1057        return mergedPolicyDecision;
1058    }
1059
1060    /**
1061     * Gets protected resources for a user identified by single sign on token
1062     * Conditions defined  in the policies are ignored while 
1063     * computing protected resources. 
1064     * Only resources that are sub resources of the  given 
1065     * <code>rootResource</code> or equal to the given <code>rootResource</code>
1066     * would be returned. 
1067     * If all policies applicable to a resource are 
1068     * only referral policies, no <code>ProtectedResource</code> would be
1069     * returned for such a resource.
1070     *
1071     * @param token single sign on token of the user
1072     * @param rootResource  only resources that are sub resources of the  
1073     *                      given <code>rootResource</code> or equal to the
1074     *                      given <code>rootResource</code> would be returned
1075     *                      <code>rootResource</code> would be returned.
1076     *                      If <code>PolicyEvaluator.ALL_RESOURCES</code> is 
1077     *                      passed as <code>rootResource</code>, resources under
1078     *                      all root  resources of the service 
1079     *                      type are considered while computing protected 
1080     *                      resources.
1081     * @return <code>Set</code> of protected resources. The set 
1082     *         contains <code>ProtectedResource</code> objects. 
1083     *
1084     * @throws SSOException if single sign on token is invalid
1085     * @throws PolicyException for any other abnormal condition
1086     * @see ProtectedResource
1087     *
1088     * @supported.api
1089     *
1090     */
1091    public Set getProtectedResourcesIgnoreConditions(
1092        SSOToken token, String rootResource)  
1093        throws SSOException, PolicyException 
1094    {
1095        if ( (rootResource == null) || (rootResource.equals("")) ) {
1096            rootResource = EMPTY_RESOURCE_NAME;
1097        }
1098        Set protectedResources = new HashSet();
1099        Set topLevelResources = null;
1100        if (rootResource.equals(ALL_RESOURCES)) {
1101            topLevelResources 
1102                    = resourceIndexManager.getTopLevelResourceNames(
1103                    serviceType);
1104        } else {
1105            topLevelResources = new HashSet();
1106            topLevelResources.add(rootResource);
1107        }
1108        Iterator iter = topLevelResources.iterator();
1109        while (iter.hasNext()) {
1110            String topLevelResource = (String)iter.next();
1111            Set resourceNames 
1112                    = getResourceNames(token, topLevelResource, true);
1113            Iterator resourceIter = resourceNames.iterator();
1114            while (resourceIter.hasNext()) {
1115                String resourceName = (String)resourceIter.next();
1116                Set protectingPolicies 
1117                        = getProtectingPolicies(token, resourceName);
1118                if ((protectingPolicies != null) 
1119                            && (!protectingPolicies.isEmpty())) {
1120                    boolean allReferralPolicies = true;
1121                    Iterator iter1 = protectingPolicies.iterator();
1122                    while (iter1.hasNext()){
1123                        Policy policy = (Policy)iter1.next();
1124                        if (!policy.isReferralPolicy()) {
1125                            allReferralPolicies = false;
1126                            break;
1127                        }
1128                    }
1129                    if (!allReferralPolicies) {
1130                        protectedResources.add(
1131                                new ProtectedResource(resourceName, 
1132                                protectingPolicies));
1133                    }
1134                }
1135            }
1136        }
1137        return protectedResources;
1138    }
1139
1140    /**
1141     * Gets policies applicable to user that are  protecting 
1142     * the specified resource.
1143     *
1144     * @param token single sign on token of the user evaluating policies
1145     * @param resourceName name of the resource the user is trying to access
1146     *
1147     * @return set of policies applicable to user that are protecting the 
1148     *         specified resource
1149     *
1150     * @throws PolicyException policy exception coming from policy framework
1151     * @throws SSOException single-sign-on token invalid or expired
1152     * 
1153     */
1154    Set getProtectingPolicies(
1155        SSOToken token, String resourceName)  
1156        throws PolicyException, SSOException 
1157    {
1158        return getProtectingPolicies(token, resourceName, new HashSet());
1159    }
1160
1161    /**
1162     * Gets policies applicable to user that are  protecting 
1163     * the specified resource.
1164     *
1165     * @param token single sign on token of the user evaluating policies
1166     * @param resourceName name of the resource the user is trying to access
1167     *
1168     * @param visitedOrgs names of organizations that have been 
1169     *            already visited during evaluation for this request
1170     * @return set of policies applicable to user that are protecting the 
1171     *         specified resource
1172     *
1173     * @throws PolicyException policy exception coming from policy framework
1174     * @throws SSOException single-sign-on token invalid or expired
1175     * 
1176     */
1177    private Set getProtectingPolicies(
1178        SSOToken token, String resourceName, Set visitedOrgs)  
1179        throws PolicyException, SSOException 
1180    {
1181
1182        Set protectingPolicies = new HashSet();
1183
1184
1185        // false - do not include super resource policies
1186        // includes EXACT_MATCH and WILD_CARD_MATCH
1187        Set policyNameSet = resourceIndexManager.getPolicyNames(
1188                serviceType, resourceName, false);
1189        Set toRemovePolicyNameSet = null;
1190        if ( DEBUG.messageEnabled() ) {
1191            String tokenPrincipal = 
1192                    (token != null) ? token.getPrincipal().getName()
1193                    : PolicyUtils.EMPTY_STRING;
1194            DEBUG.message(new StringBuffer(
1195                    "at PolicyEvaluator.getProtectingPolicies()")
1196                .append(" principal, resource name, policy names,")
1197                .append(" orgName =")
1198                .append(tokenPrincipal) .append(",  ")
1199                .append(resourceName) .append(",  ")
1200                .append(policyNameSet).append(",  ")
1201                .append(orgName).toString());
1202        }
1203        Iterator policyIter = policyNameSet.iterator();
1204        while ( policyIter.hasNext() ) {
1205            String policyName = (String) policyIter.next();
1206            Policy policy = policyManager.getPolicy(policyName);
1207            if ( policy != null && policy.isActive()) { 
1208                //policy might have been removed or inactivated
1209                if (!policy.isReferralPolicy()) {
1210                    if (policy.isApplicableToUser(token)) {
1211                        policy.setOrganizationName(orgName);
1212                        protectingPolicies.add(policy); 
1213                    }
1214                } else {
1215                    policy.setOrganizationName(orgName);
1216                    protectingPolicies.add(policy);
1217                }
1218            } else { // add policy names to toRemovePolicyNameSet
1219                if (toRemovePolicyNameSet == null) {
1220                    toRemovePolicyNameSet = new HashSet();
1221                }
1222                toRemovePolicyNameSet.add(policyName);
1223                if ( DEBUG.messageEnabled() ) {
1224                    DEBUG.message("PolicyEvaluator.getProtectingPolicies():"
1225                        +policyName+ " is inactive or non-existent");
1226                }
1227            }
1228        }
1229
1230        // remove inactive/missing policies from policyNameSet
1231        if (toRemovePolicyNameSet != null) {
1232            policyNameSet.removeAll(toRemovePolicyNameSet);
1233        }
1234
1235        //include super resource policies provided they are referral policies
1236        policyNameSet = resourceIndexManager.getSuperResourcePolicyNames(
1237                serviceType, resourceName);
1238        if (toRemovePolicyNameSet != null) {
1239            toRemovePolicyNameSet.clear();
1240        }
1241        policyIter = policyNameSet.iterator();
1242        while ( policyIter.hasNext() ) {
1243            String policyName = (String) policyIter.next();
1244            Policy policy = policyManager.getPolicy(policyName);
1245            if ( policy != null && policy.isActive()) { 
1246                //policy might have been removed or inactivated
1247                if (policy.isReferralPolicy()) {
1248                        policy.setOrganizationName(orgName);
1249                        protectingPolicies.add(policy);
1250                }
1251            } else { // add policy names to toRemovePolicyNameSet
1252                if (toRemovePolicyNameSet == null) {
1253                    toRemovePolicyNameSet = new HashSet();
1254                }
1255                toRemovePolicyNameSet.add(policyName);
1256                if ( DEBUG.messageEnabled() ) {
1257                    DEBUG.message("PolicyEvaluator.getProtectingPolicies():"
1258                        +policyName+ " is inactive or non-existent");
1259                }
1260            }
1261        }
1262        // remove inactive/missing policies from policyNameSet
1263        if (toRemovePolicyNameSet != null) {
1264            policyNameSet.removeAll(toRemovePolicyNameSet);
1265        }
1266
1267        Set orgsToVisit = getOrgsToVisit(policyNameSet);
1268        if ( DEBUG.messageEnabled() ) {
1269            DEBUG.message(new StringBuffer(
1270                    "at PolicyEvaluator.getProtectingPolicies()")
1271                .append(" orgsToVist=").append(orgsToVisit.toString())
1272                .toString());
1273        }
1274
1275        if (PolicyConfig.orgAliasMappedResourcesEnabled()
1276                    && PolicyManager.WEB_AGENT_SERVICE.equalsIgnoreCase(
1277                    serviceTypeName)) {
1278            String orgAlias = policyManager.getOrgAliasWithResource(
1279                    resourceName); 
1280            if (orgAlias != null) {
1281                String orgWithAlias = policyManager.getOrgNameWithAlias(
1282                        orgAlias);
1283                if (orgWithAlias != null) {
1284                    if ( DEBUG.messageEnabled() ) {
1285                        DEBUG.message("PolicyEvaluator.getProtectingPolicies():"
1286                                + "adding orgWithAlias to orgsToVisit="
1287                                + orgWithAlias);
1288                    }
1289                    orgsToVisit.add(orgWithAlias);
1290                }
1291            }
1292        }
1293
1294        orgsToVisit.removeAll(visitedOrgs);
1295        if ( DEBUG.messageEnabled() ) {
1296            DEBUG.message(new StringBuffer(
1297                    "at PolicyEvaluator.getProtectingPolicies()")
1298                .append(" orgsToVist(after removing already visited orgs=")
1299                .append(orgsToVisit.toString())
1300                .toString() );
1301        }
1302        while (!orgsToVisit.isEmpty() ) {
1303            String orgToVisit = (String) orgsToVisit.iterator().next();
1304            orgsToVisit.remove(orgToVisit);
1305            visitedOrgs.add(orgToVisit);
1306            try {
1307                // need to use admin sso token here. Need all privileges to
1308                // check for the organzation
1309                policyManager.verifyOrgName(orgToVisit);
1310            } catch (NameNotFoundException nnfe) {
1311                if( DEBUG.warningEnabled()) {
1312                    DEBUG.warning("Organization does not exist - "
1313                            + "skipping referral to " + orgToVisit);
1314                }
1315                continue;
1316            }
1317            PolicyEvaluator pe 
1318                    = new PolicyEvaluator(orgToVisit, serviceTypeName);
1319            Set pp = pe.getProtectingPolicies(token, resourceName,
1320                    visitedOrgs); 
1321            protectingPolicies.addAll(pp);
1322        }
1323
1324        String principalName =  (token != null) 
1325                ? token.getPrincipal().getName()
1326                : PolicyUtils.EMPTY_STRING;
1327
1328        StringBuffer sb = null;
1329        String pp = null;
1330        if (PolicyManager.debug.messageEnabled() || PolicyUtils.logStatus) {
1331            sb = new StringBuffer();
1332            Iterator pIter = protectingPolicies.iterator();
1333            while (pIter.hasNext()) {
1334                Policy policy = (Policy)pIter.next();
1335                sb.append(policy.getOrganizationName()).append(":")
1336                        .append(policy.getName()) .append(",");
1337            }
1338            pp = sb.toString();
1339        }
1340
1341
1342        if (PolicyManager.debug.messageEnabled()) {
1343            PolicyManager.debug.message("Computed policies "
1344                    + " protecting resource "
1345                    + resourceName
1346                    + "for principal:" + principalName + " " + pp);
1347        }
1348
1349        if (PolicyUtils.logStatus && (token != null)) {
1350            String[] objs = { principalName, 
1351                    resourceName, pp };
1352            PolicyUtils.logAccessMessage("PROTECTED_RESOURCES", objs, token,
1353                    serviceTypeName);
1354        }
1355        return protectingPolicies;
1356    }
1357
1358    /**
1359     * Gets resource result objects given a resource name. The set
1360     * contains <code>ResourceResult</code> objects for all resources 
1361     * that would affect policy decisions for any resource associated with the 
1362     * argument resource name. To determine whether to include the
1363     * <code>ResourceResult</code> of a resource,  we compare argument resource
1364     * name and policy resource name, treating wild characters in the policy 
1365     * resource name as wild. If the comparison resulted in
1366     * <code>EXACT_MATCH</code>, <code>WILD_CARD_MACTH</code> or
1367     * <code>SUB_RESOURCE_MACTH</code>, the resource result would be
1368     * included.
1369     *
1370     * @param token single sign on token of the user evaluating policies
1371     * @param resourceName name of the resource 
1372     * @param scope indicates whether to compute the resource result based on
1373     *              the policy decision for only the <code>resourceName</code>
1374     *              or all the resources associated with the resource name.
1375     *              The valid scope values are:
1376     *              <ul>
1377     *              <li><code>ResourceResult.SUBTREE_SCOPE</code>
1378     *              <li><code>ResourceResult.STRICT_SUBTREE_SCOPE</code>
1379     *              <li><code>ResourceResult.SELF_SCOPE</code>
1380     *              <ul>
1381     *              If the scope is <code>ResourceResult.SUBTREE_SCOPE</code>,
1382     *              the method will return a set of <code>ResourceResult</code>
1383     *              objects, one of them for the <code>resourceName</code> and
1384     *              its sub resources; the others are for resources that match
1385     *              the <code>resourceName</code> by wildcard. If the scope is
1386     *              <code>ResourceResult.STRICT_SUBTREE_SCOPE</code>, the 
1387     *              method will return a set object that contains one 
1388     *              <code>ResourceResult</code> object. The
1389     *              <code>ResourceResult</code> contains the policy decisions
1390     *              regarding the <code>resourceName</code> and its sub
1391     *              resources. If the scope is
1392     *              <code>ResourceResult.SELF_SCOPE</code>, the method will
1393     *              return a set object that contains one
1394     *              <code>ResourceResult</code> object.
1395     *              The <code>ResourceResult</code> contains the policy decision
1396     *              regarding the <code>resourceName</code> only.
1397     *
1398     * @param envParameters run-time environment parameters
1399     *
1400     * @return set of <code>ResourceResult</code> objects
1401     *
1402     * @throws SSOException if <code>token</code> is invalid
1403     * @throws PolicyException for any other abnormal condition
1404     *
1405     * @see ResourceMatch#EXACT_MATCH
1406     * @see ResourceMatch#SUB_RESOURCE_MATCH
1407     * @see ResourceMatch#WILDCARD_MATCH
1408     * @see ResourceResult#SUBTREE_SCOPE
1409     * @see ResourceResult#STRICT_SUBTREE_SCOPE
1410     * @see ResourceResult#SELF_SCOPE
1411     *
1412     * 
1413     * @supported.api
1414     */
1415    public Set getResourceResults(SSOToken token, 
1416            String resourceName, String scope, Map envParameters) 
1417            throws SSOException, PolicyException {
1418        return (PolicyManager.isMigratedToEntitlementService()) ?
1419            getResourceResultsE(token, resourceName, scope, envParameters) :
1420            getResourceResultsO(token, resourceName, scope, envParameters);
1421    }
1422    
1423    private Set getResourceResultsO(SSOToken token,
1424            String resourceName, String scope, Map envParameters)
1425            throws SSOException, PolicyException {
1426        Set resultsSet;
1427
1428        if (ResourceResult.SUBTREE_SCOPE.equals(scope)) {
1429            resultsSet = getResourceResultTree(token, resourceName, scope,
1430                                         envParameters).getResourceResults();
1431        } else if (ResourceResult.STRICT_SUBTREE_SCOPE.equals(scope)
1432                   || ResourceResult.SELF_SCOPE.equals(scope)) {
1433            ResourceResult result = getResourceResultTree(token, resourceName,
1434                                         scope, envParameters);
1435            resultsSet = new HashSet();
1436            resultsSet.add(result);
1437        } else {
1438            DEBUG.error("PolicyEvaluator: invalid request scope: " + scope);
1439            String objs[] = {scope};
1440            throw new PolicyException(ResBundleUtils.rbName,
1441                "invalid_request_scope", objs, null);
1442        }
1443
1444        return resultsSet;
1445    }
1446
1447    private Set getResourceResultsE(SSOToken token,
1448            String resourceName, String scope, Map envParameters)
1449            throws SSOException, PolicyException {
1450
1451        if ((envParameters == null) || envParameters.isEmpty()) {
1452            envParameters = new HashMap();
1453        }
1454        padEnvParameters(token, resourceName, null, envParameters);
1455
1456        Set resultsSet;
1457        boolean subTreeSearch = false;
1458
1459        if (ResourceResult.SUBTREE_SCOPE.equals(scope)) {
1460            subTreeSearch = true;
1461            //resultsSet = getResourceResultTree(token, resourceName, scope,
1462            //                            envParameters).getResourceResults();
1463        } else if (ResourceResult.STRICT_SUBTREE_SCOPE.equals(scope)
1464                   || ResourceResult.SELF_SCOPE.equals(scope)) {
1465            /*
1466            ResourceResult result = getResourceResultTree(token, resourceName,
1467                                         scope, envParameters);
1468            resultsSet = new HashSet();
1469            resultsSet.add(result);*/
1470        } else {
1471            DEBUG.error("PolicyEvaluator: invalid request scope: " + scope);
1472            String objs[] = {scope};
1473            throw new PolicyException(ResBundleUtils.rbName,
1474                "invalid_request_scope", objs, null);
1475        }
1476
1477        SSOToken adminSSOToken = (SSOToken)AccessController.doPrivileged(
1478            AdminTokenAction.getInstance());
1479
1480        try {
1481            // Parse the resource name before proceeding.
1482            resourceName = serviceType.canonicalize(resourceName);
1483
1484            Subject userSubject = SubjectUtils.createSubject(token);
1485            Evaluator eval = new Evaluator(
1486                SubjectUtils.createSubject(adminSSOToken), applicationName);
1487
1488            List<Entitlement> entitlements = eval.evaluate(
1489                realm, userSubject, resourceName,
1490                envParameters, subTreeSearch);
1491            resultsSet = new HashSet();
1492
1493            if (!entitlements.isEmpty()) {
1494                if (!subTreeSearch) {
1495                    resultsSet.add(entitlementToResourceResult(
1496                        (Entitlement)entitlements.iterator().next()));
1497                } else {
1498                    ResourceResult virtualResourceResult =
1499                        new ResourceResult(ResourceResult.VIRTUAL_ROOT,
1500                            new PolicyDecision());
1501                    for (Entitlement ent : entitlements ) {
1502                        ResourceResult r = entitlementToResourceResult(ent);
1503                        virtualResourceResult.addResourceResult(r, serviceType);
1504                    }
1505
1506                    resultsSet.addAll(
1507                        virtualResourceResult.getResourceResults());
1508                }
1509            }
1510        } catch (Exception e) {
1511            DEBUG.error("Error in getResourceResults", e);
1512            throw new PolicyException(e.getMessage()); //TOFIX
1513        }
1514
1515        return resultsSet;
1516    }
1517
1518   
1519    private ResourceResult entitlementToResourceResult(
1520        Entitlement entitlement
1521    ) throws PolicyException {
1522        return new ResourceResult(entitlement.getRequestedResourceName(),
1523            entitlementToPolicyDecision(entitlement, Collections.EMPTY_SET));
1524    }
1525    
1526    private PolicyDecision entitlementToPolicyDecision(
1527        Entitlement entitlement,
1528        Set<String> actionNames
1529    ) throws PolicyException {
1530        PolicyDecision pd = new PolicyDecision();
1531        Map actionValues = entitlement.getActionValues();
1532
1533        if ((actionValues != null) && !actionValues.isEmpty()) {
1534            for (Iterator i = actionValues.keySet().iterator(); i.hasNext();) {
1535                String actionName = (String) i.next();
1536                Set set = new HashSet();
1537                boolean isBooleanAction = true;
1538                if (serviceType != null) {
1539                    ActionSchema as = null;
1540                    try {
1541                        as = serviceType.getActionSchema(actionName);
1542                    } catch (InvalidNameException inex) {
1543                        if (DEBUG.warningEnabled()) {
1544                            DEBUG.warning("PolicyEvaluator." +
1545                                "entitlementToPolicyDecision:", inex);
1546                        }
1547                    }
1548                    isBooleanAction = (as != null) &&
1549                        as.getSyntax().equals(AttributeSchema.Syntax.BOOLEAN);
1550                }
1551
1552                if (isBooleanAction) {
1553
1554                    Boolean values = (Boolean) actionValues.get(actionName);
1555
1556                    if (values.booleanValue()) {
1557                        set.add(getActionTrueBooleanValue(actionName));
1558                    } else {
1559                        set.add(getActionFalseBooleanValue(actionName));
1560                    }
1561                } else {
1562                    // Parse the action name to get the value
1563                    int index = actionName.indexOf('_');
1564                    if (index != -1) {
1565                        set.add(actionName.substring(index+1));
1566                        actionName = actionName.substring(0, index);
1567                    } else {
1568                        set.add(actionName);
1569                    }
1570                }
1571
1572                ActionDecision ad = new ActionDecision(actionName, set);
1573                ad.setAdvices(entitlement.getAdvices());
1574                ad.setTimeToLive(entitlement.getTTL());
1575                pd.addActionDecision(ad, serviceType);
1576            }
1577        } else {
1578            Map advices = entitlement.getAdvices();
1579            if ((advices != null) && (!advices.isEmpty()) &&
1580                ((actionNames == null) || actionNames.isEmpty())) {
1581                actionNames = serviceType.getActionNames();
1582            }
1583            for (String actionName : actionNames) {
1584                Set set = new HashSet();
1585                // Determinte if the serviceType have boolean action values
1586                ActionSchema as = null;
1587                if (serviceType != null) {
1588                    try {
1589                        as = serviceType.getActionSchema(actionName);
1590                    } catch (InvalidNameException inex) {
1591                        if (DEBUG.warningEnabled()) {
1592                            DEBUG.warning("PolicyEvaluator." +
1593                                "entitlementToPolicyDecision:", inex);
1594                        }
1595                    }
1596                }
1597                if ((as == null) ||
1598                    as.getSyntax().equals(AttributeSchema.Syntax.BOOLEAN)) {
1599                    set.add(getActionFalseBooleanValue(actionName));
1600                } else {
1601                    set.addAll(as.getDefaultValues());
1602                }
1603                ActionDecision ad = new ActionDecision(actionName, set);
1604                ad.setAdvices(entitlement.getAdvices());
1605                ad.setTimeToLive(entitlement.getTTL());
1606                pd.addActionDecision(ad, serviceType);
1607            }
1608        }
1609
1610        pd.setTimeToLive(entitlement.getTTL());
1611        pd.setResponseAttributes(entitlement.getAttributes());
1612        return pd;
1613    }
1614
1615    /**
1616     * Gets resource result given a resource name. <code>ResourceResult</code>
1617     * is a tree representation of policy decisions for all resources rooted 
1618     * at the resource name.
1619     * To determine whether a resource defined in the policy
1620     * is a sub resource of argument resource name, argument resource name 
1621     * and policy resource name are compared, treating wild characters as 
1622     * literals. If comparison resulted in <code>EXACT_MACTH</code> or
1623     * <code>SUB_RESOURCE_MACTH</code>, the resource would be included
1624     *
1625     * @param token single sign on token of the user evaluating policies
1626     * @param resourceName name of the resource 
1627     * @param scope indicates whether to compute the resource result based on
1628     *              the policy decision for only the <code>resourceName</code>
1629     *              or all the resources associated with the resource name.
1630     *              The valid scope values are:
1631     *              <ul>
1632     *              <li><code>ResourceResult.SUBTREE_SCOPE</code>
1633     *              <li><code>ResourceResult.STRICT_SUBTREE_SCOPE</code>
1634     *              <li><code>ResourceResult.SELF_SCOPE</code>
1635     *              </ul>
1636     *              If the scope is <code>ResourceResult.SUBTREE_SCOPE</code> or
1637     *              <code>ResourceResult.STRICT_SUBTREE_SCOPE</code>, the method
1638     *              will return a <code>ResourceResult</code> object that
1639     *              contains the policy decisions regarding the
1640     *              <code>resourceName</code> and its sub resources.
1641     *              If the scope is <code>ResourceResult.SELF_SCOPE</code>, the
1642     *              method will return a <code>ResourceResult</code> object that
1643     *              contains the policy decision regarding the
1644     *              <code>resourceName</code> only. Note, scope values
1645     *              <code>ResourceResult.SUBTREE_SCOPE</code> and
1646     *              <code>ResourceResult.STRICT_SUBTREE_SCOPE</code> are being
1647     *              treated as the same for backword compatibility reasons. This
1648     *              method is being deprecated. The method
1649     *              <code>getResourceResults()</code> should be used instead. 
1650     *
1651     * @param envParameters run-time environment parameters
1652     *
1653     * @return <code>ResourceResult</code>.
1654     *
1655     * @throws SSOException if <code>token</code> is invalid 
1656     * @throws PolicyException for any other abnormal condition
1657     *
1658     * @see ResourceMatch#EXACT_MATCH
1659     * @see ResourceMatch#SUB_RESOURCE_MATCH
1660     * @see ResourceMatch#WILDCARD_MATCH
1661     * @see ResourceResult#SUBTREE_SCOPE
1662     * @see ResourceResult#STRICT_SUBTREE_SCOPE
1663     * @see ResourceResult#SELF_SCOPE
1664     *
1665     * @deprecated Use <code>getResourceResults()</code>
1666     *
1667     * @supported.api
1668     *
1669     */
1670    public ResourceResult getResourceResult(SSOToken token, 
1671            String resourceName, String scope, Map envParameters) 
1672            throws SSOException, PolicyException {
1673        if (ResourceResult.SUBTREE_SCOPE.equals(scope)
1674                || ResourceResult.STRICT_SUBTREE_SCOPE.equals(scope) 
1675                || ResourceResult.SELF_SCOPE.equals(scope)) {
1676            if (ResourceResult.SUBTREE_SCOPE.equals(scope)) {
1677                scope = ResourceResult.STRICT_SUBTREE_SCOPE; 
1678            }
1679            return getResourceResultTree(token, resourceName, scope, 
1680                    envParameters); 
1681        } else {
1682            DEBUG.error("PolicyEvaluator: invalid request scope: " + scope);
1683            String objs[] = {scope};
1684            throw new PolicyException(ResBundleUtils.rbName,
1685                "invalid_request_scope", objs, null);
1686        }
1687    }
1688
1689    /**
1690     * Gets resource result given a resource name. <code>ResourceResult</code>
1691     * is a tree representation of policy decisions for all resources 
1692     * that are sub resources of argument resource name. 
1693     *
1694     * @param token single sign on token of the user evaluating policies
1695     * @param resourceName name of the resource 
1696     * @param scope indicates whether to compute the resource result based on
1697     *              the policy decision for only the <code>resourceName</code>
1698     *              or all the resources associated with the resource name.
1699     * @param envParameters run-time environment parameters
1700     *
1701     * @return <code>ResourceResult</code>.
1702     *
1703     * @exception SSOException if <code>token</code> is invalid
1704     * @exception PolicyException for any other abnormal condition
1705     *
1706     * @see ResourceMatch#EXACT_MATCH
1707     * @see ResourceMatch#SUB_RESOURCE_MATCH
1708     * @see ResourceMatch#WILDCARD_MATCH
1709     *
1710     */
1711    private ResourceResult getResourceResultTree(SSOToken token, 
1712            String resourceName, String scope, Map envParameters)
1713            throws PolicyException, SSOException {
1714
1715        String userSSOTokenIDStr =  (token != null) 
1716                ? token.getTokenID().toString() 
1717                : PolicyUtils.EMPTY_STRING;
1718
1719        if (token == null) {
1720            if (DEBUG.messageEnabled()) {
1721                DEBUG.message("user sso token is null, forcing ResourceResult"
1722                        + " evaluation to self_scope");
1723            }
1724            scope = ResourceResult.SELF_SCOPE;
1725
1726        }
1727
1728        ResourceResult resourceResult = null;
1729
1730        if ( (resourceName == null) || (resourceName.equals("")) ) {
1731            resourceName = Rule.EMPTY_RESOURCE_NAME;
1732        }
1733        resourceName = serviceType.canonicalize(resourceName);
1734        Map clientEnv = PolicyUtils.cloneMap(envParameters);
1735
1736
1737        // check if we already have the result in the cache
1738        // policyResultsCache: 
1739        // serviceType -> resource -> sessionId -> scope -> result
1740        synchronized(policyResultsCache) {
1741            // rscCACHE: resource -> sessionId -> scope -> result
1742            Map rscCache = (Map)policyResultsCache.get(serviceTypeName);
1743            if (rscCache != null) {
1744                // resultCACHE: sessionId -> scope -> resourceResult
1745                Map resultsCache = (Map)rscCache.get(resourceName);
1746                if (resultsCache != null) {
1747                    Map results = (Map)resultsCache.get(userSSOTokenIDStr);
1748                    if (results != null) {
1749                        resourceResult = (ResourceResult)results.get(scope);
1750                        if (resourceResult != null) {
1751                            long currentTime = System.currentTimeMillis();
1752                            long ttlMinimal = resourceResult.getTimeToLive();
1753                            if (ttlMinimal > currentTime) {
1754
1755                                //check envMap equality of request and cache
1756                                Map cachedEnv = resourceResult.getEnvMap();
1757                                if ( ((clientEnv == null) 
1758                                            && (cachedEnv == null))
1759                                        || ((clientEnv != null)
1760                                            && clientEnv.equals(cachedEnv)) ) {
1761                                    if (DEBUG.messageEnabled()) {
1762                                        DEBUG.message("PolicyEvaluator."
1763                                        + " getResourceResult(): we get the "
1764                                        + "result from the cache.\n" 
1765                                        + resourceResult.toXML());
1766                                    }
1767                                    return resourceResult;
1768                                } else {
1769                                    if (PolicyManager.debug.messageEnabled()) {
1770                                        PolicyManager.debug.message(
1771                                        "PolicyEvaluator.getResourceesultTree()"
1772                                        + ":cached envMap does not equal "
1773                                        + "request envMap, request envMap = " 
1774                                        + clientEnv 
1775                                        + ", cachedEnv=" + cachedEnv
1776                                        );
1777                                    }
1778                                }
1779                            }
1780                        }
1781                    }
1782                }
1783            }
1784        }
1785
1786        /* compute all action names if passed in actionNames is
1787           null or empty */
1788        if ( (actionNames == null) || (actionNames.isEmpty()) ) {
1789            actionNames = serviceType.getActionNames();
1790        }
1791
1792        if (DEBUG.messageEnabled()) {
1793            DEBUG.message("PolicyEvaluator:computing policy decisions "
1794                    + " for resource : " + resourceName);
1795        }
1796        PolicyDecision policyDecision = getPolicyDecision(token, resourceName,
1797                actionNames, envParameters);
1798        resourceResult =  new ResourceResult(resourceName, policyDecision);
1799
1800        if (ResourceResult.SUBTREE_SCOPE.equals(scope)) {
1801            ResourceResult virtualResourceResult 
1802                    = new ResourceResult(ResourceResult.VIRTUAL_ROOT, 
1803                    new PolicyDecision());
1804            virtualResourceResult.addResourceResult(resourceResult, 
1805                    serviceType);
1806            resourceResult = virtualResourceResult;
1807        }
1808
1809        if (ResourceResult.SUBTREE_SCOPE.equals(scope)
1810                || ResourceResult.STRICT_SUBTREE_SCOPE.equals(scope)) {
1811            Map resourceNamesCache    
1812                    = (Map)resourceNamesMap.get(serviceTypeName);
1813            if (resourceNamesCache == null) {
1814                resourceNamesCache = new Cache(resultsCacheResourceCap);
1815                resourceNamesMap.put(serviceTypeName, resourceNamesCache);
1816            }
1817            Set resourceNames = (Set)resourceNamesCache.get(resourceName);
1818            if (resourceNames == null) {
1819                if (DEBUG.messageEnabled()) {
1820                    DEBUG.message("Computing subresources for:  "
1821                            + resourceName);
1822                }
1823                // true indicates to follow referral
1824                resourceNames = getResourceNames(token, resourceName, true);
1825                resourceNames = removeDuplicateResourceNames(resourceNames,
1826                        serviceType);
1827                resourceNames = removeResourceName(resourceNames,
1828                        serviceType, resourceName);
1829                resourceNamesCache.put(resourceName, resourceNames);
1830            }
1831            if (DEBUG.messageEnabled()) {
1832                DEBUG.message("PolicyEvaluator:computing policy decisions "
1833                        + " for subresources : " + resourceNames);
1834            }
1835
1836            Iterator resourceNameIter = resourceNames.iterator();
1837            while (resourceNameIter.hasNext()) {
1838                String subResourceName = (String) resourceNameIter.next();
1839                if (ResourceResult.SUBTREE_SCOPE.equals(scope) ||
1840                        (serviceType.compare(resourceName,
1841                        subResourceName, false).equals(
1842                        ResourceMatch.SUB_RESOURCE_MATCH))) {
1843                    PolicyDecision pDecision = getPolicyDecision(token, 
1844                            subResourceName, actionNames, envParameters);
1845                    resourceResult.addResourceResult(
1846                            new ResourceResult(subResourceName, pDecision),
1847                            serviceType);
1848                }
1849            }
1850        }
1851  
1852        // Do not cache policy decision with advices
1853        if ( (resourceResult != null) 
1854                    && !resourceResult.hasAdvices()) {
1855            resourceResult.setEnvMap(clientEnv);
1856            // add the evaluation result to the result cache
1857            Map scopeElem = null;
1858            //cacheElem: sessionId -> scope -> resourceResult
1859            Map cacheElem = null;
1860            Map rscElem = null;
1861            // serviceType -> resourceName -> sessionId -> scope -> resourceResult
1862            synchronized(policyResultsCache) { 
1863                // rscElemCACHE: resourceName -> sessionId -> scope -> resourceResult
1864                rscElem = (Map)policyResultsCache.get(
1865                                                serviceTypeName);
1866                if (rscElem != null) { // serviceType has been seen earlier
1867                    //CACHEElem: sessionId -> scope -> resourceResult
1868                    cacheElem = (Map)rscElem.get(resourceName);
1869                    if (cacheElem != null) { // resource seen earlier
1870                        scopeElem = (Map)cacheElem.get(
1871                                                userSSOTokenIDStr);
1872                        if (scopeElem == null) { // seeing sessionId first time
1873                            scopeElem = new HashMap();
1874                        }
1875                    } else { // seeing the resource first time
1876                        if (PolicyManager.debug.messageEnabled()) {
1877                            PolicyManager.debug.message(
1878                                "PolicyEvaluator.getResourceResultTree()"
1879                                + " Create Cache for:" 
1880                                + ", resourceName=" + resourceName
1881                                + ", sessionId=" + userSSOTokenIDStr
1882                                + ", scope=" + scope);
1883                        }
1884                        cacheElem = new Cache(resultsCacheSessionCap); 
1885                        scopeElem = new HashMap();
1886                    }
1887                } else { // seeing service for first time
1888                    // rscElemCACHE: resourceName -> sessionId -> scope -> resourceResult
1889                    rscElem = new Cache(resultsCacheResourceCap);
1890                    //CACHEElem: sessionId -> scope -> resourceResult
1891                    if (PolicyManager.debug.messageEnabled()) {
1892                            PolicyManager.debug.message(
1893                                "PolicyEvaluator.getResourceResultTree()"
1894                                + " Create Cache for:" 
1895                                + ", resourceName=" + resourceName
1896                                + ", sessionId=" + userSSOTokenIDStr
1897                                + ", scope=" + scope
1898                                + ", serviceType=" + serviceTypeName);
1899                    }
1900                    cacheElem = new Cache(resultsCacheSessionCap);
1901                    scopeElem = new HashMap();
1902                }
1903                scopeElem.put(scope, resourceResult);
1904                cacheElem.put(userSSOTokenIDStr, scopeElem);
1905                if (PolicyManager.debug.messageEnabled()) {
1906                        PolicyManager.debug.message(
1907                            "PolicyEvaluator.getResourceResultTree()"
1908                            + " Create Cache for:" 
1909                            + ", resourceName=" + resourceName
1910                            + ", sessionId=" + userSSOTokenIDStr
1911                            + ", scope=" + scope
1912                            + ", cacheSize=" + cacheElem.size());
1913                }
1914                rscElem.put(resourceName, cacheElem);
1915                policyResultsCache.put(serviceTypeName, rscElem);
1916            } 
1917
1918            if ( (token != null) 
1919                        && !(ssoListenerRegistry.containsKey(
1920                        userSSOTokenIDStr))) {
1921                try {
1922                    token.addSSOTokenListener(ssoListener);
1923                } catch (SSOException se) {
1924                    DEBUG.error("PolicyEvaluator:"
1925                            + "failed to add sso token listener");
1926                }
1927                ssoListenerRegistry.put(userSSOTokenIDStr, ssoListener);
1928                if (DEBUG.messageEnabled()) {
1929                    DEBUG.message("PolicyEvaluator.getResourceResultTree():"
1930                            + " sso listener added .\n");
1931                }
1932            }
1933            if (DEBUG.messageEnabled()) {
1934                DEBUG.message("PolicyEvaluator: we added the evaluation "
1935                        + " result to the cache");
1936            }
1937        } 
1938
1939        return resourceResult;
1940    }
1941
1942
1943    /**
1944     * Gets resource names that are exact matches, sub resources or 
1945     * wild card matches of argument resource name.
1946     * To determine whether to include a
1947     * resource name of a resource,  we compare argument resource name and 
1948     * policy resource name, treating wild characters in the policy 
1949     * resource name as wild. If the comparison resulted in
1950     * <code>EXACT_MATCH</code>, <code>WILD_CARD_MACTH</code> or
1951     * <code>SUB_RESOURCE_MACTH</code>, the resource result would be
1952     * included.
1953     *
1954     * @param token single sign on token
1955     *
1956     * @param resourceName resoure name
1957     * @param followReferral indicates whether to follow the referrals 
1958     *                       defined in policies to compute resource names
1959     * @return names of sub resources for the given <code>resourceName</code>.
1960     *         The return value would also include the
1961     *         <code>resourceName</code>.
1962     *
1963     * @exception SSOException if <code>token</code> is invalid
1964     * @exception PolicyException for any other abnormal condition
1965     *
1966     * @see ResourceMatch#EXACT_MATCH
1967     * @see ResourceMatch#SUB_RESOURCE_MATCH
1968     * @see ResourceMatch#WILDCARD_MATCH
1969     *
1970     */
1971     public Set getResourceNames(SSOToken token, String resourceName, 
1972             boolean followReferral) throws PolicyException, SSOException {
1973         Set visitedOrgs = new HashSet();
1974         visitedOrgs.add(policyManager.getOrganizationDN());
1975         return getResourceNames(token, resourceName, followReferral,
1976                 visitedOrgs);
1977     }
1978
1979    /**Gets resource names that are exact matches, sub resources or 
1980     * wild card matches of argument resource name.
1981     * To determine whether to include a
1982     * resource name of a resource,  we compare argument resource name and 
1983     * policy resource name, treating wild characters in the policy 
1984     * resource name as wild. If the comparsion resulted in 
1985     * <code>EXACT_MATCH</code>, <code>WILD_CARD_MACTH</code> or 
1986     * <code>SUB_RESOURCE_MACTH</code>, the resource result would be
1987     * included.
1988     *
1989     * @param token single sign on token
1990     *
1991     * @param resourceName resoure name
1992     * @param followReferral indicates whether to follow the referrals 
1993     *                       defined in policies to compute resource names
1994     * @param visitedOrgs organizations that were already visited to 
1995     *                    compute resource names
1996     * @return names of sub resources for the given <code>resourceName</code>.
1997     *         The return value would also include the
1998     *         <code>resourceName</code>.
1999     *
2000     * @exception SSOException if <code>token</code> is invalid
2001     * @exception PolicyException for any other abnormal condition
2002     *
2003     * @see ResourceMatch#EXACT_MATCH
2004     * @see ResourceMatch#SUB_RESOURCE_MATCH
2005     * @see ResourceMatch#WILDCARD_MATCH
2006     *
2007     */
2008     public Set getResourceNames(SSOToken token, String resourceName, 
2009             boolean followReferral, Set visitedOrgs) 
2010             throws PolicyException, SSOException {
2011         DEBUG.message("PolicyEvaluator.getResourceNames():entering");
2012         Set resourceNames = new HashSet();
2013         Set policyNameSet = null;
2014         Set toRemovePolicyNameSet = null;
2015         Set orgsToVisit = new HashSet();
2016         policyNameSet = resourceIndexManager.getSubResourcePolicyNames(
2017                serviceType, resourceName);
2018         policyNameSet.addAll(
2019                resourceIndexManager.getPolicyNames(serviceType,
2020                resourceName, true)); //include policies of super resources
2021         policyNameSet.addAll(
2022                resourceIndexManager.getWildSubResourcePolicyNames(
2023                serviceType, resourceName));
2024         if ( (policyNameSet != null) && (!policyNameSet.isEmpty()) ) {
2025             Iterator policyIter = policyNameSet.iterator();
2026             while (policyIter.hasNext()) {
2027                 String policyName = (String) policyIter.next();
2028                 Policy policy = policyManager.getPolicy(policyName, 
2029                        USE_POLICY_CACHE);
2030                 // policy could have been deleted
2031                 if ( policy != null && policy.isActive()) {
2032                     // true inidicates to follow referrals
2033                     Set pResourceNames = policy.getResourceNames(token, 
2034                             serviceTypeName, resourceName, true);
2035                     if (pResourceNames != null) {
2036                         resourceNames.addAll(pResourceNames);
2037                     }
2038                 } else { // add policy names to toRemovePolicyNameSet
2039                    if (toRemovePolicyNameSet == null) {
2040                        toRemovePolicyNameSet = new HashSet();
2041                    }
2042                    toRemovePolicyNameSet.add(policyName);
2043                    if ( DEBUG.messageEnabled() ) {
2044                        DEBUG.message("PolicyEvaluator.getResourceNames():"
2045                            +policyName+ " is inactive or non-existent");
2046                    }
2047                 }
2048             }
2049             // remove inactive/missing policies from policyNameSet
2050             if (toRemovePolicyNameSet != null) {
2051                 policyNameSet.removeAll(toRemovePolicyNameSet);
2052             }
2053
2054             orgsToVisit.addAll(getOrgsToVisit(policyNameSet));
2055
2056             if ( DEBUG.messageEnabled() ) {
2057                 DEBUG.message("PolicyEvaluator.getResourceNames():"
2058                     + "realmAliasEnabled=" 
2059                     + PolicyConfig.orgAliasMappedResourcesEnabled()
2060                     + ", serviceTypeName=" + serviceTypeName);
2061             }
2062         }
2063         if (PolicyConfig.orgAliasMappedResourcesEnabled()
2064                && PolicyManager.WEB_AGENT_SERVICE.equalsIgnoreCase(
2065                serviceTypeName)) {
2066             String orgAlias = policyManager.getOrgAliasWithResource(
2067                    resourceName); 
2068             if (orgAlias != null) {
2069                 String orgWithAlias = policyManager.getOrgNameWithAlias(
2070                        orgAlias);
2071                 if (orgWithAlias != null) {
2072                     if ( DEBUG.messageEnabled() ) {
2073                         DEBUG.message("PolicyEvaluator."
2074                                 + "getgetResourceNames():"
2075                                 + "adding orgWithAlias to orgsToVisit="
2076                                 + orgWithAlias);
2077                     }
2078                     orgsToVisit.add(orgWithAlias);
2079                 } else {
2080                     if ( DEBUG.messageEnabled() ) {
2081                         DEBUG.message("PolicyEvaluator."
2082                                 + "getgetResourceNames():"
2083                                 + "no realm matched orgAlias:" + orgAlias);
2084                     }
2085                 }
2086             }
2087         }
2088
2089         orgsToVisit.removeAll(visitedOrgs);
2090         while (!orgsToVisit.isEmpty() ) {
2091             String orgToVisit = (String) orgsToVisit.iterator().next();
2092             orgsToVisit.remove(orgToVisit);
2093             visitedOrgs.add(orgToVisit);
2094             //resourceNames.add(resourceName);
2095             try {
2096                 // need to use admin sso token here. Need all privileges to
2097                 // check for the organzation
2098                 policyManager.verifyOrgName(orgToVisit);
2099             } catch (NameNotFoundException nnfe) {
2100                 if( DEBUG.warningEnabled()) {
2101                     DEBUG.warning("PolicyEvaluator."
2102                            + "getgetResourceNames():"
2103                             + "Organization does not exist - "
2104                             + "skipping referral to " + orgToVisit);
2105                 }
2106                 continue;
2107             }
2108             PolicyEvaluator pe = new PolicyEvaluator(orgToVisit, 
2109                    serviceTypeName);
2110             resourceNames.addAll(pe.getResourceNames(token, 
2111                    resourceName, true,
2112                    visitedOrgs)); 
2113         }
2114         return resourceNames; 
2115     }
2116
2117     /** Adds a policy listener that would be notified whenever a policy
2118      *  is added, removed or changed
2119      *
2120      *  @param policyListener the listener to be added
2121      * 
2122      * @supported.api
2123      */
2124      public void addPolicyListener(PolicyListener policyListener) {
2125          policyCache.addPolicyListener(policyListener);
2126      }
2127
2128     /** Removes a policy listener that was previously registered 
2129      *  to receive notifications whenever a policy is added, removed
2130      *  or changed. It is not an error to attempt to remove a listener
2131      *  that was not registered. It would return silently.
2132      *
2133      *  @param policyListener the listener to be removed
2134      * 
2135      * @supported.api
2136      */
2137      public void removePolicyListener(PolicyListener policyListener) {
2138          policyCache.removePolicyListener(policyListener);
2139      }
2140     
2141      /** Merges two policy decisions.
2142       *  Merging policy decisions merges each action decision of the 
2143       *  policy with the corresponding action decision of the other 
2144       *  policy. This method also merges ResponseProviderDecision of one
2145       *  policy ( response attributes per policy) 
2146       *  with that of the other policy.
2147       *  These are the rules followed to merge each action decision:
2148       *  If the action schema has boolean syntax, boolean false value
2149       *  overrides boolean true value. The time to live of boolean false 
2150       *  value overrides the time to live of boolean true value.
2151       *  Otherwise, action values are simply  aggregated. Time to live
2152       *  is set to the minimum of time to live(s) of all values of the
2153       *  action.
2154       *  For response attributes, all response attributes are aggregated.
2155       *  In case of mutiple values for the same attribute 
2156       *  they appear as multi valued data for the attribute.
2157       *  @param serviceType service type that would be consulted to merge the
2158       *         policy decisions
2159       *  @param pd1 policy decision 1
2160       *  @param pd2 policy decision 2
2161       *  @return the merged policy decision. 
2162       *          Policy decisions pd1 and pd2 are merged into pd2 and 
2163       *          pd2 is returned.
2164       */
2165       static PolicyDecision mergePolicyDecisions(ServiceType
2166            serviceType, PolicyDecision pd1, PolicyDecision pd2) {
2167          Map actionDecisions1 = pd1.getActionDecisions();
2168          Set actions = new HashSet();
2169          actions.addAll(actionDecisions1.keySet());
2170          Iterator iter = actions.iterator();
2171          while ( iter.hasNext() ) {
2172              String action = (String) iter.next();
2173              ActionDecision ad1 = (ActionDecision) actionDecisions1.get(
2174                    action);
2175              pd2.addActionDecision(ad1, serviceType);
2176          }
2177          Map mergedReponseAttrsMap = new HashMap();
2178          PolicyUtils.appendMapToMap(pd1.getResponseAttributes(),
2179                mergedReponseAttrsMap);
2180          PolicyUtils.appendMapToMap(pd2.getResponseAttributes(), 
2181                mergedReponseAttrsMap);
2182          pd2.setResponseAttributes(mergedReponseAttrsMap);
2183          return pd2;
2184      }
2185
2186      /** Gets a set of action names for which final values have been 
2187       *  determined. We assume the final values have been determined
2188       *  for an action if the action schema syntax is boolean and 
2189       *  the value is boolean false value
2190       *
2191       *  @param serviceType service type that would be consulted to decide
2192       *         the final values for actions
2193       *  @param pd policy decision 
2194       */
2195      static Set getFinalizedActions(ServiceType
2196            serviceType, PolicyDecision pd) {
2197        Set finalizedActions = new HashSet();
2198        Map actionDecisions = pd.getActionDecisions();
2199        Iterator actions = actionDecisions.keySet().iterator();
2200        while ( actions.hasNext() ) {
2201            String action = (String) actions.next();
2202            ActionDecision actionDecision 
2203                  = (ActionDecision) actionDecisions.get(action);
2204            Set values = actionDecision.getValues();
2205            if ( (values != null) && !values.isEmpty() ) {
2206                try {
2207                    ActionSchema schema 
2208                            = serviceType.getActionSchema(action);
2209                    if ((AttributeSchema.Syntax.BOOLEAN.equals(
2210                                schema.getSyntax()))
2211                                && values.contains(schema.getFalseValue()) ) {
2212                        finalizedActions.add(action);
2213                    }
2214                } catch(InvalidNameException e) {
2215                    DEBUG.error("can not find action schmea for action = " +
2216                            action, e );
2217                }
2218
2219            }
2220              
2221
2222        }
2223        return finalizedActions;
2224      }
2225
2226    /**
2227     *  Gets names of organizations to visit for policy evaluation
2228     *  based on the give policy names.  This is used to follow 
2229     *  OrgReferral(s) defined in the policies
2230     *
2231     *  @return names of organization to visit
2232     *  @exception SSOException if <code>token</code> is invalid
2233     *  @exception PolicyException for any other abnormal condition
2234     */
2235    private Set getOrgsToVisit(Set policyNameSet) 
2236            throws PolicyException, SSOException {
2237        Set orgsToVisit = new HashSet();
2238        Iterator policyNames = policyNameSet.iterator();
2239        while ( policyNames.hasNext() ) {
2240            String policyName = (String) policyNames.next();
2241            Policy policy = policyManager.getPolicy(policyName, 
2242                USE_POLICY_CACHE);
2243            if (policy != null) {
2244                orgsToVisit.addAll(policy.getReferredToOrganizations());
2245            }
2246        }
2247        return orgsToVisit;
2248    }
2249
2250    /**
2251     *   This would be a costly operation.
2252     *   Can be avoided if ResourceName has api for getting canonical name.
2253     *   When the policies are stored, resource names would be converted to and 
2254     *   stored as canonical name.
2255     */
2256    private static Set removeDuplicateResourceNames(Set resourceNames,
2257            ServiceType serviceType) {
2258        Set answer = resourceNames;
2259        if ( (resourceNames != null) && (serviceType != null) ) {
2260            answer = new HashSet(resourceNames.size());
2261            Iterator iter = resourceNames.iterator();
2262            while ( iter.hasNext() ) {
2263                String resourceName = (String) iter.next();
2264                Iterator answerIter = answer.iterator();
2265                boolean duplicate = false;
2266                while (answerIter.hasNext()) {
2267                    String answerResourceName = (String) answerIter.next();
2268
2269                    if ( serviceType.compare(resourceName,
2270                            answerResourceName, false)
2271                            .equals(ResourceMatch.EXACT_MATCH) ) {
2272                        duplicate = true;
2273                        break;
2274                    } 
2275                } 
2276                if (!duplicate) {
2277                    answer.add(resourceName);
2278                }
2279            }
2280
2281        }
2282        return answer;
2283    }
2284
2285    /**
2286     * Removes the <code>resourceName</code> from the <code>Set</code>
2287     * of resource names matching on <code>serviceType</code> and
2288     * performing a <code>ResourceMatch.EXACT_MATCH</code>
2289     */
2290
2291    private static Set removeResourceName(Set resourceNames, 
2292            ServiceType serviceType, String resourceName) {
2293        Set answer = resourceNames;
2294        if ( (resourceNames != null) && (serviceType != null) 
2295                    && (resourceName != null) ) {
2296            answer = new HashSet(resourceNames.size());
2297            answer.addAll(resourceNames);
2298            Iterator iter = resourceNames.iterator();
2299            while ( iter.hasNext() ) {
2300                String rName = (String) iter.next();
2301                if ( serviceType.compare(resourceName,
2302                        rName, false).equals(ResourceMatch.EXACT_MATCH) ) {
2303                    answer.remove(rName);
2304                }
2305            }
2306
2307        }
2308        return answer;
2309    }
2310
2311
2312    /**
2313     * Handles policyChanged notifications - clears the cached resource
2314     * names for the service type name
2315     *
2316     * @param serviceTypeName service type name
2317     * @param pe policy event
2318     */
2319    static void policyChanged(String serviceTypeName, PolicyEvent pe) {
2320
2321        if (DEBUG.messageEnabled()) {
2322            DEBUG.message("PolicyEvaulator.policyChanged():serviceTypeName="
2323                    + serviceTypeName);
2324        }
2325        resourceNamesMap.remove(serviceTypeName);
2326
2327        Cache resourceNamesCache    
2328                = (Cache)resourceNamesMap.get(serviceTypeName);
2329        if ((resourceNamesCache == null) || (resourceNamesCache.isEmpty())) {
2330            return;
2331        }
2332        try {
2333            DEBUG.error("PolicyEvaluator.policyChanged: enterred try block");
2334            ServiceTypeManager stm = ServiceTypeManager.getServiceTypeManager();
2335            ServiceType serviceType = stm.getServiceType(serviceTypeName);
2336            Set resourceNamesToRemove = new HashSet();
2337            synchronized(resourceNamesCache) {
2338                Enumeration resourceNames = resourceNamesCache.keys();
2339                while (resourceNames.hasMoreElements()) {
2340                    String resourceName = (String)resourceNames.nextElement();
2341                    if (resourceNamesToRemove.contains(resourceName)) {
2342                        continue;
2343                    }
2344                    Set affectedResourceNames = pe.getResourceNames();
2345                    Iterator iter = affectedResourceNames.iterator();
2346                    while (iter.hasNext())  {
2347                        String affectedResourceName = (String)iter.next();
2348                        if (serviceType.compare(resourceName, 
2349                                    affectedResourceName)
2350                                    != ResourceMatch.NO_MATCH) {
2351                            resourceNamesToRemove.add(resourceName);
2352                        }
2353                    }
2354                }
2355                Iterator iter1 = resourceNamesToRemove.iterator();
2356                while (iter1.hasNext()) {
2357                    String resourceNameToRemove = (String) iter1.next();
2358                    resourceNamesCache.remove(resourceNameToRemove);
2359                }
2360            }
2361        } catch (SSOException e) {
2362            DEBUG.error("PolicyEvaluator.policyChanged:", e);
2363        } catch (PolicyException pex) {
2364            DEBUG.error("PolicyEvaluator.policyChanged:", pex);
2365        }
2366        if (DEBUG.messageEnabled()) {
2367            DEBUG.message("PolicyEvaulator.policyChanged():serviceTypeName="
2368                    + serviceTypeName
2369                    + ", new cached resoruceNames=" 
2370                    + resourceNamesMap.get(serviceTypeName));
2371        }
2372    }
2373
2374    /**
2375     * Add an advice to the policy decision.
2376     * @param pd <code>PolicyDecision</code> in which to add the advice.
2377     * @param adviceKey key to the condition generating the advice
2378     *        like SessionCondition.SESSION_CONDITION_ADVICE, 
2379     *        AuthSchemeCondition.AUTH_SCHEME_CONDITION_ADVICE
2380     * @param adviceValue advice message to be added to the advice
2381     */
2382    private static void addAdvice(PolicyDecision pd, String adviceKey, 
2383            String adviceValue) {
2384        if ((pd != null) 
2385                    && (pd.hasAdvices())) {
2386            Map actionDecisions = pd.getActionDecisions();
2387            Iterator actionDecisionIter = actionDecisions.keySet().iterator();
2388            while (actionDecisionIter.hasNext()) {
2389                String key = (String) actionDecisionIter.next();
2390                ActionDecision ad = (ActionDecision) actionDecisions.get(key);
2391                Map advices = ad.getAdvices();
2392                if ((advices != null) && !advices.isEmpty()) {
2393                    Set values = (Set)advices.get(adviceKey);
2394                    if (values == null) {
2395                        values = new HashSet();
2396                    }
2397                    values.add(adviceValue);
2398                    advices.put(adviceKey, values);
2399                }
2400            }
2401        }
2402    }
2403
2404    /**
2405     * Get the policy decision for a resource ignoring the subject
2406     */
2407
2408    PolicyDecision getPolicyDecisionIgnoreSubjects(String resourceName, 
2409            Set actionNames, Map env) throws PolicyException, SSOException  {
2410
2411        Set originalResourceNames = new HashSet(2);
2412        originalResourceNames.add(resourceName);
2413
2414        /*
2415         * Add request resourceName and request actionNames to the envParameters
2416         * so that Condition(s)/ResponseProvider(s) can use them if necessary
2417         */
2418        Set resourceNames = new HashSet(2);
2419        resourceNames.add(resourceName);
2420
2421        /* compute for all action names if passed in actionNames is
2422           null or empty */
2423        if ( (actionNames == null) || (actionNames.isEmpty()) ) {
2424            actionNames = serviceType.getActionNames();
2425        }
2426
2427        Set actions = new HashSet();
2428        if (actionNames != null) {
2429            actions.addAll(actionNames);
2430        }
2431
2432        //We create new HashMap in place of empty map since
2433        //Collections.EMPTY_MAP can not be modified
2434        if ((env == null) || env.isEmpty()) {
2435            env = new HashMap();
2436        }
2437
2438        env.put(SUN_AM_REQUESTED_RESOURCE, resourceNames);
2439        env.put(SUN_AM_ORIGINAL_REQUESTED_RESOURCE, 
2440                originalResourceNames);
2441        env.put(SUN_AM_REQUESTED_ACTIONS, actions);
2442        env.put(REALM_DN, asSet(policyManager.getOrganizationDN()));
2443
2444        return getPolicyDecision(null, resourceName, actionNames, env,
2445                new HashSet());
2446    }
2447
2448
2449    /**
2450     * Get the set of role DNs of a user. The role DNs are cached to 
2451     * improve the performance of IdentityServerRole subject membership
2452     * validation.
2453     *
2454     * @param token single sign on token of the user evaluating policies
2455     *
2456     * @return The set of user <code>nsRole</code> attribute values
2457     *
2458     * @exception SSOException single-sign-on token invalid or expired
2459     * @exception PolicyException if an error occured while getting the
2460     *            user's nsRole attribute value set
2461     */
2462     public static Set getUserNSRoleValues(SSOToken token)
2463        throws SSOException, PolicyException {
2464        if (userNSRoleCacheTTL == 0) {
2465            synchronized(userNSRoleCache) {
2466                String orgName = ServiceManager.getBaseDN();
2467                Map pConfigValues = PolicyConfig.getPolicyConfig(orgName);
2468                userNSRoleCacheTTL = 
2469                     PolicyConfig.getSubjectsResultTtl(pConfigValues);
2470                if (userNSRoleCacheTTL <= 0) {
2471                    userNSRoleCacheTTL = DEFAULT_USER_NSROLE_CACHE_TTL;
2472                    if (DEBUG.warningEnabled()) {
2473                        DEBUG.warning("Invalid TTL got from configuration."
2474                                    + " Set TTL to default:" 
2475                                    + userNSRoleCacheTTL);
2476                    }
2477                }
2478                if (DEBUG.messageEnabled()) {
2479                    DEBUG.message("userNSRoleCacheTTL=" 
2480                                   + userNSRoleCacheTTL);
2481                }
2482            }
2483        }
2484        if (token == null) {
2485            return null;
2486        }
2487        String tokenIDStr = token.getTokenID().toString();
2488        Object[] element = (Object[])userNSRoleCache.get(tokenIDStr);
2489        if (element != null) {
2490            Long timeStamp = (Long)element[0];
2491            long timeToLive = 0;
2492            if (timeStamp != null) {
2493                timeToLive = timeStamp.longValue();
2494            }
2495            long currentTime = System.currentTimeMillis();
2496            if (timeToLive > currentTime) {
2497                if (DEBUG.messageEnabled()) {
2498                    DEBUG.message("PolicyEvaluator.getUserNSRoleValues():"
2499                              + " get the nsRole values from cache.\n");
2500                }
2501                return (HashSet)element[1];
2502            }
2503        }
2504        // add or update the cache entry.
2505        // we come here either the token is first registered with the
2506        // cache or the cache element is out of date. 
2507        try {
2508            AMStoreConnection am = new AMStoreConnection(token);
2509            AMUser user = am.getUser(token.getPrincipal().getName());
2510            if ((user == null) || !(user.isActivated())) {
2511                return null;
2512            }
2513            Set roleSet = new HashSet();
2514            Set roles = new HashSet();
2515            // get all the roles assigned to the user
2516            Set staticRoles = user.getRoleDNs();
2517            Set filteredRoles = user.getFilteredRoleDNs();
2518            if (staticRoles != null) {
2519                roles.addAll(staticRoles);
2520            }
2521            if (filteredRoles != null) {
2522                roles.addAll(filteredRoles);
2523            }
2524            if (!roles.isEmpty()) {
2525                Iterator iter = roles.iterator();
2526                while (iter.hasNext()) {
2527                    String role = (String) iter.next();
2528                    if (role != null) { 
2529                        roleSet.add((new DN(role)).toRFCString().toLowerCase());
2530                    }
2531                }
2532            }
2533            if (DEBUG.messageEnabled()) {
2534                DEBUG.message("PolicyEvaluator.getUserNSRoleValues():"
2535                            + " added user nsRoles: " + roleSet);
2536            }
2537            Object[] elem = new Object[2];
2538            elem[0] = new Long(System.currentTimeMillis() 
2539                               + userNSRoleCacheTTL);
2540            elem[1] = roleSet;
2541            userNSRoleCache.put(tokenIDStr, elem);
2542            if (!ssoListenerRegistry.containsKey(tokenIDStr)) {
2543                token.addSSOTokenListener(ssoListener);
2544                ssoListenerRegistry.put(tokenIDStr, ssoListener);
2545                if (DEBUG.messageEnabled()) {
2546                    DEBUG.message("PolicyEvaluator.getUserNSRoleValues():"
2547                            + " sso listener added .\n");
2548                }
2549            }
2550            return roleSet;
2551        } catch (AMException e) {
2552            throw (new PolicyException(e));
2553        }
2554    }
2555
2556    /**
2557     * record stats for policyResultsCache,  ssoListenerRegistry, 
2558     * policyListenerRegistry, userNSRoleCache, resouceNamesMap
2559     */
2560    static void printStats(Stats policyStats) {
2561
2562
2563        int resultsCacheSize = 0;
2564        synchronized (policyResultsCache) {
2565            resultsCacheSize = policyResultsCache.size();
2566        }
2567        policyStats.record("PolicyEvaluator: Number of services in "
2568                + " resultsCache: " + resultsCacheSize);
2569
2570        policyStats.record("PolicyEvaluator: Number of token IDs in "
2571                + " sessionListernerRgistry:"
2572                + ssoListenerRegistry.size());
2573
2574        policyStats.record("PolicyEvaluator: Number of serviceNames "
2575                + " in policyListenerRegistry: "
2576                + policyListenerRegistry.size());
2577
2578        policyStats.record("PolicyEvaluator: Number of token IDs "
2579                + " in role cahce: " + userNSRoleCache.size());
2580
2581        policyStats.record("PolicyEvaluator:Number of serviceNames in "
2582                + " resourceNames cache: " 
2583                + resourceNamesMap.size());
2584    }
2585}




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.