001    package org.apache.commons.ognl;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.lang.reflect.Method;
023    
024    /**
025     * Superclass for OGNL exceptions, incorporating an optional encapsulated exception.
026     * 
027     * @author Luke Blanshard (blanshlu@netscape.net)
028     * @author Drew Davidson (drew@ognl.org)
029     */
030    public class OgnlException
031        extends Exception
032    {
033        // cache initCause method - if available..to be used during throwable constructor
034        // to properly setup superclass.
035    
036        private static final long serialVersionUID = -842845048743721078L;
037    
038        static Method initCause;
039        static
040        {
041            try
042            {
043                initCause = OgnlException.class.getMethod( "initCause", new Class[] { Throwable.class } );
044            }
045            catch ( NoSuchMethodException e )
046            {
047                /** ignore */
048            }
049        }
050    
051        /**
052         * The root evaluation of the expression when the exception was thrown
053         */
054        private Evaluation evaluation;
055    
056        /**
057         * Why this exception was thrown.
058         * 
059         * @serial
060         */
061        private Throwable reason;
062    
063        /** Constructs an OgnlException with no message or encapsulated exception. */
064        public OgnlException()
065        {
066            this( null, null );
067        }
068    
069        /**
070         * Constructs an OgnlException with the given message but no encapsulated exception.
071         * 
072         * @param msg the exception's detail message
073         */
074        public OgnlException( String msg )
075        {
076            this( msg, null );
077        }
078    
079        /**
080         * Constructs an OgnlException with the given message and encapsulated exception.
081         * 
082         * @param msg the exception's detail message
083         * @param reason the encapsulated exception
084         */
085        public OgnlException( String msg, Throwable reason )
086        {
087            super( msg );
088            this.reason = reason;
089    
090            if ( initCause != null )
091            {
092                try
093                {
094                    initCause.invoke( this, reason );
095                }
096                catch ( Exception ignored )
097                {
098                    /** ignore */
099                }
100            }
101        }
102    
103        /**
104         * Returns the encapsulated exception, or null if there is none.
105         * 
106         * @return the encapsulated exception
107         */
108        public Throwable getReason()
109        {
110            return reason;
111        }
112    
113        /**
114         * Returns the Evaluation that was the root evaluation when the exception was thrown.
115         * 
116         * @return The {@link Evaluation}.
117         */
118        public Evaluation getEvaluation()
119        {
120            return evaluation;
121        }
122    
123        /**
124         * Sets the Evaluation that was current when this exception was thrown.
125         * 
126         * @param value The {@link Evaluation}.
127         */
128        public void setEvaluation( Evaluation value )
129        {
130            evaluation = value;
131        }
132    
133        /**
134         * Returns a string representation of this exception.
135         * 
136         * @return a string representation of this exception
137         */
138        @Override
139        public String toString()
140        {
141            if ( reason == null )
142            {
143                return super.toString();
144            }
145    
146            return super.toString() + " [" + reason + "]";
147        }
148    
149        /**
150         * Prints the stack trace for this (and possibly the encapsulated) exception on System.err.
151         */
152        @Override
153        public void printStackTrace()
154        {
155            printStackTrace( System.err );
156        }
157    
158        /**
159         * Prints the stack trace for this (and possibly the encapsulated) exception on the given print stream.
160         */
161        @Override
162        public void printStackTrace( java.io.PrintStream s )
163        {
164            synchronized ( s )
165            {
166                super.printStackTrace( s );
167                if ( reason != null )
168                {
169                    s.println( "/-- Encapsulated exception ------------\\" );
170                    reason.printStackTrace( s );
171                    s.println( "\\--------------------------------------/" );
172                }
173            }
174        }
175    
176        /**
177         * Prints the stack trace for this (and possibly the encapsulated) exception on the given print writer.
178         */
179        @Override
180        public void printStackTrace( java.io.PrintWriter s )
181        {
182            synchronized ( s )
183            {
184                super.printStackTrace( s );
185                if ( reason != null )
186                {
187                    s.println( "/-- Encapsulated exception ------------\\" );
188                    reason.printStackTrace( s );
189                    s.println( "\\--------------------------------------/" );
190                }
191            }
192        }
193    }