001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2005 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: SMSException.java,v 1.7 2009/01/28 05:35:03 ww203982 Exp $ 026 * 027 */ 028 029/* 030 * Portions Copyrighted [2011] [ForgeRock AS] 031 */ 032package com.sun.identity.sm; 033 034import com.sun.identity.authentication.internal.InvalidAuthContextException; 035import com.sun.identity.shared.debug.Debug; 036import com.sun.identity.shared.locale.AMResourceBundleCache; 037import com.sun.identity.shared.locale.L10NMessage; 038import com.sun.identity.shared.locale.Locale; 039import com.iplanet.am.sdk.AMException; 040import com.iplanet.services.ldap.LDAPServiceException; 041import com.iplanet.services.ldap.event.EventException; 042import com.iplanet.services.util.XMLException; 043import com.iplanet.sso.SSOException; 044import com.iplanet.ums.IUMSConstants; 045import java.io.PrintWriter; 046import java.io.StringWriter; 047import java.text.MessageFormat; 048import java.util.ResourceBundle; 049import com.sun.identity.shared.ldap.LDAPException; 050 051/** 052 * The exception class whose instance is thrown if there is any error during the 053 * operation of objects of the <code>com.sun.identity.sms</code> package. This 054 * class maps the exception that occurred at a lower level to a high level 055 * error. Using the exception status code <code>getExceptionCode()</code> the 056 * errors are categorized as a <code>ABORT</code>, <code>RETRY</code>, 057 * <code>CONFIG_PROBLEM</code> or <code>LDAP_OP_FAILED</code> (typically a 058 * bug). 059 * 060 * @supported.all.api 061 */ 062public class SMSException extends Exception implements L10NMessage { 063 064 transient AMResourceBundleCache amCache = AMResourceBundleCache.getInstance(); 065 066 transient Debug debug = Debug.getInstance(IUMSConstants.UMS_DEBUG); 067 068 private int exceptionStatus = STATUS_NONE; 069 070 private Throwable rootCause; 071 072 private String message; 073 074 private String bundleName = IUMSConstants.UMS_BUNDLE_NAME; 075 076 private String errorCode; 077 078 private Object[] args; 079 080 /** 081 * Default constructor for <code> SMSException </code> 082 */ 083 public SMSException() { 084 super(); 085 exceptionStatus = STATUS_NONE; 086 } 087 088 /** 089 * @param status 090 * The exception status code. 091 * @param errorCode 092 * Key to resource bundle. 093 */ 094 public SMSException(int status, String errorCode) { 095 super(); 096 exceptionStatus = status; 097 this.errorCode = errorCode; 098 this.message = getL10NMessage(java.util.Locale.ENGLISH); 099 } 100 101 /** 102 * @param status 103 * The Exception status code. 104 * @param exMessage 105 * The message provided by the object which is throwing the 106 * exception 107 * @param errorCode 108 * Key to resource bundle. 109 */ 110 public SMSException(int status, String exMessage, String errorCode) { 111 exceptionStatus = status; 112 this.errorCode = errorCode; 113 this.message = exMessage + ": " + 114 getL10NMessage(java.util.Locale.ENGLISH); 115 } 116 117 /** 118 * @param msg 119 * The message provided by the object which is throwing the 120 * exception 121 */ 122 public SMSException(String msg) { 123 exceptionStatus = STATUS_NONE; 124 this.message = msg; 125 } 126 127 /** 128 * @param msg 129 * The message provided by the object which is throwing the 130 * exception 131 * @param errorCode 132 * Key to resource bundle. 133 */ 134 public SMSException(String msg, String errorCode) { 135 exceptionStatus = STATUS_NONE; 136 this.errorCode = errorCode; 137 this.message = msg + ": " + getL10NMessage(java.util.Locale.ENGLISH); 138 } 139 140 /** 141 * Constructs an <code>SMSException</code>. 142 * 143 * @param t 144 * The <code>Throwable</code> object provided by the object 145 * which is throwing the exception 146 * @param errorCode 147 * Key to resource bundle. 148 */ 149 public SMSException(Throwable t, String errorCode) { 150 // super(t); (can be used with JDK 1.4 and higher) 151 rootCause = t; 152 this.errorCode = errorCode; 153 this.message = getL10NMessage(java.util.Locale.ENGLISH); 154 exceptionMapper(); 155 } 156 157 /** 158 * Constructs an <code>SMSException</code>. 159 * 160 * @param message 161 * exception message. 162 * @param t 163 * The <code>Throwable</code> object provided by the object 164 * which is throwing the exception. 165 * @param errorCode 166 * Key to resource bundle. 167 */ 168 public SMSException(String message, Throwable t, String errorCode) { 169 // super(message, t); (can be used with JDK 1.4 and higher) 170 rootCause = t; 171 this.errorCode = errorCode; 172 this.message = message + ": " + 173 getL10NMessage(java.util.Locale.ENGLISH); 174 exceptionMapper(); 175 } 176 177 /** 178 * Constructs an <code>SMSException</code>. 179 * 180 * @param rbName 181 * Resource bundle Name to be used for getting localized error 182 * message. 183 * @param message 184 * exception message. 185 * @param t 186 * The <code>Throwable</code> object provided by the object 187 * which is throwing the exception. 188 * @param errorCode 189 * Key to resource bundle. 190 */ 191 public SMSException(String rbName, String message, Throwable t, 192 String errorCode) { 193 // super(message, t); (can be used with JDK 1.4 and higher) 194 rootCause = t; 195 this.errorCode = errorCode; 196 this.bundleName = rbName; 197 this.message = message + ": " + 198 getL10NMessage(java.util.Locale.ENGLISH); 199 if (rootCause != null && !(rootCause instanceof AMException)) { 200 exceptionMapper(); 201 } 202 } 203 204 /** 205 * This constructor is used to pass the localized error message At this 206 * level, the locale of the caller is not known and it is not possible to 207 * throw localized error message at this level. Instead this constructor 208 * provides Resource Bundle name and error code for correctly locating the 209 * error message. The default <code>getMessage()</code> will always return 210 * English messages only. This is in consistent with current JRE. 211 * 212 * @param rbName 213 * Resource bundle Name to be used for getting localized error 214 * message. 215 * @param errorCode 216 * Key to resource bundle. You can use <code>ResourceBundle rb = 217 * ResourceBunde.getBundle(rbName,locale); 218 * String localizedStr = rb.getString(errorCode)</code>. 219 * @param args 220 * arguments to message. If it is not present pass the as null. 221 */ 222 public SMSException(String rbName, String errorCode, Object[] args) { 223 exceptionStatus = STATUS_NONE; 224 this.bundleName = rbName; 225 this.errorCode = errorCode; 226 this.args = args; 227 this.message = getL10NMessage(java.util.Locale.ENGLISH); 228 } 229 230 /** 231 * Returns a localized error message 232 * 233 * @param locale 234 * Uses the locale object to create the appropriate localized 235 * error message 236 * @return localized error message. 237 * @see #SMSException(String, String, Object[]) 238 */ 239 public String getL10NMessage(java.util.Locale locale) { 240 String result = errorCode; 241 if (bundleName != null && locale != null) { 242 ResourceBundle bundle = amCache.getResBundle(bundleName, locale); 243 String mid = Locale.getString(bundle, errorCode, debug); 244 if (args == null || args.length == 0) { 245 result = mid; 246 } else { 247 result = MessageFormat.format(mid, args); 248 } 249 } 250 return result; 251 } 252 253 /** 254 * Returns <code>ResourceBundle</code> Name associated with this error 255 * message. 256 * 257 * @return <code>ResourceBundle</code> name associated with this error 258 * message. 259 * @see #SMSException(String, String, Object[]) 260 */ 261 public String getResourceBundleName() { 262 return bundleName; 263 } 264 265 /** 266 * Returns error code associated with this error message. 267 * 268 * @return Error code associated with this error message. 269 * @see #SMSException(String, String, Object[]) 270 */ 271 public String getErrorCode() { 272 return errorCode; 273 } 274 275 /** 276 * Returns arguments for formatting this error message. 277 * 278 * @return arguments for formatting this error message. You need to use 279 * <code>MessageFormat</code> class to format the message It can 280 * be null. 281 * @see #SMSException(String, String, Object[]) 282 */ 283 public Object[] getMessageArgs() { 284 return args; 285 } 286 287 /** 288 * Returns the status code for this exception. 289 * 290 * @return Integer representing the exception status code 291 */ 292 public int getExceptionCode() { 293 return exceptionStatus; 294 } 295 296 /** 297 * The this package can set the exception code. 298 * 299 * @param status 300 * The exception status code. 301 */ 302 void setExceptionCode(int status) { 303 exceptionStatus = status; 304 } 305 306 public String toString() { 307 StringBuilder buf = new StringBuilder(); 308 if (exceptionStatus != -1) { 309 buf.append("SMSException Exception Code:"); 310 buf.append(exceptionStatus); 311 buf.append('\n'); 312 } 313 String msg = message; 314 if (msg != null && msg.length() > 0) { 315 buf.append("Message:"); 316 buf.append(msg); 317 buf.append("\n"); 318 } 319 320 if (rootCause != null) { 321 buf.append("--------------------------------------------------\n"); 322 buf.append("The lower level exception message\n"); 323 buf.append(rootCause.getMessage()); 324 buf.append('\n'); 325 buf.append("The lower level exception:\n"); 326 StringWriter sw = new StringWriter(100); 327 rootCause.printStackTrace(new PrintWriter(sw)); 328 buf.append(sw.toString()); 329 buf.append('\n'); 330 } 331 return buf.toString(); 332 } 333 334 /** 335 * Returns the error message of this exception. 336 * 337 * @return String representing the error message 338 */ 339 public String getMessage() { 340 return message; 341 } 342 343 private String getString(String msgID) { 344 errorCode = msgID; 345 ResourceBundle bundle = null; 346 if (bundleName != null) { 347 bundle = amCache.getResBundle(bundleName, java.util.Locale.ENGLISH); 348 } 349 return (Locale.getString(bundle, msgID, debug)); 350 } 351 352 private void exceptionMapper() { 353 if (rootCause == null) { 354 return; 355 } 356 if (rootCause instanceof LDAPException) { 357 message = mapLDAPException(); 358 } else if (rootCause instanceof LDAPServiceException) { 359 // do nothing 360 } else if (rootCause instanceof EventException) { 361 exceptionStatus = STATUS_ABORT; 362 message = getString(IUMSConstants.SMS_EVENT_NOTIFICATION_FAILED); 363 } else if (rootCause instanceof XMLException) { 364 exceptionStatus = STATUS_ABORT; 365 message = getString(IUMSConstants.SMS_XML_PARSER_EXCEPTION); 366 } else if (rootCause instanceof InvalidAuthContextException) { 367 message = getString(IUMSConstants.SMS_AUTHENTICATION_ERROR); 368 exceptionStatus = STATUS_ABORT; 369 } else if (rootCause instanceof SSOException) { 370 message = getString(IUMSConstants.SMS_AUTHENTICATION_ERROR); 371 exceptionStatus = STATUS_ABORT; 372 } else { 373 message = getString(IUMSConstants.SMS_UNKNOWN_EXCEPTION_OCCURRED); 374 exceptionStatus = STATUS_UNKNOWN_EXCEPTION; 375 } 376 } 377 378 private String mapLDAPException() { 379 int resultCode = ((LDAPException) rootCause).getLDAPResultCode(); 380 381 String message = null; 382 383 switch (resultCode) { 384 // //////////////////////////////// 385 // Errors that need to be handled 386 // //////////////////////////////// 387 388 // Helpless errors 389 // All errors are helpless situations 390 // but some are more helpless than the others. 391 // These errors are either problems in connection 392 // or configuration. So, some can be retired and 393 // some are already busted. 394 case LDAPException.SERVER_DOWN: 395 case LDAPException.OTHER: 396 message = getString(IUMSConstants.SMS_SERVER_DOWN); 397 exceptionStatus = STATUS_RETRY; 398 break; 399 case LDAPException.LDAP_NOT_SUPPORTED: 400 message = getString(IUMSConstants.SMS_LDAP_NOT_SUPPORTED); 401 exceptionStatus = STATUS_ABORT; 402 break; 403 case LDAPException.BUSY: 404 message = getString(IUMSConstants.SMS_LDAP_SERVER_BUSY); 405 exceptionStatus = STATUS_RETRY; 406 break; 407 408 case LDAPException.INVALID_CREDENTIALS: 409 message = getString("INVALID_CREDENTIALS"); 410 exceptionStatus = STATUS_CONFIG_PROBLEM; 411 break; 412 413 // Application must show exactly what is happening 414 case LDAPException.NO_SUCH_OBJECT: 415 message = getString(IUMSConstants.SMS_NO_SUCH_OBJECT); 416 exceptionStatus = STATUS_LDAP_OP_FAILED; 417 break; 418 419 case LDAPException.INSUFFICIENT_ACCESS_RIGHTS: 420 message = getString(IUMSConstants.SMS_INSUFFICIENT_ACCESS_RIGHTS); 421 exceptionStatus = STATUS_NO_PERMISSION; 422 break; 423 424 case LDAPException.ADMIN_LIMIT_EXCEEDED: 425 message = getString(IUMSConstants.SMS_ADMIN_LIMIT_EXCEEDED); 426 exceptionStatus = STATUS_ABORT; 427 break; 428 429 case LDAPException.TIME_LIMIT_EXCEEDED: 430 message = getString(IUMSConstants.SMS_TIME_LIMIT_EXCEEDED); 431 exceptionStatus = STATUS_ABORT; 432 break; 433 434 case LDAPException.REFERRAL: 435 message = getString(IUMSConstants.SMS_LDAP_REFERRAL_EXCEPTION); 436 exceptionStatus = STATUS_CONFIG_PROBLEM; 437 break; 438 439 // We screwed up with something 440 case LDAPException.OBJECT_CLASS_VIOLATION: 441 case LDAPException.NAMING_VIOLATION: 442 case LDAPException.CONSTRAINT_VIOLATION: 443 case LDAPException.INVALID_DN_SYNTAX: 444 case LDAPException.ENTRY_ALREADY_EXISTS: 445 case LDAPException.ATTRIBUTE_OR_VALUE_EXISTS: 446 case LDAPException.PROTOCOL_ERROR: 447 case LDAPException.UNDEFINED_ATTRIBUTE_TYPE: 448 SMSEntry.debug.error(rootCause.toString()); 449 message = getString(IUMSConstants.SMS_LDAP_OPERATION_FAILED); 450 exceptionStatus = STATUS_LDAP_OP_FAILED; 451 break; 452 453 // Exception code that means logical operation. 454 case LDAPException.COMPARE_TRUE: 455 case LDAPException.COMPARE_FALSE: 456 case LDAPException.LDAP_PARTIAL_RESULTS: 457 exceptionStatus = STATUS_QUO_ANTE; 458 break; 459 460 default: 461 message = getString(IUMSConstants.SMS_UNEXPECTED_LDAP_EXCEPTION); 462 exceptionStatus = STATUS_UNKNOWN_EXCEPTION; 463 } 464 return message; 465 } 466 467 // Error codes 468 /** No status code is set */ 469 public static final int STATUS_NONE = -1; 470 471 /** Retry connection to data store */ 472 public static final int STATUS_RETRY = 0; 473 474 /** Repeated retry to data store failed */ 475 public static final int STATUS_REPEATEDLY_FAILED = 0; 476 477 /** Status to abort operation */ 478 public static final int STATUS_ABORT = 1; 479 480 /** 481 * If root LDAP cause is <code>LDAP_PARTIAL_RESULTS </code> then this 482 * status is set 483 */ 484 public static final int STATUS_QUO_ANTE = 2; 485 486 /** 487 * If root LDAP cause is an LDAP exception with one of the following error 488 * codes then this status is set. 489 * <p> 490 * 491 * <PRE> 492 * 493 * NO_SUCH_OBJECT OBJECT_CLASS_VIOLATION NAMING_VIOLATION 494 * CONSTRAINT_VIOLATION INVALID_DN_SYNTAX ENTRY_ALREADY_EXISTS 495 * ATTRIBUTE_OR_VALUE_EXISTS PROTOCOL_ERROR UNDEFINED_ATTRIBUTE_TYPE 496 * 497 * </PRE> 498 */ 499 500 public static final int STATUS_LDAP_OP_FAILED = 3; 501 502 /** 503 * If the root LDAP exception is <code> INVALID_CREDENTIALS </code> or 504 * <code> REFERRAL </code> then this status is set 505 */ 506 public static final int STATUS_CONFIG_PROBLEM = 4; 507 508 /** If root cause is other than any of those listed in other status codes */ 509 public static final int STATUS_UNKNOWN_EXCEPTION = 5; 510 511 /** If the root LDAP cause is <code> INSUFFICIENT_ACCESS_RIGHTS </code> */ 512 public static final int STATUS_NO_PERMISSION = 8; 513 514 /** the operation is not allowed. */ 515 public static final int STATUS_NOT_ALLOW = 9; 516 517}
Copyright © 2010-2017, ForgeRock All Rights Reserved.