/*
* JBoss, Home of Professional Open Source
* Copyright 2014, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.
*/
package org.jboss.shrinkwrap.impl.gradle.archive.importer.embedded;
import java.io.File;
import java.io.FilenameFilter;
import java.net.URI;
import org.gradle.tooling.BuildLauncher;
import org.gradle.tooling.GradleConnector;
import org.gradle.tooling.ProjectConnection;
import org.gradle.tooling.model.DomainObjectSet;
import org.gradle.tooling.model.GradleProject;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.Assignable;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.gradle.archive.importer.embedded.ConfigurationStage;
import org.jboss.shrinkwrap.api.gradle.archive.importer.embedded.DistributionConfigurationStage;
import org.jboss.shrinkwrap.api.gradle.archive.importer.embedded.EmbeddedGradleImporter;
import org.jboss.shrinkwrap.api.importer.ZipImporter;
import org.jboss.shrinkwrap.impl.base.Validate;
/**
* @author <a href="mailto:mmatloka@gmail.com">Michal Matloka</a>
*/
public class EmbeddedGradleImporterImpl implements EmbeddedGradleImporter, DistributionConfigurationStage {
private static final String SAX_PARSER_FACTORY_KEY = "javax.xml.parsers.SAXParserFactory";
private final Archive<?> archive;
private final GradleConnector connector = GradleConnector.newConnector();
private String[] tasks = new String[] { "build" };
private String[] arguments = new String[] { "--exclude-task", "test" };
private BuildLauncher buildLauncher;
private ProjectConnection projectConnection;
private String projectName;
private File buildResult;
private BuildLauncher getBuildLauncher() {
if (buildLauncher == null) {
projectConnection = connector.connect();
buildLauncher = projectConnection.newBuild();
}
return buildLauncher;
}
public EmbeddedGradleImporterImpl(Archive<?> archive) {
this.archive = archive;
}
@Override
public DistributionConfigurationStage forProjectDirectory(final File projectDir) {
Validate.notNull(projectDir, "Project directory file can not be null!");
final File absoluteFile = projectDir.getAbsoluteFile();
if (!absoluteFile.exists()) {
throw new IllegalArgumentException("Given project dir do not exist: " + absoluteFile);
} else if (!absoluteFile.isDirectory()) {
throw new IllegalArgumentException("Given project dir is not a directory" + absoluteFile);
}
projectName = absoluteFile.getName();
connector.forProjectDirectory(absoluteFile);
return this;
}
@Override
public DistributionConfigurationStage forProjectDirectory(final String projectDir) {
Validate.notNull(projectDir, "Project directory path can not be null or empty");
return this.forProjectDirectory(new File(projectDir));
}
@Override
public DistributionConfigurationStage forThisProjectDirectory() {
return forProjectDirectory("");
}
@Override
public <TYPE extends Assignable> TYPE as(final Class<TYPE> clazz) {
final File result;
if (buildResult == null) {
result = importFromDefaultLibsDirectory();
} else {
result = importFromConfiguredPath();
}
return ShrinkWrap.create(ZipImporter.class, archive.getName()).importFrom(result).as(clazz);
}
private File importFromDefaultLibsDirectory() {
final GradleProject currentGradleProject = findCurrentGradleProject();
final File buildDir = currentGradleProject.getBuildDirectory();
final File libsDir = new File(buildDir, "libs");
final File[] results = libsDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(final File dir, final String name) {
return name.startsWith(currentGradleProject.getName());
}
});
if (results == null || results.length == 0) {
throw new IllegalArgumentException(
"Wrong project directory is used. Tests have to be run from working directory which is a current sub-module directory.");
}
return results[0];
}
private File importFromConfiguredPath() {
return buildResult;
}
private GradleProject findCurrentGradleProject() {
final GradleProject rootGradleProject = projectConnection.getModel(GradleProject.class);
if (!rootGradleProject.getName().equals(projectName)) {
final GradleProject child = findChildProject(rootGradleProject, projectName);
if (child != null) {
return child;
}
}
return rootGradleProject;
}
private GradleProject findChildProject(GradleProject gradleProject, String childProjectName) {
final DomainObjectSet<? extends GradleProject> children = gradleProject.getChildren();
for (GradleProject child : children) {
if (child.getName().equals(childProjectName)) {
return child;
}
}
for (GradleProject child : children) {
final GradleProject foundChild = findChildProject(child, childProjectName);
if (foundChild != null) {
return foundChild;
}
}
return null;
}
@Override
public ConfigurationStage useGradleVersion(final String version) {
connector.useGradleVersion(version);
return this;
}
@Override
public ConfigurationStage useDistribution(final URI gradleDistribution) {
connector.useDistribution(gradleDistribution);
return this;
}
@Override
public ConfigurationStage useInstallation(final File gradleHome) {
connector.useInstallation(gradleHome);
return this;
}
@Override
public ConfigurationStage useDefaultDistribution() {
return this;
}
@Override
public ConfigurationStage useGradleUserHomeDir(final File gradleUserHomeDir) {
connector.useGradleUserHomeDir(gradleUserHomeDir);
return this;
}
@Override
public ConfigurationStage forTasks(final String... tasks) {
this.tasks = tasks;
return this;
}
@Override
public ConfigurationStage withArguments(final String... arguments) {
this.arguments = arguments;
return this;
}
@Override
public ConfigurationStage setJavaHome(final File javaHome) {
getBuildLauncher().setJavaHome(javaHome);
return this;
}
@Override
public ConfigurationStage setJvmArguments(final String... jvmArguments) {
getBuildLauncher().setJvmArguments(jvmArguments);
return this;
}
@Override
public Assignable importBuildOutput() {
final String oldValue = removeSAXParserFactoryProperty();
getBuildLauncher().forTasks(tasks).withArguments(arguments).run();
setSAXParserFactoryProperty(oldValue);
return this;
}
@Override
public Assignable importBuildOutput(File buildResult) {
this.buildResult = buildResult.getAbsoluteFile();
return importBuildOutput();
}
@Override
public Assignable importBuildOutput(String buildResult) {
return importBuildOutput(new File(buildResult));
}
private String removeSAXParserFactoryProperty() {
// solution for https://issues.jboss.org/browse/SHRINKRES-212
final Object value = System.getProperties().remove(SAX_PARSER_FACTORY_KEY);
return value != null ? (String) value : null;
}
private void setSAXParserFactoryProperty(String oldValue) {
if (oldValue != null) {
System.setProperty(SAX_PARSER_FACTORY_KEY, oldValue);
}
}
}