Package org.openengsb.itests.util

Source Code of org.openengsb.itests.util.AbstractExamTestHelper

/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI 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.openengsb.itests.util;

import static org.apache.karaf.tooling.exam.options.KarafDistributionOption.debugConfiguration;
import static org.apache.karaf.tooling.exam.options.KarafDistributionOption.editConfigurationFilePut;
import static org.apache.karaf.tooling.exam.options.KarafDistributionOption.karafDistributionConfiguration;
import static org.apache.karaf.tooling.exam.options.KarafDistributionOption.logLevel;
import static org.ops4j.pax.exam.CoreOptions.maven;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.OptionUtils.combine;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.inject.Inject;

import org.apache.commons.lang.ObjectUtils;
import org.apache.karaf.tooling.exam.options.ConfigurationPointer;
import org.apache.karaf.tooling.exam.options.LogLevelOption.LogLevel;
import org.apache.karaf.tooling.exam.options.configs.ManagementCfg;
import org.apache.karaf.tooling.exam.options.configs.WebCfg;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.shiro.mgt.SecurityManager;
import org.junit.Before;
import org.openengsb.connector.usernamepassword.Password;
import org.openengsb.core.api.security.AuthenticationContext;
import org.openengsb.core.api.security.service.UserDataManager;
import org.openengsb.core.workflow.api.RuleManager;
import org.openengsb.core.workflow.api.model.RuleBaseElementId;
import org.openengsb.core.workflow.api.model.RuleBaseElementType;
import org.openengsb.core.workflow.drools.OsgiHelper;
import org.openengsb.domain.auditing.AuditingDomain;
import org.openengsb.domain.authentication.AuthenticationDomain;
import org.openengsb.domain.authentication.AuthenticationException;
import org.openengsb.domain.authorization.AuthorizationDomain;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.TestProbeBuilder;
import org.ops4j.pax.exam.junit.ProbeBuilder;
import org.ops4j.pax.exam.options.extra.VMOption;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ImmutableMap;

