package edu.stanford.peer.rbtm.engine; import java.util.*; import edu.stanford.peer.rbtm.credential.*; import edu.stanford.peer.rbtm.util.*; /** * The parent class of all proof nodes. This is the base class which contains * default implementations of all common methods. */ public abstract class AbstractProofNode implements ProofNode { // The following two fields can't be changed by other classes. // If subclasses need to access them, use get methods /** The EntityExpression this node is about. */ EntityExpression _roleExp; /** * The proof _graph this node is in, this reference is used while * processing this node */ ProofGraph _graph; /** Processing mode for subclassed node types */ public final boolean addRole = true; /** Nodes that can reach this node directly, evidences are credentials. */ protected ResultEvidenceMap parents; /** Nodes that this node can reach directly, evidecens are credentials. */ protected ResultEvidenceMap children; /** Backward solutions on this node */ protected ResultEvidenceMap backwardSolutions; /** Forward solutions on this node */ protected ResultEvidenceMap forwardSolutions; protected ArrayList backwardListeners; protected ArrayList forwardListeners; boolean backwardProcessed; boolean forwardProcessed; AbstractProofNode (ProofGraph graph, EntityExpression re, int trackType) { _graph = graph; _roleExp = re; Debug.debugInfo("A new node is created for " + re); parents = new ResultEvidenceMap(trackType); children = new ResultEvidenceMap(trackType); backwardSolutions = new ResultEvidenceMap(trackType); forwardSolutions = new ResultEvidenceMap(trackType); backwardListeners = new ArrayList(10); forwardListeners = new ArrayList(10); } public ProofGraph getGraph() { return _graph; } public EntityExpression getRoleExp() { return _roleExp; } public ResultEvidenceMap getForwardSolutions() { return forwardSolutions; } public ResultEvidenceMap getBackwardSolutions() { return backwardSolutions; } public ResultEvidenceMap getChildren() { return children; } public ResultEvidenceMap getParents() { return parents; } /** * A single iteration of evidence gathering. This recursive method is * polymorphic and may be extended in child proof node implementations. * @param size the size of the evidence set (of credentials) * @param target the parent expression to be found in the cred graph */ public HashSet getChain(int size, EntityExpression target) { return new HashSet(size); } public void invalidateForward() { Debug.debugInfo("Invalidate forward result on " + this); if(forwardProcessed) { forwardProcessed = false; //reuse the credential and update the forward search getGraph().addForwardNode(getRoleExp()); } } public void invalidateBackward() { Debug.debugInfo("Invalidate backward result on " + this); if(backwardProcessed) { backwardProcessed = false; //reuse the credential and update the backward search getGraph().addBackwardNode(getRoleExp()); } } public void backwardProcess() { if (backwardProcessed) { return; } Predicate p = getGraph().getPredicate(); EntityExpression expr = getRoleExp(); Debug.debugInfo("Backward processing " + this); if(p == null) { // cred mgr has null predicate // backwards compatibility for credential manager backwardSolutionAdded(this, expr); additionalBackwardProcess(); } else { if(p.test(expr)) { // add this expression to the soln and stop backwardSolutionAdded(this, expr); } else { // skip this soln and continue processing additionalBackwardProcess(); } } backwardProcessed = true; } // The method that does the work when we visit a node public void forwardProcess() { if (forwardProcessed) { return; } // first step: go over all credentials that have this as subject Debug.debugInfo("Forward processing " + this); Iterator credIt = _graph.findCredentialsBySubject(_roleExp); while (credIt.hasNext()) { StaticCredential credential = (StaticCredential) credIt.next(); Debug.debugInfo("Find one credential: " + credential); ProofNode node = _graph.addForwardNode(credential.getDefinedRole()); node.addParent(this, credential); //_graph.addProofEdge(this, node, credential); } additionalForwardProcess(); forwardProcessed = true; // second step: find partial solutions which match this node's // role expression, unless its an intersection if (_roleExp instanceof Intersection) { return; } credIt = _graph.findCredentialsByPartialSubject(_roleExp); while (credIt.hasNext()) { StaticCredential credential = (StaticCredential) credIt.next(); ProofNode node = _graph.addForwardNode(credential.getSubject()); node.backwardProcess(); // Forward discovery of roles // // This is not reuired according to the algorithm from // "Distributed Credential Chain Discovery in Trust Management" // in JCS but is needed for credential discovery in ATN where // forward search takes place from sensitive roles. node.forwardProcess(); //int j = //((Intersection) credential.getSubject()).getIndexOf(_roleExp); //forward.solutionAdded(new PartialSolution(_roleExp, j)); } } abstract protected void additionalForwardProcess(); abstract protected void additionalBackwardProcess(); public void addBackwardListener(BackwardSolutionListener sl) { Debug.debugInfo(sl + " is now listening on " + this + " for backward solutions"); backwardListeners.add(sl); propagateBackwardSolutionsTo(sl); } public void addForwardListener(ForwardSolutionListener sl) { Debug.debugInfo(sl + " is now listening on " + this + " for forward solutions"); forwardListeners.add(sl); propagateForwardSolutionsTo(sl); } /** * Add a node as a parent to this node * @param node: the parent node */ public void addParent(ProofNode node, Object evidence) { if (parents.putResultEvidence(node.getRoleExp(), evidence)) { addForwardListener(node); } } public void addChild(ProofNode node, Object evidence) { if (children.putResultEvidence(node.getRoleExp(), evidence)) { addBackwardListener(node); } } public void backwardSolutionAdded(ProofNode s, BackwardSolution r) { if (backwardSolutions.putResultEvidence(r, s)) { // when solution r is new Debug.debugInfo("Backward solution added to: " + this + " from: " + s + " value: " + r); propagateBackwardSolution(r); } } public void forwardSolutionAdded(ProofNode s, ForwardSolution r) { /* if (r instanceof PartialSolution) { Intersection re = r.getIntersection(); Integer index = r.getNumber(); HashMap value = (HashMap) partialSols.get(re); if (value == null) { // first piece value = new HashMap(); partialSols.put(re, value); } SmallSet evidences = value.get(index); if (evidences == null) { // A new piece evidences = new SmallSet(s); value.put(index, evidences); if (value.size() == re.getK()) { // have all pieces // Add an edge from current node to re // addEdge(); } } else if (trackAll) { evidences.add(s); } return; } */ if (forwardSolutions.putResultEvidence(r, s)) { Debug.debugInfo("Forward solution added to: " + this + " from: " + s + " value: " + r); propagateForwardSolution(r); } } /** propagate backward solutions to all listening nodes. */ protected void propagateBackwardSolutionsTo(BackwardSolutionListener listener) { Object[] sols = backwardSolutions.resultSet().toArray(); for (int i=0; i