33 34 import java.util.Vector; 35 import com.sun.jndi.toolkit.ctx.Continuation; 36 37 /** 38 * Gathers information to generate events by using the Persistent Search 39 * control. 40 *<p> 41 * This class maintains a list of listeners all interested in the same 42 * "search" request. It creates a thread that does the persistent search 43 * and blocks, collecting the results of the search. 44 * For each result that it receives from the search, it fires the 45 * corresponding event to its listeners. If an exception is encountered, 46 * it fires a NamingExceptionEvent. 47 * 48 * @author Rosanna Lee 49 */ 50 final class NamingEventNotifier implements Runnable { 51 private final static boolean debug = false; 52 53 private Vector namingListeners; 54 private Thread worker; 55 private LdapCtx context; 56 private EventContext eventSrc; 57 private EventSupport support; 58 private NamingEnumeration results; 59 60 // package private; used by EventSupport to remove it 61 NotifierArgs info; 62 63 NamingEventNotifier(EventSupport support, LdapCtx ctx, NotifierArgs info, 64 NamingListener firstListener) throws NamingException { 65 this.info = info; 66 this.support = support; 67 68 Control psearch; 69 try { 70 psearch = new PersistentSearchControl( 71 info.mask, 72 true /* no info about original entry(s) */, 73 true /* additional info about changes */, 74 Control.CRITICAL); 75 } catch (java.io.IOException e) { 76 NamingException ne = new NamingException( 77 "Problem creating persistent search control"); 78 ne.setRootCause(e); 79 throw ne; 80 } 81 82 // Add psearch control to existing list 83 context = (LdapCtx)ctx.newInstance(new Control[]{psearch}); 84 eventSrc = ctx; 85 86 namingListeners = new Vector(); 87 namingListeners.addElement(firstListener); 88 89 worker = Obj.helper.createThread(this); 90 worker.setDaemon(true); // not a user thread 91 worker.start(); 92 } 93 94 // package private; used by EventSupport; namingListener already synchronized 95 void addNamingListener(NamingListener l) { 96 namingListeners.addElement(l); 97 } 98 99 // package private; used by EventSupport; namingListener already synchronized 100 void removeNamingListener(NamingListener l) { 101 namingListeners.removeElement(l); 102 } 103 104 // package private; used by EventSupport; namingListener already synchronized 105 boolean hasNamingListeners() { 106 return namingListeners.size() > 0; 107 } 108 109 /** 110 * Execute "persistent search". 111 * For each result, create the appropriate NamingEvent and 112 * queue to be dispatched to listeners. 113 */ 114 public void run() { 115 try { 116 Continuation cont = new Continuation(); 117 cont.setError(this, info.name); 118 Name nm = (info.name == null || info.name.equals("")) ? 119 new CompositeName() : new CompositeName().add(info.name); 120 121 results = context.searchAux(nm, info.filter, info.controls, 122 true, false, cont); 123 124 // Change root of search results so that it will generate 125 // names relative to the event context instead of that 126 // named by nm 127 ((LdapSearchEnumeration)results).setStartName(context.currentParsedDN); 128 129 SearchResult si; 130 Control[] respctls; 131 EntryChangeResponseControl ec; 132 long changeNum; 133 134 while (results.hasMore()) { 135 si = (SearchResult)results.next(); 136 respctls = (si instanceof HasControls) ? 137 ((HasControls) si).getControls() : null; 138 139 if (debug) { 140 System.err.println("notifier: " + si); 141 System.err.println("respCtls: " + respctls); 142 } 143 144 // Just process ECs; ignore all the rest 145 if (respctls != null) { 146 for (int i = 0; i < respctls.length; i++) { 147 // %%% Should be checking OID instead of class 148 // %%% in case using someone else's EC ctl 149 if (respctls[i] instanceof EntryChangeResponseControl) { 150 ec = (EntryChangeResponseControl)respctls[i]; 151 changeNum = ec.getChangeNumber(); 152 switch (ec.getChangeType()) { 153 case EntryChangeResponseControl.ADD: 154 fireObjectAdded(si, changeNum); 155 break; | 33 34 import java.util.Vector; 35 import com.sun.jndi.toolkit.ctx.Continuation; 36 37 /** 38 * Gathers information to generate events by using the Persistent Search 39 * control. 40 *<p> 41 * This class maintains a list of listeners all interested in the same 42 * "search" request. It creates a thread that does the persistent search 43 * and blocks, collecting the results of the search. 44 * For each result that it receives from the search, it fires the 45 * corresponding event to its listeners. If an exception is encountered, 46 * it fires a NamingExceptionEvent. 47 * 48 * @author Rosanna Lee 49 */ 50 final class NamingEventNotifier implements Runnable { 51 private final static boolean debug = false; 52 53 private Vector<NamingListener> namingListeners; 54 private Thread worker; 55 private LdapCtx context; 56 private EventContext eventSrc; 57 private EventSupport support; 58 private NamingEnumeration<SearchResult> results; 59 60 // package private; used by EventSupport to remove it 61 NotifierArgs info; 62 63 NamingEventNotifier(EventSupport support, LdapCtx ctx, NotifierArgs info, 64 NamingListener firstListener) throws NamingException { 65 this.info = info; 66 this.support = support; 67 68 Control psearch; 69 try { 70 psearch = new PersistentSearchControl( 71 info.mask, 72 true /* no info about original entry(s) */, 73 true /* additional info about changes */, 74 Control.CRITICAL); 75 } catch (java.io.IOException e) { 76 NamingException ne = new NamingException( 77 "Problem creating persistent search control"); 78 ne.setRootCause(e); 79 throw ne; 80 } 81 82 // Add psearch control to existing list 83 context = (LdapCtx)ctx.newInstance(new Control[]{psearch}); 84 eventSrc = ctx; 85 86 namingListeners = new Vector<>(); 87 namingListeners.addElement(firstListener); 88 89 worker = Obj.helper.createThread(this); 90 worker.setDaemon(true); // not a user thread 91 worker.start(); 92 } 93 94 // package private; used by EventSupport; namingListener already synchronized 95 void addNamingListener(NamingListener l) { 96 namingListeners.addElement(l); 97 } 98 99 // package private; used by EventSupport; namingListener already synchronized 100 void removeNamingListener(NamingListener l) { 101 namingListeners.removeElement(l); 102 } 103 104 // package private; used by EventSupport; namingListener already synchronized 105 boolean hasNamingListeners() { 106 return namingListeners.size() > 0; 107 } 108 109 /** 110 * Execute "persistent search". 111 * For each result, create the appropriate NamingEvent and 112 * queue to be dispatched to listeners. 113 */ 114 public void run() { 115 try { 116 Continuation cont = new Continuation(); 117 cont.setError(this, info.name); 118 Name nm = (info.name == null || info.name.equals("")) ? 119 new CompositeName() : new CompositeName().add(info.name); 120 121 results = context.searchAux(nm, info.filter, info.controls, 122 true, false, cont); 123 124 // Change root of search results so that it will generate 125 // names relative to the event context instead of that 126 // named by nm 127 ((LdapSearchEnumeration)(NamingEnumeration)results) 128 .setStartName(context.currentParsedDN); 129 130 SearchResult si; 131 Control[] respctls; 132 EntryChangeResponseControl ec; 133 long changeNum; 134 135 while (results.hasMore()) { 136 si = results.next(); 137 respctls = (si instanceof HasControls) ? 138 ((HasControls) si).getControls() : null; 139 140 if (debug) { 141 System.err.println("notifier: " + si); 142 System.err.println("respCtls: " + respctls); 143 } 144 145 // Just process ECs; ignore all the rest 146 if (respctls != null) { 147 for (int i = 0; i < respctls.length; i++) { 148 // %%% Should be checking OID instead of class 149 // %%% in case using someone else's EC ctl 150 if (respctls[i] instanceof EntryChangeResponseControl) { 151 ec = (EntryChangeResponseControl)respctls[i]; 152 changeNum = ec.getChangeNumber(); 153 switch (ec.getChangeType()) { 154 case EntryChangeResponseControl.ADD: 155 fireObjectAdded(si, changeNum); 156 break; |