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 | |
---|