ContainerImplTest.java
/*
* 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.struts2.inject;
import org.apache.commons.lang3.JavaVersion;
import org.apache.commons.lang3.SystemUtils;
import org.junit.Before;
import org.junit.Test;
import java.security.Permission;
import java.util.concurrent.Callable;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
/**
* ContainerImpl Tester.
*
* @author Lukasz Lenart
* @version 1.0
* @since <pre>11/26/2008</pre>
*/
public class ContainerImplTest {
private Container c;
@Before
public void setUp() throws Exception {
ContainerBuilder cb = new ContainerBuilder();
cb.constant("methodCheck.name", "Lukasz");
cb.constant("fieldCheck.name", "Lukasz");
cb.constant("constructorCheck.name", "Lukasz");
cb.factory(EarlyInitializable.class, EarlyInitializableBean.class, Scope.SINGLETON);
cb.factory(Initializable.class, InitializableBean.class, Scope.SINGLETON);
cb.factory(EarlyInitializable.class, "prototypeEarlyInitializable", EarlyInitializableBean.class, Scope.PROTOTYPE);
cb.factory(Initializable.class, "prototypeInitializable", InitializableBean.class, Scope.PROTOTYPE);
cb.factory(Initializable.class, "requestInitializable", InitializableBean.class, Scope.REQUEST);
cb.factory(Initializable.class, "sessionInitializable", InitializableBean.class, Scope.SESSION);
cb.factory(Initializable.class, "threadInitializable", InitializableBean.class, Scope.THREAD);
cb.factory(Initializable.class, "wizardInitializable", InitializableBean.class, Scope.WIZARD);
c = cb.create(false);
c.setScopeStrategy(new TestScopeStrategy());
Class.forName(FieldCheck.class.getName());
Class.forName(ContainerImpl.FieldInjector.class.getName());
}
@Test
public void fieldInjector() {
FieldCheck fieldCheck = new FieldCheck();
c.inject(fieldCheck);
assertEquals("Lukasz", fieldCheck.getName());
}
@Test
public void methodInjector() {
MethodCheck methodCheck = new MethodCheck();
c.inject(methodCheck);
assertEquals("Lukasz", methodCheck.getName());
}
@Test
public void constructorInjector() {
ConstructorCheck constructorCheck = c.inject(ConstructorCheck.class);
assertEquals("Lukasz", constructorCheck.getName());
}
@Test
public void optionalConstructorInjector() {
OptionalConstructorCheck constructorCheck = c.inject(OptionalConstructorCheck.class);
assertNull(constructorCheck.getName());
}
@Test
public void requiredOptionalConstructorInjector() {
RequiredOptionalConstructorCheck constructorCheck = c.inject(RequiredOptionalConstructorCheck.class);
assertNotNull(constructorCheck.getExistingName());
assertNull(constructorCheck.getNonExitingName());
}
@Test
public void optionalRequiredConstructorInjector() {
OptionalRequiredConstructorCheck constructorCheck = c.inject(OptionalRequiredConstructorCheck.class);
assertNull(constructorCheck.getNonExitingName());
assertNotNull(constructorCheck.getExistingName());
}
/**
* Inject values into field under SecurityManager
*/
@Test
public void testFieldInjectorWithSecurityEnabled() throws Exception {
assumeTrue(SystemUtils.isJavaVersionAtMost(JavaVersion.JAVA_20));
System.setSecurityManager(new TestSecurityManager());
assertThrows(DependencyException.class, () -> c.inject(new FieldCheck()));
System.setSecurityManager(null);
}
/**
* Inject values into method under SecurityManager
*/
@Test
public void testMethodInjectorWithSecurityEnabled() {
assumeTrue(SystemUtils.isJavaVersionAtMost(JavaVersion.JAVA_20));
System.setSecurityManager(new TestSecurityManager());
assertThrows(DependencyException.class, () -> c.inject(new MethodCheck()));
System.setSecurityManager(null);
}
@Test
public void testEarlyInitializable() {
assertTrue("should being initialized already", EarlyInitializableBean.initializedEarly);
EarlyInitializableCheck earlyInitializableCheck = new EarlyInitializableCheck();
c.inject(earlyInitializableCheck);
assertEquals("initialized early", ((EarlyInitializableBean) earlyInitializableCheck.getEarlyInitializable()).getMessage());
assertEquals("initialized early", ((EarlyInitializableBean) earlyInitializableCheck.getPrototypeEarlyInitializable()).getMessage());
EarlyInitializableCheck earlyInitializableCheck2 = new EarlyInitializableCheck();
c.inject(earlyInitializableCheck2);
assertEquals("singletons should not being initialized twice", "initialized early",
((EarlyInitializableBean) earlyInitializableCheck2.getEarlyInitializable()).getMessage());
assertEquals("initialized early", ((EarlyInitializableBean) earlyInitializableCheck2.getPrototypeEarlyInitializable()).getMessage());
assertEquals("singletons should being instantiated once",
earlyInitializableCheck.getEarlyInitializable(), earlyInitializableCheck2.getEarlyInitializable());
assertNotSame("prototypes should being instantiated for each injection",
earlyInitializableCheck.getPrototypeEarlyInitializable(), earlyInitializableCheck2.getPrototypeEarlyInitializable());
}
@Test
public void testInitializable() throws Exception {
assertFalse("should not being initialized already", InitializableBean.initialized);
InitializableCheck initializableCheck = new InitializableCheck();
c.inject(initializableCheck);
assertTrue("should being initialized here", InitializableBean.initialized);
assertEquals("initialized", ((InitializableBean) initializableCheck.getInitializable()).getMessage());
assertEquals("initialized", ((InitializableBean) initializableCheck.getPrototypeInitializable()).getMessage());
InitializableCheck initializableCheck2 = new InitializableCheck();
c.inject(initializableCheck2);
assertEquals("singletons should not being initialized twice", "initialized",
((InitializableBean) initializableCheck2.getInitializable()).getMessage());
assertEquals("initialized", ((InitializableBean) initializableCheck2.getPrototypeInitializable()).getMessage());
assertEquals("threads should not being initialized twice", "initialized",
((InitializableBean) initializableCheck2.getThreadInitializable()).getMessage());
assertEquals("singletons should being instantiated once",
initializableCheck.getInitializable(), initializableCheck2.getInitializable());
assertNotSame("prototypes should being instantiated for each injection",
initializableCheck.getPrototypeInitializable(), initializableCheck2.getPrototypeInitializable());
assertEquals("threads should being instantiated once for each thread",
initializableCheck.getThreadInitializable(), initializableCheck2.getThreadInitializable());
final InitializableCheck initializableCheck3 = new InitializableCheck();
final TestScopeStrategy testScopeStrategy = new TestScopeStrategy();
Thread thread = new Thread(() -> {
ContainerBuilder cb2 = new ContainerBuilder();
cb2.factory(EarlyInitializable.class, EarlyInitializableBean.class, Scope.SINGLETON);
cb2.factory(Initializable.class, InitializableBean.class, Scope.SINGLETON);
cb2.factory(EarlyInitializable.class, "prototypeEarlyInitializable", EarlyInitializableBean.class, Scope.PROTOTYPE);
cb2.factory(Initializable.class, "prototypeInitializable", InitializableBean.class, Scope.PROTOTYPE);
cb2.factory(Initializable.class, "requestInitializable", InitializableBean.class, Scope.REQUEST);
cb2.factory(Initializable.class, "sessionInitializable", InitializableBean.class, Scope.SESSION);
cb2.factory(Initializable.class, "threadInitializable", InitializableBean.class, Scope.THREAD);
cb2.factory(Initializable.class, "wizardInitializable", InitializableBean.class, Scope.WIZARD);
Container c2 = cb2.create(false);
c2.setScopeStrategy(testScopeStrategy);
c2.inject(initializableCheck3);
});
thread.run();
thread.join();
assertNotSame("threads should being instantiated in new threads",
initializableCheck.getThreadInitializable(), initializableCheck3.getThreadInitializable());
assertEquals("initialized", ((InitializableBean) initializableCheck3.getThreadInitializable()).getMessage());
assertEquals("initialized", ((InitializableBean) initializableCheck3.getRequestInitializable()).getMessage());
assertEquals("initialized", ((InitializableBean) initializableCheck3.getSessionInitializable()).getMessage());
assertEquals("initialized", ((InitializableBean) initializableCheck3.getWizardInitializable()).getMessage());
assertEquals(testScopeStrategy.requestInitializable, initializableCheck3.getRequestInitializable());
assertEquals(testScopeStrategy.sessionInitializable, initializableCheck3.getSessionInitializable());
assertEquals(testScopeStrategy.wizardInitializable, initializableCheck3.getWizardInitializable());
}
public static class FieldCheck {
@Inject("fieldCheck.name")
private String name;
public String getName() {
return name;
}
}
public static class MethodCheck {
private String name;
@Inject("methodCheck.name")
private void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static class ConstructorCheck {
private String name;
@Inject("constructorCheck.name")
public ConstructorCheck(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static class OptionalConstructorCheck {
private String name;
@Inject(value = "nonExistingConstant", required = false)
public OptionalConstructorCheck(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static class RequiredOptionalConstructorCheck {
private final String existingName;
private final String nonExitingName;
@Inject(required = false)
public RequiredOptionalConstructorCheck(
@Inject("constructorCheck.name") String existingName,
@Inject(value = "nonExistingConstant", required = false) String nonExitingName
) {
this.existingName = existingName;
this.nonExitingName = nonExitingName;
}
public String getExistingName() {
return existingName;
}
public String getNonExitingName() {
return nonExitingName;
}
}
public static class OptionalRequiredConstructorCheck {
private final String existingName;
private final String nonExitingName;
@Inject(required = false)
public OptionalRequiredConstructorCheck(
@Inject(value = "nonExistingConstant", required = false) String nonExitingName,
@Inject("constructorCheck.name") String existingName
) {
this.existingName = existingName;
this.nonExitingName = nonExitingName;
}
public String getExistingName() {
return existingName;
}
public String getNonExitingName() {
return nonExitingName;
}
}
class InitializableCheck {
private Initializable initializable;
private Initializable prototypeInitializable;
private Initializable requestInitializable;
private Initializable sessionInitializable;
private Initializable threadInitializable;
private Initializable wizardInitializable;
@Inject
public void setInitializable(Initializable initializable) {
this.initializable = initializable;
}
@Inject("prototypeInitializable")
public void setPrototypeInitializable(Initializable prototypeInitializable) {
this.prototypeInitializable = prototypeInitializable;
}
@Inject("requestInitializable")
public void setRequestInitializable(Initializable requestInitializable) {
this.requestInitializable = requestInitializable;
}
@Inject("sessionInitializable")
public void setSessionInitializable(Initializable sessionInitializable) {
this.sessionInitializable = sessionInitializable;
}
@Inject("threadInitializable")
public void setThreadInitializable(Initializable threadInitializable) {
this.threadInitializable = threadInitializable;
}
@Inject("wizardInitializable")
public void setWizardInitializable(Initializable wizardInitializable) {
this.wizardInitializable = wizardInitializable;
}
public Initializable getRequestInitializable() {
return requestInitializable;
}
public Initializable getSessionInitializable() {
return sessionInitializable;
}
public Initializable getThreadInitializable() {
return threadInitializable;
}
public Initializable getWizardInitializable() {
return wizardInitializable;
}
public Initializable getInitializable() {
return initializable;
}
public Initializable getPrototypeInitializable() {
return prototypeInitializable;
}
}
class EarlyInitializableCheck {
private EarlyInitializable earlyInitializable;
private EarlyInitializable prototypeEarlyInitializable;
@Inject
public void setEarlyInitializable(EarlyInitializable earlyInitializable) {
this.earlyInitializable = earlyInitializable;
}
@Inject("prototypeEarlyInitializable")
public void setPrototypeEarlyInitializable(EarlyInitializable prototypeEarlyInitializable) {
this.prototypeEarlyInitializable = prototypeEarlyInitializable;
}
public EarlyInitializable getEarlyInitializable() {
return earlyInitializable;
}
public EarlyInitializable getPrototypeEarlyInitializable() {
return prototypeEarlyInitializable;
}
}
class TestSecurityManager extends SecurityManager {
@Override
public void checkPermission(Permission perm) {
if (!"setSecurityManager".equals(perm.getName())) {
super.checkPermission(perm);
}
}
}
class TestScopeStrategy implements Scope.Strategy {
Initializable requestInitializable;
Initializable sessionInitializable;
Initializable wizardInitializable;
@Override
public <T> T findInRequest(Class<T> type, String name, Callable<? extends T> factory) throws Exception {
if (requestInitializable == null) {
requestInitializable = (Initializable) factory.call();
}
return (T) requestInitializable;
}
@Override
public <T> T findInSession(Class<T> type, String name, Callable<? extends T> factory) throws Exception {
if (sessionInitializable == null) {
sessionInitializable = (Initializable) factory.call();
}
return (T) sessionInitializable;
}
@Override
public <T> T findInWizard(Class<T> type, String name, Callable<? extends T> factory) throws Exception {
if (wizardInitializable == null) {
wizardInitializable = (Initializable) factory.call();
}
return (T) wizardInitializable;
}
}
}