diff --git a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/ReflectionBuilder.java b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/ReflectionBuilder.java index 77a1db6298..8ff214d563 100644 --- a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/ReflectionBuilder.java +++ b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/ReflectionBuilder.java @@ -287,10 +287,15 @@ private String parseBeanId(String lhs) { } processor.execute(); - } - //SHIRO-413: init method must be called for constructed objects that are Initializable - LifecycleUtils.init(objects.values()); + //SHIRO-778: onInit method on AuthenticatingRealm is called twice + objects.keySet().stream() + .filter(key -> !kvPairs.containsKey(key)) + .forEach(key -> LifecycleUtils.init(objects.get(key))); + } else { + //SHIRO-413: init method must be called for constructed objects that are Initializable + LifecycleUtils.init(objects.values()); + } return objects; } diff --git a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/ReflectionBuilderTest.groovy b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/ReflectionBuilderTest.groovy index 5fd0950dfe..8bc4a4ffa7 100644 --- a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/ReflectionBuilderTest.groovy +++ b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/ReflectionBuilderTest.groovy @@ -18,6 +18,7 @@ */ package org.apache.shiro.config.ogdl +import org.apache.shiro.config.ogdl.beans.InitCountBean import org.apache.shiro.lang.codec.Base64 import org.apache.shiro.lang.codec.CodecSupport import org.apache.shiro.lang.codec.Hex @@ -26,6 +27,8 @@ import org.apache.shiro.config.Ini import org.apache.shiro.config.ogdl.event.BeanEvent import org.junit.Test +import java.util.concurrent.ConcurrentHashMap + import static org.junit.Assert.* import static org.hamcrest.Matchers.* @@ -640,6 +643,37 @@ class ReflectionBuilderTest { assertNotNull(beanMap.get("two")) } + @Test + void testNotMultipleInitialization() { + // given + Map defs = new ConcurrentHashMap<>() + defs.put("initcountbean", InitCountBean.getCanonicalName()) + ReflectionBuilder builder = new ReflectionBuilder() + + // when + builder.buildObjects(defs) + + // then + assertEquals(1, InitCountBean.getInitCount()) + InitCountBean.resetCount() + } + + @Test + void testNotMultipleInitializationWithNullFirst() { + // given + Map defs = new ConcurrentHashMap<>() + defs.put("initcountbean", InitCountBean.getCanonicalName()) + ReflectionBuilder builder = new ReflectionBuilder() + + // when + builder.buildObjects(null) + builder.buildObjects(defs) + + // then + assertEquals(1, InitCountBean.getInitCount()) + InitCountBean.resetCount() + } + void assertInstantiatedEvents(String name, Map objects, int expected) { def bean = objects.get(name) as RecordingBeanListener def events = bean.getInstantiatedEvents() diff --git a/config/ogdl/src/test/java/org/apache/shiro/config/ogdl/beans/InitCountBean.java b/config/ogdl/src/test/java/org/apache/shiro/config/ogdl/beans/InitCountBean.java new file mode 100644 index 0000000000..1dccf0ae7e --- /dev/null +++ b/config/ogdl/src/test/java/org/apache/shiro/config/ogdl/beans/InitCountBean.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.config.ogdl.beans; + +import org.apache.shiro.lang.ShiroException; +import org.apache.shiro.lang.util.Initializable; + +import java.util.StringJoiner; +import java.util.concurrent.atomic.LongAdder; + +public class InitCountBean implements Initializable { + private static final LongAdder INIT_COUNT = new LongAdder(); + + public InitCountBean() { + super(); + } + + public static long getInitCount() { + return INIT_COUNT.longValue(); + } + + public static void resetCount() { + INIT_COUNT.reset(); + } + + @Override + public String toString() { + return new StringJoiner(", ", InitCountBean.class.getSimpleName() + "[", "]") + .add("INIT_COUNT=" + getInitCount()) + .toString(); + } + + @Override + public void init() throws ShiroException { + INIT_COUNT.increment(); + } +}