All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.otto.jlineup.web.JLineupRunnerFactory Maven / Gradle / Ivy

package de.otto.jlineup.web;

import de.otto.jlineup.JLineupRunner;
import de.otto.jlineup.RunStepConfig;
import de.otto.jlineup.config.JobConfig;
import de.otto.jlineup.config.RunStep;
import de.otto.jlineup.config.UrlConfig;
import de.otto.jlineup.service.BrowserNotInstalledException;
import de.otto.jlineup.web.configuration.JLineupWebProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
import java.util.stream.Collectors;

import static de.otto.jlineup.browser.BrowserUtils.RANDOM_FOLDER_PLACEHOLDER;
import static de.otto.jlineup.config.JobConfig.DEFAULT_REPORT_FORMAT;

@Component
public class JLineupRunnerFactory {

    private final JLineupWebProperties properties;

    @Autowired
    public JLineupRunnerFactory(JLineupWebProperties properties) {
        this.properties = properties;
    }

    public JLineupRunner createBeforeRun(String id, JobConfig jobConfig) throws Exception {
        return createRun(id, jobConfig, RunStep.before);
    }

    public JLineupRunner createAfterRun(String id, JobConfig jobConfig) throws Exception {
        return createRun(id, jobConfig, RunStep.after);
    }

    private JLineupRunner createRun(String id, JobConfig jobConfig, RunStep step) throws Exception {

        JobConfig webJobConfig = sanitizeJobConfig(jobConfig);

        //Replace id placeholder in approval link with runId
        if (webJobConfig.approvalLink != null && webJobConfig.approvalLink.contains("{id}")) {
            webJobConfig = JobConfig.copyOfBuilder(webJobConfig)
                    .withApprovalLink(webJobConfig.approvalLink.replace("{id}", id))
                    .build();
        }

        return new JLineupRunner(webJobConfig, RunStepConfig.runStepConfigBuilder()
                .withWorkingDirectory(properties.getWorkingDirectory())
                .withScreenshotsDirectory(properties.getScreenshotsDirectory().replace("{id}", id))
                .withReportDirectory(properties.getReportDirectory().replace("{id}", id))
                .withChromeParameters(properties.getChromeLaunchParameters().stream()
                        .map(param -> param.replace("{id}", id))
                        .map(param -> param.startsWith("--user-data-dir") ? param + "/" + RANDOM_FOLDER_PLACEHOLDER : param)
                        .collect(Collectors.toList()))
                .withFirefoxParameters(properties.getFirefoxLaunchParameters().stream()
                        .map(param -> param.replace("{id}", id))
                        .map(param -> param.startsWith("-profile ") || param.startsWith("-P ") ? param + "/" + RANDOM_FOLDER_PLACEHOLDER : param)
                        .collect(Collectors.toList()))
                .withCleanupProfile(properties.isCleanupProfile())
                .withStep(step)
                .build());
    }

    JobConfig sanitizeJobConfig(final JobConfig jobConfig) throws BrowserNotInstalledException, IllegalArgumentException {

        if (!properties.getInstalledBrowsers().contains(jobConfig.browser)) {
            throw new BrowserNotInstalledException(jobConfig.browser);
        }

        if (!properties.getAllowedUrlPrefixes().isEmpty()) {
            for (UrlConfig urlConfig : jobConfig.urls.values()) {
                if (properties.getAllowedUrlPrefixes().stream().noneMatch(urlConfig.getUrl()::startsWith)) {
                    throw new IllegalArgumentException("URL " + urlConfig.url + " is not allowed. Allowed prefixes are: " + properties.getAllowedUrlPrefixes());
                }

                if (urlConfig.javaScript != null) {
                    String javaScript = urlConfig.javaScript;
                    try {
                        while (true) {
                            String decodedJavaScript = URLDecoder.decode(javaScript, "UTF-8");
                            if (!decodedJavaScript.equals(javaScript)) {
                                javaScript = decodedJavaScript;
                            } else {
                                break;
                            }
                        }
                    } catch (UnsupportedEncodingException e) {
                        throw new IllegalArgumentException("JavaScript code must be UTF-8 encoded.");
                    }
                    if (javaScript.contains("http://") || javaScript.contains("https://")) {
                        //Check the javascript code for urls that dont start with one of the allowed prefixes
                        List urls = findSubstringsStartingWithSearchString(javaScript, "http://");
                        urls.addAll(findSubstringsStartingWithSearchString(javaScript, "https://"));
                        for (String url : urls) {
                            if (properties.getAllowedUrlPrefixes().stream().noneMatch(url::startsWith)) {
                                throw new IllegalArgumentException("URL " + url + " is not allowed. Allowed prefixes are: " + properties.getAllowedUrlPrefixes());
                            }
                        }
                    }
                }
            }
        }

        return JobConfig.copyOfBuilder(jobConfig)
                .withThreads(calculateNumberOfThreads(jobConfig))
                .withDebug(false)
                .withLogToFile(false)
                .withReportFormat(DEFAULT_REPORT_FORMAT)
                .build();
    }

    private int calculateNumberOfThreads(JobConfig jobConfig) {
        return jobConfig.threads == 0 ? properties.getMaxThreadsPerJob() : Math.min(jobConfig.threads, properties.getMaxThreadsPerJob());
    }

    private static List findSubstringsStartingWithSearchString(String input, String searchString) {
        List substrings = new ArrayList<>();
        int index = 0;

        while (index < input.length()) {
            index = input.indexOf(searchString, index);
            if (index == -1) {
                break;
            }
            int endIndex = input.indexOf(' ', index);
            if (endIndex == -1) {
                endIndex = input.length();
            }
            substrings.add(input.substring(index, endIndex));
            index += searchString.length();
        }

        return substrings;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy