/* * Copyright 2016 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * 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.keycloak.testsuite.arquillian.containers; import org.jboss.arquillian.config.descriptor.api.ContainerDef; import org.jboss.arquillian.container.impl.ContainerCreationException; import org.jboss.arquillian.container.impl.ContainerImpl; 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.DeployableContainer; import org.jboss.arquillian.container.spi.client.deployment.TargetDescription; import org.jboss.arquillian.core.api.Injector; import org.jboss.arquillian.core.spi.ServiceLoader; import org.jboss.arquillian.core.spi.Validate; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import static org.keycloak.testsuite.arquillian.containers.RegistryCreator.ADAPTER_IMPL_CONFIG_STRING; import static org.keycloak.testsuite.arquillian.containers.RegistryCreator.getAdapterImplClassValue; import static org.keycloak.testsuite.arquillian.containers.RegistryCreator.getContainerAdapter; import static org.keycloak.testsuite.arquillian.containers.SecurityActions.isClassPresent; import static org.keycloak.testsuite.arquillian.containers.SecurityActions.loadClass; /** * This class registers all adapters which are specified in the arquillian.xml. * * In the case there is only one adapter implementation on the classpath, it is * not necessary to specify it in the container configuration since it will be * used automatically. You have to specify it only in the case you are going to * use more than one container. * * @author Dominik Pospisil <dpospisi@redhat.com> * @author Stefan Miklosovic <smikloso@redhat.com> * @author Tomas Kyjovsky <tkyjovsk@redhat.com> */ public class Registry implements ContainerRegistry { private final List<Container> containers; private Injector injector; private static final Logger logger = Logger.getLogger(RegistryCreator.class.getName()); public Registry(Injector injector) { this.containers = new ArrayList<>(); this.injector = injector; } @Override public Container create(ContainerDef definition, ServiceLoader loader) { Validate.notNull(definition, "Definition must be specified"); try { logger.log(Level.FINE, "Registering container: {0}", definition.getContainerName()); @SuppressWarnings("rawtypes") Collection<DeployableContainer> containerAdapters = loader.all(DeployableContainer.class); DeployableContainer<?> dcService = null; if (containerAdapters.size() == 1) { // just one container on cp dcService = containerAdapters.iterator().next(); } else { Container domainContainer = domainContainer(loader, definition); if (domainContainer != null) { return domainContainer; } if (dcService == null) { dcService = getContainerAdapter(getAdapterImplClassValue(definition), containerAdapters); } if (dcService == null) { throw new ConfigurationException("Unable to get container adapter from Arquillian configuration."); } } // before a Container is added to a collection of containers, inject into its injection point return addContainer(injector.inject( new ContainerImpl(definition.getContainerName(), dcService, definition))); } catch (Exception e) { throw new ContainerCreationException("Could not create Container " + definition.getContainerName(), e); } } private Container domainContainer(ServiceLoader loader, ContainerDef definition) { for (Container container : containers) { String adapterImplClassValue = container.getContainerConfiguration().getContainerProperties() .get(ADAPTER_IMPL_CONFIG_STRING); if (isServiceLoaderClassAssignableFromAdapterImplClass(loader, adapterImplClassValue.trim())) { try { return addContainer((Container) injector.inject( new ContainerImpl( definition.getContainerName(), (DeployableContainer) loader.onlyOne(DeployableContainer.class), definition))); } catch (Exception ex) { throw new ContainerCreationException( "Could not create Container " + definition.getContainerName(), ex); } } } return null; } private boolean isServiceLoaderClassAssignableFromAdapterImplClass(ServiceLoader loader, String adapterImplClassValue) { if (adapterImplClassValue == null && loader == null) { return false; } if (isClassPresent(adapterImplClassValue)) { Class<?> aClass = loadClass(adapterImplClassValue); String loaderClassName = loader.getClass().getName(); if (loaderClassName.contains("$")) { loaderClassName = loaderClassName.substring(0, loaderClassName.indexOf("$")); } return loadClass(loaderClassName).isAssignableFrom(aClass); } return false; } @Override public List<Container> getContainers() { return Collections.unmodifiableList(new ArrayList<>(containers)); } @Override public Container getContainer(TargetDescription target) { Validate.notNull(target, "Target must be specified"); if (TargetDescription.DEFAULT.equals(target)) { return findDefaultContainer(); } return findMatchingContainer(target.getName()); } private Container addContainer(Container container) { containers.add(container); return container; } private Container findDefaultContainer() { if (containers.size() == 1) { return containers.get(0); } for (Container container : containers) { if (container.getContainerConfiguration().isDefault()) { return container; } } return null; } private Container findMatchingContainer(String name) { for (Container container : containers) { if (container.getName().equals(name)) { return container; } } return null; } @Override public Container getContainer(String name) { return findMatchingContainer(name); } }