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}