package com.nailabs.abac.process; import com.nailabs.abac.trust.*; import com.nailabs.abac.test.*; import java.util.*; /** * The strategy handles processing a working list of nodes in the trust target * graph to be processed. */ public class Strategy extends Observable { /** The context for which this strategy is negotiating */ protected NegotiationContext context; /** The worklist for nodes to be processed */ private LinkedList workList = new LinkedList(); private SatisfactionState state = new SatisfactionState(SatisfactionState.UNKNOWN); /** The last message sent out */ protected Message lastMessage = null; /** The current message just received */ protected Message currentMessage = null; /** creates a new strategy to process a trust negotiation */ public Strategy(NegotiationContext context) { this.context = context; //context.setStrategy(this); } /** Adds a node to the work list of nodes to be processed */ public void addToWorklist(TTGNode node) { if(node != null && workList.add(node)) { debug("worklist", node.getGoal() + " added to worklist"); debug("strategy", "worklist = " + workList); } } /** Adds a set of node to the work list */ public void addToWorklist(TTGNodeSet list) { if(list == null)return; Iterator i = list.values().iterator(); while(i.hasNext()) { try { TTGNode node = (TTGNode)i.next(); addToWorklist(node); } catch(Exception ex) { ex.printStackTrace(System.err); } } } /** determine the current state of negotiation */ public int getSatisfactionState() { int state = SatisfactionState.UNKNOWN; try { state = context.getGraph().getRoot().getSatisfactionValue(); } catch(Exception ex) { debug("strategy", "graph = " + context.getGraph()); debug("strategy", "root = " + context.getGraph().getRoot()); ex.printStackTrace(System.err); } if(isStuck() && (state != SatisfactionState.SATISFIED)) { debug("strategy", "Strategy: is stuck!"); return SatisfactionState.FAILED; } return state; } /** process nodes on the work list until the list is empty */ public SatisfactionState process(Message msg) { TTG graph = context.getGraph(); int state = getSatisfactionState(); addMessage(msg); if(state == SatisfactionState.SATISFIED || state == SatisfactionState.FAILED) { debug("strategy", "negotiation is complete status: " + state); return new SatisfactionState(state); } if(isStuck()) { debug("strategy", "negotiation is stuck!"); return new SatisfactionState(SatisfactionState.FAILED); } iterate(); addMessage(graph.getChanges()); if(isStuck()) { debug("strategy", "negotiation is stuck!"); return new SatisfactionState(SatisfactionState.FAILED); } return new SatisfactionState(state); } /** iterate through the work list until it is empty */ public void iterate() { debug("worklist", "worklist = " + workList); setChanged(); notifyObservers("location = local"); //while worklist is not empty while(!workList.isEmpty()) { //check for success or failure if(getSatisfactionState() != SatisfactionState.UNKNOWN) { return; } //process node at head of list //add list of nodes returned from process to the worklist TTGNode current = ((TTGNode)workList.removeFirst()); setCurrentParent(current); current.process(context); scheduleOperationsForNode(current); debug("strategy", "processing node " + current.getGoal()); debug("worklist", "worklist = " + workList); } } /** * Notify the strategy that a new edge needs to be added to the graph. * The strategy is responsible for performing the operation on the graph, * whether the strategy chooses to defer the operation or not. */ public void scheduleOperation(Operation op) { if(op instanceof EdgeOperation) { context.getGraph().performEdge((EdgeOperation)op); } else { context.getGraph().performNode((NodeOperation)op); } } /** Place-holder for stingy strategy. */ public void addSatisfiedControlChild(TTGNode node) { } /** Place-holder for stingy strategy */ public void addNewNode(TTGNode node) { } /** * convenience method for determining whether this negotiator has * a deadlock in processing the negotiation. This method can be * overridden is subsequent versions. */ protected boolean isStuck() { // if there's no history, we cannot be stuck yet if(currentMessage == null) return false; // if both messages contain no changes, then a deadlock has occurred return (currentMessage.getOperationsCount() == 0 ); } /** * add the current message to the queue. Note: the initial message will * also be null. */ protected void addMessage(Message msg) { lastMessage = currentMessage; currentMessage = msg; } /** Note the beginning of a new parent node being processed */ protected void setCurrentParent(TTGNode parent) { } /** Note the conclusion of a new parent node being processed */ protected void scheduleOperationsForNode(TTGNode parent) { } /** */ protected void debug(String key, String message) { StringBuffer buff = new StringBuffer("Strategy["); buff.append(context.getSelf()).append("]: ").append(message); Debug.debug(key, buff.toString()); } /** */ public void addObserver(Observer o) { super.addObserver(o); setChanged(); notifyObservers("location = init"); } }