001/**
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2008 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: Evaluator.java,v 1.2 2009/09/10 16:35:38 veiming Exp $
026 *
027 * Portions copyright 2013 ForgeRock AS.
028 */
029package com.sun.identity.entitlement;
030
031import com.sun.identity.entitlement.util.NetworkMonitor;
032import java.util.ArrayList;
033import java.util.List;
034import java.util.Map;
035import java.util.Set;
036import javax.security.auth.Subject;
037
038/**
039 * The class evaluates entitlement request and provides decisions.
040 * @supported.api
041 */
042public class Evaluator {
043
044    // Application retrieval log message code.
045    private static final int APP_RETRIEVAL_ERROR = 248;
046
047    private Subject adminSubject;
048    private String applicationName =
049        ApplicationTypeManager.URL_APPLICATION_TYPE_NAME;
050
051    public static final int DEFAULT_POLICY_EVAL_THREAD = 10;
052
053    // Statistics monitors
054    private static final NetworkMonitor HAS_ENTITLEMENT_MONITOR =
055        NetworkMonitor.getInstance("hasEntitltmentMonitor");
056    private static final NetworkMonitor EVAL_SINGLE_LEVEL_MONITOR =
057        NetworkMonitor.getInstance("evalSingleLevelMonitor");
058    private static final NetworkMonitor EVAL_SUB_TREE_MONITOR =
059        NetworkMonitor.getInstance("evalSubTreeMonitor");
060    
061    /**
062     * Constructor to create an evaluator of default service type.
063     *
064     * @throws EntitlementException if any other abnormal condition occ.
065     */
066    private Evaluator()
067        throws EntitlementException {
068    }
069
070    /**
071     * Constructor to create an evaluator given the service type.
072     *
073     * @param subject Subject who credential is used for performing the 
074     *        evaluation.
075     * @param applicationName the name of the aplication for
076     *        which this evaluator can be used.
077     * @throws EntitlementException if any other abnormal condition occured.
078     */
079    public Evaluator(Subject subject, String applicationName)
080        throws EntitlementException {
081        adminSubject = subject;
082        this.applicationName = applicationName;
083    }
084
085    /**
086     * Constructor to create an evaluator the default service type.
087     *
088     * @param subject Subject who credential is used for performing the 
089     *        evaluation.
090     * @throws EntitlementException if any other abnormal condition occured.
091     */
092    public Evaluator(Subject subject)
093        throws EntitlementException {
094        adminSubject = subject;
095    }
096    
097    /**
098     * Returns <code>true</code> if the subject is granted to an
099     * entitlement.
100     *
101     * @param realm Realm name.
102     * @param subject Subject who is under evaluation.
103     * @param e Entitlement object which describes the resource name and 
104     *          actions.
105     * @param envParameters Map of environment parameters.
106     * @return <code>true</code> if the subject is granted to an
107     *         entitlement.
108     * @throws EntitlementException if the result cannot be determined.
109     */
110    public boolean hasEntitlement(
111        String realm,
112        Subject subject, 
113        Entitlement e,
114        Map<String, Set<String>> envParameters
115    ) throws EntitlementException {
116        long start = HAS_ENTITLEMENT_MONITOR.start();
117
118        PrivilegeEvaluator evaluator = new PrivilegeEvaluator();
119        boolean result = evaluator.hasEntitlement(realm,
120            adminSubject, subject, applicationName, e, envParameters);
121
122        HAS_ENTITLEMENT_MONITOR.end(start);
123        return result;
124    }
125
126    /**
127     * Returns a list of entitlements for a given subject, resource names
128     * and environment.
129     *
130     * @param realm Realm Name.
131     * @param subject Subject who is under evaluation.
132     * @param resourceNames Resource names.
133     * @param environment Environment parameters.
134     * @return a list of entitlements for a given subject, resource name
135     *         and environment.
136     * @throws EntitlementException if the result cannot be determined.
137     */
138    public List<Entitlement> evaluate(
139        String realm,
140        Subject subject,
141        Set<String> resourceNames,
142        Map<String, Set<String>> environment
143    ) throws EntitlementException {
144        if ((resourceNames == null) || resourceNames.isEmpty()) {
145            throw new EntitlementException(424);
146        }
147
148        List<Entitlement> results = new ArrayList<Entitlement>();
149
150        for (String res : resourceNames) {
151            List<Entitlement> r = evaluate(realm, subject, res, environment,
152                false);
153            if ((r != null) && !r.isEmpty()) {
154                results.addAll(r);
155            }
156        }
157        return results;
158    }
159
160    /**
161     * Returns a list of entitlements for a given subject, resource name
162     * and environment.
163     *
164     * @param realm
165     *         Realm Name.
166     * @param subject
167     *         Subject who is under evaluation.
168     * @param resourceName
169     *         Resource name.
170     * @param environment
171     *         Environment parameters.
172     * @param recursive
173     *         <code>true</code> to perform evaluation on sub resources
174     *         from the given resource name.
175     * @return a list of entitlements for a given subject, resource name
176     *         and environment.
177     * @throws EntitlementException
178     *         if the result cannot be determined.
179     */
180    public List<Entitlement> evaluate(
181            String realm,
182            Subject subject,
183            String resourceName,
184            Map<String, Set<String>> environment,
185            boolean recursive
186    ) throws EntitlementException {
187        long start = (recursive) ? EVAL_SUB_TREE_MONITOR.start() : EVAL_SINGLE_LEVEL_MONITOR.start();
188
189        Application application = ApplicationManager.getApplication(adminSubject, realm, applicationName);
190
191        if (application == null) {
192            // App retrieval error.
193            throw new EntitlementException(APP_RETRIEVAL_ERROR, new String[] {realm});
194        }
195
196        // Normalise the incoming resource URL.
197        resourceName = application.getResourceComparator().canonicalize(resourceName);
198
199        PrivilegeEvaluator evaluator = new PrivilegeEvaluator();
200        List<Entitlement> results = evaluator.evaluate(realm, adminSubject, subject,
201                applicationName, resourceName, environment, recursive);
202
203        if (recursive) {
204            EVAL_SUB_TREE_MONITOR.end(start);
205        } else {
206            EVAL_SINGLE_LEVEL_MONITOR.end(start);
207        }
208
209        return results;
210    }
211
212    /**
213     * Returns application name.
214     * 
215     * @return application name.
216     */
217    public String getApplicationName() {
218        return applicationName;
219    }
220}
221