[8780cbec] | 1 | package edu.stanford.peer.rbtm.engine; |
---|
| 2 | |
---|
| 3 | import java.util.*; |
---|
| 4 | |
---|
| 5 | import edu.stanford.peer.rbtm.credential.*; |
---|
| 6 | import edu.stanford.peer.rbtm.util.*; |
---|
| 7 | |
---|
| 8 | /** |
---|
| 9 | * The parent class of all proof nodes. This is the base class which contains |
---|
| 10 | * default implementations of all common methods. |
---|
| 11 | */ |
---|
| 12 | public abstract class AbstractProofNode implements ProofNode |
---|
| 13 | { |
---|
| 14 | // The following two fields can't be changed by other classes. |
---|
| 15 | // If subclasses need to access them, use get methods |
---|
| 16 | |
---|
| 17 | /** The EntityExpression this node is about. */ |
---|
| 18 | EntityExpression _roleExp; |
---|
| 19 | |
---|
| 20 | /** |
---|
| 21 | * The proof _graph this node is in, this reference is used while |
---|
| 22 | * processing this node |
---|
| 23 | */ |
---|
| 24 | ProofGraph _graph; |
---|
| 25 | |
---|
| 26 | /** Processing mode for subclassed node types */ |
---|
| 27 | public final boolean addRole = true; |
---|
| 28 | |
---|
| 29 | /** Nodes that can reach this node directly, evidences are credentials. */ |
---|
| 30 | protected ResultEvidenceMap parents; |
---|
| 31 | |
---|
| 32 | /** Nodes that this node can reach directly, evidecens are credentials. */ |
---|
| 33 | protected ResultEvidenceMap children; |
---|
| 34 | |
---|
| 35 | /** Backward solutions on this node */ |
---|
| 36 | protected ResultEvidenceMap backwardSolutions; |
---|
| 37 | |
---|
| 38 | /** Forward solutions on this node */ |
---|
| 39 | protected ResultEvidenceMap forwardSolutions; |
---|
| 40 | |
---|
| 41 | protected ArrayList backwardListeners; |
---|
| 42 | protected ArrayList forwardListeners; |
---|
| 43 | |
---|
| 44 | boolean backwardProcessed; |
---|
| 45 | boolean forwardProcessed; |
---|
| 46 | |
---|
| 47 | AbstractProofNode (ProofGraph graph, EntityExpression re, int trackType) |
---|
| 48 | { |
---|
| 49 | _graph = graph; |
---|
| 50 | _roleExp = re; |
---|
| 51 | Debug.debugInfo("A new node is created for " + re); |
---|
| 52 | |
---|
| 53 | parents = new ResultEvidenceMap(trackType); |
---|
| 54 | children = new ResultEvidenceMap(trackType); |
---|
| 55 | backwardSolutions = new ResultEvidenceMap(trackType); |
---|
| 56 | forwardSolutions = new ResultEvidenceMap(trackType); |
---|
| 57 | |
---|
| 58 | backwardListeners = new ArrayList(10); |
---|
| 59 | forwardListeners = new ArrayList(10); |
---|
| 60 | } |
---|
| 61 | |
---|
| 62 | public ProofGraph getGraph() { |
---|
| 63 | return _graph; |
---|
| 64 | } |
---|
| 65 | |
---|
| 66 | public EntityExpression getRoleExp() { |
---|
| 67 | return _roleExp; |
---|
| 68 | } |
---|
| 69 | |
---|
| 70 | public ResultEvidenceMap getForwardSolutions() { |
---|
| 71 | return forwardSolutions; |
---|
| 72 | } |
---|
| 73 | |
---|
| 74 | public ResultEvidenceMap getBackwardSolutions() { |
---|
| 75 | return backwardSolutions; |
---|
| 76 | } |
---|
| 77 | |
---|
| 78 | public ResultEvidenceMap getChildren() { |
---|
| 79 | return children; |
---|
| 80 | } |
---|
| 81 | |
---|
| 82 | public ResultEvidenceMap getParents() { |
---|
| 83 | return parents; |
---|
| 84 | } |
---|
| 85 | |
---|
| 86 | /** |
---|
| 87 | * A single iteration of evidence gathering. This recursive method is |
---|
| 88 | * polymorphic and may be extended in child proof node implementations. |
---|
| 89 | * @param size the size of the evidence set (of credentials) |
---|
| 90 | * @param target the parent expression to be found in the cred graph |
---|
| 91 | */ |
---|
| 92 | public HashSet getChain(int size, EntityExpression target) { |
---|
| 93 | return new HashSet(size); |
---|
| 94 | } |
---|
| 95 | |
---|
| 96 | |
---|
| 97 | public void invalidateForward() { |
---|
| 98 | Debug.debugInfo("Invalidate forward result on " + this); |
---|
| 99 | if(forwardProcessed) { |
---|
| 100 | forwardProcessed = false; |
---|
| 101 | //reuse the credential and update the forward search |
---|
| 102 | getGraph().addForwardNode(getRoleExp()); |
---|
| 103 | } |
---|
| 104 | } |
---|
| 105 | |
---|
| 106 | public void invalidateBackward() { |
---|
| 107 | Debug.debugInfo("Invalidate backward result on " + this); |
---|
| 108 | if(backwardProcessed) { |
---|
| 109 | backwardProcessed = false; |
---|
| 110 | //reuse the credential and update the backward search |
---|
| 111 | getGraph().addBackwardNode(getRoleExp()); |
---|
| 112 | } |
---|
| 113 | } |
---|
| 114 | |
---|
| 115 | public void backwardProcess() { |
---|
| 116 | if (backwardProcessed) { return; } |
---|
| 117 | Predicate p = getGraph().getPredicate(); |
---|
| 118 | EntityExpression expr = getRoleExp(); |
---|
| 119 | Debug.debugInfo("Backward processing " + this); |
---|
| 120 | if(p == null) { // cred mgr has null predicate |
---|
| 121 | // backwards compatibility for credential manager |
---|
| 122 | backwardSolutionAdded(this, expr); |
---|
| 123 | additionalBackwardProcess(); |
---|
| 124 | } |
---|
| 125 | else { |
---|
| 126 | if(p.test(expr)) { |
---|
| 127 | // add this expression to the soln and stop |
---|
| 128 | backwardSolutionAdded(this, expr); |
---|
| 129 | } else { |
---|
| 130 | // skip this soln and continue processing |
---|
| 131 | additionalBackwardProcess(); |
---|
| 132 | } |
---|
| 133 | } |
---|
| 134 | backwardProcessed = true; |
---|
| 135 | } |
---|
| 136 | |
---|
| 137 | // The method that does the work when we visit a node |
---|
| 138 | public void forwardProcess() |
---|
| 139 | { |
---|
| 140 | if (forwardProcessed) { |
---|
| 141 | return; |
---|
| 142 | } |
---|
| 143 | |
---|
| 144 | // first step: go over all credentials that have this as subject |
---|
| 145 | Debug.debugInfo("Forward processing " + this); |
---|
| 146 | Iterator credIt = _graph.findCredentialsBySubject(_roleExp); |
---|
| 147 | while (credIt.hasNext()) { |
---|
| 148 | StaticCredential credential = (StaticCredential) credIt.next(); |
---|
| 149 | Debug.debugInfo("Find one credential: " + credential); |
---|
| 150 | ProofNode node = _graph.addForwardNode(credential.getDefinedRole()); |
---|
| 151 | node.addParent(this, credential); |
---|
| 152 | //_graph.addProofEdge(this, node, credential); |
---|
| 153 | } |
---|
| 154 | |
---|
| 155 | additionalForwardProcess(); |
---|
| 156 | forwardProcessed = true; |
---|
| 157 | |
---|
| 158 | // second step: find partial solutions which match this node's |
---|
| 159 | // role expression, unless its an intersection |
---|
| 160 | if (_roleExp instanceof Intersection) { return; } |
---|
| 161 | credIt = _graph.findCredentialsByPartialSubject(_roleExp); |
---|
| 162 | while (credIt.hasNext()) { |
---|
| 163 | StaticCredential credential = (StaticCredential) credIt.next(); |
---|
| 164 | ProofNode node = _graph.addForwardNode(credential.getSubject()); |
---|
| 165 | node.backwardProcess(); |
---|
| 166 | // Forward discovery of roles |
---|
| 167 | // |
---|
| 168 | // This is not reuired according to the algorithm from |
---|
| 169 | // "Distributed Credential Chain Discovery in Trust Management" |
---|
| 170 | // in JCS but is needed for credential discovery in ATN where |
---|
| 171 | // forward search takes place from sensitive roles. |
---|
| 172 | node.forwardProcess(); |
---|
| 173 | //int j = |
---|
| 174 | //((Intersection) credential.getSubject()).getIndexOf(_roleExp); |
---|
| 175 | //forward.solutionAdded(new PartialSolution(_roleExp, j)); |
---|
| 176 | } |
---|
| 177 | } |
---|
| 178 | |
---|
| 179 | abstract protected void additionalForwardProcess(); |
---|
| 180 | abstract protected void additionalBackwardProcess(); |
---|
| 181 | |
---|
| 182 | |
---|
| 183 | public void addBackwardListener(BackwardSolutionListener sl) { |
---|
| 184 | Debug.debugInfo(sl + " is now listening on " + this + |
---|
| 185 | " for backward solutions"); |
---|
| 186 | backwardListeners.add(sl); |
---|
| 187 | propagateBackwardSolutionsTo(sl); |
---|
| 188 | } |
---|
| 189 | |
---|
| 190 | public void addForwardListener(ForwardSolutionListener sl) { |
---|
| 191 | Debug.debugInfo(sl + " is now listening on " + this + |
---|
| 192 | " for forward solutions"); |
---|
| 193 | forwardListeners.add(sl); |
---|
| 194 | propagateForwardSolutionsTo(sl); |
---|
| 195 | } |
---|
| 196 | |
---|
| 197 | /** |
---|
| 198 | * Add a node as a parent to this node |
---|
| 199 | * @param node: the parent node |
---|
| 200 | */ |
---|
| 201 | public void addParent(ProofNode node, Object evidence) { |
---|
| 202 | if (parents.putResultEvidence(node.getRoleExp(), evidence)) { |
---|
| 203 | addForwardListener(node); |
---|
| 204 | } |
---|
| 205 | } |
---|
| 206 | |
---|
| 207 | public void addChild(ProofNode node, Object evidence) { |
---|
| 208 | if (children.putResultEvidence(node.getRoleExp(), evidence)) { |
---|
| 209 | addBackwardListener(node); |
---|
| 210 | } |
---|
| 211 | } |
---|
| 212 | |
---|
| 213 | public void backwardSolutionAdded(ProofNode s, BackwardSolution r) |
---|
| 214 | { |
---|
| 215 | if (backwardSolutions.putResultEvidence(r, s)) { |
---|
| 216 | // when solution r is new |
---|
| 217 | Debug.debugInfo("Backward solution added to: " + this + |
---|
| 218 | " from: " + s + " value: " + r); |
---|
| 219 | propagateBackwardSolution(r); |
---|
| 220 | } |
---|
| 221 | } |
---|
| 222 | |
---|
| 223 | public void forwardSolutionAdded(ProofNode s, ForwardSolution r) { |
---|
| 224 | /* |
---|
| 225 | if (r instanceof PartialSolution) { |
---|
| 226 | Intersection re = r.getIntersection(); |
---|
| 227 | Integer index = r.getNumber(); |
---|
| 228 | HashMap value = (HashMap) partialSols.get(re); |
---|
| 229 | if (value == null) { // first piece |
---|
| 230 | value = new HashMap(); |
---|
| 231 | partialSols.put(re, value); |
---|
| 232 | } |
---|
| 233 | SmallSet evidences = value.get(index); |
---|
| 234 | if (evidences == null) { // A new piece |
---|
| 235 | evidences = new SmallSet(s); |
---|
| 236 | value.put(index, evidences); |
---|
| 237 | if (value.size() == re.getK()) { // have all pieces |
---|
| 238 | // Add an edge from current node to re |
---|
| 239 | // addEdge(); |
---|
| 240 | } |
---|
| 241 | } else if (trackAll) { |
---|
| 242 | evidences.add(s); |
---|
| 243 | } |
---|
| 244 | return; |
---|
| 245 | } |
---|
| 246 | */ |
---|
| 247 | if (forwardSolutions.putResultEvidence(r, s)) { |
---|
| 248 | Debug.debugInfo("Forward solution added to: " + this + |
---|
| 249 | " from: " + s + " value: " + r); |
---|
| 250 | propagateForwardSolution(r); |
---|
| 251 | } |
---|
| 252 | } |
---|
| 253 | |
---|
| 254 | /** propagate backward solutions to all listening nodes. */ |
---|
| 255 | protected void propagateBackwardSolutionsTo(BackwardSolutionListener listener) |
---|
| 256 | { |
---|
| 257 | Object[] sols = backwardSolutions.resultSet().toArray(); |
---|
| 258 | for (int i=0; i<sols.length; i++) { |
---|
| 259 | listener.backwardSolutionAdded(this, (BackwardSolution)(sols[i])); |
---|
| 260 | } |
---|
| 261 | } |
---|
| 262 | |
---|
| 263 | protected void propagateForwardSolutionsTo(ForwardSolutionListener listener) |
---|
| 264 | { |
---|
| 265 | Object[] sols = forwardSolutions.resultSet().toArray(); |
---|
| 266 | for (int i=0; i<sols.length; i++) { |
---|
| 267 | listener.forwardSolutionAdded(this, (ForwardSolution)(sols[i])); |
---|
| 268 | } |
---|
| 269 | } |
---|
| 270 | |
---|
| 271 | protected void propagateBackwardSolution(BackwardSolution g) |
---|
| 272 | { |
---|
| 273 | Object[] listeners = backwardListeners.toArray(); |
---|
| 274 | for (int i=0; i<listeners.length; i++) { |
---|
| 275 | ((BackwardSolutionListener)listeners[i]).backwardSolutionAdded(this, g); |
---|
| 276 | } |
---|
| 277 | } |
---|
| 278 | |
---|
| 279 | protected void propagateForwardSolution(ForwardSolution g) |
---|
| 280 | { |
---|
| 281 | Object[] listeners = forwardListeners.toArray(); |
---|
| 282 | for (int i=0; i<listeners.length; i++) { |
---|
| 283 | ((ForwardSolutionListener)listeners[i]).forwardSolutionAdded(this, g); |
---|
| 284 | } |
---|
| 285 | } |
---|
| 286 | |
---|
| 287 | public String toString() |
---|
| 288 | { |
---|
| 289 | return "node " + _roleExp; |
---|
| 290 | } |
---|
| 291 | |
---|
| 292 | |
---|
| 293 | // boolean hasParent(ProofNode node) { return parents.containsResult(node._roleExp); } |
---|
| 294 | |
---|
| 295 | |
---|
| 296 | //////////// code for SelectiveProofNode |
---|
| 297 | /* |
---|
| 298 | * The following two fields store desired goals. Only desired goals are |
---|
| 299 | * passed through edges. Setting them to null means all goals are |
---|
| 300 | * desired. |
---|
| 301 | * In backward search, if child A.r only wants to see one solution, while |
---|
| 302 | * child A.r1.r2 wants to see all solutions. All goals are desired, so |
---|
| 303 | * they are passed to A.r as well. But A.r should have only one desired |
---|
| 304 | * solution, and so A.r will not propagate them further. |
---|
| 305 | */ |
---|
| 306 | // SmallSet backwardGoals = new SmallSet(); |
---|
| 307 | // SmallSet forwardGoals = new SmallSet(); |
---|
| 308 | |
---|
| 309 | /* |
---|
| 310 | void enableBackwardGoal(EntityExpression g) |
---|
| 311 | { |
---|
| 312 | if (backwardGoals != null && ! backwardGoals.containsGoal(g)) { |
---|
| 313 | // has not been enabled before |
---|
| 314 | backwardGoals.addGoal(g); |
---|
| 315 | if (backwardSoltuions.containsResult(g)) { |
---|
| 316 | propagateBackwardSolution(g); |
---|
| 317 | } |
---|
| 318 | // Enable this backward goal for all parents |
---|
| 319 | Object[] list = parents.toArray(); // inform listeners |
---|
| 320 | for (int i=0; i<list.length; i++) { |
---|
| 321 | ((ProofNode)list[i]).enableBackwardGoal(g); |
---|
| 322 | } |
---|
| 323 | } |
---|
| 324 | } |
---|
| 325 | |
---|
| 326 | void enableAllBackwardGoals() |
---|
| 327 | { |
---|
| 328 | if (backwardGoals == null ) { |
---|
| 329 | backwardGoals = null; |
---|
| 330 | // if have been procesed, loop over all parents, and enable them |
---|
| 331 | // if haven't been processed, just enable it |
---|
| 332 | } |
---|
| 333 | } |
---|
| 334 | */ |
---|
| 335 | } // End of class ProofNode |
---|
| 336 | |
---|
| 337 | |
---|
| 338 | |
---|
| 339 | |
---|
| 340 | |
---|
| 341 | |
---|