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: AuthLoginException.java,v 1.4 2008/06/25 05:42:06 qcheng Exp $ 026 * 027 */ 028 029/* 030 * Portions Copyright 2011-2013 ForgeRock AS 031 */ 032package com.sun.identity.authentication.spi; 033 034import com.sun.identity.shared.locale.AMResourceBundleCache; 035import com.sun.identity.shared.locale.L10NMessage; 036import java.text.MessageFormat; 037import java.util.Locale; 038import java.util.ResourceBundle; 039import javax.security.auth.login.LoginException; 040 041/** 042 * This class is for handling message localization in LoginException. 043 * 044 * @supported.api 045 */ 046public class AuthLoginException extends LoginException implements L10NMessage { 047 048 private static AMResourceBundleCache amCache = AMResourceBundleCache.getInstance(); 049 050 private String _bundleName = null; 051 052 private String _errorCode = null; 053 054 private Object[] _args = null; 055 056 private ResourceBundle _bundle = null; 057 058 /** 059 * Constructs an exception with given message and the nested exception. 060 * 061 * @param message 062 * message of this exception 063 * @param nestedException 064 * Exception caught by the code block throwing this exception 065 */ 066 public AuthLoginException(String message, Throwable nestedException) { 067 super(message); 068 initCause(nestedException); 069 } 070 071 /** 072 * Constructs an <code>AuthLoginException</code> with given 073 * <code>Throwable</code>. 074 * 075 * @param nestedException 076 * Exception nested in the new exception. 077 * 078 * @supported.api 079 */ 080 public AuthLoginException(Throwable nestedException) { 081 initCause(nestedException); 082 if (nestedException instanceof L10NMessage) { 083 _errorCode = ((L10NMessage) nestedException).getErrorCode(); 084 } 085 } 086 087 /** 088 * Constructs a new <code>AuthLoginException</code> with the given 089 * message. 090 * 091 * @param message 092 * message for this exception. This message can be later 093 * retrieved by <code>getMessage()</code> method. 094 * 095 * @supported.api 096 */ 097 public AuthLoginException(String message) { 098 super(message); 099 } 100 101 /** 102 * Constructs an instance of <code> AuthLoginException </code> to pass the 103 * localized error message At this level, the locale of the caller is not 104 * known and it is not possible to throw localized error message at this 105 * level. Instead this constructor provides Resource Bundle name and 106 * <code>errorCode</code> for correctly locating the error message. The 107 * default <code>getMessage()</code> will always return English messages 108 * only. This is consistent with current JRE. 109 * 110 * @param rbName 111 * Resource Bundle Name to be used for getting localized error 112 * message. 113 * @param errorCode 114 * Key to resource bundle. You can use 115 * 116 * <pre> 117 * ResourceBundle rb = ResourceBunde.getBundle (rbName,locale); 118 * String localizedStr = rb.getString(errorCode) 119 * </pre> 120 * 121 * @param args 122 * arguments to message. If it is not present pass them as null 123 * @param nestedException 124 * The nested <code>Throwable</code>. 125 * 126 * @supported.api 127 */ 128 public AuthLoginException(String rbName, String errorCode, Object[] args, 129 Throwable nestedException) { 130 initCause(nestedException); 131 _bundleName = rbName; 132 _errorCode = errorCode; 133 _args = args; 134 135 } 136 137 /** 138 * Constructs a new <code>AuthLoginException</code> without a nested 139 * <code>Throwable</code>. 140 * 141 * @param rbName 142 * Resource Bundle Name to be used for getting localized error 143 * message. 144 * @param errorCode 145 * Key to resource bundle. You can use 146 * 147 * <pre> 148 * ResourceBundle rb = ResourceBunde.getBundle (rbName,locale); 149 * String localizedStr = rb.getString(errorCode) 150 * </pre> 151 * 152 * @param args 153 * arguments to message. If it is not present pass them as null 154 * 155 * @supported.api 156 */ 157 public AuthLoginException(String rbName, String errorCode, Object[] args) { 158 this(rbName, errorCode, args, null); 159 } 160 161 /** 162 * Returns the localized message of the given locale. 163 * 164 * @param locale 165 * the locale in which the message will be returned. 166 * @return String localized error message. 167 * 168 * @supported.api 169 */ 170 public String getL10NMessage(Locale locale) { 171 String result = super.getMessage(); 172 173 if (_bundleName != null && locale != null && _errorCode != null) { 174 _bundle = amCache.getResBundle(_bundleName, locale); 175 String mid = _bundle.getString(_errorCode); 176 if (_args == null || _args.length == 0) { 177 result = mid; 178 } else { 179 result = MessageFormat.format(mid, _args); 180 } 181 } 182 String chainedMessage = null; 183 Throwable nestedException = getCause(); 184 if (nestedException != null) { 185 if (nestedException instanceof L10NMessage) { 186 L10NMessage lex = (L10NMessage) nestedException; 187 chainedMessage = lex.getL10NMessage(locale); 188 } else { 189 chainedMessage = nestedException.getMessage(); 190 } 191 } 192 if (result == null) { 193 result = chainedMessage; 194 } else if (chainedMessage != null) { 195 result = result + "\n" + chainedMessage; 196 } 197 return result; 198 } 199 200 /** 201 * Returns the resource bundle name. 202 * 203 * @return Resource Bundle Name associated with this error message. 204 * @see #getL10NMessage(java.util.Locale). 205 * 206 * @supported.api 207 */ 208 public String getResourceBundleName() { 209 return _bundleName; 210 } 211 212 /** 213 * Returns the error code. 214 * 215 * @return Error code associated with this error message. 216 * 217 * @supported.api 218 */ 219 public String getErrorCode() { 220 return _errorCode; 221 } 222 223 /** 224 * Returns the error message arguments. 225 * 226 * @return arguments for formatting this error message. You need to use 227 * <code>MessageFormat</code> class to format the message. It can 228 * be null. 229 * 230 * @supported.api 231 */ 232 public Object[] getMessageArgs() { 233 return _args; 234 } 235 236 /** 237 * Gets messages of the exceptions including the nested exceptions. 238 * 239 * @return messages of the exceptions including nested exceptions. The 240 * returned string is formed by concatenating messages of all the 241 * exceptions, with a new line separator, starting from this 242 * exception, all the way to the root exception, by following the 243 * nested exceptions. The message returned is always in English 244 * locale. To get localized message, use the getL10NMessage(Locale) 245 * method. 246 * 247 * @supported.api 248 */ 249 public String getMessage() { 250 return getL10NMessage(Locale.ENGLISH); 251 } 252}