/** On network error, create ExceptionEvent and delever it to all listeners on all events. */ protected void processNetworkError(Exception ex) { Hashtable tmpRequestList = new Hashtable(); tmpRequestList.putAll(_requestList); int[] ids = _msgQueue.getMessageIDs(); if (ids != null) { for (int i = 0; i < ids.length; i++) { tmpRequestList.remove(Integer.toString(ids[i])); } } Collection reqList = tmpRequestList.values(); for (Iterator iter = reqList.iterator(); iter.hasNext(); ) { Request request = (Request) iter.next(); dispatchException(ex, request); } }
/** * Reset error searches. Clear cache only if true is passed to argument * * @param clearCaches */ protected void resetErrorSearches(boolean clearCaches) { Hashtable tmpReqList = new Hashtable(); tmpReqList.putAll(_requestList); int[] ids = _msgQueue.getMessageIDs(); if (ids != null) { for (int i = 0; i < ids.length; i++) { String reqID = Integer.toString(ids[i]); tmpReqList.remove(reqID); } } Collection reqList = tmpReqList.values(); for (Iterator iter = reqList.iterator(); iter.hasNext(); ) { Request req = (Request) iter.next(); _requestList.remove(req.getRequestID()); } _retryInterval = getPropertyIntValue(EVENT_CONNECTION_RETRY_INTERVAL, _retryInterval); RetryTask task = new RetryTask(tmpReqList); task.clearCache(clearCaches); SystemTimer.getTimer() .schedule(task, new Date(((System.currentTimeMillis() + _retryInterval) / 1000) * 1000)); }
/** * Main monitor thread loop. Wait for persistent search change notifications * * @supported.api */ public void run() { try { if (debugger.messageEnabled()) { debugger.message( "EventService.run(): Event Thread is running! " + "No Idle timeout Set: " + _idleTimeOut + " minutes."); } boolean successState = true; LDAPMessage message = null; while (successState) { try { if (debugger.messageEnabled()) { debugger.message("EventService.run(): Waiting for " + "response"); } synchronized (this) { if (_requestList.isEmpty()) { wait(); } } message = _msgQueue.getResponse(); successState = processResponse(message); } catch (LDAPInterruptedException ex) { if (_shutdownCalled) { break; } else { if (debugger.warningEnabled()) { debugger.warning("EventService.run() " + "LDAPInterruptedException received:", ex); } } } catch (LDAPException ex) { if (_shutdownCalled) { break; } else { int resultCode = ex.getLDAPResultCode(); if (debugger.warningEnabled()) { debugger.warning("EventService.run() LDAPException " + "received:", ex); } _retryErrorCodes = getPropertyRetryErrorCodes(EVENT_CONNECTION_ERROR_CODES); // Catch special error codition in // LDAPSearchListener.getResponse String msg = ex.getLDAPErrorMessage(); if ((resultCode == LDAPException.OTHER) && (msg != null) && msg.equals("Invalid response")) { // We should not try to resetError and retry processNetworkError(ex); } else { if (_retryErrorCodes.contains("" + resultCode)) { resetErrorSearches(true); } else { // Some other network error processNetworkError(ex); } } } } } // end of while loop } catch (InterruptedException ex) { if (!_shutdownCalled) { if (debugger.warningEnabled()) { debugger.warning("EventService.run(): Interrupted exception" + " caught.", ex); } } } catch (RuntimeException ex) { if (debugger.warningEnabled()) { debugger.warning("EventService.run(): Runtime exception " + "caught.", ex); } // rethrow the Runtime exception to let the container handle the // exception. throw ex; } catch (Exception ex) { if (debugger.warningEnabled()) { debugger.warning("EventService.run(): Unknown exception " + "caught.", ex); } // no need to rethrow. } catch (Throwable t) { // Catching Throwable to prevent the thread from exiting. if (debugger.warningEnabled()) { debugger.warning( "EventService.run(): Unknown exception " + "caught. Sleeping for a while.. ", t); } // rethrow the Error to let the container handle the error. throw new Error(t); } finally { synchronized (this) { if (!_shutdownCalled) { // try to restart the monitor thread. _monitorThread = null; startMonitorThread(); } } } } // end of thread
/** * Adds a listener to the directory. * * @supported.api */ protected synchronized String addListener( SSOToken token, IDSEventListener listener, String base, int scope, String filter, int operations) throws LDAPException, EventException { if (_shutdownCalled) { throw new EventException(i18n.getString(IUMSConstants.DSCFG_CONNECTFAIL)); } LDAPConnection lc = null; try { // Check for SMS listener and use "sms" group if present if ((listener.getClass().getName().equals("com.sun.identity.sm.ldap.LDAPEventManager")) && (cm.getServerGroup("sms") != null)) { lc = cm.getNewConnection("sms", LDAPUser.Type.AUTH_ADMIN); } else { lc = cm.getNewAdminConnection(); } } catch (LDAPServiceException le) { throw new EventException(i18n.getString(IUMSConstants.DSCFG_CONNECTFAIL), le); } LDAPSearchConstraints cons = lc.getSearchConstraints(); // Create Persistent Search Control object LDAPPersistSearchControl psearchCtrl = new LDAPPersistSearchControl(operations, CHANGES_ONLY, RETURN_CONTROLS, IS_CRITICAL); // Add LDAPControl array to the search constraint object cons.setServerControls(psearchCtrl); cons.setBatchSize(1); // Listeners can not read attributes from the event. // Request only javaClassName to be able to determine object type String[] attrs = new String[] {"objectclass"}; LDAPSearchListener searchListener = null; // Set (asynchronous) persistent search request in the DS try { if (debugger.messageEnabled()) { debugger.message( "EventService.addListener() - Submiting " + "Persistent Search on: " + base + " for listener: " + listener); } searchListener = lc.search(base, scope, filter, attrs, false, null, cons); } catch (LDAPException le) { if ((lc != null) && lc.isConnected()) { try { lc.disconnect(); } catch (Exception ex) { // ignored } } debugger.error( "EventService.addListener() - Failed to set " + "Persistent Search" + le.getMessage()); throw le; } int[] outstandingRequests = searchListener.getMessageIDs(); int id = outstandingRequests[outstandingRequests.length - 1]; String reqID = Integer.toString(id); long startTime = System.currentTimeMillis(); Request request = new Request( id, reqID, token, base, scope, filter, attrs, operations, listener, lc, startTime); _requestList.put(reqID, request); // Add this search request to the m_msgQueue so it can be // processed by the monitor thread if (_msgQueue == null) { _msgQueue = searchListener; } else { _msgQueue.merge(searchListener); } if (!_isThreadStarted) { startMonitorThread(); } else { if (_requestList.size() == 1) { notify(); } } if (debugger.messageEnabled()) { outstandingRequests = _msgQueue.getMessageIDs(); debugger.message( "EventService.addListener(): merged Listener: " + " requestID: " + reqID + " & Request: " + request + " on to message Queue. No. of current outstanding " + "requests = " + outstandingRequests.length); } // Create new (EventService) Thread, if one doesn't exist. return reqID; }