/** * Copyright 2007-2008 University Of Southern California * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package edu.isi.pegasus.common.util; import edu.isi.pegasus.common.util.DynamicLoader; /** * The base exception class to notify of errors, while instantiating classes * via any of the factories. Each factory, should throw an exception that is * a subclass of this class. * * @author Karan Vahi * @author Jens-S. Vöckler * @author Gaurang Mehta */ public class FactoryException // method A: no need to change interface, obsfuscated use, though extends java.lang.RuntimeException //method B: needs API small change, but makes things clear. //extends java.lang.Exception { /** * The default classname that is associated with the exception. */ public static final String DEFAULT_NAME = "Object"; /** * The name of the class that was trying to be instantiated when this * error occured, or some other signifier like module name. */ protected String mClassname; /** * Converts most of the common instantiation exceptions from the class * loader into an error message. Use for getting sensible error messages, * of the causes that are associated with a FactoryException. The index * in the messages starts from 0. * * @return the error message */ public String convertException(){ return convertException( mClassname, this, 0 ); } /** * Converts most of the common instantiation exceptions from the class * loader into an error message. Use for getting sensible error messages, * of the causes that are associated with a FactoryException. The index * in the messages starts from 0. * * @param index the index to start from. * * @return the error message. */ public String convertException( int index ){ return convertException( mClassname, this , index ); } /** * Converts most of the common instantiation exceptions from the class * loader into an error message. Use for getting sensible error messages, * of the causes that are associated with a FactoryException. * * @param classname the class that was trying to be loaded or some other * signifier. * @param e the FactoryException that is thrown. * @param index the index to start from. * * @return the error message. */ public static String convertException( String classname, Throwable e , int index){ Throwable prev = null; StringBuffer message = new StringBuffer(); int i = index; //append all the causes for(Throwable cause = e; cause != null ; cause = cause.getCause()){ message.append("\n [").append(Integer.toString(++i) ).append( "]: "); if ( cause instanceof FactoryException ){ message.append( cause.getMessage() ); classname = ((FactoryException)cause).getClassname(); } else if ( prev != null && prev instanceof FactoryException ){ //we can use the convert method message.append( DynamicLoader.convertExceptionToString( classname, cause ) ); } else{ //for all other exceptions just chain the message message.append( cause.getMessage() ); } //append just one elment of stack trace for each exception message.append( " at " ).append( cause.getStackTrace()[0] ); prev = cause; } return message.toString(); } /** * Constructs a <code>FactoryException</code> with no detail * message. The associated classname is set to value specified by * <code>DEFAULT_NAME</code>. * * @param msg the detailed message. * * @see #DEFAULT_NAME */ public FactoryException( String msg ) { super( msg ); mClassname = this.DEFAULT_NAME; } /** * Constructs a <code>FactoryException</code> with the specified detailed * message. * * @param msg is the detailed message. * @param classname the name of class that was trying to be instantiated or * some other signifier like module name. */ public FactoryException(String msg, String classname) { super( msg ); mClassname = classname; } /** * Constructs a <code>FactoryException</code> with the * specified detailed message and a cause. The associated classname is set * to value specified by <code>DEFAULT_NAME</code>. * * @param msg is the detailed message that is to be logged. * @param cause is the cause (which is saved for later retrieval by the * {@link java.lang.Throwable#getCause()} method). A <code>null</code> * value is permitted, and indicates that the cause is nonexistent or * unknown. * * @see #DEFAULT_NAME */ public FactoryException(String msg, Throwable cause) { super(msg, cause); mClassname = this.DEFAULT_NAME; } /** * Constructs a <code>FactoryException</code> with the * specified detailed message and a cause. * * @param msg is the detailed message that is to be logged. * @param classname the name of class that was trying to be instantiated. * @param cause is the cause (which is saved for later retrieval by the * {@link java.lang.Throwable#getCause()} method). A <code>null</code> * value is permitted, and indicates that the cause is nonexistent or * unknown. */ public FactoryException(String msg, String classname, Throwable cause) { super(msg, cause); mClassname = classname; } /** * Returns the name of the class that was trying to be loaded when this * error occured, or some other signifier like a module name. * * @return the name of the class. */ public String getClassname(){ return this.mClassname; } }