      1 /*
      2  * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25
     26 package java.security;
     27
     28 import java.io.IOException;
     29 import java.io.ObjectInputStream;
     30 import java.io.ObjectOutputStream;
     31 import java.io.ObjectStreamField;
     32 import jdk.internal.access.SharedSecrets;
     33
     34 /**
     35  * This exception is thrown by
     36  * {@code doPrivileged(PrivilegedExceptionAction)} and
     37  * {@code doPrivileged(PrivilegedExceptionAction,
     38  * AccessControlContext context)} to indicate
     39  * that the action being performed threw a checked exception.  The exception
     40  * thrown by the action can be obtained by calling the
     41  * {@code getException} method.  In effect, an
     42  * {@code PrivilegedActionException} is a "wrapper"
     43  * for an exception thrown by a privileged action.
     44  *
     45  * <p>As of release 1.4, this exception has been retrofitted to conform to
     46  * the general purpose exception-chaining mechanism.  The "exception thrown
     47  * by the privileged computation" that is provided at construction time and
     48  * accessed via the {@link #getException()} method is now known as the
     49  * <i>cause</i>, and may be accessed via the {@link Throwable#getCause()}
     50  * method, as well as the aforementioned "legacy method."
     51  *
     52  * @since 1.2
     53  * @see PrivilegedExceptionAction
     54  * @see AccessController#doPrivileged(PrivilegedExceptionAction)
     55  * @see AccessController#doPrivileged(PrivilegedExceptionAction,AccessControlContext)
     56  */
     57 public class PrivilegedActionException extends Exception {
     58     // use serialVersionUID from JDK 1.2.2 for interoperability
     59     @java.io.Serial
     60     private static final long serialVersionUID = 4724086851538908602L;
     61
     62     /**
     63      * Constructs a new PrivilegedActionException &quot;wrapping&quot;
     64      * the specific Exception.
     65      *
     66      * @param exception The exception thrown
     67      */
     68     public PrivilegedActionException(Exception exception) {
     69         super(null, exception);  // Disallow initCause
     70     }
     71
     72     /**
     73      * Returns the exception thrown by the privileged computation that
     74      * resulted in this {@code PrivilegedActionException}.
     75      *
     76      * <p>This method predates the general-purpose exception chaining facility.
     77      * The {@link Throwable#getCause()} method is now the preferred means of
     78      * obtaining this information.
     79      *
     80      * @return the exception thrown by the privileged computation that
     81      *         resulted in this {@code PrivilegedActionException}.
     82      * @see PrivilegedExceptionAction
     83      * @see AccessController#doPrivileged(PrivilegedExceptionAction)
     84      * @see AccessController#doPrivileged(PrivilegedExceptionAction,
     85      *                                            AccessControlContext)
     86      */
     87     public Exception getException() {
     88         return (Exception)super.getCause();
     89     }
     90
     91     public String toString() {
     92         String s = getClass().getName();
     93         Throwable cause = super.getCause();
     94         return (cause != null) ? (s + ": " + cause.toString()) : s;
     95     }
     96
     97
     98     /**
     99      * Serializable fields for UndeclaredThrowableException.
    100      *
    101      * @serialField exception Exception the undeclaredThrowable
    102      */
    103     @java.io.Serial
    104     private static final ObjectStreamField[] serialPersistentFields = {
    105         new ObjectStreamField("exception", Exception.class)
    106     };
    107
    108     /**
    109      * Reconstitutes the PrivilegedActionException instance from a stream
    110      * and initialize the cause properly when deserializing from an older
    111      * version.
    112      *
    113      * <p>The getException and getCause method returns the private "exception"
    114      * field in the older implementation and PrivilegedActionException::cause
    115      * was set to null.
    116      *
    117      * @param  s the {@code ObjectInputStream} from which data is read
    118      * @throws IOException if an I/O error occurs
    119      * @throws ClassNotFoundException if a serialized class cannot be loaded
    120      */
    121     @java.io.Serial
    122     private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
    123         ObjectInputStream.GetField fields = s.readFields();
    124         Exception exception = (Exception) fields.get("exception", null);
    125         if (exception != null) {
    126             SharedSecrets.getJavaLangAccess().setCause(this, exception);
    127         }
    128     }
    129
    130     /**
    131      * To maintain compatibility with older implementation, write a serial
    132      * "exception" field with the cause as the value.
    133      *
    134      * @param  out the {@code ObjectOutputStream} to which data is written
    135      * @throws IOException if an I/O error occurs
    136      */
    137     @java.io.Serial
    138     private void writeObject(ObjectOutputStream out) throws IOException {
    139         ObjectOutputStream.PutField fields = out.putFields();
    140         fields.put("exception", super.getCause());
    141         out.writeFields();
    142     }
    143 }
    --- EOF ---