package com.nailabs.abac.trust; import com.nailabs.abac.process.*; import edu.stanford.peer.rbtm.credential.*; import java.util.*; /** * A target node is the parent class for the *TTNode classes, * which have the following common elements: satisfaction state, implication * parents, and control parents. */ public abstract class TargetNode extends TTGNode implements SatisfactionListener { /** The satisfaction state of this node */ protected SatisfactionState satisfier; /** * A set of implication parent nodes. Each parent represents a separate * edge in the trust target graph. * @see com.nailabs.abac.process.ImplicationEdge */ protected TTGNodeSet implicationParents = new TTGNodeSet(); /** * A set of control parent nodes. Each parent represents a separate edge * in the trust target graph. * @see com.nailabs.abac.process.ControlEdge */ protected TTGNodeSet controlParents = new TTGNodeSet(); /** Default constructor for a TargetNode */ public TargetNode(TrustTarget target) { super(target); subName = "TargetNode"; processor = new ProcessingState(); satisfier = new SatisfactionState(SatisfactionState.UNKNOWN); satisfier.addObserver(this); } /** Constructor which also creates a trust target implicitly */ public TargetNode(Entity verifier, EntityExpression target, Entity subject) throws CredentialParsingException, TrustTargetParsingException { this(new TrustTarget(verifier, target, subject)); } /** * This method should be polymorphic since children will have customized * fields. */ public void update(Observable obs, Object obj) { if(obs == satisfier) { setChanged(); notifyObservers(satisfier); } else { super.update(obs, obj); } } /** Read-only accessor method for the satisfaction state. */ public int getSatisfactionValue() { if(satisfier == null) return -1; return satisfier.getState(); } /** * Accessor method for setting the satisfaction state field. * @param state The new satisfaction state. * @return The old satisfaction state. */ protected SatisfactionState setState(SatisfactionState state) { SatisfactionState old = satisfier; satisfier = state; debug("satisfaction", "satisfaction state for " + getGoal() + " = " + state); //if(!satisfier.equals(old)) { setChanged(); notifyObservers(state); //} return old; } /** * Process a node whose trust target verifier entity is not self * @see RMINegotiator */ public abstract void opponentProcess(NegotiationContext context); /** * Process a node whose trust target verifier entity is self * @see RMINegotiator */ public abstract void verifierProcess(NegotiationContext context); /** * Records the new state and then propagates it to the parent listeners. * @param state The new satisfaction state to be propagated. */ public TTGNodeSet receive(TrustTarget source, SatisfactionState state) { TTGNodeSet results = new TTGNodeSet(); debug("satisfaction", getGoal() + " received " + state + " from " + source); // if the state has not changed stop propagating it if(!(this instanceof TrivialTTNode)) { if(satisfier.getState() == state.getState() || getGoal().equals(source)) { debug("satisfaction", "not trivial and received same state bailing out now!"); return results; } } setState(state); //} Iterator i = implicationParents.values().iterator(); while(i.hasNext()) { try { // this will fail if the parent is a linking goal SatisfactionListener listener = (SatisfactionListener)i.next(); TTGNodeSet branchResult = listener.receive((TrustTarget)getGoal(), state); if(branchResult == null && branchResult.size() > 0) { results.addAll(branchResult); } } catch(Exception ex) { // to print out exception uncomment ex.printStackTrace(); } } //if(state.getState() == SatisfactionState.FAILED) { //bail out for now... //return results; //} // Work with the control parents i = controlParents.values().iterator(); Strategy strategy = context.getStrategy(); //if satisfied and there exist control parent(s), then notify strategy if(state.getState() == SatisfactionState.SATISFIED) { if(i.hasNext()) { //notify strategy that a control child has been satisfied strategy.addSatisfiedControlChild(this); } while(i.hasNext()) { //place each control parent on the worklist TTGNode controlParent = (TTGNode)i.next(); strategy.addToWorklist(controlParent); } } System.out.println("TargetNode: " + getGoal() + "exiting receive method"); return results; } /** Add a goal as an implication parent of this node. */ public void addImplicationParent(TargetNode parent) { if(parent != null){ debug("node", "adding implication parent"); implicationParents.add(parent); parent.receive((TrustTarget)getGoal(), satisfier); } } /** Add a goal as a control parent of this node. */ public void addControlParent(TargetNode parent) { if(parent != null) { controlParents.add(parent); if(getSatisfactionValue() == SatisfactionState.SATISFIED) { context.getStrategy().addToWorklist(parent); } //setChanged(); //notifyObservers(); } //receive((TrustTarget)getGoal(), satisfier); } /** Convenience accessor method for the target role expression */ public EntityExpression getTargetExpression() { return ((TrustTarget)getGoal()).getTargetRole(); } public String toXML() { return toXML(new String("")); } public String toXML(String options) { return toXML(options, satisfier.toXML()); } /** Print out a node in human readable format */ public String toString() { StringBuffer buff = new StringBuffer("["); buff.append(getClass().getName()).append(", "); buff.append(processor).append(", "); buff.append(satisfier).append(", "); buff.append(getGoal().toString()).append("]"); return buff.toString(); } }