/*
* #%L
* Wisdom-Framework
* %%
* Copyright (C) 2013 - 2014 Wisdom Framework
* %%
* 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.
* #L%
*/
package org.wisdom.test.internals;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.AbstractFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.Properties;
/**
* A couple of methods used by Runners to detect the wisdom runtime and the current application bundle.
* Be aware that these methods make the assumption that the current execution directory if the project's base directory.
*/
public class RunnerUtils {
/**
* Checks if a file having somewhat the current tested application name is contained in the given directory. This
* method follows the default maven semantic. The final file is expected to have a name compliant with the
* following rules: <code>artifactId-version.jar</code>. If the version ends with <code>-SNAPSHOT</code>,
* it just checks for <code>artifactId-stripped_version</code>, where stripped version is the version without the
* <code>SNAPSHOT</code> part.
* <p>
* The artifactId and version are read from the <code>target/osgi/osgi.properties</code> file,
* that should have been written by the Wisdom build process.
*
* @param directory the directory
* @return the bundle file if found
* @throws java.io.IOException if something bad happens.
*/
public static File detectApplicationBundleIfExist(File directory) throws IOException {
Properties properties = getMavenProperties();
if (properties == null || directory == null || !directory.isDirectory()) {
return null;
}
final String artifactId = properties.getProperty("project.artifactId");
final String groupId = properties.getProperty("project.groupId");
final String bsn = getBundleSymbolicName(groupId, artifactId);
String version = properties.getProperty("project.version");
final String strippedVersion;
if (version.endsWith("-SNAPSHOT")) {
strippedVersion = version.substring(0, version.length() - "-SNAPSHOT".length());
} else {
strippedVersion = version;
}
Iterator<File> files = FileUtils.iterateFiles(directory, new AbstractFileFilter() {
@Override
public boolean accept(File file) {
return file.isFile()
&& file.getName().startsWith(bsn + "-" + strippedVersion)
&& file.getName().endsWith(".jar");
}
}, TrueFileFilter.INSTANCE);
if (files.hasNext()) {
return files.next();
}
return null;
}
/**
* Gets the (Maven) artifact's file if exists.
*
* @param chameleonRoot the root of the chameleon
* @return the artifact's file (the jar file) if it exists, {@code null} otherwise.
* @throws IOException if the Maven properties cannot be read.
*/
public static File getApplicationArtifactIfExists(File chameleonRoot) throws IOException {
Properties properties = getMavenProperties();
if (properties == null || chameleonRoot == null || !chameleonRoot.isDirectory()) {
return null;
}
final String artifactId = properties.getProperty("project.artifactId");
String version = properties.getProperty("project.version");
File artifact = new File(chameleonRoot.getParentFile(), artifactId + "-" + version + ".jar");
if (artifact.isFile()) {
return artifact;
}
return null;
}
/**
* We should have generated a target/osgi/osgi.properties file will all the metadata we inherit from Maven.
*
* @return the properties read from the file.
*/
public static Properties getMavenProperties() throws IOException {
File osgi = new File("target/osgi/osgi.properties");
if (osgi.isFile()) {
FileInputStream fis = null;
try {
Properties read = new Properties();
fis = new FileInputStream(osgi);
read.load(fis);
return read;
} finally {
IOUtils.closeQuietly(fis);
}
}
return null;
}
/**
* Checks whether the Wisdom server was correctly unpacked. If so, return the base directory.
*
* @return the Wisdom base directory if there, {@literal null} otherwise.
*/
public static File checkWisdomInstallation() {
File directory = new File("target/wisdom");
if (!directory.isDirectory()) {
throw new ExceptionInInitializerError("Wisdom is not installed in " + directory.getAbsolutePath() + " - " +
"please check your execution directory, and that Wisdom is prepared correctly. To setup Wisdom, " +
"run 'mvn pre-integration-test' from your application directory");
}
File conf = new File(directory, "conf/application.conf");
if (!conf.isFile()) {
throw new ExceptionInInitializerError("Wisdom is not correctly installed in " + directory.getAbsolutePath()
+ " - the configuration file does not exist. Please check your Wisdom runtime. To setup Wisdom, " +
"run 'mvn clean pre-integration-test' from your application directory");
}
return directory;
}
/**
* Computes the bundle file name for the current project.
*
* @return the name of the bundle.
* @throws IOException if Maven properties cannot be read
*/
public static String getBundleFileName() throws IOException {
Properties properties = getMavenProperties();
if (properties == null) {
throw new IllegalStateException("Cannot read the Maven properties");
}
final String artifactId = properties.getProperty("project.artifactId");
final String groupId = properties.getProperty("project.groupId");
final String bsn = getBundleSymbolicName(groupId, artifactId);
String version = properties.getProperty("project.version");
return bsn + "-" + version + ".jar";
}
/**
* Get the symbolic name as groupId + "." + artifactId, with the following exceptions. Unlike the original method
* from the Maven Bundle Plugin, this method does not use the bundle inspection,
* as the artifact's file does not exist when this method is called.
* <ul>
* <li>if artifactId is equal to last section of groupId then groupId is returned. eg.
* org.apache.maven:maven -> org.apache.maven</li>
* <li>if artifactId starts with last section of groupId that portion is removed. eg.
* org.apache.maven:maven-core -> org.apache.maven.core</li>
* <li>if artifactId starts with groupId then the artifactId is removed. eg.
* org.apache:org.apache.maven.core -> org.apache.maven.core</li>
* </ul>
*
* @param groupId the groupId
* @param artifactId the artifactId
* @return the symbolic name for the given artifact coordinates
*/
public static String getBundleSymbolicName(String groupId, String artifactId) {
int i = groupId.lastIndexOf('.');
String lastSection = groupId.substring(++i);
if (artifactId.equals(lastSection)) {
return groupId;
}
if (artifactId.equals(groupId)
|| artifactId.startsWith(groupId + ".")) {
return artifactId;
}
if (artifactId.startsWith(lastSection)) {
artifactId = artifactId.substring(lastSection.length());
if (!Character.isLetterOrDigit(artifactId.charAt(0))) {
return (groupId + "." + artifactId.substring(1)).replace("-", ".");
}
// Else fall to the default case.
}
return (groupId + "." + artifactId).replace("-", ".");
}
}