| /* |
| * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| // 08/29/2016 Jody Grassel |
| // - 500441: Eclipselink core has System.getProperty() calls that are not potentially executed under doPriv() |
| package org.eclipse.persistence.exceptions; |
| |
| import java.io.PrintStream; |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| |
| import org.eclipse.persistence.exceptions.i18n.ExceptionMessageGenerator; |
| import org.eclipse.persistence.internal.security.PrivilegedAccessHelper; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| |
| /** |
| * <p> |
| * <b>Purpose</b>: Any exception raised by EclipseLink should be a subclass of this exception class. |
| */ |
| public abstract class EclipseLinkException extends RuntimeException { |
| protected transient AbstractSession session; |
| protected Throwable internalException; |
| protected static Boolean shouldPrintInternalException = null; |
| protected String indentationString; |
| protected int errorCode; |
| protected static final String CR = PrivilegedAccessHelper.getSystemProperty("line.separator"); |
| //Bug#3559280 Added to avoid logging an exception twice |
| protected boolean hasBeenLogged; |
| |
| /** |
| * INTERNAL: |
| * Return a new exception. |
| */ |
| protected EclipseLinkException() { |
| this(""); |
| } |
| |
| /** |
| * INTERNAL: |
| * EclipseLink exception should only be thrown by EclipseLink. |
| */ |
| protected EclipseLinkException(String theMessage) { |
| super(theMessage); |
| this.indentationString = ""; |
| hasBeenLogged = false; |
| } |
| |
| /** |
| * INTERNAL: |
| * EclipseLink exception should only be thrown by EclipseLink. |
| */ |
| protected EclipseLinkException(String message, Throwable internalException) { |
| this(message); |
| setInternalException(internalException); |
| } |
| |
| /** |
| * INTERNAL: |
| * Convenience method - return a platform-specific line-feed. |
| */ |
| protected static String cr() { |
| return org.eclipse.persistence.internal.helper.Helper.cr(); |
| } |
| |
| /** |
| * PUBLIC: |
| * Return the exception error code. |
| */ |
| public int getErrorCode() { |
| return errorCode; |
| } |
| |
| /** |
| * INTERNAL: |
| * Used to print things nicely in the testing tool. |
| */ |
| public String getIndentationString() { |
| return indentationString; |
| } |
| |
| /** |
| * PUBLIC: |
| * Return the internal native exception. |
| * EclipseLink frequently catches Java exceptions and wraps them in its own exception |
| * classes to provide more information. |
| * The internal exception can still be accessed if required. |
| */ |
| public Throwable getInternalException() { |
| return internalException; |
| } |
| |
| /** |
| * PUBLIC: |
| * Return the exception error message. |
| * EclipseLink error messages are multi-line so that detail descriptions of the exception are given. |
| */ |
| @Override |
| public String getMessage() { |
| StringWriter writer = new StringWriter(100); |
| |
| // Avoid printing internal exception error message twice. |
| if ((getInternalException() == null) || ((super.getMessage() != null) && !super.getMessage().equals(getInternalException().toString()))) { |
| writer.write(cr()); |
| writer.write(getIndentationString()); |
| writer.write(ExceptionMessageGenerator.getHeader("DescriptionHeader")); |
| writer.write(super.getMessage()); |
| } |
| |
| if (getInternalException() != null) { |
| writer.write(cr()); |
| writer.write(getIndentationString()); |
| writer.write(ExceptionMessageGenerator.getHeader("InternalExceptionHeader")); |
| writer.write(getInternalException().toString()); |
| |
| if ((getInternalException() instanceof java.lang.reflect.InvocationTargetException) && ((((java.lang.reflect.InvocationTargetException) getInternalException()).getTargetException()) != null)) { |
| writer.write(cr()); |
| writer.write(getIndentationString()); |
| writer.write(ExceptionMessageGenerator.getHeader("TargetInvocationExceptionHeader")); |
| writer.write(((java.lang.reflect.InvocationTargetException) getInternalException()).getTargetException().toString()); |
| } |
| } |
| |
| return writer.toString(); |
| } |
| |
| /** |
| * PUBLIC: |
| * Return the session. |
| */ |
| public AbstractSession getSession() { |
| return session; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return if this exception has been logged to avoid being logged more than once. |
| */ |
| public boolean hasBeenLogged() { |
| return hasBeenLogged; |
| } |
| |
| /** |
| * PUBLIC: |
| * Print both the normal and internal stack traces. |
| */ |
| @Override |
| public void printStackTrace() { |
| printStackTrace(System.err); |
| } |
| |
| /** |
| * PUBLIC: |
| * Print both the normal and internal stack traces. |
| */ |
| @Override |
| public void printStackTrace(PrintStream outStream) { |
| printStackTrace(new PrintWriter(outStream)); |
| } |
| |
| /** |
| * PUBLIC: |
| * Print both the normal and internal stack traces. |
| */ |
| @Override |
| public void printStackTrace(PrintWriter writer) { |
| writer.write(ExceptionMessageGenerator.getHeader("LocalExceptionStackHeader")); |
| writer.write(cr()); |
| super.printStackTrace(writer); |
| |
| if ((getInternalException() != null) && shouldPrintInternalException()) { |
| writer.write(ExceptionMessageGenerator.getHeader("InternalExceptionStackHeader")); |
| writer.write(cr()); |
| getInternalException().printStackTrace(writer); |
| |
| if ((getInternalException() instanceof java.lang.reflect.InvocationTargetException) && ((((java.lang.reflect.InvocationTargetException) getInternalException()).getTargetException()) != null)) { |
| writer.write(ExceptionMessageGenerator.getHeader("TargetInvocationExceptionStackHeader")); |
| writer.write(cr()); |
| ((java.lang.reflect.InvocationTargetException) getInternalException()).getTargetException().printStackTrace(writer); |
| } |
| } |
| writer.flush(); |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| public void setErrorCode(int errorCode) { |
| this.errorCode = errorCode; |
| } |
| |
| /** |
| * INTERNAL: |
| * Set this flag to avoid logging an exception more than once. |
| */ |
| public void setHasBeenLogged(boolean logged) { |
| this.hasBeenLogged = logged; |
| } |
| |
| /** |
| * INTERNAL: |
| * Used to print things nicely in the testing tool. |
| */ |
| public void setIndentationString(String indentationString) { |
| this.indentationString = indentationString; |
| } |
| |
| /** |
| * INTERNAL: |
| * Used to specify the internal exception. |
| */ |
| public void setInternalException(Throwable exception) { |
| internalException = exception; |
| if (getCause() == null) { |
| initCause(exception); |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| public void setSession(AbstractSession session) { |
| this.session = session; |
| } |
| |
| /** |
| * PUBLIC: |
| * Allows overriding of EclipseLink's exception chaining detection. |
| * @param printException - If printException is true, the EclipseLink-stored |
| * Internal exception will be included in a stack trace or in the exception message of a EclipseLinkException. |
| * If printException is false, the EclipseLink-stored Internal Exception will not be included |
| * in the stack trace or the exception message of EclipseLinkExceptions |
| */ |
| public static void setShouldPrintInternalException(boolean printException) { |
| shouldPrintInternalException = printException; |
| } |
| |
| /** |
| * INTERNAL |
| * Check to see if the EclipseLink-stored internal exception should be printed in this |
| * a EclipseLinkException's stack trace. This method will check the static ShouldPrintInternalException |
| * variable and if it is not set, estimate based on the JDK version used. |
| */ |
| public static boolean shouldPrintInternalException() { |
| if (shouldPrintInternalException == null) { |
| shouldPrintInternalException = Boolean.FALSE; |
| } |
| return shouldPrintInternalException; |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| @Override |
| public String toString() { |
| return getIndentationString() + ExceptionMessageGenerator.getHeader("ExceptionHeader") + getErrorCode() + "] (" + org.eclipse.persistence.sessions.DatabaseLogin.getVersion() + "): " + getClass().getName() + getMessage(); |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| public String getUnformattedMessage() { |
| return super.getMessage(); |
| } |
| } |