diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/CircularImportException.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/CircularImportException.java deleted file mode 100644 index 7a6dae2f165850f96d8716884237f23358556668..0000000000000000000000000000000000000000 --- a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/CircularImportException.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2002-2009 the original author or authors. - * - * 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 org.springframework.config.java.support; - -import static java.lang.String.*; - -import java.util.Stack; - - -/** - * Thrown by {@link ConfigurationParser} upon detecting circular use of the {@link Import} annotation. - * - * @author Chris Beams - * @see Import - * @see ImportStack - * @see ImportStackHolder - */ -@SuppressWarnings("serial") -class CircularImportException extends IllegalStateException { - public CircularImportException(ConfigurationClass attemptedImport, Stack currentImportStack) { - super(format("A circular @Import has been detected: " + - "Illegal attempt by @Configuration class '%s' to import class '%s' as '%s' is " + - "already present in the current import stack [%s]", - currentImportStack.peek().getSimpleName(), attemptedImport.getSimpleName(), - attemptedImport.getSimpleName(), currentImportStack)); - } -} diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationClassPostProcessor.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationClassPostProcessor.java index 76bfd3a1fe9ebdd0361d9bfccb99f7d811ba1c22..246449176411ccca97999514362b591b7cbfcb4e 100644 --- a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationClassPostProcessor.java +++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationClassPostProcessor.java @@ -104,7 +104,7 @@ public class ConfigurationClassPostProcessor extends AbstractConfigurationClassP */ @Override protected ConfigurationParser createConfigurationParser() { - return new ConfigurationParser(beanFactory.getBeanClassLoader()); + return new ConfigurationParser(this.getProblemReporter(), beanFactory.getBeanClassLoader()); } /** diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationClassVisitor.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationClassVisitor.java index e15a9e863f6dc16b9dae076bfd7d2c438e869f0b..ffca110287fa5db8180f281a1c9e2212588fd923 100644 --- a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationClassVisitor.java +++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationClassVisitor.java @@ -15,20 +15,27 @@ */ package org.springframework.config.java.support; +import static java.lang.String.*; import static org.springframework.config.java.support.MutableAnnotationUtils.*; import static org.springframework.config.java.support.Util.*; import static org.springframework.util.ClassUtils.*; import java.lang.annotation.Annotation; import java.util.HashMap; +import java.util.Stack; import org.springframework.asm.AnnotationVisitor; import org.springframework.asm.ClassAdapter; import org.springframework.asm.ClassReader; import org.springframework.asm.MethodVisitor; import org.springframework.asm.Opcodes; +import org.springframework.asm.commons.EmptyVisitor; +import org.springframework.beans.factory.parsing.Location; +import org.springframework.beans.factory.parsing.Problem; +import org.springframework.beans.factory.parsing.ProblemReporter; import org.springframework.config.java.Configuration; import org.springframework.config.java.Import; +import org.springframework.core.io.FileSystemResource; /** @@ -43,15 +50,18 @@ class ConfigurationClassVisitor extends ClassAdapter { private final ConfigurationClass configClass; private final ConfigurationModel model; + private final ProblemReporter problemReporter; private final HashMap innerClasses = new HashMap(); private boolean processInnerClasses = true; private final ClassLoader classLoader; - public ConfigurationClassVisitor(ConfigurationClass configClass, ConfigurationModel model, ClassLoader classLoader) { + public ConfigurationClassVisitor(ConfigurationClass configClass, ConfigurationModel model, + ProblemReporter problemReporter, ClassLoader classLoader) { super(AsmUtils.EMPTY_VISITOR); this.configClass = configClass; this.model = model; + this.problemReporter = problemReporter; this.classLoader = classLoader; } @@ -86,7 +96,8 @@ class ConfigurationClassVisitor extends ClassAdapter { if (OBJECT_DESC.equals(superTypeDesc)) return; - ConfigurationClassVisitor visitor = new ConfigurationClassVisitor(configClass, model, classLoader); + ConfigurationClassVisitor visitor = + new ConfigurationClassVisitor(configClass, model, problemReporter, classLoader); ClassReader reader = AsmUtils.newClassReader(superTypeDesc, classLoader); reader.accept(visitor, false); @@ -113,15 +124,18 @@ class ConfigurationClassVisitor extends ClassAdapter { return new MutableAnnotationVisitor(mutableConfiguration, classLoader); } - if (Import.class.getName().equals(annoTypeName)) { + if (Import.class.getName().equals(annoTypeName)) { ImportStack importStack = ImportStackHolder.getImportStack(); - if (importStack.contains(configClass)) - throw new CircularImportException(configClass, importStack); + if (importStack.contains(configClass)) { + //throw new CircularImportException(configClass, importStack); + problemReporter.error(new CircularImportProblem(configClass, importStack)); + return new EmptyVisitor(); + } importStack.push(configClass); - return new ImportAnnotationVisitor(model, classLoader); + return new ImportAnnotationVisitor(model, problemReporter, classLoader); } /* ------------------------------------- @@ -217,7 +231,7 @@ class ConfigurationClassVisitor extends ClassAdapter { ConfigurationClass innerConfigClass = new ConfigurationClass(); ConfigurationClassVisitor ccVisitor = - new ConfigurationClassVisitor(innerConfigClass, new ConfigurationModel(), classLoader); + new ConfigurationClassVisitor(innerConfigClass, new ConfigurationModel(), problemReporter, classLoader); ccVisitor.setProcessInnerClasses(false); ClassReader reader = AsmUtils.newClassReader(name, classLoader); @@ -230,4 +244,27 @@ class ConfigurationClassVisitor extends ClassAdapter { if (innerConfigClass.getMetadata() != null) innerClasses.put(name, innerConfigClass); } + + + /** + * {@link Problem} registered upon detection of a circular {@link Import}. + * + * @see Import + * @see ImportStack + * @see ImportStackHolder + */ + class CircularImportProblem extends Problem { + + public CircularImportProblem(ConfigurationClass attemptedImport, Stack currentImportStack) { + super(format("A circular @Import has been detected: " + + "Illegal attempt by @Configuration class '%s' to import class '%s' as '%s' is " + + "already present in the current import stack [%s]", + currentImportStack.peek().getSimpleName(), attemptedImport.getSimpleName(), + attemptedImport.getSimpleName(), currentImportStack), + new Location(new FileSystemResource("/dev/null")) + ); + } + + } + } diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationParser.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationParser.java index af5abb6ecfd2e917bdea97d749e44834ad74a916..dc8a36bc943068a93f8e575e0dd4f774df0274c1 100644 --- a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationParser.java +++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationParser.java @@ -17,6 +17,7 @@ package org.springframework.config.java.support; import org.springframework.asm.ClassReader; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.parsing.ProblemReporter; import org.springframework.config.java.Configuration; import org.springframework.util.ClassUtils; @@ -41,17 +42,18 @@ public class ConfigurationParser { * Model to be populated during calls to {@link #parse(Object, String)} */ private final ConfigurationModel model; + private final ProblemReporter problemReporter; private final ClassLoader classLoader; /** * Creates a new parser instance that will be used to populate model. - * * @param model model to be populated by each successive call to * {@link #parse(Object, String)} */ - public ConfigurationParser(ClassLoader classLoader) { - this.classLoader = classLoader; + public ConfigurationParser(ProblemReporter problemReporter, ClassLoader classLoader) { this.model = new ConfigurationModel(); + this.problemReporter = problemReporter; + this.classLoader = classLoader; } /** @@ -71,7 +73,7 @@ public class ConfigurationParser { ConfigurationClass configClass = new ConfigurationClass(); configClass.setBeanName(configurationId); - configClassReader.accept(new ConfigurationClassVisitor(configClass, model, classLoader), false); + configClassReader.accept(new ConfigurationClassVisitor(configClass, model, problemReporter, classLoader), false); model.add(configClass); } diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ImportAnnotationVisitor.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ImportAnnotationVisitor.java index 54ffa60830b74b51947500adc0baa58a2fcefe15..22c127469020498f358f994365c2cab272ed0594 100644 --- a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ImportAnnotationVisitor.java +++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ImportAnnotationVisitor.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import org.springframework.asm.AnnotationVisitor; import org.springframework.asm.ClassReader; import org.springframework.asm.Type; +import org.springframework.beans.factory.parsing.ProblemReporter; import org.springframework.config.java.Import; import org.springframework.util.Assert; @@ -42,11 +43,13 @@ import org.springframework.util.Assert; class ImportAnnotationVisitor extends AnnotationAdapter { private final ArrayList classesToImport = new ArrayList(); private final ConfigurationModel model; + private final ProblemReporter problemReporter; private final ClassLoader classLoader; - public ImportAnnotationVisitor(ConfigurationModel model, ClassLoader classLoader) { + public ImportAnnotationVisitor(ConfigurationModel model, ProblemReporter problemReporter, ClassLoader classLoader) { super(AsmUtils.EMPTY_VISITOR); this.model = model; + this.problemReporter = problemReporter; this.classLoader = classLoader; } @@ -77,7 +80,7 @@ class ImportAnnotationVisitor extends AnnotationAdapter { ClassReader reader = newClassReader(convertClassNameToResourcePath(classToImport), classLoader); - reader.accept(new ConfigurationClassVisitor(configClass, model, classLoader), false); + reader.accept(new ConfigurationClassVisitor(configClass, model, problemReporter, classLoader), false); model.add(configClass); } diff --git a/org.springframework.config.java/src/test/java/org/springframework/config/java/support/AbstractCircularImportDetectionTests.java b/org.springframework.config.java/src/test/java/org/springframework/config/java/support/AbstractCircularImportDetectionTests.java index b68ba7dd34975e2ef4927def0250c7808eca092a..45f9e31b63519e78fe82c90d75f17a849c161974 100644 --- a/org.springframework.config.java/src/test/java/org/springframework/config/java/support/AbstractCircularImportDetectionTests.java +++ b/org.springframework.config.java/src/test/java/org/springframework/config/java/support/AbstractCircularImportDetectionTests.java @@ -18,6 +18,7 @@ package org.springframework.config.java.support; import static org.junit.Assert.*; import org.junit.Test; +import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.config.java.Bean; import org.springframework.config.java.Import; @@ -40,7 +41,7 @@ public abstract class AbstractCircularImportDetectionTests { boolean threw = false; try { newParser().parse(loadAsConfigurationSource(A.class), null); - } catch (CircularImportException ex) { + } catch (BeanDefinitionParsingException ex) { assertTrue("Wrong message. Got: " + ex.getMessage(), ex.getMessage().contains( "Illegal attempt by @Configuration class 'AbstractCircularImportDetectionTests.B' " + @@ -57,7 +58,7 @@ public abstract class AbstractCircularImportDetectionTests { boolean threw = false; try { newParser().parse(loadAsConfigurationSource(X.class), null); - } catch (CircularImportException ex) { + } catch (BeanDefinitionParsingException ex) { assertTrue("Wrong message. Got: " + ex.getMessage(), ex.getMessage().contains( "Illegal attempt by @Configuration class 'AbstractCircularImportDetectionTests.Z2' " + diff --git a/org.springframework.config.java/src/test/java/org/springframework/config/java/support/AsmCircularImportDetectionTests.java b/org.springframework.config.java/src/test/java/org/springframework/config/java/support/AsmCircularImportDetectionTests.java index 5b8e0bb0baf39cae63c0f49617799763646590ac..ab510bca989d5fb71027b3add59f23a003019bab 100644 --- a/org.springframework.config.java/src/test/java/org/springframework/config/java/support/AsmCircularImportDetectionTests.java +++ b/org.springframework.config.java/src/test/java/org/springframework/config/java/support/AsmCircularImportDetectionTests.java @@ -15,6 +15,7 @@ */ package org.springframework.config.java.support; +import org.springframework.beans.factory.parsing.FailFastProblemReporter; import org.springframework.config.java.Import; import org.springframework.util.ClassUtils; @@ -32,7 +33,7 @@ import org.springframework.util.ClassUtils; public class AsmCircularImportDetectionTests extends AbstractCircularImportDetectionTests { @Override protected ConfigurationParser newParser() { - return new ConfigurationParser(ClassUtils.getDefaultClassLoader()); + return new ConfigurationParser(new FailFastProblemReporter(), ClassUtils.getDefaultClassLoader()); } @Override