diff --git a/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/container/internal/DependenciesDeployer.java b/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/container/internal/DependenciesDeployer.java index ffff53d2c..c63424924 100644 --- a/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/container/internal/DependenciesDeployer.java +++ b/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/container/internal/DependenciesDeployer.java @@ -31,9 +31,8 @@ import org.apache.commons.io.FileUtils; import org.ops4j.pax.exam.ExamSystem; import org.ops4j.pax.exam.karaf.options.KarafFeaturesOption; -import org.ops4j.pax.exam.options.BootClasspathLibraryOption; -import org.ops4j.pax.exam.options.ProvisionOption; -import org.ops4j.pax.exam.options.UrlReference; +import org.ops4j.pax.exam.karaf.options.SystemBundleOption; +import org.ops4j.pax.exam.options.*; /** * Deploys exam and the user specified dependencies and creates the @@ -69,7 +68,25 @@ public void copyBootClasspathLibraries() throws IOException { karafHome + "/lib"), new String[] { "jar" })); } } - + + /** + * + * Copies SystemBundleOption entries into the Karaf system folder using the Maven repository folder convention. + * + * @throws IOException if copy fails + */ + public void copySystemLibraries() throws IOException { + SystemBundleOption[] systemBundleOptions = subsystem + .getOptions(SystemBundleOption.class); + for (SystemBundleOption systemBundleOption : systemBundleOptions) { + UrlReference libraryUrl = systemBundleOption.getLibraryUrl(); + String destPath = karafHome + "/system" + systemBundleOption.getRepositoryPath(); + FileUtils.copyURLToFile( + new URL(libraryUrl.getURL()), + new File(destPath)); + } + } + /** * Copy dependencies specified as ProvisionOption in system to the deploy folder */ diff --git a/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/container/internal/KarafTestContainer.java b/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/container/internal/KarafTestContainer.java index f367aaec1..28af2e12b 100644 --- a/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/container/internal/KarafTestContainer.java +++ b/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/container/internal/KarafTestContainer.java @@ -156,6 +156,7 @@ public synchronized TestContainer start() { DependenciesDeployer deployer = new DependenciesDeployer(subsystem, karafBase, karafHome); deployer.copyBootClasspathLibraries(); + deployer.copySystemLibraries(); updateLogProperties(karafHome, subsystem); setupSystemProperties(karafHome, subsystem); diff --git a/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/options/KarafDistributionOption.java b/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/options/KarafDistributionOption.java index 2ffb4859b..8605016c5 100644 --- a/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/options/KarafDistributionOption.java +++ b/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/options/KarafDistributionOption.java @@ -29,6 +29,8 @@ import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel; +import org.ops4j.pax.exam.options.CompositeOption; +import org.ops4j.pax.exam.options.DefaultCompositeOption; import org.ops4j.pax.exam.options.UrlReference; import org.ops4j.pax.exam.options.extra.VMOption; @@ -47,7 +49,7 @@ private KarafDistributionOption() { /** * Per default the folder pax-exam is deleting the test directories after a test is over. If you * want to keep those directories (for later evaluation) simply set this option. - * + * * @return keep runtime folder option */ public static Option keepRuntimeFolder() { @@ -56,7 +58,7 @@ public static Option keepRuntimeFolder() { /** * Provides an option to configure the internals of the PaxExamKaraf subsystem runner. - * + * * @param invoker * probe invoker name * @return option @@ -70,7 +72,7 @@ public static Option useOwnKarafExamSystemConfiguration(String invoker) { * we take the freedom of adding a console logger and changing the log level directly. IF you * like to configure the file manually (or had so in your distribution) add this option to avoid * any automatic modifications to this file! - * + * * @return option */ public static Option doNotModifyLogConfiguration() { @@ -80,7 +82,7 @@ public static Option doNotModifyLogConfiguration() { /** * This option allows to configure the start level of the bundles in the exam features * descriptor. - * + * * @param startLevel * bundle start level * @return option @@ -92,7 +94,7 @@ public static Option useOwnExamBundlesStartLevel(int startLevel) { /** * Returns an option object which can be used to configure the -Dkaraf.startLocalConsole and * -Dkaraf.startRemoteShell options. By default both are true. - * + * * @return option */ public static KarafDistributionConfigurationConsoleOption configureConsole() { @@ -102,18 +104,46 @@ public static KarafDistributionConfigurationConsoleOption configureConsole() { /** * Returns an option object which can be used to configure the security, especially the * MBeanServerBuilder. By default, it's disabled. - * + * * @return option */ public static KarafDistributionConfigurationSecurityOption configureSecurity() { return new KarafDistributionConfigurationSecurityOption(null); } + /** + * Returns an option to adding an artifact to the Karaf system directory using the provided file. + * A corresponding (maven) entry will also be placed into the startup.properties configuration. + * + * @return + */ + public static CompositeOption systemBundle(String aGroup, String artifact, String version, File file) { + return new DefaultCompositeOption( + new SystemBundleOption(aGroup, artifact, version, file), + editConfigurationFilePut("etc/startup.properties", + "mvn:" + aGroup + "/" + artifact + "/" + version, "5") + ); + } + + /** + * Returns an option to adding an artifact to the Karaf system directory using the provided file. + * A corresponding (maven) entry will also be placed into the startup.properties configuration. + * + * @return + */ + public static CompositeOption systemBundle(String aGroup, String artifact, String version) { + return new DefaultCompositeOption( + new SystemBundleOption(aGroup, artifact, version), + editConfigurationFilePut("etc/startup.properties", + "mvn:" + aGroup + "/" + artifact + "/" + version, "5") + ); + } + /** * Configures which distribution options to use. Relevant are the frameworkURL, the * frameworkName and the Karaf version since all of those params are relevant to decide which * wrapper configurations to use. - * + * * @param frameworkURL * frameworkURL * @param name @@ -123,7 +153,7 @@ public static KarafDistributionConfigurationSecurityOption configureSecurity() { * @return option */ public static KarafDistributionBaseConfigurationOption karafDistributionConfiguration( - String frameworkURL, String name, String karafVersion) { + String frameworkURL, String name, String karafVersion) { return new KarafDistributionConfigurationOption(frameworkURL, name, karafVersion); } @@ -131,7 +161,7 @@ public static KarafDistributionBaseConfigurationOption karafDistributionConfigur * Configures which distribution options to use. Relevant are the frameworkURL, the * frameworkName and the Karaf version since all of those params are relevant to decide which * wrapper configurations to use. - * + * * @return option */ public static KarafDistributionBaseConfigurationOption karafDistributionConfiguration() { @@ -144,7 +174,7 @@ public static KarafDistributionBaseConfigurationOption karafDistributionConfigur *

* If you like to extend an option (e.g. make a=b to a=b,c) please make use of the * {@link KarafDistributionConfigurationFileExtendOption}. - * + * * @param configurationFilePath * configuration file path * @param key @@ -154,7 +184,7 @@ public static KarafDistributionBaseConfigurationOption karafDistributionConfigur * @return option */ public static Option editConfigurationFilePut(String configurationFilePath, String key, - String value) { + String value) { return new KarafDistributionConfigurationFilePutOption(configurationFilePath, key, value); } @@ -164,7 +194,7 @@ public static Option editConfigurationFilePut(String configurationFilePath, Stri *

* If you like to extend an option (e.g. make a=b to a=b,c) please make use of the * {@link KarafDistributionConfigurationFileExtendOption}. - * + * * @param configurationPointer * reference to configuration file * @param value @@ -172,7 +202,7 @@ public static Option editConfigurationFilePut(String configurationFilePath, Stri * @return option */ public static Option editConfigurationFilePut(ConfigurationPointer configurationPointer, - String value) { + String value) { return new KarafDistributionConfigurationFilePutOption(configurationPointer, value); } @@ -181,7 +211,7 @@ public static Option editConfigurationFilePut(ConfigurationPointer configuration * value is "put" which means it is either replaced or added. For simpler configuration you can * add a file source. If you want to put all values from this file do not configure any * keysToUseFromSource; otherwise define them to use only those specific values. - * + * * @param configurationFilePath * configuration file path * @param source @@ -191,13 +221,13 @@ public static Option editConfigurationFilePut(ConfigurationPointer configuration * @return option array */ public static Option[] editConfigurationFilePut(final String configurationFilePath, - File source, String... keysToUseFromSource) { + File source, String... keysToUseFromSource) { return createOptionListFromFile(source, new FileOptionFactory() { @Override public Option createOption(String key, String value) { return new KarafDistributionConfigurationFilePutOption(configurationFilePath, key, - value); + value); } }, keysToUseFromSource); } @@ -208,15 +238,13 @@ private interface FileOptionFactory { } private static Option[] createOptionListFromFile(File source, FileOptionFactory optionFactory, - String... keysToUseFromSource) { + String... keysToUseFromSource) { Properties props = new Properties(); try { props.load(new FileInputStream(source)); - } - catch (FileNotFoundException e) { + } catch (FileNotFoundException e) { throw new IllegalStateException(e); - } - catch (IOException e) { + } catch (IOException e) { throw new IllegalStateException(e); } List

* If you would like to have add or replace functionality please use the * {@link KarafDistributionConfigurationFilePutOption} instead. - * + * * @param configurationFilePath * configuration file path * @param key @@ -253,7 +280,7 @@ private static Option[] createOptionListFromFile(File source, FileOptionFactory * @return option */ public static Option editConfigurationFileExtend(String configurationFilePath, String key, - String value) { + String value) { return new KarafDistributionConfigurationFileExtendOption(configurationFilePath, key, value); } @@ -264,16 +291,16 @@ public static Option editConfigurationFileExtend(String configurationFilePath, S *

* If you would like to have add or replace functionality please use the * {@link KarafDistributionConfigurationFilePutOption} instead. - * + * * @param configurationPointer * reference to configuration key * @param value * additional configuration value - * + * * @return option */ public static Option editConfigurationFileExtend(ConfigurationPointer configurationPointer, - String value) { + String value) { return new KarafDistributionConfigurationFileExtendOption(configurationPointer, value); } @@ -282,7 +309,7 @@ public static Option editConfigurationFileExtend(ConfigurationPointer configurat * value is "extend" which means it is either replaced or added. For simpler configuration you * can add a file source. If you want to put all values from this file do not configure any * keysToUseFromSource; otherwise define them to use only those specific values. - * + * * @param configurationFilePath * configuration file path * @param source @@ -292,13 +319,13 @@ public static Option editConfigurationFileExtend(ConfigurationPointer configurat * @return option array */ public static Option[] editConfigurationFileExtend(final String configurationFilePath, - File source, String... keysToUseFromSource) { + File source, String... keysToUseFromSource) { return createOptionListFromFile(source, new FileOptionFactory() { @Override public Option createOption(String key, String value) { return new KarafDistributionConfigurationFileExtendOption(configurationFilePath, - key, value); + key, value); } }, keysToUseFromSource); } @@ -307,23 +334,23 @@ public Option createOption(String key, String value) { * This option allows to simply replace an entire configuration file with your own one. Simply * point to the configuration file you would like to have replaced and add the source file which * should replace it. - * + * * @param configurationFilePath * path to configuration file * @param source * configuration file replacement - * + * * @return option */ public static Option replaceConfigurationFile(String configurationFilePath, File source) { return new KarafDistributionConfigurationFileReplacementOption(configurationFilePath, - source); + source); } /** * Activates debugging on the embedded Karaf container using the standard 5005 port and holds * the vm till you've attached the debugger. - * + * * @return option */ public static Option debugConfiguration() { @@ -333,7 +360,7 @@ public static Option debugConfiguration() { /** * A very simple and convinient method to set a specific log level without the need of configure * the specific option itself. - * + * * @param logLevel * log level * @return option @@ -345,7 +372,7 @@ public static Option logLevel(LogLevel logLevel) { /** * A very simple and convinient method to set a specific log level without the need of configure * the specific option itself. - * + * * @return option */ public static LogLevelOption logLevel() { @@ -354,7 +381,7 @@ public static LogLevelOption logLevel() { /** * Returns an easy option to activate and configure remote debugging for the Karaf container. - * + * * @param port * remote debugger port * @param hold @@ -363,17 +390,17 @@ public static LogLevelOption logLevel() { */ public static Option debugConfiguration(String port, boolean hold) { return new VMOption(format("-Xrunjdwp:transport=dt_socket,server=y,suspend=%s,address=%s", - hold ? "y" : "n", port)); + hold ? "y" : "n", port)); } /** * Creates a {@link KarafFeaturesOption}. - * + * * @param repositoryUrl * url of features respository to be scanned * @param features * features to be scanned - * + * * @return features option */ public static KarafFeaturesOption features(final String repositoryUrl, final String... features) { @@ -382,16 +409,16 @@ public static KarafFeaturesOption features(final String repositoryUrl, final Str /** * Creates a {@link KarafFeaturesOption}. - * + * * @param repositoryUrl * url of features respository to be scanned * @param features * features to be scanned - * + * * @return features option */ public static KarafFeaturesOption features(final UrlReference repositoryUrl, - final String... features) { + final String... features) { return new KarafFeaturesOption(repositoryUrl, features); } } diff --git a/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/options/SystemBundleOption.java b/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/options/SystemBundleOption.java new file mode 100644 index 000000000..3a66371f5 --- /dev/null +++ b/containers/pax-exam-container-karaf/src/main/java/org/ops4j/pax/exam/karaf/options/SystemBundleOption.java @@ -0,0 +1,103 @@ +/* + * 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.ops4j.pax.exam.karaf.options; + +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.options.MavenArtifactUrlReference; +import org.ops4j.pax.exam.options.RawUrlReference; +import org.ops4j.pax.exam.options.UrlReference; + +import java.io.File; +import java.net.MalformedURLException; + +/** + * Copies the specified file into the Karaf system folder. (A Karaf folder that follows the m2 directory structure) + */ +public class SystemBundleOption implements Option { + + private String group; + private String artifact; + private String version; + private File file; + + + public SystemBundleOption(String aGroup, String artifact, String version, File file) { + addSystemBundle(aGroup, artifact, version, file); + } + + public SystemBundleOption(String aGroup, String artifact, String version) { + addSystemBundle(aGroup, artifact, version); + } + + public String getGroup() { + return group; + } + + public String getArtifact() { + return artifact; + } + + public String getVersion() { + return version; + } + + public SystemBundleOption addSystemBundle(String aGroup, String artifact, String version) { + return addSystemBundle(aGroup, artifact, version, null); + } + + public SystemBundleOption addSystemBundle(String aGroup, String artifact, String version, File file) { + this.group = aGroup; + this.artifact = artifact; + this.version = version; + this.file = file; + return this; + } + + /** + * + * @return The URL to fetch the artifact + */ + public UrlReference getLibraryUrl() { + if (file != null) { + try { + return new RawUrlReference(file.toURI().toURL().toString()); + } catch (MalformedURLException e) { + e.printStackTrace(); + return null; + } + } else { + return new MavenArtifactUrlReference().groupId(group).artifactId(artifact).version(version); + } + } + + /** + * + * @return The maven repository path to the artifact. Must start with /. + * This path should not include the /system prefix. + */ + public String getRepositoryPath() { + String path = "/" + getGroup().replace(".", "/"); + path += "/" + getArtifact(); + path += "/" + getVersion(); + if (file != null) { + path += "/" + file.getName(); + } else { + path += "/" + getArtifact() + "-" + getVersion() + ".jar"; + } + return path; + } +}