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: FSRedirectException.java,v 1.2 2008/06/25 05:46:40 qcheng Exp $ 026 * Portions Copyrighted 2014 ForgeRock AS 027 */ 028 029/* 030 * Portions Copyright 2013 ForgeRock AS 031 */ 032package com.sun.identity.federation.common; 033 034import com.sun.identity.shared.locale.L10NMessageImpl; 035import java.io.PrintWriter; 036import java.io.StringWriter; 037 038/** 039 * <PRE> 040 * This class is the super-class for all Federation <B>checked</B> exceptions. 041 * 042 * 043 * Some Exception throwing guidelines: 044 * ------------------------------------- 045 * 046 * <B> Checked exceptions </B> are sub-classes of java.lang.Exception; methods 047 * throwing this type of exception are forced to define a throws clause 048 * in the method signature and client programmers need to catch and 049 * handle the exception with a try/catch block or declare the throws clause 050 * in their methods. 051 * <B> Unchecked exceptions </B> are sub-classes of java.lang.RuntimeException. 052 * Client programmers don't have to deal with the exception using a 053 * try/catch block and the method throwing it does not have to define it 054 * in its signature. 055 * 056 * - If your method encounters an abnormal condition which causes it 057 * to be unable to fulfill its contract, or throw a checked or 058 * unchecked exception (either FSRedirectException or RuntimeException). 059 * 060 * - If your method discovers that a client has breached its contract, 061 * for example, passing a null as a parameter where a non-null value is 062 * required, throw an unchecked exception (RuntimeException). 063 * 064 * - If your method is unable to fulfill its contract and you feel client 065 * programmers should consciously decide how to handle, throw checked 066 * exceptions (FSRedirectException). 067 * 068 * 069 * Embedded/Nested Exceptions: 070 * -------------------------- 071 * 072 * An exception of type FSRedirectException can embed any 073 * exception of type Throwable. Embedded exceptions ensure traceability 074 * of errors in a multi-tiered application. For example, in a simple 3- 075 * Tier model - presentation/client tier, middle/domain tier and 076 * database/persistence tier - the real cause of error might be lost by the 077 * time control, which is passed back from the persistence tier to the client 078 * tier. To ensure tracking info, the constructor FSRedirectException( 079 * message,Throwable) should be used while throwing the exception. 080 * Client programs can then invoke the #getRootCause() method 081 * to get the underlying cause. 082 * 083 * Exception hierarchy should be defined: 084 * ------------------------------------- 085 * An exception for each abnormal cause should be created. 086 * FSRedirectException should probably be thrown only by external API's. 087 * Even these should have embedded exceptions from lower level tiers. 088 * Every package should define its own exception hierarchies specific 089 * to its context, for example, account management exceptions should be 090 * defined in the accountmgmt package. 091 * 092 * Localizing Error Messages 093 * ------------------------- 094 * The java resource bundle mechanism is used to implement localization. 095 * The ResourceSet and ResourceSetManager classes are used to implement 096 * localization. 097 * 098 * Steps for creating FSRedirectException Sub-classes and messages 099 * ------------------------------------------------------ 100 * 101 * 1. Identify the package this exception will belong to. 102 * account management related exception 103 * should be part of the accountmgmt package. 104 * 105 * 2. Each package should have its own properties file to store 106 * error messages. 107 * For example accountmgmt.properties in package accountmgmt 108 109 * 3. Create a sub-class of FSRedirectException and override the constructors. 110 * 111 * public class FSAccountManagementException extends FSRedirectException { 112 * public FSAccountManagementException() { 113 * super(); 114 * } 115 * public FSAccountManagementException(String msg) { 116 * super(msg); 117 * } 118 * public FSAccountManagementException(String msg, Throwable t) { 119 * super(msg,t); 120 * } 121 * 122 * 123 * Throwing/Catching Exception Examples: 124 * ------------------------------------ 125 * 126 * 1. Throwing a non-nested Exception 127 * <B>(not recommended, use Ex. 3 below)</B> 128 * FSRedirectException ux = 129 * new FSRedirectException("Some weird error!..."); 130 * throw ux; 131 * 132 * 2. Throwing a nested Exception 133 * <B>(not recommended, use Ex. 3 below)</B> 134 * try { 135 * ....... 136 * ....... 137 * } catch (UMSException umse) { 138 * FSRedirectException fse = 139 * new FSRedirectException("Some weird error!...", le); 140 * throw ux; 141 * } 142 * 143 * 3. Throwing an Exception using the ResourceSetManager 144 * <TBD : write some eg & format for properties file> 145 * 146 * - Logging/Dealing with an Exception, inclunding all nested exceptions 147 * try { 148 * ....... 149 * ....... 150 * } catch (FSRedirectException fse) { 151 * 152 * if (fse.getRootCause() instanceof UMSException) { 153 * PrintWriter pw = new PrintWriter(<some file stream>); 154 * fse.log(pw); 155 * } else { 156 * System.out.println(fse.getMessage()); 157 * } 158 * } 159 * 160 * </PRE> 161 * 162 * @see #FSRedirectException(String, Object[], Throwable) 163 * @see #getRootCause() 164 * @see java.lang.Exception 165 * @see java.lang.RuntimeException 166 * 167 * @supported.api 168 * @deprecated since 12.0.0 169 */ 170@Deprecated 171public class FSRedirectException extends L10NMessageImpl { 172 protected String _message = null; 173 protected Throwable rootCause = null; 174 175 /** 176 * Constructor 177 * 178 * @param errorCode Key of the error message in resource bundle. 179 * @param args Arguments to the message. 180 */ 181 public FSRedirectException(String errorCode, Object[] args) { 182 super(FSUtils.BUNDLE_NAME, errorCode, args); 183 } 184 185 /** 186 * Constructor 187 * 188 * @param errorCode Key of the error message in resource bundle. 189 * @param args Arguments to the message. 190 * @param rootCause An embedded exception 191 */ 192 public FSRedirectException(String errorCode, Object[] args, 193 Throwable rootCause) { 194 super(FSUtils.BUNDLE_NAME, errorCode, args); 195 this.rootCause = rootCause; 196 } 197 198 /** 199 * Constructor 200 * Constructs a <code>FSRedirectException</code> with a detailed message. 201 * 202 * @param message 203 * Detailed message for this exception. 204 * @supported.api 205 */ 206 public FSRedirectException(String message) { 207 super(message); 208 _message = message; 209 } 210 211 /** 212 * Constructor 213 * Constructs a <code>FSRedirectException</code> with a message and 214 * an embedded exception. 215 * 216 * @param message Detailed message for this exception. 217 * @param rootCause An embedded exception 218 * @supported.api 219 */ 220 public FSRedirectException(Throwable rootCause, String message) { 221 super(message); 222 _message = message; 223 this.rootCause = rootCause; 224 } 225 226 /** 227 * Constructor 228 * Constructs a <code>FSRedirectException</code> with an exception. 229 * 230 * @param ex Exception 231 * @supported.api 232 */ 233 public FSRedirectException(Exception ex) { 234 super(ex); 235 } 236 237 /** 238 * Returns the embedded exception. 239 * 240 * @return the embedded exception. 241 * @supported.api 242 */ 243 public Throwable getRootCause() { 244 return rootCause; 245 } 246 247 /** 248 * Formats this <code>FSRedirectException</code> to a 249 * <code>PrintWriter</code>. 250 * 251 * @param out <code>PrintWriter</code> to write exception to. 252 * @return The out parameter passed in. 253 * @see java.io.PrintWriter 254 * @supported.api 255 */ 256 public PrintWriter log(PrintWriter out) { 257 return log(this, out); 258 } 259 260 /** 261 * Formats an Exception to a <code>PrintWriter</code>. 262 * 263 * @param xcpt <code>Exception</code> to log. 264 * @param out <code>PrintWriter</code> to write exception to. 265 * @return The out parameter passed in. 266 * @see java.io.PrintWriter 267 * @supported.api 268 */ 269 static public PrintWriter log(Throwable xcpt, PrintWriter out) { 270 271 out.println("-----------"); 272 out.println(xcpt.toString()); 273 out.println("Stack Trace:"); 274 out.print(getStackTrace(xcpt)); 275 out.println("-----------"); 276 out.flush(); 277 return out; 278 } 279 280 /** 281 * Returns a formatted <code>FSRedirectException</code> exception message; 282 * includes embedded exceptions. 283 * 284 * @return a formatted <code>FSRedirectException</code> exception message. 285 * @supported.api 286 */ 287 public String toString() { 288 289 StringBuffer buf = new StringBuffer(); 290 buf.append("--------------------------------------"); 291 buf.append("Got Federation Exception\n"); 292 293 String msg = getMessage(); 294 if(msg != null && msg.length() > 0) { 295 buf.append("Message: ").append(getMessage()); 296 } 297 298 // Invoke toString() of rootCause first 299 if (rootCause != null) { 300 buf.append("\nLower level exception: "); 301 buf.append(getRootCause()); 302 } 303 304 return buf.toString(); 305 } 306 307 /** 308 * Prints this exception's stack trace to <tt>System.err</tt>. 309 * If this exception has a root exception; the stack trace of the 310 * root exception is printed to <tt>System.err</tt> instead. 311 * @supported.api 312 */ 313 public void printStackTrace() { 314 printStackTrace( System.err ); 315 } 316 317 /** 318 * Prints this exception's stack trace to a print stream. 319 * If this exception has a root exception, the stack trace of the 320 * root exception is printed to the print stream instead. 321 * @param ps The non-null print stream to which to print. 322 * @supported.api 323 */ 324 public void printStackTrace(java.io.PrintStream ps) { 325 if ( rootCause != null ) { 326 String superString = super.toString(); 327 synchronized ( ps ) { 328 ps.print(superString 329 + (superString.endsWith(".") ? "" : ".") 330 + " Root exception is "); 331 rootCause.printStackTrace( ps ); 332 } 333 } else { 334 super.printStackTrace( ps ); 335 } 336 } 337 338 /** 339 * Prints this exception's stack trace to a print writer. 340 * If this exception has a root exception; the stack trace of the 341 * root exception is printed to the print writer instead. 342 * @param pw The non-null print writer to which to print. 343 * @supported.api 344 */ 345 public void printStackTrace(java.io.PrintWriter pw) { 346 if ( rootCause != null ) { 347 String superString = super.toString(); 348 synchronized (pw) { 349 pw.print(superString 350 + (superString.endsWith(".") ? "" : ".") 351 + " Root exception is "); 352 rootCause.printStackTrace( pw ); 353 } 354 } else { 355 super.printStackTrace( pw ); 356 } 357 } 358 359 /** 360 * Gets exception stack trace as a string. 361 * <pre> 362 * java.lang.Throwable 363 * java.lang.Exception 364 * FSRedirectException 365 * <name of exception being thrown> 366 * </pre> 367 */ 368 static private String getStackTrace(Throwable xcpt) { 369 StringWriter sw = new StringWriter(); 370 PrintWriter pw = new PrintWriter(sw); 371 372 xcpt.printStackTrace(pw); 373 374 return sw.toString(); 375 } 376}