public abstract class AbstractExamTestHelper {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractExamTestHelper.class);

    /*
     * to configure loglevel and debug-flag, create a file called itests.local.properties in src/test/resources. This
     * file should only contain simple properties. You can use debug=true and loglevel=INFO in this file. Additional
     * possible properties are debugport=5005 and hold=true. The debugport option specifies the port where the container
     * is reachable and the hold option if the container should wait for a debugger to be attached or not.
     */

    private static final int DEBUG_PORT = 5005;
    private static final String LOG_LEVEL = "ERROR";
    public static final long DEFAULT_TIMEOUT = 90000;

    @Inject
    private BundleContext bundleContext;

    private AuthenticationContext authenticationContext;

    @Before
    public void setupFramework() throws Exception {
        waitForFrameworkToStart();
        waitForRequiredTasks();
    }
   
    private void waitForRequiredTasks() throws Exception {
        authenticationContext = getOsgiService(AuthenticationContext.class);
        waitForUserDataInitializer();
        RuleManager rm = getOsgiService(RuleManager.class);
        int count = 0;
        while (rm.getGlobalType("auditing") == null) {
            LOGGER.warn("waiting for auditing to finish init");
            waitasec();
            if (count++ > 100) {
                throw new IllegalStateException("auditing-config did not finish in time");
            }
        }
        count = 0;
        while (!rm.listImports().contains(OsgiHelper.class.getName())) {
            LOGGER.warn("waiting for auditing to finish init");
            waitasec();
            if (count++ > 100) {
                throw new IllegalStateException("auditing-config did not finish in time");
            }
        }
        count = 0;
        while (rm.get(new RuleBaseElementId(RuleBaseElementType.Process, "humantask")) == null) {
            LOGGER.warn("waiting for taskboxConfig to finish init");
            waitasec();
            if (count++ > 100) {
                throw new IllegalStateException("taskbox-config did not finish in time");
            }
        }
        authenticationContext = getOsgiService(AuthenticationContext.class);
    }
   
    private void waitForFrameworkToStart() throws Exception {
        waitForOsgiBundle("org.openengsb.domain.authentication");
        waitForOsgiBundle("org.openengsb.domain.authorization");
        waitForOsgiBundle("org.openengsb.connector.usernamepassword");
        waitForOsgiBundle("org.openengsb.framework.common");
        waitForOsgiBundle("org.openengsb.framework.util");
        waitForOsgiBundle("org.openengsb.framework.services");
        waitForOsgiBundle("org.openengsb.connector.memoryauditing");
       
        queryOsgiService(AuditingDomain.class, null, 10000, true);
        queryOsgiService(AuthenticationDomain.class, "(location.root=authentication-root)", 25000, true);
        queryOsgiService(AuthorizationDomain.class, "(location.root=authorization-root)", 25000, true);
    }

    private static final Map<Integer, String> STATES = ImmutableMap.of(1, "UNINSTALLED", 2, "INSTALLED", 4, "RESOLVED",
        8, "STARTING", 32, "ACTIVE");

    private void waitasec() throws InterruptedException {
        for (Bundle b : bundleContext.getBundles()) {
            if (b.getState() == Bundle.ACTIVE) {
                continue;
            }
            LOGGER.info(String.format("[%s]-[%s] - %s", b.getBundleId(), STATES.get(b.getState()),
                b.getSymbolicName()));
        }
        Thread.sleep(1000);
    }

    protected <T> T getOsgiService(Class<T> type, long timeout) {
        return getOsgiService(type, null, timeout);
    }

    protected <T> T getOsgiService(Class<T> type) {
        return getOsgiService(type, null, DEFAULT_TIMEOUT);
    }

    protected Bundle getInstalledBundle(String symbolicName) {
        for (Bundle b : bundleContext.getBundles()) {
            if (b.getSymbolicName().equals(symbolicName)) {
                return b;
            }
        }
        return null;
    }

    protected void waitForSiteToBeAvailable(String urlToWatchFor, Integer maxWaitTime) throws InterruptedException {
        Integer localCounter = maxWaitTime;
        while (localCounter != 0) {
            if (isUrlReachable(urlToWatchFor)) {
                return;
            }
            waitasec();
            localCounter--;
        }
        throw new IllegalStateException(String.format("Couldn't reach page %s within %s seconds", urlToWatchFor,
            maxWaitTime));
    }

    @SuppressWarnings("deprecation")
    protected boolean isUrlReachable(String url) {
        URL downloadUrl;
        InputStream is = null;
        DataInputStream dataInputStream;
        try {
            downloadUrl = new URL(url);
            is = downloadUrl.openStream();
            dataInputStream = new DataInputStream(new BufferedInputStream(is));
            while (dataInputStream.readLine() != null) {
                return true;
            }
        } catch (Exception e) {
            // well... what should we say; this could happen...
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException ioe) {
            }
        }
        return false;
    }

    protected void waitForOsgiBundle(String symbolicName) throws Exception {
        waitForOsgiBundle(symbolicName, DEFAULT_TIMEOUT);
    }

    protected void waitForOsgiBundle(String symbolicName, long timeout) throws Exception {
        int sleepTime = 1000;
        int i = 0;
        Bundle b = null;
        do {
            b = getInstalledBundle(symbolicName);
            if (b.getState() == Bundle.ACTIVE) {
                break;
            }
            // break the loop after timeout to avoid endless loop
            if ((i * sleepTime) >= timeout) {
                throw new RuntimeException("bundle " + symbolicName
                    + " didn't start after " + timeout / 1000 + " seconds");
            }
            Thread.sleep(sleepTime);
            i++;
        } while (b.getState() != Bundle.ACTIVE);
    }

    protected <T> T getOsgiService(Class<T> type, String filter, long timeout) {
        return queryOsgiService(type, filter, timeout, true);
    }

    protected Boolean isOsgiServiceAvailable(Class<?> type, String filter) {
        return queryOsgiService(type, filter, 100, false) != null;
    }

    protected <T> T queryOsgiService(Class<T> type, String filter, long timeout, boolean throwException) {
        ServiceTracker tracker;
        try {
            String flt;
            if (filter != null) {
                if (filter.startsWith("(")) {
                    flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")" + filter + ")";
                } else {
                    flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")(" + filter + "))";
                }
            } else {
                flt = "(" + Constants.OBJECTCLASS + "=" + type.getName() + ")";
            }
            Filter osgiFilter = FrameworkUtil.createFilter(flt);
            tracker = new ServiceTracker(bundleContext, osgiFilter, null);
            tracker.open(true);
            // Note that the tracker is not closed to keep the reference
            // This is buggy, as the service reference may change i think
            Object svc = type.cast(tracker.waitForService(timeout));
            if (svc == null && throwException) {
                @SuppressWarnings("rawtypes")
                Dictionary dic = bundleContext.getBundle().getHeaders();
                LOGGER.error("Test bundle headers: {}", explode(dic));

                for (ServiceReference<?> ref : asCollection(bundleContext.getAllServiceReferences(null, null))) {
                    LOGGER.error("ServiceReference: {}", ref);
                }

                for (ServiceReference<?> ref : asCollection(bundleContext.getAllServiceReferences(null, flt))) {
                    LOGGER.error("Filtered ServiceReference: {}", ref);
                }

                throw new RuntimeException("Gave up waiting for service " + flt);
            }
            return svc != null ? type.cast(svc) : null;
        } catch (InvalidSyntaxException e) {
            throw new IllegalArgumentException("Invalid filter", e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    @SuppressWarnings("rawtypes")
    private static String explode(Dictionary dictionary) {
        Enumeration keys = dictionary.keys();
        StringBuffer result = new StringBuffer();
        while (keys.hasMoreElements()) {
            Object key = keys.nextElement();
            result.append(String.format("%s=%s", key, dictionary.get(key)));
            if (keys.hasMoreElements()) {
                result.append(", ");
            }
        }
        return result.toString();
    }

    /*
     * Provides an iterable collection of references, even if the original array is null
     */
    private static Collection<ServiceReference<?>> asCollection(ServiceReference<?>[] references) {
        List<ServiceReference<?>> result = new LinkedList<ServiceReference<?>>();
        if (references != null) {
            for (ServiceReference<?> reference : references) {
                result.add(reference);
            }
        }
        return result;
    }

    protected BundleContext getBundleContext() {
        return bundleContext;
    }

    protected static String getWorkingDirectory() {
        return "target/paxrunner/features/";
    }

    protected void authenticateAsAdmin() throws InterruptedException, AuthenticationException {
        authenticate("admin", "password");
    }

    protected void authenticate(String user, String password) throws InterruptedException, AuthenticationException {
        authenticationContext.login(user, new Password(password));
    }

    protected void waitForUserDataInitializer() throws InterruptedException {
        SecurityManager sm = null;
        int count = 0;
        while (sm == null) {
            try {
                sm = SecurityUtils.getSecurityManager();
            } catch (UnavailableSecurityManagerException e) {
                LOGGER.warn("waiting for security-manager to be set");
                waitasec();
            }
            if (count++ > 100) {
                throw new IllegalStateException("security-manager was not set in time");
            }
        }
        UserDataManager userDataManager = getOsgiService(UserDataManager.class, "(internal=true)", 20000);
        count = 0;
        while (userDataManager.getUserList().isEmpty()) {
            LOGGER.warn("waiting for users to be initialized");
            waitasec();
            if (count++ > 100) {
                throw new IllegalStateException("user-data-initializer did not finish in time");
            }
        }
        getOsgiService(AuthenticationDomain.class, "(connector=usernamepassword)", 15000);
    }

    @ProbeBuilder
    public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) throws IOException {
        InputStream stream = ClassLoader.getSystemResourceAsStream("META-INF/maven/dependencies.properties");
        Properties depProperties = new Properties();
        depProperties.load(stream);
        String projectVersion = ((String) depProperties
            .get("org.openengsb.domain/org.openengsb.domain.example/version"))
            .replace("-", ".");
        probe.setHeader("Project-Version", projectVersion);
        return probe;
    }

    public static Option[] baseConfiguration() throws Exception {
        String loglevel = LOG_LEVEL;
        String debugPort = Integer.toString(DEBUG_PORT);
        boolean hold = true;
        boolean debug = false;
        InputStream paxLocalStream = ClassLoader.getSystemResourceAsStream("itests.local.properties");
        if (paxLocalStream != null) {
            Properties properties = new Properties();
            properties.load(paxLocalStream);
            loglevel = (String) ObjectUtils.defaultIfNull(properties.getProperty("loglevel"), loglevel);
            debugPort = "5005"; // (String) ObjectUtils.defaultIfNull(properties.getProperty("debugport"), debugPort);
            debug = true; // ObjectUtils.equals(Boolean.TRUE.toString(), properties.getProperty("debug"));
            hold = true; // ObjectUtils.equals(Boolean.TRUE.toString(), properties.getProperty("hold"));
        }
        Properties portNames = new Properties();
        InputStream portsPropertiesFile = ClassLoader.getSystemResourceAsStream("ports.properties");
        if (portsPropertiesFile == null) {
            throw new IllegalStateException("ports-configuration not found");
        }
        portNames.load(portsPropertiesFile);
        LOGGER.warn("running itests with the following port-config");
        LOGGER.warn(portNames.toString());
        LogLevel realLogLevel = transformLogLevel(loglevel);
        Option[] mainOptions =
            new Option[]{
                new VMOption("-Xmx2048m"),
                new VMOption("-XX:MaxPermSize=256m"),
                karafDistributionConfiguration().frameworkUrl(
                    maven().groupId("org.openengsb.framework").artifactId("openengsb-framework").type("zip")
                        .versionAsInProject()),
                logLevel(realLogLevel),
                editConfigurationFilePut(WebCfg.HTTP_PORT, (String) portNames.get("jetty.http.port")),
                editConfigurationFilePut(ManagementCfg.RMI_SERVER_PORT, (String) portNames.get("rmi.server.port")),
                editConfigurationFilePut(ManagementCfg.RMI_REGISTRY_PORT, (String) portNames.get("rmi.registry.port")),
                editConfigurationFilePut(new ConfigurationPointer("etc/org.openengsb.infrastructure.jms.cfg",
                    "openwire"), (String) portNames.get("jms.openwire.port")),
                editConfigurationFilePut(new ConfigurationPointer("etc/org.openengsb.infrastructure.jms.cfg",
                    "stomp"), (String) portNames.get("jms.stomp.port")),
                mavenBundle(maven().groupId("org.openengsb.wrapped").artifactId("net.sourceforge.htmlunit-all")
                    .versionAsInProject()) };
        mainOptions = combine(mainOptions, getDefaultEDBConfiguration());
        if (debug) {
            return combine(mainOptions, debugConfiguration(debugPort, hold));
        }
        return mainOptions;
    }

    private static Option[] getDefaultEDBConfiguration() {
        String cfg = "etc/org.openengsb.infrastructure.jpa.cfg";

        return new Option[]{
            editConfigurationFilePut(cfg, "url", "jdbc:h2:mem:itests"),
            editConfigurationFilePut(cfg, "driverClassName", "org.h2.jdbcx.JdbcDataSource"),
            editConfigurationFilePut(cfg, "username", ""),
            editConfigurationFilePut(cfg, "password", "")
        };
    }

    public String getConfigProperty(String config, String name) throws IOException {
        ConfigurationAdmin cm = getOsgiService(ConfigurationAdmin.class);
        Configuration configuration = cm.getConfiguration(config);
        return (String) configuration.getProperties().get(name);
    }

    private static LogLevel transformLogLevel(String logLevel) {
        switch (logLevel) {
            case "ERROR":
                return LogLevel.ERROR;
            case "WARN":
                return LogLevel.WARN;
            case "INFO":
                return LogLevel.INFO;
            case "DEBUG":
                return LogLevel.DEBUG;
            case "TRACE":
                return LogLevel.TRACE;
            default:
                return LogLevel.WARN;
        }
    }

    protected String getOsgiProjectVersion() {
        return bundleContext.getBundle().getHeaders().get("Project-Version");
    }
}
TOP

Related Classes of org.openengsb.itests.util.AbstractExamTestHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.