diff --git a/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/ContainerImpl.java b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/ContainerImpl.java
index dbe3fe3e4..f1cf57978 100644
--- a/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/ContainerImpl.java
+++ b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/ContainerImpl.java
@@ -20,6 +20,7 @@
import org.jboss.arquillian.config.descriptor.api.ProtocolDef;
import org.jboss.arquillian.container.spi.Container;
import org.jboss.arquillian.container.spi.ServerKillProcessor;
+import org.jboss.arquillian.container.spi.client.container.ConfigurationMapper;
import org.jboss.arquillian.container.spi.client.container.ContainerConfiguration;
import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
import org.jboss.arquillian.container.spi.client.container.LifecycleException;
@@ -47,25 +48,25 @@
* @author Aslak Knutsen
* @version $Revision: $
*/
-public class ContainerImpl implements Container {
+public class ContainerImpl implements Container {
@Inject
private Event event;
@Inject
@ContainerScoped
- private InstanceProducer containerProducer;
+ private InstanceProducer> containerProducer;
@Inject
private Instance serviceLoader;
- private DeployableContainer> deployableContainer;
+ private DeployableContainer deployableContainer;
private String name;
private State state = State.STOPPED;
private Throwable failureCause;
private ContainerDef containerConfiguration;
- public ContainerImpl(String name, DeployableContainer> deployableContainer, ContainerDef containerConfiguration) {
+ public ContainerImpl(String name, DeployableContainer deployableContainer, ContainerDef containerConfiguration) {
Validate.notNull(name, "Name must be specified");
Validate.notNull(deployableContainer, "DeployableContainer must be specified");
Validate.notNull(containerConfiguration, "ConfigurationConfiguration must be specified");
@@ -87,7 +88,7 @@ public String getName() {
* @see org.jboss.arquillian.container.impl.ContainerT#getDeployableContainer()
*/
@Override
- public DeployableContainer> getDeployableContainer() {
+ public DeployableContainer getDeployableContainer() {
return deployableContainer;
}
@@ -103,10 +104,15 @@ public ContainerDef getContainerConfiguration() {
* @see org.jboss.arquillian.container.impl.ContainerT#createDeployableConfiguration()
*/
@Override
- public ContainerConfiguration createDeployableConfiguration() throws Exception {
- ContainerConfiguration config = SecurityActions.newInstance(
- deployableContainer.getConfigurationClass(), new Class>[0], new Object[0]);
- MapObject.populate(config, containerConfiguration.getContainerProperties());
+ public T createDeployableConfiguration() throws Exception {
+ Class configClass = (Class) deployableContainer.getConfigurationClass();
+ T config = SecurityActions.newInstance(configClass, new Class>[0], new Object[0]);
+ ConfigurationMapper mapper = deployableContainer.getConfigurationMapper();
+ if(mapper != null) {
+ mapper.populateConfiguration(config, containerConfiguration);
+ } else {
+ MapObject.populate(config, containerConfiguration.getContainerProperties());
+ }
config.validate();
return config;
}
diff --git a/container/impl-base/src/test/java/org/jboss/arquillian/container/impl/ContainerRegistryTestCase.java b/container/impl-base/src/test/java/org/jboss/arquillian/container/impl/ContainerRegistryTestCase.java
index 8ab81eac2..6e5f85cf0 100644
--- a/container/impl-base/src/test/java/org/jboss/arquillian/container/impl/ContainerRegistryTestCase.java
+++ b/container/impl-base/src/test/java/org/jboss/arquillian/container/impl/ContainerRegistryTestCase.java
@@ -16,10 +16,12 @@
*/
package org.jboss.arquillian.container.impl;
+import org.jboss.arquillian.config.descriptor.api.ContainerDef;
import org.jboss.arquillian.config.descriptor.impl.ContainerDefImpl;
import org.jboss.arquillian.container.spi.ConfigurationException;
import org.jboss.arquillian.container.spi.Container;
import org.jboss.arquillian.container.spi.ContainerRegistry;
+import org.jboss.arquillian.container.spi.client.container.ConfigurationMapper;
import org.jboss.arquillian.container.spi.client.container.ContainerConfiguration;
import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
import org.jboss.arquillian.container.spi.client.deployment.TargetDescription;
@@ -140,6 +142,46 @@ public void shouldBeAbleToCreatePrivateContainerConfiguration() throws Exception
((PrivateDummyContainerConfiguration) container.createDeployableConfiguration()).getProperty());
}
+ @Test
+ public void shouldBeAbleToCreateContainerConfigurationCustomMapper() throws Exception {
+ ServiceLoader serviceLoader = Mockito.mock(ServiceLoader.class);
+ DeployableContainer deployableContainer =
+ Mockito.mock(DeployableContainer.class);
+
+ Mockito.when(serviceLoader.onlyOne(Mockito.same(DeployableContainer.class))).thenReturn(deployableContainer);
+ Mockito.when(deployableContainer.getConfigurationClass()).thenReturn(CustomContainerConfiguration.class);
+ Mockito.when(deployableContainer.getConfigurationMapper()).thenReturn(new CustomMapper());
+
+ String name = "custom-container";
+ String prop = "prop-value";
+ String[] hosts = {"host1", "host2", "host3"};
+
+ ContainerRegistry registry = new LocalContainerRegistry(injector.get());
+ ContainerDefImpl containerDef = new ContainerDefImpl(ARQUILLIAN_XML);
+ containerDef.setContainerName(name);
+ containerDef.property("property", prop);
+ containerDef.property("hosts", "host1,host2,host3");
+
+ registry.create(containerDef, serviceLoader);
+
+ Container container = registry.getContainer(new TargetDescription(name));
+
+ Assert.assertEquals(
+ "Verify that the only registered container is returned as default",
+ name, container.getName());
+
+ CustomContainerConfiguration config = container.createDeployableConfiguration();
+ Assert.assertEquals(
+ "Verify that the custom configuration 'property' was populated",
+ prop,
+ config.getProperty());
+
+ Assert.assertArrayEquals(
+ "Verify that the custom configuration 'hosts' was populated",
+ hosts,
+ config.getHosts());
+ }
+
@Test
public void shouldBeAbleToSpecifyTarget() throws Exception {
String name = "some-name";
@@ -197,4 +239,23 @@ private static class PrivateDummyContainerConfiguration extends DummyContainerCo
private PrivateDummyContainerConfiguration() {
}
}
+ private static class CustomContainerConfiguration extends DummyContainerConfiguration {
+ private String[] hosts;
+ public String[] getHosts() {
+ return hosts;
+ }
+ public void setHosts(String[] hosts) {
+ this.hosts = hosts;
+ }
+ }
+ private static class CustomMapper implements ConfigurationMapper {
+ @Override
+ public void populateConfiguration(CustomContainerConfiguration containerConfiguration, ContainerDef definition) {
+ String property = definition.getContainerProperty("property");
+ containerConfiguration.setProperty(property);
+ String hostsString = definition.getContainerProperty("hosts");
+ String[] hosts = hostsString.split(",");
+ containerConfiguration.setHosts(hosts);
+ }
+ }
}
diff --git a/container/spi/src/main/java/org/jboss/arquillian/container/spi/Container.java b/container/spi/src/main/java/org/jboss/arquillian/container/spi/Container.java
index 59f2b79ab..8ef4c6d37 100644
--- a/container/spi/src/main/java/org/jboss/arquillian/container/spi/Container.java
+++ b/container/spi/src/main/java/org/jboss/arquillian/container/spi/Container.java
@@ -30,7 +30,7 @@
* @author Aslak Knutsen
* @version $Revision: $
*/
-public interface Container {
+public interface Container {
/**
* @return the name
@@ -40,7 +40,7 @@ public interface Container {
/**
* @return the deployableContainer
*/
- DeployableContainer> getDeployableContainer();
+ DeployableContainer getDeployableContainer();
/**
* @return the containerConfiguration
@@ -50,7 +50,7 @@ public interface Container {
/**
* @return the configuration
*/
- ContainerConfiguration createDeployableConfiguration() throws Exception;
+ T createDeployableConfiguration() throws Exception;
boolean hasProtocolConfiguration(ProtocolDescription description);
@@ -73,4 +73,4 @@ public interface Container {
enum State {
SETUP, SETUP_FAILED, STARTED, STARTED_FAILED, STOPPED, STOPPED_FAILED, KILLED, KILLED_FAILED;
}
-}
\ No newline at end of file
+}
diff --git a/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/ConfigurationMapper.java b/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/ConfigurationMapper.java
new file mode 100644
index 000000000..d0d715e85
--- /dev/null
+++ b/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/ConfigurationMapper.java
@@ -0,0 +1,36 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2024 Red Hat Inc. and/or its affiliates and other contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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.jboss.arquillian.container.spi.client.container;
+
+import org.jboss.arquillian.config.descriptor.api.ContainerDef;
+
+/**
+ * An interface that {@link DeployableContainer} can use to control how the mapping
+ * from the externalized container definition, as found in an arquillian.xml file
+ * for example, is applied to the {@link ContainerConfiguration} instances
+ *
+ * @param the type of ContainerConfiguration
+ */
+public interface ConfigurationMapper {
+ /**
+ *
+ * @param containerConfiguration - the deployable container configuration instance to populate
+ * @param definition - the container definition from the ArquillianDescriptor that
+ * was parsed
+ */
+ void populateConfiguration(T containerConfiguration, ContainerDef definition);
+}
diff --git a/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/DeployableContainer.java b/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/DeployableContainer.java
index 9e4425a91..513356a7b 100644
--- a/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/DeployableContainer.java
+++ b/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/DeployableContainer.java
@@ -37,6 +37,17 @@ public interface DeployableContainer {
// ControllableContainer
Class getConfigurationClass();
+ /**
+ * Provide a mapping instance that takes the {@link org.jboss.arquillian.config.descriptor.api.ContainerDef}
+ * for the arquillian.xml or other configured descriptor and populates the container configuration
+ * instance from the descriptor values.
+ *
+ * @return A possibly null ConfigurationMapper. If null, the default logic to map from string based
+ * properties as implemented in org.jboss.arquillian.container.impl.MapObject will be used.
+ */
+ default ConfigurationMapper getConfigurationMapper() {
+ return null;
+ }
default void setup(T configuration) {
}