/** * Copy the existing request set map and pass it on to ThreadPool as part of a FlushTask. * Initiatize a new map as the new request set map for future remote logging calls. */ public synchronized void nonBlockingFlush() { if (recCount <= 0) { if (Debug.messageEnabled()) { Debug.message("RemoteHandler.nonBlockingFlush(): no records " + "in buffer to send"); } return; } FlushTask task = new FlushTask(reqSetMap); try { thread.run(task); } catch (ThreadPoolException ex) { // Use current thread to complete the task if ThreadPool can not // execute it. if (Debug.messageEnabled()) { Debug.message( "RemoteHandler.nonBlockingFlush(): ThreadPoolException" + ". Performing blocking flush."); } task.run(); } this.recCount = 0; reqSetMap = new HashMap(); }
/** * The class which publishes the log message to a remote log service. Also does buffering of * LogRecords upto the number specified in the log configuration. This buffer is emptied when the * number of log records in the buffer reaches the specified number or when the specified time * interval is exceeded. */ public class RemoteHandler extends Handler { private static LogManager manager; static { manager = (LogManager) LogManagerUtil.getLogManager(); } private int recCount = 0; private String bufferSize; private int recCountLimit; // Map with loggedBySID as key & reqSet as value. // It's to make remote loggging work properly when buffering is enabled // and log request is directed to different OpenSSO servers. private Map reqSetMap; private TimeBufferingTask bufferTask; private boolean timeBufferingEnabled = false; private String logName; private URL logServURL; private LoggingThread thread = LoggingThread.getInstance(); private void configure() { bufferSize = manager.getProperty(LogConstants.BUFFER_SIZE); if (bufferSize != null && bufferSize.length() > 0) { try { recCountLimit = Integer.parseInt(bufferSize); } catch (NumberFormatException e) { recCountLimit = 1; } } else { recCountLimit = 1; } String status = manager.getProperty(LogConstants.TIME_BUFFERING_STATUS); if (status != null && status.equalsIgnoreCase("ON")) { timeBufferingEnabled = true; } setLevel(Level.ALL); setFilter(null); String urlString = manager.getProperty(LogConstants.LOGGING_SERVICE_URL); try { logServURL = new URL(urlString); } catch (MalformedURLException mue) { if (Debug.warningEnabled()) { Debug.warning( "RemoteHandler.getLogHostURL(): '" + urlString + "' is malformed. " + mue.getMessage()); } } } /** * Constructor in which the configuration of the handler is done. * * @param dummyParam dummy parameter. To make instantation generic for all handlers. */ public RemoteHandler(String dummyParam) { reqSetMap = new HashMap(); configure(); if (timeBufferingEnabled) { startTimeBufferingThread(); } // Redundant instantiation of FlushTask for early class loading // and hence performance improvement. new FlushTask(reqSetMap); } /** * This method sends the LogRecord to the remote logging service. * * @param logRecord The LogRecord to be published to the remote logging service. */ public synchronized void publish(java.util.logging.LogRecord logRecord) { logName = logRecord.getLoggerName(); String xml = getFormatter().format(logRecord); if (xml == null || xml.length() <= 0) { if (Debug.warningEnabled()) { Debug.warning(logName + ":RemoteHandler.publish : formatted xml is null"); } return; } Request request = new Request(xml); if (logRecord instanceof ILogRecord) { Map logInfoMap = ((ILogRecord) logRecord).getLogInfoMap(); String loggedBySid = (String) logInfoMap.get(LogConstants.LOGGED_BY_SID); if (loggedBySid != null) { RequestSet reqSet = (RequestSet) reqSetMap.get(loggedBySid); if (reqSet == null) { reqSet = new RequestSet("Logging"); } reqSet.addRequest(request); reqSetMap.put(loggedBySid, reqSet); } } this.recCount++; if (this.recCount >= recCountLimit) { if (Debug.messageEnabled()) { Debug.message( logName + ":RemoteHandler.publish(): got " + recCount + " records, flushing all"); } nonBlockingFlush(); } } /** * Flushes any buffered output by calling flush(), and then close the handler and free all * associated resources with this handler. */ public void close() { flush(); stopBufferTimer(); } /** Flush any buffered output. */ public synchronized void flush() { if (recCount <= 0) { if (Debug.messageEnabled()) { Debug.message("RemoteHandler.flush(): no records " + "in buffer to send"); } return; } Vector responses = new Vector(); if (Debug.messageEnabled()) { Debug.message("RemoteHandler.flush(): sending buffered records"); } String thisAMException = null; try { Iterator sidIter = reqSetMap.keySet().iterator(); while (sidIter.hasNext()) { String currentLoggedBySID = (String) sidIter.next(); URL logHostURL = getLogHostURL(currentLoggedBySID); if (logHostURL == null) { Debug.error("RemoteHandler.flush(): logHostURL is null"); this.recCount = 0; reqSetMap = new HashMap(); return; } RequestSet reqSet = (RequestSet) reqSetMap.get(currentLoggedBySID); responses = PLLClient.send(logHostURL, reqSet); Iterator respIter = responses.iterator(); while (respIter.hasNext()) { Response resp = (Response) respIter.next(); String respContent = resp.getContent(); if (!respContent.equals("OK")) { Debug.error("RemoteHandler.flush(): " + respContent + " on remote machine"); if (thisAMException == null) { thisAMException = "RemoteHandler.flush(): " + respContent + " on remote machine"; } } } } } catch (Exception e) { Debug.error("RemoteHandler.flush(): ", e); } this.recCount = 0; reqSetMap = new HashMap(); if (thisAMException != null) { throw new AMLogException(thisAMException); } } /** * Copy the existing request set map and pass it on to ThreadPool as part of a FlushTask. * Initiatize a new map as the new request set map for future remote logging calls. */ public synchronized void nonBlockingFlush() { if (recCount <= 0) { if (Debug.messageEnabled()) { Debug.message("RemoteHandler.nonBlockingFlush(): no records " + "in buffer to send"); } return; } FlushTask task = new FlushTask(reqSetMap); try { thread.run(task); } catch (ThreadPoolException ex) { // Use current thread to complete the task if ThreadPool can not // execute it. if (Debug.messageEnabled()) { Debug.message( "RemoteHandler.nonBlockingFlush(): ThreadPoolException" + ". Performing blocking flush."); } task.run(); } this.recCount = 0; reqSetMap = new HashMap(); } private URL getLogHostURL(String loggedBySID) { SessionID sid = new SessionID(loggedBySID); String sessionProtocol = sid.getSessionServerProtocol(); String sessionHost = sid.getSessionServer(); String sessionPort = sid.getSessionServerPort(); String sessionURI = sid.getSessionServerURI(); // // if remote logging service and protocol, host, and port // are null, get them from the logging service url in the // AMConfig.properties file. // if ((!manager.isLocal) && ((sessionProtocol == null) || (sessionProtocol.length() <= 0) || (sessionHost == null) || (sessionHost.length() <= 0))) { if (Debug.messageEnabled()) { Debug.message("RemoteHandler.getLogHostURL(): remote serv = " + logServURL); } return (logServURL); } if (Debug.messageEnabled()) { Debug.message( "RemoteHandler.getLogHostURL(): " + " sessionProtocol: " + sessionProtocol + " sessionHost: " + sessionHost + " sessionPort: " + sessionPort + " sessionURI: " + sessionURI); } URL loggingURL = null; try { loggingURL = WebtopNaming.getServiceURL( LogConstants.LOGGING_SERVICE, sessionProtocol, sessionHost, sessionPort, sessionURI); if (Debug.messageEnabled()) { Debug.message( "RemoteHandler.getLogHostURL(): WebtopNaming logging" + "service URL: " + loggingURL); } } catch (URLNotFoundException unfe) { Debug.error("RemoteHandler.getLogHostURL(): URLNotFoundException: ", unfe); return null; } return loggingURL; } /** * This inner class is instantiated by the nonBlockingFlush() method to create task for flushing * out (asynchronously) the current buffer of log record requests. */ private class FlushTask implements Runnable { private Map<String, RequestSet> logReqsMap = null; FlushTask(Map<String, RequestSet> reqSetMap) { this.logReqsMap = reqSetMap; } public void run() { Vector responses = new Vector(); if (Debug.messageEnabled()) { Debug.message("RemoteHandler.FlushTask.run(): " + "sending buffered records"); } String thisAMException = null; try { for (String currentLoggedBySID : logReqsMap.keySet()) { URL logHostURL = getLogHostURL(currentLoggedBySID); if (logHostURL == null) { Debug.error("RemoteHandler.FlushTask.run(): " + "logHostURL is null"); return; } RequestSet reqSet = (RequestSet) logReqsMap.get(currentLoggedBySID); responses = PLLClient.send(logHostURL, reqSet); Iterator respIter = responses.iterator(); while (respIter.hasNext()) { Response resp = (Response) respIter.next(); String respContent = resp.getContent(); if (!respContent.equals("OK")) { Debug.error("RemoteHandler.FlushTask.run(): " + respContent + " on remote machine"); if (thisAMException == null) { thisAMException = "RemoteHandler.FlushTask.run(): " + respContent + " on remote machine"; } } } } } catch (Exception e) { Debug.error("RemoteHandler.FlushTask.run(): ", e); } if (thisAMException != null) { throw new AMLogException(thisAMException); } } } private class TimeBufferingTask extends GeneralTaskRunnable { private long runPeriod; public TimeBufferingTask(long runPeriod) { this.runPeriod = runPeriod; } /** The method which implements the GeneralTaskRunnable. */ public void run() { if (Debug.messageEnabled()) { Debug.message("RemoteHandler:TimeBufferingTask.run() called"); } flush(); } /** Methods that need to be implemented from GeneralTaskRunnable. */ public boolean isEmpty() { return true; } public boolean addElement(Object obj) { return false; } public boolean removeElement(Object obj) { return false; } public long getRunPeriod() { return runPeriod; } } private void startTimeBufferingThread() { String period = manager.getProperty(LogConstants.BUFFER_TIME); long interval; if ((period != null) || (period.length() != 0)) { interval = Long.parseLong(period); } else { interval = LogConstants.BUFFER_TIME_DEFAULT; } interval *= 1000; if (bufferTask == null) { bufferTask = new TimeBufferingTask(interval); try { SystemTimer.getTimer() .schedule( bufferTask, new Date(((System.currentTimeMillis() + interval) / 1000) * 1000)); } catch (IllegalArgumentException e) { Debug.error(logName + ":RemoteHandler:BuffTimeArg: " + e.getMessage()); } catch (IllegalStateException e) { if (Debug.messageEnabled()) { Debug.message(logName + ":RemoteHandler:BuffTimeState: " + e.getMessage()); } } if (Debug.messageEnabled()) { Debug.message("RemoteHandler: Time Buffering Thread Started"); } } } private void stopBufferTimer() { if (bufferTask != null) { bufferTask.cancel(); bufferTask = null; if (Debug.messageEnabled()) { Debug.message("RemoteHandler: Buffer Timer Stopped"); } } } }