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: ActionDecision.java,v 1.5 2008/06/25 05:43:43 qcheng Exp $
026 *
027 * Portions Copyrighted 2011-2014 ForgeRock AS.
028 */
029package com.sun.identity.policy;
030
031import com.sun.identity.shared.debug.Debug;
032import com.sun.identity.shared.xml.XMLUtils;
033import java.util.Map;
034import java.util.HashMap;
035import java.util.Set;
036import java.util.HashSet;
037import java.util.Iterator;
038import org.w3c.dom.*;
039
040
041/**
042 * The <code>ActionDecision</code> class represents the action results of a 
043 * policy evaluation. It has action values for a given <code>action</code> and 
044 * <code>advice</code>. 
045 *
046 * @supported.api
047 * @deprecated since 12.0.0
048 */
049@Deprecated
050public class ActionDecision {
051
052    static final String ACTION_DECISION = "ActionDecision";
053    static final String ADVICES = "Advices";
054    static final String VALUES = "Values";
055    static final String TIME_TO_LIVE = "timeToLive";
056    static Debug debug = Debug.getInstance("amPolicy");
057
058    private String actionName;
059    private Set values;
060    private long timeToLive = Long.MAX_VALUE;
061    private Map advices;
062
063    /**
064     *  Difference of system clock on the client machine compared to 
065     * policy server machine. Valid life of policy decisions are extended 
066     * by this skew on the client side.
067     * Value for this is set by reading property 
068     * com.sun.identity.policy.client.clockSkew
069     * from SystemProperties
070     * If the value is not defined in AMConfig.properties, 
071     * this would default to 0.
072     */
073    private static long clientClockSkew = 0;
074
075    /**
076     * No argument constructor
077     * @deprecated No replacement API provided. 
078     * There should be no need to invoke this constructor.
079     */
080    public ActionDecision() {
081    }
082
083    /**
084     * Constructor
085     * @param actionName name of the action.
086     * @param values a <code>Set></code> of <code>String</code> values for the 
087     * action
088     * @supported.api
089     */
090    public ActionDecision(String actionName, Set values) {
091        this.actionName = actionName;
092        this.values = values;
093    }
094
095    /**
096     * Constructor
097     * @param actionName action name
098     * @param values a <code>Set</code> of <code>String</code> values for the 
099     * action
100     * @param advices <code>advices</code> associated with this action 
101     *       decision. The advice name is the key to the Map. The
102     *       value is a set of advice message Strings corresponding 
103     *       to the  advice name.
104     * @param timeToLive the GMT time in milliseconds since epoch 
105     *       when this object is to  be treated as expired. 
106     *       That is the action values would likely be different
107     *       after that time.
108     * @supported.api
109     */
110    public ActionDecision(String actionName, Set values, Map advices,
111        long timeToLive
112    ) {
113        this.actionName = actionName;
114        this.values = values;
115        this.advices = advices;
116        this.timeToLive = timeToLive;
117    }
118
119    /**
120     * Gets the name of the action
121     *
122     * @return name of the action
123     * @supported.api
124     */
125    public String getActionName() {
126        return actionName;
127    }
128
129    /**
130     * Sets the action values for the action.  
131     *
132     * @param values a <code>Set</code> of String values
133     * @supported.api
134     */
135    public void setValues(Set values) {
136        this.values = values;
137    }
138
139    /**
140     * Gets the action values for the action.  
141     *
142     * @return a <code>Set>/code> of String values
143     * @supported.api
144     */
145    public Set getValues() {
146        return values;
147    }
148
149    /**
150     * Gets the GMT time in milliseconds since epoch when this object is to
151     * be treated as expired. That is the action values would likely be 
152     * different after that time.
153     * This is computed as a result of <code>SimpleTimeCondition(s)</code>
154     * specified in the Policy definition. 
155     *
156     * @return long represeting the time to live for this object.
157     * @supported.api
158     */
159    public long getTimeToLive() {
160        return timeToLive;
161    }
162
163    /**
164     * Sets the GMT time in milliseconds since epoch when this object is to
165     * be treated as expired. That is the action values would likely be 
166     * different after that time.
167     * This is computed as a result of <code>SimpleTimeCondition(s)</code> 
168     * specified in the Policy definition. 
169     *
170     * @param timeToLive time to live
171     * @supported.api
172     */
173    public void setTimeToLive(long timeToLive) {
174        this.timeToLive = timeToLive;
175    }
176
177    /**
178     * Sets <code>advices</code> associated with this <code>ActionDecision
179     * </code>.
180     * The advice name is the key to the <code>Map</code>. The
181     * value is a <code>Set</code> of advice message Strings corresponding to 
182     * the advice name. The two  possible advices are authentication 
183     * level(<code>AuthLevel</code>) and authentication modules
184     * (<code>AuthSchemes</code>). The advice message Strings for
185     * <code>AuthLevel</code> are integer valued.
186     *
187     * @param advices map of advices
188     * @supported.api
189     */
190    public void setAdvices(Map advices) {
191        this.advices = advices;
192    }
193
194    /**
195     * Returns a <code>Map</code> of <code>advices</code> associated with this 
196     * object. 
197     * The advice name is the key to the <code>Map</code>. The
198     * value is a <code>Set</code> of advice message Strings corresponding to 
199     * the advice name. The two  possible advices are authentication 
200     * level(<code>AuthLevel</code>) and authentication modules
201     * (<code>AuthSchemes</code>). The advice message Strings for
202     * <code>AuthLevel</code> are integer valued.
203     *
204     * @return advices associated with this <code>ActionDecision</code>.
205     * @supported.api
206     */
207    public Map getAdvices() {
208        return advices;
209    }
210
211    /**
212     * Gets a String representation of this object
213     *
214     * @return a String representation of this object
215     * @supported.api
216     */
217    public String toString() {
218        return actionName + "=" + values;
219    }
220
221    /**
222     * Gets an XML representation of this object
223     *
224     * @return XML representation of this object
225     * @supported.api
226     */
227     public String toXML() {
228        StringBuilder sb  = new StringBuilder(300);
229        sb.append("<").append(ACTION_DECISION).append(" ");
230        sb.append(TIME_TO_LIVE).append("=").append(
231                PolicyUtils.quote(timeToLive)).append(">");
232        sb.append(PolicyUtils.CRLF);
233        sb.append(PolicyUtils.attributeValuePairToXMLString(getActionName(), 
234            values));
235        sb.append("<").append(ADVICES).append(">").append(PolicyUtils.CRLF);
236        if (advices != null) {
237            sb.append(PolicyUtils.mapToXMLString(advices));
238        }
239        sb.append("</").append(ADVICES).append(">").append(PolicyUtils.CRLF);
240        sb.append("</").append(ACTION_DECISION).append(">").append(
241            PolicyUtils.CRLF);
242        return sb.toString();
243     }
244
245     /**
246     * Creates an ActionDecisions object given a w3c DOM node
247      *  @param actionDecisionNode w3c DOM node for action decision
248      *
249      *  @return ActionDecisions object created using the w3c DOM node
250      *  @throws PolicyException if any error occurs during parsing.
251      */
252     public static ActionDecision parseActionDecision(Node actionDecisionNode) 
253             throws PolicyException {
254        ActionDecision actionDecision = null;
255        //process action name and values
256        Set nodeSet = XMLUtils.getChildNodes(actionDecisionNode, 
257        PolicyUtils.ATTRIBUTE_VALUE_PAIR);
258        if ( (nodeSet == null) ||  (nodeSet.isEmpty()) ) {
259            debug.error("parseActionDecision: missing element " 
260            + PolicyUtils.ATTRIBUTE_VALUE_PAIR);
261            return null;
262        }
263        Iterator nodes = nodeSet.iterator();
264        Node node = (Node)nodes.next();
265        String actionName = PolicyUtils.getAttributeName(node);
266        Set actionValues = PolicyUtils.getAttributeValues(node);
267        actionDecision = new ActionDecision(actionName,
268        actionValues);
269
270        //process timeToLive
271        long timeToLive = Long.MAX_VALUE;
272        String ttlString = XMLUtils.getNodeAttributeValue(actionDecisionNode,
273        ActionDecision.TIME_TO_LIVE) ;
274        if ( ttlString != null ) {
275            try {
276                timeToLive = Long.parseLong(ttlString);
277                if (timeToLive != Long.MAX_VALUE) {
278                    timeToLive += clientClockSkew;
279                }
280            } catch (Exception e) {
281                debug.error("Error while parsing timeToLive in "
282                + " ActionDecision:" + ttlString);
283                Object [] args = { new Long(timeToLive) };
284                throw new PolicyException(ResBundleUtils.rbName,
285                        "invalid_time_to_live",
286                    args,e);
287            }
288        }
289        actionDecision.setTimeToLive(timeToLive);
290        
291        //process advices
292        Map advices = new HashMap();
293        nodeSet = XMLUtils.getChildNodes(actionDecisionNode,
294        ActionDecision.ADVICES);
295        if (nodeSet != null) {
296            nodes = nodeSet.iterator();
297            node = (Node) nodes.next();
298            nodeSet = XMLUtils.getChildNodes(node, 
299                PolicyUtils.ATTRIBUTE_VALUE_PAIR);
300            if ( nodeSet != null ) {
301                nodes = nodeSet.iterator();
302                while ( nodes.hasNext() ) {
303                    node = (Node) nodes.next();
304                    String adviceName = PolicyUtils.getAttributeName(node);
305                    if ( adviceName != null ) {
306                        Set adviceMessages = PolicyUtils.
307                            getAttributeValues(node);
308                        advices.put(adviceName, adviceMessages);
309                    }
310                }
311            }
312        }
313        actionDecision.setAdvices(advices);
314
315        return actionDecision;
316     }
317
318    /**
319     * Creates and returns a copy of this object.
320     *
321     * @return a copy of this object
322     */
323    public Object clone() {
324        ActionDecision clone = new ActionDecision();
325        clone.actionName = actionName;
326        clone.timeToLive = timeToLive;
327
328        if (values != null) {
329            Iterator valuesIter = values.iterator();
330            clone.values = new HashSet(values.size());
331            while (valuesIter.hasNext()) {
332                clone.values.add(valuesIter.next());
333            }
334        }
335
336        if (advices != null) {
337            Iterator adviceIter = advices.keySet().iterator();
338            clone.advices = new HashMap(advices.size());
339
340            while (adviceIter.hasNext()) {
341                String key = (String) adviceIter.next();
342                clone.advices.put(key, advices.get(key));
343            }
344        }
345
346        return clone;
347    }
348
349    /**
350     * Sets the client clock skew 
351     * @param skew the time skew in milliseconds, serverTime - clientTime
352     */
353    public static void setClientClockSkew(long skew) {
354        clientClockSkew = skew;
355    }
356
357}