KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ca > directory > jxplorer > broker > Broker


1
2 package com.ca.directory.jxplorer.broker;
3
4 import com.ca.directory.jxplorer.*;
5
6 import com.ca.commons.naming.DN;
7 import com.ca.commons.naming.DXEntry;
8 import com.ca.commons.naming.DXNamingEnumeration;
9 import com.ca.commons.jndi.SchemaOps;
10
11 import javax.naming.directory.DirContext JavaDoc;
12 import javax.naming.NamingException JavaDoc;
13 import java.util.Vector JavaDoc;
14 import java.util.ArrayList JavaDoc;
15
16 public abstract class Broker implements Runnable JavaDoc, DataSource
17 {
18     protected Vector JavaDoc requestQueue = new Vector JavaDoc(10); // the core list of outstanding queries.
19
// also the object that everything synchronizes on...
20
protected Vector JavaDoc listeners = new Vector JavaDoc();
21
22     private static int noBrokers = 0; // for debugging, assign a unique sequential ID to each object created
23

24     public int id;
25
26     protected DataQuery current = null;
27
28     StopMonitor stopMonitor = null;
29
30     public Broker() { id = (noBrokers++); }
31
32     private static boolean debug = false;
33
34     /**
35      * Registers a stop monitor that is used by the gui to allow user
36      * cancellation of in-progress broker actions.
37      */

38
39     public void registerStopMonitor(StopMonitor monitor) { stopMonitor = monitor; }
40
41     /**
42      * Adds a DataQuery to the request Queue.
43      * Primarily used by the DataSource methods to
44      * register requests.
45      */

46
47     public DataQuery push(DataQuery request)
48     {
49         for (int i=0; i<listeners.size(); i++)
50             request.addDataListener((DataListener)listeners.get(i));
51
52         synchronized(requestQueue)
53         {
54             requestQueue.add(request);
55         }
56
57         if (stopMonitor != null) stopMonitor.updateWatchers();
58
59         synchronized(requestQueue)
60         {
61             requestQueue.notifyAll();
62         }
63
64
65         return request; // returns the same request for easy chaining.
66
}
67
68     /**
69      * Gets the next DataQuery from the request Queue,
70      * removing it from the queue as it does so.
71      */

72
73     public DataQuery pop()
74     {
75         DataQuery request = null;
76
77         synchronized(requestQueue)
78         {
79             if (requestQueue.isEmpty()) return null;
80             request = (DataQuery)requestQueue.firstElement();
81             requestQueue.removeElementAt(0);
82             request.setRunning(); // set the running flag (for use by StopMonitor)
83
}
84
85         return request;
86     }
87
88     /**
89      * Removes a particular query from the pending query list...
90      */

91
92      public void removeQuery(DataQuery query)
93      {
94          synchronized(requestQueue)
95          {
96              requestQueue.remove(query);
97          }
98      }
99
100     /**
101      * Returns whether there are more DataQuerys pending.
102      */

103
104     public boolean hasRequests()
105     {
106         synchronized(requestQueue)
107         {
108             return !requestQueue.isEmpty();
109         }
110     }
111
112     /**
113      * Wait until notified that something (presumably
114      * an addition to the queue) has occured. When woken,
115      * process all queue requests, and then go back to
116      * waiting.
117      */

118
119     public void run()
120     {
121         while (true)
122         {
123 if (debug) System.out.println("Thread: " + Thread.currentThread().getName() + " processing Queue of length: " + requestQueue.size() + " in broker " + id);
124             if (processQueue()==false)
125             {
126 if (debug) System.out.println("Thread: " + Thread.currentThread().getName() + " ending." + requestQueue.size());
127                 return;
128             }
129
130             try
131             {
132 if (debug) System.out.println("Thread: " + Thread.currentThread().getName() + " waiting in run() loop");
133                 synchronized(requestQueue)
134                 {
135                     requestQueue.wait();
136                 }
137 if (debug) System.out.println("Thread: " + Thread.currentThread().getName() + " notified in run() loop");
138             }
139             catch (Exception JavaDoc e)
140             {
141 if (debug) System.out.println("Thread: " + Thread.currentThread().getName() + " interrupted in run() loop \n " + e);
142             }
143         }
144     }
145
146     /**
147      * process all queue requests
148      */

149
150     protected boolean processQueue()
151     {
152         while (hasRequests())
153         {
154             current = pop(); // keep track of the current query for reporting
155

156             if (current == null) return true; // sanity check: fantastically small (?) chance of thread magic causing a null return?
157

158             processRequest(current);
159
160             if (stopMonitor != null) stopMonitor.updateWatchers();
161
162             if (current != null && current.isCancelled()) // if the request was cancelled by the user, then
163
{ // it had probably hung, and another broker thread
164
return false; // will have been started - so kill this thread off.
165
}
166             else
167             {
168                 current = null;
169             }
170         }
171
172         return true; // completed queue without any cancellations
173
}
174
175     /**
176      * Process a specific request.
177      */

178
179     protected void processRequest(DataQuery request)
180     {
181 if (debug) System.out.println("Thread: " + Thread.currentThread().getName() + " process request " + request.id );
182
183         if (request.isCancelled() == true)
184         {
185             request.finish();
186             return;
187         }
188
189         try
190         {
191             if (!isActive())
192                 request.setException(new Exception JavaDoc("No Data Connection Enabled"));
193
194             if (debug) System.out.println("Thread: " + Thread.currentThread().getName() + " process request " + request.id + " of type " + request.getTypeString());
195
196             switch(request.getType())
197             {
198                 case DataQuery.EXISTS: doExistsQuery(request); break;
199
200                 case DataQuery.READENTRY: doEntryQuery(request); break;
201
202                 case DataQuery.LIST: doListQuery(request); break;
203
204                 case DataQuery.SEARCH: doSearchQuery(request); break;
205
206                 case DataQuery.MODIFY: doModifyQuery(request); break;
207
208                 case DataQuery.COPY: doCopyQuery(request); break;
209
210 // case DataQuery.GETALLOC: doGetAllOCsQuery(request); break;
211

212                 case DataQuery.GETRECOC: doGetRecOCsQuery(request); break;
213
214                 case DataQuery.EXTENDED: doExtendedQuery(request); break;
215
216                 case DataQuery.UNKNOWN:
217
218                 default: throw new NamingException JavaDoc("JX Internal Error: Unknown Data Broker Request type: " + request.getType());
219             }
220         }
221         catch (Exception JavaDoc e)
222         {
223             request.setException(e);
224         }
225
226         // request *should* already be finished by this stage, but just in case...
227
request.finish();
228
229     }
230
231
232     //
233
// DATA SOURCE INTERFACE
234
//
235
// (Constructs appropriate DataQuerys and queues them)
236

237
238     public DataQuery getChildren(DN nodeDN)
239     {
240         return push(new DataQuery(DataQuery.LIST, nodeDN));
241     }
242
243     public DataQuery getEntry(DN nodeDN)
244     {
245         return push(new DataQuery(DataQuery.READENTRY, nodeDN));
246     }
247
248     public DataQuery exists(DN nodeDN)
249     {
250         return push(new DataQuery(DataQuery.EXISTS, nodeDN));
251     }
252 /*
253     public DataQuery getObjectClasses()
254     {
255         return push(new DataQuery(DataQuery.GETALLOC));
256     }
257 */

258     public DataQuery getRecommendedObjectClasses(DN dn)
259     {
260         return push(new DataQuery(DataQuery.GETRECOC, dn));
261     }
262
263     public DataQuery modifyEntry(DXEntry oldEntry, DXEntry newEntry)
264     {
265         return push(new DataQuery(DataQuery.MODIFY, oldEntry, newEntry));
266     }
267
268     public DataQuery copyTree(DN oldNodeDN, DN newNodeDN)
269     {
270         return push(new DataQuery(DataQuery.COPY, oldNodeDN, newNodeDN));
271     }
272
273     public DataQuery search(DN nodeDN, String JavaDoc filter, int searchLevel, String JavaDoc[] returnAttributes)
274     {
275         return push(new DataQuery(DataQuery.SEARCH, nodeDN, filter, searchLevel, returnAttributes));
276     }
277
278     public DataQuery extendedRequest(DataQuery query)
279     {
280         return push(query);
281     }
282
283     /**
284      * Adds a data listener to every DataQuery generated by this broker.
285      * For threading simplicity, no data listeners are added to DataQuerys
286      * <i>allready</i> in the request queue.<p>
287      * While it is not an error to register a listener multiple times,
288      * a listener will still only be notified once.
289      */

290     public void addDataListener(DataListener l)
291     {
292         if (listeners.contains(l) == false)
293         {
294             listeners.add(l);
295         }
296     }
297     
298     
299     
300    /**
301     * Removes a data listener from every DataQuery generated by this broker.
302     * @param l the listener to be notified when the data is ready.
303     */

304         
305     public void removeDataListener(DataListener l)
306     {
307         if (listeners.contains(l)==true)
308         {
309             listeners.remove(l);
310         }
311     }
312
313
314
315     // Abstract DataSource methods - must be extended
316

317     public abstract boolean isModifiable();
318
319     public abstract DirContext JavaDoc getDirContext();
320
321     public abstract boolean isActive();
322
323     public abstract SchemaOps getSchemaOps();
324
325     /**
326      * Sets the finish flag of a request and returns
327      * the query. Often overloaded by derived broker classes.
328      */

329
330     protected DataQuery finish(DataQuery request)
331     {
332         if (debug) System.out.println("Thread: " + Thread.currentThread().getName() + " request " + request.id + " finished ");
333         request.finish();
334         return request;
335     }
336
337
338
339
340     // Methods for the stop monitor - return a list of outstanding tasks
341

342     /**
343      * Returns the DataQuery currently being processed (if any).
344      * @return the current DataQuery (may be null if there is none).
345      */

346     public DataQuery getCurrent() { return current; }
347
348     /**
349      * Returns the vector of outstanding queries.
350      * @return a vector of (DataQuery).
351      */

352     public synchronized Vector JavaDoc getRequestQueue()
353     {
354         return requestQueue;
355     }
356
357     // this one doesn't need to be abstract...
358

359     protected DataQuery doExtendedQuery(DataQuery request)
360             throws NamingException JavaDoc
361     {
362         request.doExtendedRequest(this);
363         return finish(request);
364     }
365
366
367     /**
368      * Method for the Broker interface - chains to
369      * dirOp.exists().
370      */

371
372     protected DataQuery doExistsQuery(DataQuery request)
373         throws NamingException JavaDoc
374     {
375         unthreadedExists(request.requestDN());
376         request.setStatus(true);
377         return finish(request);
378     }
379
380     /**
381      * Method for the Broker interface - chains to
382      * list().
383      */

384
385     protected DataQuery doListQuery(DataQuery request)
386             throws NamingException JavaDoc
387     {
388         request.setEnum(unthreadedList(request.requestDN()));
389         return finish(request);
390     }
391
392     /**
393      * Method for the Broker interface - chains to
394      * dirOp.read().
395      */

396
397     protected DataQuery doEntryQuery(DataQuery request)
398             throws NamingException JavaDoc
399     {
400         request.setEntry(unthreadedReadEntry(request.requestDN(), null));
401         return finish(request);
402     }
403
404     /**
405      * Method for the Broker interface - chains to
406      * search().
407      */

408
409     protected DataQuery doSearchQuery(DataQuery request)
410             throws NamingException JavaDoc
411     {
412         DXNamingEnumeration en = unthreadedSearch(request.requestDN(), request.filter(), request.searchLevel(), request.returnAttributes());
413         request.setEnum(en);
414         return finish(request);
415     }
416
417     /**
418      * Method for the Broker interface - chains to
419      * modifyEntry().
420      */

421
422     protected DataQuery doModifyQuery(DataQuery request)
423             throws NamingException JavaDoc
424     {
425         unthreadedModify(request.oldEntry(), request.newEntry());
426         request.setStatus(true);
427         return finish(request);
428     }
429
430     /**
431      * Method for the Broker interface - chains to
432      * copyTree().
433      */

434
435     protected DataQuery doCopyQuery(DataQuery request)
436             throws NamingException JavaDoc
437     {
438         unthreadedCopy(request.oldDN(), request.requestDN());
439         request.setStatus(true);
440         return finish(request);
441     }
442
443     /**
444      * Method for the Broker interface - chains to
445      * unthreadedGetRecOCs.
446      */

447
448     protected DataQuery doGetRecOCsQuery(DataQuery request)
449             throws NamingException JavaDoc
450     {
451         request.setArrayList(unthreadedGetRecOCs(request.requestDN()));
452         return finish(request);
453     }
454
455     /**
456      * Method for the Broker interface - chains to
457      * getObjectClasses().
458      */

459 /*
460     protected DataQuery doGetAllOCsQuery(DataQuery request)
461     {
462         request.setVector(unthreadedGetAllOCs());
463         return finish(request);
464     }
465 */

466     /**
467      * returns the next level of a directory tree, returning
468      * a Enumeration of the results
469      *
470      * @param searchbase the node in the tree to expand
471      * @return list of results (NameClassPair); the next layer of the tree...
472      */

473
474     public abstract DXNamingEnumeration unthreadedList(DN searchbase) throws NamingException JavaDoc;
475
476     /**
477      * Performs a directory search.
478      *
479      * @param dn the domain name (relative to initial context in ldap) to seach from.
480      * @param filter the non-null filter to use for the search
481      * @param search_level whether to search the base object, the next level or the whole subtree.
482      * @param returnAttributes a vector of string names of attributes to return in the search.
483      * (null means 'return all entries', a zero length array means 'return no attributes'.)
484      * @return list of results ('SearchResult's); the next layer of the tree...
485      */

486
487     public abstract DXNamingEnumeration unthreadedSearch(DN dn, String JavaDoc filter, int search_level, String JavaDoc[] returnAttributes) throws NamingException JavaDoc;
488
489    /**
490     * Copies a DN representing a subtree to a new subtree, including
491     * copying all subordinate entries.
492     *
493     * @param oldNodeDN the original DN of the sub tree root
494     * to be copied (may be a single entry).
495     * @param newNodeDN the target DN for the tree to be moved to.
496     */

497     public abstract void unthreadedCopy(DN oldNodeDN, DN newNodeDN) throws NamingException JavaDoc;
498
499     /**
500      * Checks the existance of a given entry.
501      */

502
503     public abstract boolean unthreadedExists(DN checkMe) throws NamingException JavaDoc;
504
505     /**
506      * Returns a complete list of all known object classes.
507      */

508
509     //public abstract Vector unthreadedGetAllOCs();
510

511     /**
512      * Reads an entry with all its attributes from
513      * the directory.
514      * @param entryDN the DN of the object to read.
515      * @param returnAttributes a vector of string names of attributes to return in the search.
516      * (null means 'return all entries', a zero length array means 'return no attributes'.)
517      */

518
519     public abstract DXEntry unthreadedReadEntry(DN entryDN, String JavaDoc[] returnAttributes) throws NamingException JavaDoc;
520
521
522    /**
523     * Update an entry with the designated DN.
524     * @param oldEntry oldSet the old set of attributes of the object.
525     * @param newEntry newSet the replacement set of attributes..
526     */

527
528     public abstract void unthreadedModify(DXEntry oldEntry, DXEntry newEntry) throws NamingException JavaDoc;
529
530     /**
531      * Gets a list of the object classes most likely
532      * to be used for the next Level of the DN...
533      * @param dn the dn of the parent to determine likely
534      * child object classes for
535      * @return list of recommended object classes...
536      */

537
538     public abstract ArrayList JavaDoc unthreadedGetRecOCs(DN dn) throws NamingException JavaDoc;
539
540
541
542     /**
543      * Utility method for extended queries - returns whether
544      * a 'masked' exception has occured.
545      * @return the exception, or null if there is none.
546      */

547
548     public Exception JavaDoc getException()
549     {
550         return null;
551     }
552
553     /**
554      * Utility method for extended queries - allows
555      * a 'masked' exception to be cleared.
556      */

557
558     public void clearException()
559     {
560     }
561
562         /**
563      * As a way to directly access the directory broker, a DataSource
564      * MAY choose to publish the directory broker.
565      * @return the Broker - may be null.
566      */

567
568     public Broker getBroker() { return this; }
569
570 }
Popular Tags