001/*
002 * Copyright 2002-2016 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.beans.factory;
018
019import java.io.PrintStream;
020import java.io.PrintWriter;
021import java.util.LinkedList;
022import java.util.List;
023
024import org.springframework.beans.FatalBeanException;
025import org.springframework.core.NestedRuntimeException;
026
027/**
028 * Exception thrown when a BeanFactory encounters an error when
029 * attempting to create a bean from a bean definition.
030 *
031 * @author Juergen Hoeller
032 */
033@SuppressWarnings("serial")
034public class BeanCreationException extends FatalBeanException {
035
036        private String beanName;
037
038        private String resourceDescription;
039
040        private List<Throwable> relatedCauses;
041
042
043        /**
044         * Create a new BeanCreationException.
045         * @param msg the detail message
046         */
047        public BeanCreationException(String msg) {
048                super(msg);
049        }
050
051        /**
052         * Create a new BeanCreationException.
053         * @param msg the detail message
054         * @param cause the root cause
055         */
056        public BeanCreationException(String msg, Throwable cause) {
057                super(msg, cause);
058        }
059
060        /**
061         * Create a new BeanCreationException.
062         * @param beanName the name of the bean requested
063         * @param msg the detail message
064         */
065        public BeanCreationException(String beanName, String msg) {
066                super("Error creating bean" + (beanName != null ? " with name '" + beanName + "'" : "") + ": " + msg);
067                this.beanName = beanName;
068        }
069
070        /**
071         * Create a new BeanCreationException.
072         * @param beanName the name of the bean requested
073         * @param msg the detail message
074         * @param cause the root cause
075         */
076        public BeanCreationException(String beanName, String msg, Throwable cause) {
077                this(beanName, msg);
078                initCause(cause);
079        }
080
081        /**
082         * Create a new BeanCreationException.
083         * @param resourceDescription description of the resource
084         * that the bean definition came from
085         * @param beanName the name of the bean requested
086         * @param msg the detail message
087         */
088        public BeanCreationException(String resourceDescription, String beanName, String msg) {
089                super("Error creating bean" + (beanName != null ? " with name '" + beanName + "'" : "") +
090                                (resourceDescription != null ? " defined in " + resourceDescription : "") + ": " + msg);
091                this.resourceDescription = resourceDescription;
092                this.beanName = beanName;
093        }
094
095        /**
096         * Create a new BeanCreationException.
097         * @param resourceDescription description of the resource
098         * that the bean definition came from
099         * @param beanName the name of the bean requested
100         * @param msg the detail message
101         * @param cause the root cause
102         */
103        public BeanCreationException(String resourceDescription, String beanName, String msg, Throwable cause) {
104                this(resourceDescription, beanName, msg);
105                initCause(cause);
106        }
107
108
109        /**
110         * Return the name of the bean requested, if any.
111         */
112        public String getBeanName() {
113                return this.beanName;
114        }
115
116        /**
117         * Return the description of the resource that the bean
118         * definition came from, if any.
119         */
120        public String getResourceDescription() {
121                return this.resourceDescription;
122        }
123
124        /**
125         * Add a related cause to this bean creation exception,
126         * not being a direct cause of the failure but having occurred
127         * earlier in the creation of the same bean instance.
128         * @param ex the related cause to add
129         */
130        public void addRelatedCause(Throwable ex) {
131                if (this.relatedCauses == null) {
132                        this.relatedCauses = new LinkedList<Throwable>();
133                }
134                this.relatedCauses.add(ex);
135        }
136
137        /**
138         * Return the related causes, if any.
139         * @return the array of related causes, or {@code null} if none
140         */
141        public Throwable[] getRelatedCauses() {
142                if (this.relatedCauses == null) {
143                        return null;
144                }
145                return this.relatedCauses.toArray(new Throwable[this.relatedCauses.size()]);
146        }
147
148
149        @Override
150        public String toString() {
151                StringBuilder sb = new StringBuilder(super.toString());
152                if (this.relatedCauses != null) {
153                        for (Throwable relatedCause : this.relatedCauses) {
154                                sb.append("\nRelated cause: ");
155                                sb.append(relatedCause);
156                        }
157                }
158                return sb.toString();
159        }
160
161        @Override
162        public void printStackTrace(PrintStream ps) {
163                synchronized (ps) {
164                        super.printStackTrace(ps);
165                        if (this.relatedCauses != null) {
166                                for (Throwable relatedCause : this.relatedCauses) {
167                                        ps.println("Related cause:");
168                                        relatedCause.printStackTrace(ps);
169                                }
170                        }
171                }
172        }
173
174        @Override
175        public void printStackTrace(PrintWriter pw) {
176                synchronized (pw) {
177                        super.printStackTrace(pw);
178                        if (this.relatedCauses != null) {
179                                for (Throwable relatedCause : this.relatedCauses) {
180                                        pw.println("Related cause:");
181                                        relatedCause.printStackTrace(pw);
182                                }
183                        }
184                }
185        }
186
187        @Override
188        public boolean contains(Class<?> exClass) {
189                if (super.contains(exClass)) {
190                        return true;
191                }
192                if (this.relatedCauses != null) {
193                        for (Throwable relatedCause : this.relatedCauses) {
194                                if (relatedCause instanceof NestedRuntimeException &&
195                                                ((NestedRuntimeException) relatedCause).contains(exClass)) {
196                                        return true;
197                                }
198                        }
199                }
200                return false;
201        }
202
203}