/*
* JBoss, Home of Professional Open Source
* Copyright 2010 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.impl.client.container;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.arquillian.config.descriptor.api.ArquillianDescriptor;
import org.jboss.arquillian.config.descriptor.api.ContainerDef;
import org.jboss.arquillian.config.descriptor.api.GroupDef;
import org.jboss.arquillian.config.descriptor.impl.ContainerDefImpl;
import org.jboss.arquillian.container.impl.LocalContainerRegistry;
import org.jboss.arquillian.container.spi.ContainerRegistry;
import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
import org.jboss.arquillian.core.api.Injector;
import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.InstanceProducer;
import org.jboss.arquillian.core.api.annotation.ApplicationScoped;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.core.api.annotation.Observes;
import org.jboss.arquillian.core.spi.ServiceLoader;
/**
* ContainerRegistryCreator
*
* @author <a href="mailto:aslak@redhat.com">Aslak Knutsen</a>
* @version $Revision: $
*/
public class ContainerRegistryCreator {
static final String ARQUILLIAN_LAUNCH_PROPERTY = "arquillian.launch";
static final String ARQUILLIAN_LAUNCH_DEFAULT = "arquillian.launch_file";
@Deprecated
static final String ARQUILLIAN_LAUNCH_DEFAULT_DEPRECATED = "arquillian.launch";
private Logger log = Logger.getLogger(ContainerRegistryCreator.class.getName());
@Inject
@ApplicationScoped
private InstanceProducer<ContainerRegistry> registry;
@Inject
private Instance<Injector> injector;
@Inject
private Instance<ServiceLoader> loader;
public void createRegistry(@Observes ArquillianDescriptor event) {
LocalContainerRegistry reg = new LocalContainerRegistry(injector.get());
ServiceLoader serviceLoader = loader.get();
validateConfiguration(event);
String activeConfiguration = getActivatedConfiguration();
for (ContainerDef container : event.getContainers()) {
if (
(activeConfiguration != null && activeConfiguration.equals(container.getContainerName())) ||
(activeConfiguration == null && container.isDefault())) {
reg.create(container, serviceLoader);
}
}
for (GroupDef group : event.getGroups()) {
if (
(activeConfiguration != null && activeConfiguration.equals(group.getGroupName())) ||
(activeConfiguration == null && group.isGroupDefault())) {
for (ContainerDef container : group.getGroupContainers()) {
reg.create(container, serviceLoader);
}
}
}
if (activeConfiguration == null && reg.getContainers().size() == 0) {
DeployableContainer<?> deployableContainer = null;
try {
// 'check' if there are any DeployableContainers on CP
deployableContainer = serviceLoader.onlyOne(DeployableContainer.class);
} catch (IllegalStateException e) {
StringBuilder stringBuilder = new StringBuilder()
.append("Could not add a default container to registry because multiple instances of ")
.append(DeployableContainer.class.getName())
.append(" found on classpath (candidates are: ");
String separator = "";
for (DeployableContainer s : serviceLoader.all(DeployableContainer.class)) {
stringBuilder.append(separator)
.append(s.getConfigurationClass().getName());
separator = ", ";
}
stringBuilder.append(")");
throw new IllegalStateException(stringBuilder.toString());
} catch (Exception e) {
throw new IllegalStateException("Could not create the default container instance", e);
}
if (deployableContainer != null) {
reg.create(new ContainerDefImpl("arquillian.xml").setContainerName("default"), serviceLoader);
}
} else if (activeConfiguration != null && reg.getContainers().size() == 0) {
throw new IllegalArgumentException(
"No container or group found that match given qualifier: " + activeConfiguration);
}
// export
registry.set(reg);
}
/**
* Validate that the Configuration given is sane
*
* @param desc
* The read Descriptor
*/
private void validateConfiguration(ArquillianDescriptor desc) {
Object defaultConfig = null;
// verify only one container is marked as default
for (ContainerDef container : desc.getContainers()) {
if (container.isDefault()) {
if (defaultConfig != null) {
throw new IllegalStateException("Multiple Containers defined as default, only one is allowed:\n"
+ defaultConfig
+ ":"
+ container);
}
defaultConfig = container;
}
}
boolean containerMarkedAsDefault = defaultConfig != null;
// verify only one container or group is marked as default
for (GroupDef group : desc.getGroups()) {
if (group.isGroupDefault()) {
if (defaultConfig != null) {
if (containerMarkedAsDefault) {
throw new IllegalStateException(
"Multiple Containers/Groups defined as default, only one is allowed:\n"
+ defaultConfig
+ ":"
+ group);
}
throw new IllegalStateException(
"Multiple Groups defined as default, only one is allowed:\n" + defaultConfig + ":" + group);
}
defaultConfig = group;
}
ContainerDef defaultInGroup = null;
// verify only one container in group is marked as default
for (ContainerDef container : group.getGroupContainers()) {
if (container.isDefault()) {
if (defaultInGroup != null) {
throw new IllegalStateException(
"Multiple Containers within Group defined as default, only one is allowed:\n" + group);
}
defaultInGroup = container;
}
}
}
}
private String getActivatedConfiguration() {
if (exists(SecurityActions.getProperty(ARQUILLIAN_LAUNCH_PROPERTY))) {
return SecurityActions.getProperty(ARQUILLIAN_LAUNCH_PROPERTY);
}
String qualifier = readLaunchFile(ARQUILLIAN_LAUNCH_DEFAULT);
if (qualifier == null) {
qualifier = readLaunchFile(ARQUILLIAN_LAUNCH_DEFAULT_DEPRECATED);
if (qualifier != null) {
log.log(Level.WARNING,
"The use of "
+ ARQUILLIAN_LAUNCH_DEFAULT_DEPRECATED
+ " has been deprecated and replaced with "
+ ARQUILLIAN_LAUNCH_DEFAULT
+
". The .launch file extension caused warnings when found in Eclipse due to conflicts with the Eclipse Launch Profile files. "
+
"See https://issues.jboss.org/browse/ARQ-1607 for more information.");
}
}
return qualifier;
}
private String readLaunchFile(String resourceName) {
InputStream arquillianLaunchStream = SecurityActions.getThreadContextClassLoader()
.getResourceAsStream(resourceName);
if (arquillianLaunchStream != null) {
try {
return readActivatedValue(new BufferedReader(new InputStreamReader(arquillianLaunchStream)));
} catch (Exception e) {
log.log(Level.WARNING, "Could not read resource " + resourceName, e);
}
}
return null;
}
private String readActivatedValue(BufferedReader reader)
throws Exception {
try {
String value;
while ((value = reader.readLine()) != null) {
if (value.startsWith("#")) {
continue;
}
return value;
}
} finally {
reader.close();
}
return null;
}
private boolean exists(String value) {
if (value == null || value.trim().length() == 0) {
return false;
}
return true;
}
}