blob: 4ca38407fbbd9a8c9781e367871f5cd34340983e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* 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.apache.sling.testing.teleporter.client;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.junit.rules.TeleporterRule;
import org.apache.sling.junit.rules.TeleporterRule.Customizer;
/**
* This is the default {@link Customizer} which is used in case {@code TeleporterRule.forClass(Class)} was called. It relies on system
* properties to configure the important aspects of teleporting. <br>
* It assumes that there is already a running Sling server at the given baseUrl. To provision such a server the
* <a href="https://sling.apache.org/documentation/development/slingstart.html#slingstart-maven-plugin">slingstart-maven-plugin</a> could be
* used for example. <br>
* The following system properties must be set for this Customizer to work
* <ul>
* <li>{@code ClientSideTeleporter.baseUrl}, the server url on which Sling is already running</li>
* </ul>
*
* The following system properties may be set to further tweak the behavior:
* <ul>
* <li>{@code ClientSideTeleporter.includeDependencyPrefixes}, comma-separated list of package prefixes for classes referenced from the IT.
* Only the classes having one of the given package prefix are included in the bundle being deployed to the given Sling instance together
* with the IT class itself. They are only included though in case they are referenced! If this is not set, no referenced classes will be
* included.</li>
* <li>{@code ClientSideTeleporter.excludeDependencyPrefixes}, comma-separated list of package prefixes for classes referenced from the IT.
* Classes having one of the given package prefix will not be included in the bundle being deployed to the given Sling instance together
* with the IT class itself. This takes precedence over the {@code ClientSideTeleporter.includeDependencyPrefixes}.</li>
* <li>{@code ClientSideTeleporter.embedClasses}, comma-separated list of fully qualified class names which should be embedded in the test
* bundle. Use this only for classes which are not detected automatically by the Maven Dependency Analyzer but still should be embedded in
* the test bundle</li>
* <li>{@code ClientSideTeleporter.embedClassesDirectories}, comma-separated list directories containing class files which should be
* embedded in the test bundle. Use this only for classes which are not detected automatically by the Maven Dependency Analyzer but still
* should be embedded in the test bundle</li>
* <li>{@code ClientSideTeleporter.additionalBundleHeaders}, comma-separated list of entries in the format {@code <name>:<value>} which
* should be added to the test bundle as additional headers</li>
* <li>{@code ClientSideTeleporter.testReadyTimeoutSeconds}, how long to wait for our test to be ready on the server-side in seconds, after
* installing the test bundle. By default {@code 12}.</li>
* <li>{@code ClientSideTeleporter.serverUsername}, the username with which to send requests to the Sling server. By default
* {@code admin}.</li>
* <li>{@code ClientSideTeleporter.serverPassword}, the password with which to send requests to the Sling server. By default
* {@code admin}.</li>
* <li>{@code ClientSideTeleporter.enableLogging}, set to true to log the tasks being performed by the teleporter. Useful for
* debugging.</li>
* <li>{@code ClientSideTeleporter.preventToUninstallBundle}, set to true to not automatically uninstall the test bundle after test
* execution. Useful for debugging.</li>
* <li>{@code ClientSideTeleporter.testBundleDirectory}, if set the test bundles are being persisted (before being installed) within the
* given directory name. If the directory does not exist, it will be automatically created. Useful for debugging.</li>
* </ul>
*/
public class DefaultPropertyBasedCustomizer implements Customizer {
static final String PROPERTY_BASE_URL = "ClientSideTeleporter.baseUrl";
static final String PROPERTY_INCLUDE_DEPENDENCY_PREFIXES = "ClientSideTeleporter.includeDependencyPrefixes";
static final String PROPERTY_EXCLUDE_DEPENDENCY_PREFIXES = "ClientSideTeleporter.excludeDependencyPrefixes";
static final String PROPERTY_EMBED_CLASSES = "ClientSideTeleporter.embedClasses";
static final String PROPERTY_EMBED_CLASSES_DIRECTORIES = "ClientSideTeleporter.embedClassesDirectories";
static final String PROPERTY_SERVER_PASSWORD = "ClientSideTeleporter.serverPassword";
static final String PROPERTY_SERVER_USERNAME = "ClientSideTeleporter.serverUsername";
static final String PROPERTY_TESTREADY_TIMEOUT_SECONDS = "ClientSideTeleporter.testReadyTimeoutSeconds";
static final String PROPERTY_TESTBUNDLE_DIRECTORY = "ClientSideTeleporter.testBundleDirectory";
static final String PROPERTY_ENABLE_LOGGING = "ClientSideTeleporter.enableLogging";
static final String PROPERTY_PREVENT_TO_UNINSTALL_BUNDLE = "ClientSideTeleporter.preventToUninstallBundle";
static final String PROPERTY_ADDITIONAL_BUNDLE_HEADERS = "ClientSideTeleporter.additionalBundleHeaders";
static final String LIST_SEPARATOR = ",";
static final String NAME_VALUE_SEPARATOR = ":";
private final int testReadyTimeout;
private final String serverUsername;
private final String serverPassword;
private final String includeDependencyPrefixes;
private final String excludeDependencyPrefixes;
private final String embedClasses;
private final String embedClassesDirectories;
private final String baseUrl;
private final String testBundleDirectory;
private final boolean enableLogging;
private final boolean preventToUninstallBundle;
private final String additionalBundleHeaders;
public DefaultPropertyBasedCustomizer() {
testReadyTimeout = Integer.getInteger(PROPERTY_TESTREADY_TIMEOUT_SECONDS, 12);
serverUsername = System.getProperty(PROPERTY_SERVER_USERNAME, "admin");
serverPassword = System.getProperty(PROPERTY_SERVER_PASSWORD, "admin");
includeDependencyPrefixes = System.getProperty(PROPERTY_INCLUDE_DEPENDENCY_PREFIXES);
excludeDependencyPrefixes = System.getProperty(PROPERTY_EXCLUDE_DEPENDENCY_PREFIXES);
embedClasses = System.getProperty(PROPERTY_EMBED_CLASSES);
embedClassesDirectories = System.getProperty(PROPERTY_EMBED_CLASSES_DIRECTORIES);
baseUrl = System.getProperty(PROPERTY_BASE_URL);
additionalBundleHeaders = System.getProperty(PROPERTY_ADDITIONAL_BUNDLE_HEADERS);
testBundleDirectory = System.getProperty(PROPERTY_TESTBUNDLE_DIRECTORY);
enableLogging = Boolean.getBoolean(PROPERTY_ENABLE_LOGGING);
preventToUninstallBundle = Boolean.getBoolean(PROPERTY_PREVENT_TO_UNINSTALL_BUNDLE);
}
@Override
public void customize(TeleporterRule rule, String options) {
final ClientSideTeleporter cst = (ClientSideTeleporter)rule;
if (StringUtils.isBlank(baseUrl)) {
fail("The mandatory system property " + PROPERTY_BASE_URL + " is not set!");
}
cst.setEnableLogging(enableLogging);
cst.setPreventToUninstallBundle(preventToUninstallBundle);
if (StringUtils.isNotBlank(testBundleDirectory)) {
cst.setDirectoryForPersistingTestBundles(new File(testBundleDirectory));
}
cst.setBaseUrl(baseUrl);
cst.setServerCredentials(serverUsername, serverPassword);
cst.setTestReadyTimeoutSeconds(testReadyTimeout);
if (StringUtils.isNotBlank(includeDependencyPrefixes)) {
for (String includeDependencyPrefix : includeDependencyPrefixes.split(LIST_SEPARATOR)) {
if (StringUtils.isNotBlank(includeDependencyPrefix)) {
cst.includeDependencyPrefix(includeDependencyPrefix);
}
}
}
if (StringUtils.isNotBlank(excludeDependencyPrefixes)) {
for (String excludeDependencyPrefix : excludeDependencyPrefixes.split(LIST_SEPARATOR)) {
if (StringUtils.isNotBlank(excludeDependencyPrefix)) {
cst.excludeDependencyPrefix(excludeDependencyPrefix);
}
}
}
if (StringUtils.isNotBlank(embedClassesDirectories)) {
for (String embedClassesDirectory : embedClassesDirectories.split(LIST_SEPARATOR)) {
if (StringUtils.isNotBlank(embedClassesDirectory)) {
try {
cst.embedClassesDirectory(new File(embedClassesDirectory));
} catch (ClassNotFoundException | IOException e) {
fail("Could not load class directory '" + embedClassesDirectory + "': " + e.getMessage());
}
}
}
}
if (StringUtils.isNotBlank(embedClasses)) {
for (String embedClass : embedClasses.split(LIST_SEPARATOR)) {
if (StringUtils.isNotBlank(embedClass)) {
try {
Class<?> clazz = this.getClass().getClassLoader().loadClass(embedClass);
cst.embedClass(clazz);
} catch (ClassNotFoundException e) {
fail("Could not load class with name '" + embedClass + "': " + e.getMessage());
}
}
}
}
if (StringUtils.isNotBlank(additionalBundleHeaders)) {
for (String additionalBundleHeader : additionalBundleHeaders.split(LIST_SEPARATOR)) {
if (StringUtils.isNotBlank(additionalBundleHeader)) {
// split up by name and value
int pos = additionalBundleHeader.indexOf(NAME_VALUE_SEPARATOR);
if (pos < 1 || pos >= additionalBundleHeader.length() -1) {
fail("Each entry given to property '" + PROPERTY_ADDITIONAL_BUNDLE_HEADERS +
"' must have exactly the format <name>:<value>, but one entry is '" + additionalBundleHeader + "'.");
}
cst.addAdditionalBundleHeader(additionalBundleHeader.substring(0, pos), additionalBundleHeader.substring(pos+1));
}
}
}
}
}