001/*
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: Logger.java,v 1.15 2009/12/09 00:34:21 bigfatrat Exp $
026 *
027 * Portions Copyrighted 2011-2015 ForgeRock AS.
028 */
029
030package com.sun.identity.log;
031
032import java.io.File;
033import java.io.IOException;
034import java.lang.reflect.Constructor;
035import java.util.Enumeration;
036import java.util.MissingResourceException;
037import java.util.ResourceBundle;
038import java.util.logging.Filter;
039import java.util.logging.Formatter;
040import java.util.logging.Handler;
041import java.util.logging.Level;
042import java.util.logging.LogRecord;
043
044import com.iplanet.am.util.SystemProperties;
045import com.iplanet.sso.SSOException;
046import com.iplanet.sso.SSOToken;
047import com.sun.identity.common.ReaderWriterLock;
048import com.sun.identity.log.messageid.LogMessageProviderBase;
049import com.sun.identity.log.messageid.MessageProviderFactory;
050import com.sun.identity.log.spi.Authorizer;
051import com.sun.identity.log.spi.Debug;
052import com.sun.identity.monitoring.Agent;
053import com.sun.identity.monitoring.MonitoringUtil;
054import com.sun.identity.monitoring.SsoServerLoggingSvcImpl;
055import com.sun.identity.monitoring.SsoServerLoggingHdlrEntryImpl;
056import com.sun.identity.shared.Constants;
057import java.text.SimpleDateFormat;
058import java.util.Date;
059import java.util.Set;
060import javax.security.auth.Subject;
061
062/**
063 * OpenAM extension to the jdk1.4 Logger
064 * This extension gives some functionality required by
065 * OpenAM secure logger.
066 * For <code>JDK1.4</code> Logger please refer to
067 * <pre>
068 * http://java.sun.com/j2se/1.4.1/docs/api/java/util/logging/Logger.html
069 * </pre>
070 * @supported.all.api
071 */
072public class Logger extends java.util.logging.Logger {
073    
074    public static ThreadLocal token = new ThreadLocal();
075    private String currentFileName = new String();
076    private static LogManager lm;
077    private String logName;
078    protected static boolean resolveHostName;
079
080    /**
081     * Lock to prevent parallel writing and reading at the same time.
082     */
083    public static ReaderWriterLock rwLock = new ReaderWriterLock();
084    
085    static {
086        lm = (com.sun.identity.log.LogManager) LogManagerUtil.getLogManager();
087        try {
088            lm.readConfiguration();
089        } catch (Exception ex) {
090            ex.printStackTrace();
091            /* our Debug system will no be up now, so can't Debug */
092        }
093        String location = lm.getProperty(LogConstants.LOG_LOCATION);
094        String type = lm.getProperty(LogConstants.BACKEND);
095        if ((location != null) && type.equals("File")) {
096            File dir = new File(location);
097            if (!dir.exists()) {
098                if (!dir.mkdirs()) {
099                    Debug.error("Logger:Creation of Log Directory failed: " +
100                        location);
101                }
102            }
103        }
104
105        /* Check if hostnames have to be resolved */
106        resolveHostName = Boolean.valueOf(
107            lm.getProperty(LogConstants.LOG_RESOLVE_HOSTNAME_ATTR)).
108                booleanValue();
109    }
110    
111    /**
112     * Protected method to construct a logger for a named subsystem.
113     * <p>
114     * The logger will be initially configured with a null Level
115     * and with useParentHandlers true.
116     *
117     * @param name A name for the logger.  This should be a
118     *        dot-separated name and should normally be based on the
119     *        package name or class name of the subsystem, such as java.net
120     *        or javax.swing.  It may be null for anonymous Loggers.
121     * @param resourceBundleName Name of the ResourceBundle to be used for
122     *        localizing messages for this logger.  May be null if none
123     *        of the messages require localization.
124     * @throws MissingResourceException if the ResourceBundleName is
125     *         non-null and no corresponding resource can be found.
126     */
127    protected Logger(String name,String resourceBundleName) {
128        super(name,resourceBundleName);
129    }
130
131    /**
132     * To add handlers and formatters to the new logger object
133     */
134    private static void processNewLoggerObject (Logger result) {
135        Formatter formatter = null;
136        String handlerClass = LogManager.HANDLER;
137        String formatterClass = LogManager.FORMATTER;
138        String levelProp = LogConstants.LOG_PROP_PREFIX + "." +
139            result.logName + ".level";
140        
141        /*
142         *  see if logging level for this file already defined.
143         *  if not, then check AMConfig.properties.
144         *  if not, then use Logging service config value.
145         *  if not, then use default ("INFO")
146         */
147        String levelString = lm.getProperty(levelProp);
148
149        if ((levelString == null) || !(levelString.length() > 0)) {
150            levelString = SystemProperties.get (levelProp);
151            if ((levelString == null) || !(levelString.length() > 0)) {
152                levelString = lm.getProperty(LogConstants.LOGGING_LEVEL);
153                if ((levelString == null) || !(levelString.length() > 0)) {
154                    levelString = LogConstants.DEFAULT_LOGGING_LEVEL_STR;
155                }
156            }
157        }
158        Level logLevel = null;
159        try {
160            logLevel = Level.parse(levelString);
161        } catch (IllegalArgumentException iaex) {
162            logLevel = LogConstants.DEFAULT_LOGGING_LEVEL;
163        }
164
165        result.setLevel(logLevel);
166
167        //  but disabled logging in AMConfig.properties takes precedence
168        String logStatus = lm.getProperty(LogConstants.LOG_STATUS_ATTR);
169        if (logStatus != null && logStatus.startsWith("INACTIVE")) {
170            logLevel = Level.OFF;
171        }
172        result.setLevel(logLevel);
173
174        Class clz = null;
175        Class [] parameters = {String.class};
176        Object [] parameterObjects = {result.logName};
177        Constructor cons = null;
178        Handler handler = null;
179        
180        if (handlerClass == null) {
181            Debug.error("Logger:processNewLoggerObject:" +
182                "HandlerClass not in classpath ");
183            return;
184        }
185        try {
186            clz = Class.forName(handlerClass);
187        } catch (Exception e) {
188            Debug.error("Logger:processNewLoggerObject:" +
189                "HandlerClass not in classpath: " + handlerClass, e);
190            return;
191        }
192        try {
193            if(clz != null) {
194                cons = clz.getDeclaredConstructor(parameters);
195            }
196        } catch (Exception e) {
197            Debug.error("Logger:processNewLoggerObject:" +
198                "constructor parameter mismatch ", e);
199            return;
200        }
201        try {
202            if(cons != null) {
203                handler = (Handler) cons.newInstance(parameterObjects);
204            }
205        } catch (Exception e) {
206            Debug.error("Logger:processNewLoggerObject:" +
207                "Could not instantiate handler: " + handlerClass, e);
208            return;
209        }
210        if (formatterClass == null) {
211            Debug.error("Logger:processNewLoggerObject:" +
212                "formatterClass not in classpath ");
213            return;
214        }
215        try {
216            clz = Thread.currentThread().getContextClassLoader().
217                loadClass(formatterClass);
218        } catch (Exception e) {
219            Debug.error("Logger:processNewLoggerObject:" +
220                "Could not load Formatter Class: " + formatterClass, e);
221            return;
222        }
223        try {
224            if(clz != null) {
225                formatter = (Formatter) clz.newInstance();
226            }
227        } catch (Exception e) {
228            Debug.error("Logger:processNewLoggerObject:" +
229                "Could not get Formatter instance " + formatterClass, e);
230            return;
231        }
232        try {
233            handler.setFormatter(formatter);
234            result.addHandler(handler);
235        } catch (Exception e) {
236            Debug.error("Logger:processNewLoggerObject:" +
237                "Unable to add Handler", e);
238            return;
239        }
240        String filterClassName = lm.getProperty(LogConstants.FILTER_CLASS_NAME);
241        try {
242            if (filterClassName != null) {
243                Filter filter =
244                    (Filter)Class.forName(filterClassName).newInstance();
245                result.setFilter(filter);
246            }
247        } catch (Exception e) {
248            Debug.error("Logger:processNewLoggerObject:" +
249                "Could not set Filter: "+ filterClassName, e);
250        }
251        
252        result.setUseParentHandlers(false);
253
254        resolveHostName = Boolean.valueOf(
255            lm.getProperty(LogConstants.LOG_RESOLVE_HOSTNAME_ATTR)).
256                booleanValue();
257    }
258    
259    /**
260     * Directs every log call to <code>log(LogRecord, Object)</code>
261     * And thus the default authorization check does not allow logging 
262     * when an application uses this interface.
263     *
264     * @param record The <code>LogRecord</code> to be logged.
265     */
266    public void log(LogRecord record) {
267        if (record instanceof ILogRecord) {
268            log((ILogRecord)record);
269        } else {
270            Object obj = token.get();
271            log(record, obj);
272        }
273    }
274
275    private boolean validateLogBy(Object cred) {
276        if (!LogManager.isLocal) {
277            if (cred == null) {
278                /* In case of remote sso token must be provide. */
279                Debug.error("Logger.validateLogBy:" + logName +
280                    ": remote logging, ssoToken is null; Will not log");
281                return false;
282            }
283        } else {
284            /* Authorizer need not be called in the case of remote. */
285            if (!Authorizer.isAuthorized(logName, "MODIFY", cred)) {
286                incMonReject(); // increment log svc and handler stats
287                Debug.error("Logger.validateLogBy:" + logName +
288                    ": authorization failed; Will not log");
289                throw new AMLogException(logName + ":" +
290                    AMLogException.LOG_WRT_AUTH_FAILED);
291            }
292        }
293        return true;
294    }
295
296    private void addLogByInfo(ILogRecord record, Object cred) {
297        if (cred instanceof SSOToken) {
298            SSOToken ssoToken = (SSOToken) cred;
299            String loggedBySID = ssoToken.getTokenID().toString();
300            record.addLogInfo(LogConstants.LOGGED_BY_SID, loggedBySID);
301            String clientID = null;
302            try {
303                clientID = ssoToken.getPrincipal().getName();
304            } catch (SSOException ssoe) {
305                Debug.error("Logger:log:" + logName +
306                    ": could not get clientID from ssoToken:", ssoe);
307            }
308            record.addLogInfo(LogConstants.LOGGED_BY, clientID);
309        }
310    }
311
312    private void addModuleName(ILogRecord record) {
313        String existModuleName =
314            (String)record.getLogInfoMap().get(LogConstants.MODULE_NAME);
315        if (existModuleName == null || existModuleName.length() <= 0) {
316            /* add module name only if it's already not added. */
317            record.addLogInfo(LogConstants.MODULE_NAME, this.getName());
318        }
319
320    }
321
322    /**
323     * Log entitlement log record.
324     *
325     * @param record Log record.
326     */
327    public void log(ILogRecord record) {
328        try {
329            extractInfoFromLogFor(record);
330        } catch (SSOException e) {
331            Debug.error("Logger.log " + e.getMessage());
332        }
333
334        if (record instanceof java.util.logging.LogRecord) {
335            Object logBy = record.getLogBy();
336            Object cred = (logBy instanceof Subject) ?
337                getPrivateCred((Subject)logBy) : logBy;
338            log((java.util.logging.LogRecord)record, cred);
339        } else {
340            Debug.error(
341                "Logger.log: cannot log non java.util.logging.LogRecord class");
342        }
343    }
344
345    private static Object getPrivateCred(Subject sbj) {
346        Set privCreds = sbj.getPrivateCredentials();
347        return ((privCreds != null) && !privCreds.isEmpty()) ?
348            privCreds.iterator().next() : null;
349    }
350
351    /**
352     * Calls super.log after checking authorization.
353     * Data is not logged at all if this check fails.
354     *
355     * @param record The <code>LogRecord</code> to be logged.
356     * @param cred To prove authorization for log WRITE.
357     *        The default authorization hook checks validity of the single
358     *        sign on token which should be passed as the <code>cred</code>.
359     */
360    public void log(LogRecord record, Object cred) {
361        validateLogBy(cred);
362        if (record instanceof com.sun.identity.log.ILogRecord) {
363            com.sun.identity.log.ILogRecord openssoLogRecord =
364                (com.sun.identity.log.ILogRecord)record;
365            addLogByInfo(openssoLogRecord, cred);
366            addModuleName(openssoLogRecord);
367        }
368
369        /*
370         * These are normally done by the LogManager private method
371         * doLog(). But since this record is not passing through that
372         * method we have to explicitly do this.
373         * ResourceBundle logic has been simplified.
374         */
375        record.setLoggerName(getName());
376        String rbName = this.getResourceBundleName();
377        if (rbName != null) {
378            ResourceBundle bundle = ResourceBundle.getBundle(rbName);
379            record.setResourceBundle(bundle);
380        }
381        writeToLog(record);
382    }
383
384    private void writeToLog(LogRecord record) {
385        try {
386            rwLock.readRequest();
387            /*
388             * this is to serialize logging,signing and verifying
389             * threads so that no signing or verification takes
390             * place once a logging thread has gone past this point
391             */
392            if (lm.isSecure()) {
393                synchronized (this) {
394                    super.log(record);
395                }
396            } else {
397                super.log(record);
398            }
399        } catch (Exception ex) {
400            Debug.error("Logger.writeToLog:" + logName + ":" + ex.getMessage());
401            throw new AMLogException(logName + ":" + ex.getMessage());
402        } finally {
403            rwLock.readDone();
404        }
405    }
406
407    /** Writes all the buffered log records.
408     */
409    public void flush() {
410        /*
411         * Post the LogRecord to all our Handlers, and then to
412         * our parents' handlers, all the way up the tree.
413         */
414        Logger logger = this;
415        Handler targets[] = logger.getHandlers();
416        if (targets != null) {
417            for (int i = 0; i < targets.length; i++) {
418                targets[i].flush();
419            }
420        }
421    }
422   
423    /**
424     * Find or create a logger for a named subsystem.  If a logger has
425     * already been created with the given name it is returned.  Otherwise
426     * a new logger is created.
427     * <p>
428     * If a new logger is created its log level will be configured
429     * based on the <code>LogManager</code> and it will be configured NOT to
430     * send logging output to its parent loggers Handlers.  It will be
431     * registered in the <code>LogManager</code> global namespace.
432     *
433     * @param name A name for the logger.  This should be a dot-separated name
434     *        and should be the file name you want to have for your logs,
435     *        such as <code>amSSO.access</code>, or audit.
436     * @return a suitable <code>Logger</code>.
437     */
438    public static synchronized java.util.logging.Logger getLogger(String name)
439    {
440        if ((name == null) || (name.length() == 0) || name.indexOf("..") >= 0)
441        {
442            /* Do not allow logging if logName has "..". */
443            return null;
444        }
445        Logger result;
446
447        boolean loggerExists = false;
448        Enumeration e = lm.getLoggerNames();
449        while (e.hasMoreElements()) {
450            if (((String) e.nextElement()).equals(name)) {
451                loggerExists = true;
452            }
453        }
454
455        if (loggerExists)  {
456            result = (Logger) lm.getLogger(name);
457            if (result != null) {
458                return result;
459            }
460        }
461        java.util.logging.Logger newLog = (java.util.logging.Logger)
462            java.util.logging.Logger.getLogger(name);
463        lm.addLogger(newLog);
464        result = (Logger) lm.getLogger(name);
465
466        result.logName = name;
467        processNewLoggerObject(result);
468        if (SystemProperties.isServerMode()) {
469            logStartRecord(result);
470        }
471
472        /* Logging service starts earlier than Monitoring.
473         * Because of this the first call to LogManager's readConfiguration()
474         * does not update the monitoring handle with the config information for
475         * logging. Hence we need to call updateMonitConfigForLogService() here
476         * to make sure the monitoring handle does get updated with the config
477         * information eventually.
478         */
479        if(!lm.isMonitoringInit){
480            lm.updateMonitConfigForLogService();
481        }
482        return result;
483    }
484    
485    /** Find or create a logger for a named subsystem.  If a logger has
486     * already been created with the given name it is returned.  Otherwise
487     * a new logger is created.
488     * <p>
489     * If a new logger is created, its log level will be configured
490     * based on the <code>LogManager</code> and it will configured to also
491     * send logging output to its parent logger's Handlers.  It will be
492     * registered in the <code>LogManager</code> global namespace.
493     * <p>
494     * If the named Logger already exists and does not yet have a
495     * localization resource bundle then the given resource bundle
496     * name is used.  If the named Logger already exists and has
497     * a different resource bundle name then an
498     * <code>IllegalArgumentException</code> is thrown.
499     *
500     * @param name A name for the logger.  This should be a dot-separated name
501     *        and should be the file name you want to have for your logs, such
502     *        as <code>amSSO.access</code> or audit.
503     * @param rbName A resource bundle to be used for localizing the log
504     *        messages.
505     * @return logger for a named subsystem.
506     */
507    public static synchronized java.util.logging.Logger getLogger(
508        String name, String rbName)
509    {
510        if ((name == null) || (name.length() == 0) || name.indexOf("..") >= 0) {
511            /* Do not allow logging if logName has "..". */
512            return null;
513        }
514        boolean loggerExists = false;
515        Enumeration e = lm.getLoggerNames();
516        while (e.hasMoreElements()) {
517            if (((String) e.nextElement()).equals(name)) {
518                // The LoggerName is in the list, but we should check whether the
519                // referenced Logger still exists, see OPENAM-14
520                if (lm.getLogger(name) != null) {
521                    loggerExists = true;
522                }
523            }
524        }
525        Logger result = (Logger)
526        java.util.logging.Logger.getLogger(name, rbName);
527        result.logName = name;
528        if (loggerExists)  {
529            return result;
530        }
531        /*
532         * if the logger is a new object, we have to set the appropriate
533         * handlers and formatters to the logger before returning the result.
534         */
535        
536        processNewLoggerObject(result);
537        if (SystemProperties.isServerMode()) {
538            logStartRecord(result);
539        }
540        return result;
541    }
542    
543    /**
544     *  Log a LogRecord indicating the start of logging to this file
545     */
546    private static void logStartRecord (Logger logger) {
547        /*
548         *  SSOToken not required to instantiate a log file, so
549         *  need one to say who's doing the logging of the record,
550         *  and whose it "about".
551         */
552        try {
553            LogMessageProviderBase provider =
554                (LogMessageProviderBase)MessageProviderFactory.getProvider(
555                    "Logging");
556            SSOToken ssot = LogManagerUtil.getLoggingSSOToken();
557            String location = lm.getProperty(LogConstants.LOG_LOCATION);
558            String[] s = {location};
559            com.sun.identity.log.LogRecord lr =
560            provider.createLogRecord(LogConstants.START_LOG_NEW_LOGGER_NAME,
561                s, ssot);
562            logger.log(lr, ssot);
563        } catch (IOException ioex) {
564            Debug.error("Logger.logStartRecord:could not log to " + 
565                logger.getName() + ":" + ioex.getMessage());
566        }
567    }
568
569    /**
570     * Returns the current file to which the logger's handler is writing.
571     * This is useful only in case of file..
572     *
573     * @return the current file to which the logger's handler is writing.
574     */
575    public String getCurrentFile() {
576        return currentFileName;
577    }
578    
579    /**
580     * Set the current file to which the logger's handler is writing.
581     *
582     * @param fileName name of file.
583     */
584    public void setCurrentFile(String fileName) {
585        currentFileName = fileName;
586    }
587    
588    /**
589     * Return whether resolve host name is enabled
590     *
591     * @return <code>resolveHostName</code> 
592     */
593    public static boolean resolveHostNameEnabled() {
594        return resolveHostName;
595    }
596
597    static void extractInfoFromLogFor(ILogRecord rec)
598        throws SSOException {
599        Object logFor = rec.getLogFor();
600        Object cred = (logFor instanceof Subject) ?
601            getPrivateCred((Subject)logFor) : logFor;
602
603        if (!(cred instanceof SSOToken)) {
604            return;
605        }
606        SSOToken ssoToken = (SSOToken)cred;
607        rec.addLogInfo(LogConstants.LOGIN_ID_SID,
608            ssoToken.getTokenID().toString());
609
610        String ctxID = ssoToken.getProperty(Constants.AM_CTX_ID);
611        if ((ctxID != null) && (ctxID.length() > 0)) {
612            rec.addLogInfo(LogConstants.CONTEXT_ID, ctxID);
613        }
614
615        resolveHostName(rec, ssoToken);
616        String clientDomain = ssoToken.getProperty("Organization");
617        if (clientDomain == null || clientDomain.length() == 0) {
618            clientDomain = ssoToken.getProperty("cdomain");
619        }
620        rec.addLogInfo(LogConstants.DOMAIN, clientDomain);
621        rec.addLogInfo(LogConstants.LOGIN_ID,
622            ssoToken.getPrincipal().getName());
623
624        Date date = new Date();
625        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
626
627        /*
628         * these are the compulsory fields ... to be logged even if there are
629         * exceptions while getting domain, loginid, ipaddr, hostname
630         */
631        rec.addLogInfo(LogConstants.TIME, sdf.format(date));
632
633        if (rec instanceof java.util.logging.LogRecord) {
634            java.util.logging.LogRecord jLogRecord =
635                (java.util.logging.LogRecord)rec;
636            rec.addLogInfo(LogConstants.DATA, jLogRecord.getMessage());
637            rec.addLogInfo(LogConstants.LOG_LEVEL,
638                jLogRecord.getLevel().toString());
639        }
640
641    }
642
643    static void resolveHostName(ILogRecord rec, SSOToken ssoToken)
644        throws SSOException {
645        /*
646         *  using the SSOToken, get the hostname first, as
647         *  getting the IPAddr appears to use an Inet call using
648         *  the hostname...
649         *
650         *  if com.sun.identity.log.resolveHostName=false, then
651         *  IPAddr field will end up "Not Available"
652         */
653        String hostName = ssoToken.getHostName();
654        String ipAddress = null;
655
656        if (Logger.resolveHostName) {
657            java.net.InetAddress ipAddr = ssoToken.getIPAddress();
658            if (ipAddr != null) {
659                /*
660                 * getting a leading "/" from InetAddress.getByName(host)
661                 * in SSOTokenImpl.java when "host" is an IPaddress.
662                 */
663                ipAddress = ipAddr.getHostAddress();
664
665                /*
666                 *  if no hostname returned, or only IP address,
667                 *  try getting hostname from InetAddr
668                 */
669                if ((hostName == null) ||
670                    ((ipAddress != null) && (ipAddress.equals(hostName)))) {
671                    hostName = ipAddr.getHostName();
672                }
673            }
674        }
675        rec.addLogInfo(LogConstants.HOST_NAME, hostName);
676        rec.addLogInfo(LogConstants.IP_ADDR, ipAddress);
677    }
678
679    /*
680     *  increment the logging service LoggingRecsRejected attribute and
681     *  the logging handler's (File, DB, and Secure only) LoggingHdlrFailureCt.
682     *  this is for the count of rejections due to unauthorized userid trying
683     *  to write to the log.
684     */
685    private void incMonReject() {
686        if (LogManager.isLocal && MonitoringUtil.isRunning()) {
687            // logging service stat
688            SsoServerLoggingSvcImpl logSvcMon =
689                Agent.getLoggingSvcMBean();
690            if (logSvcMon != null) {
691                 logSvcMon.incSsoServerLoggingRecsRejected();
692            }
693
694            // handler's stat
695            // if DB then database, else if secure then secure file, else file
696            SsoServerLoggingHdlrEntryImpl logH = null;
697            if (lm.isDBLogging()) {
698                logH = logSvcMon.getHandler(
699                        SsoServerLoggingSvcImpl.DB_HANDLER_NAME);
700            } else if (lm.isSecure()) {
701                logH = logSvcMon.getHandler(
702                        SsoServerLoggingSvcImpl.SECURE_FILE_HANDLER_NAME);
703            } else {
704                logH = logSvcMon.getHandler(
705                        SsoServerLoggingSvcImpl.FILE_HANDLER_NAME);
706            } 
707            if (logH != null) {
708                logH.incHandlerFailureCount(1);
709                /*
710                 *  also increment handler's request count.  if it gets
711                 *  through the authorization check, it gets incremented
712                 *  in the handler itself.
713                 */
714                logH.incHandlerRequestCount(1);
715            }
716        }
717    }
718}