gradle plugin supports, build, native, dev

This commit is contained in:
Ståle Pedersen
2019-02-06 02:56:08 +01:00
parent 62b3b258b3
commit 2fa569b35d
22 changed files with 2130 additions and 0 deletions

2
.gitignore vendored
View File

@@ -26,6 +26,8 @@ graph-output.dot
*.swp
*.swo
ObjectStore
.gradle
build
docker/distroless/bazel-*

View File

@@ -0,0 +1,44 @@
plugins {
id 'java'
}
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile localGroovy()
compile gradleApi()
compile fileTree(dir: 'target/dependencies/compile', include: '*.jar')
testCompile gradleTestKit()
testCompile fileTree(dir: 'target/dependencies/test', include: '*.jar')
}
jar {
manifest {
attributes 'Implementation-Version': (version ? version : 'unknown')
}
}
test {
testLogging {
events "passed", "skipped", "failed"
}
}
task sourcesJar(type: Jar) {
classifier = 'sources'
from sourceSets.main.allSource
}
task javadocJar(type: Jar) {
classifier = "javadoc"
from javadoc
}
artifacts {
archives sourcesJar
archives javadocJar
}

View File

@@ -0,0 +1 @@
projectName = quarkus-gradle-plugin

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

172
devtools/gradle/gradlew vendored Executable file
View File

@@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
devtools/gradle/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

215
devtools/gradle/pom.xml Normal file
View File

@@ -0,0 +1,215 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-build-parent</artifactId>
<version>1.0.0.Alpha1-SNAPSHOT</version>
<relativePath>../../build-parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>quarkus-gradle-plugin</artifactId>
<packaging>pom</packaging>
<name>Quarkus - Gradle Plugin</name>
<description>Quarkus - Gradle Plugin</description>
<properties>
<gradle.executable>./gradlew</gradle.executable>
<gradle.task>build</gradle.task>
<skip.gradle.build>false</skip.gradle.build>
</properties>
<dependencies>
<!-- Compile -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-devtools-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-devtools-common-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-development-mode</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-creator</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-compile-dependencies</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<inherited>false</inherited>
<configuration>
<includeScope>compile</includeScope>
<outputDirectory>${project.build.directory}/dependencies/compile</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-test-dependencies</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<inherited>false</inherited>
<configuration>
<includeScope>test</includeScope>
<outputDirectory>${project.build.directory}/dependencies/test</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>gradle</id>
<phase>prepare-package</phase>
<configuration>
<executable>${gradle.executable}</executable>
<arguments>
<argument>clean</argument>
<argument>${gradle.task}</argument>
<argument>-Pversion=${project.version}</argument>
<argument>-Pdescription=${project.description}</argument>
<argument>-S</argument>
</arguments>
<skip>${skip.gradle.build}</skip>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>attach-artifacts</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>build/libs/${project.artifactId}-${project.version}.jar</file>
<type>jar</type>
</artifact>
<artifact>
<file>build/libs/${project.artifactId}-${project.version}-javadoc.jar</file>
<type>jar</type>
<classifier>javadoc</classifier>
</artifact>
<artifact>
<file>build/libs/${project.artifactId}-${project.version}-sources.jar</file>
<type>jar</type>
<classifier>sources</classifier>
</artifact>
</artifacts>
<skipAttach>${skip.gradle.build}</skipAttach>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>windows</id>
<activation>
<os>
<family>windows</family>
</os>
</activation>
<properties>
<gradle.executable>gradlew.bat</gradle.executable>
</properties>
</profile>
<profile>
<id>skipTests</id>
<activation>
<property>
<name>skipTests</name>
<value>true</value>
</property>
</activation>
<properties>
<gradle.task>assemble</gradle.task>
</properties>
</profile>
<profile>
<id>full</id>
<activation>
<property>
<name>full</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>attach-zip</id>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>${project.build.directory}/${project.artifactId}-${project.version}-docs.zip</file>
<type>zip</type>
<classifier>docs</classifier>
</artifact>
</artifacts>
<skipAttach>${skip.gradle.build}</skipAttach>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>java8</id>
<activation>
<jdk>[8,)</jdk>
</activation>
<properties>
<skip.gradle.build>true</skip.gradle.build>
</properties>
</profile>
</profiles>
</project>

View File

@@ -0,0 +1 @@
rootProject.name = projectName

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2019 Red Hat, Inc.
*
* 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 io.quarkus.gradle;
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.util.GradleVersion;
import io.quarkus.gradle.tasks.QuarkusAddExtension;
import io.quarkus.gradle.tasks.QuarkusBuild;
import io.quarkus.gradle.tasks.QuarkusDev;
import io.quarkus.gradle.tasks.QuarkusListExtensions;
import io.quarkus.gradle.tasks.QuarkusNative;
/**
* @author <a href="mailto:stalep@gmail.com">Ståle Pedersen</a>
*/
public class QuarkusPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
verifyGradleVersion();
//register extension
project.getExtensions().create("quarkus", QuarkusPluginExtension.class, project);
registerListExtensions(project);
}
private void registerListExtensions(Project project) {
project.getTasks().create("list-extensions", QuarkusListExtensions.class);
project.getTasks().create("add-extension", QuarkusAddExtension.class);
project.getTasks().create("quarkus-dev", QuarkusDev.class).dependsOn("build");
project.getTasks().create("quarkus-build", QuarkusBuild.class).dependsOn("build");
project.getTasks()
.create("quarkus-native", QuarkusNative.class)
.dependsOn("quarkus-build");
}
private void verifyGradleVersion() {
if (GradleVersion.current().compareTo(GradleVersion.version("5.0")) < 0) {
throw new GradleException("Quarkus plugin requires Gradle 5.0 or later. Current version is: " +
GradleVersion.current());
}
}
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright 2019 Red Hat, Inc.
*
* 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 io.quarkus.gradle;
import java.io.File;
import java.util.Set;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
/**
* @author <a href="mailto:stalep@gmail.com">Ståle Pedersen</a>
*/
public class QuarkusPluginExtension {
private final Project project;
private File buildDir;
private String transformedClassesDirectory = "transformed-classes";
private String wiringClassesDirectory = "wiring-classes";
private String libDir = "lib";
private String outputDirectory;
private String finalName;
private String sourceDir;
public QuarkusPluginExtension(Project project) {
this.project = project;
}
public File buildDir() {
if (buildDir == null)
return project.getBuildDir();
else
return buildDir;
}
public void setBuildDir(File buildDir) {
this.buildDir = buildDir;
}
public File transformedClassesDirectory() {
return new File(project.getBuildDir() + File.separator + transformedClassesDirectory);
}
public void setTransformedClassesDirectory(String transformedClassesDirectory) {
this.transformedClassesDirectory = transformedClassesDirectory;
}
public File outputDirectory() {
if (outputDirectory == null)
outputDirectory = project.getConvention().getPlugin(JavaPluginConvention.class)
.getSourceSets().getByName("main").getOutput().getClassesDirs().getAsPath();
return new File(outputDirectory);
}
public void setOutputDirectory(String outputDirectory) {
this.outputDirectory = outputDirectory;
}
public File sourceDir() {
if (sourceDir == null)
sourceDir = project.getConvention().getPlugin(JavaPluginConvention.class)
.getSourceSets().getByName("main").getAllJava().getSourceDirectories().getAsPath();
return new File(sourceDir);
}
public void setSourceDir(String sourceDir) {
this.sourceDir = sourceDir;
}
public File wiringClassesDirectory() {
return new File(project.getBuildDir() + File.separator + wiringClassesDirectory);
}
public void setWiringClassesDirectory(String wiringClassesDirectory) {
this.wiringClassesDirectory = wiringClassesDirectory;
}
public File libDir() {
return new File(project.getBuildDir() + File.separator + libDir);
}
public void setLibDir(String libDir) {
this.libDir = libDir;
}
public String finalName() {
if (finalName == null || finalName.length() == 0)
return project.getName();
else
return finalName;
}
public void setFinalName(String finalName) {
this.finalName = finalName;
}
public String groupId() {
return project.getGroup().toString();
}
public String artifactId() {
return project.getName();
}
public String version() {
return project.getVersion().toString();
}
public boolean uberJar() {
return false;
}
public Set<File> resourcesDir() {
return project.getConvention().getPlugin(JavaPluginConvention.class)
.getSourceSets().getByName("main").getResources().getSrcDirs();
}
public Set<File> dependencyFiles() {
SourceSet sourceSet = project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().getByName("main");
return sourceSet.getCompileClasspath().getFiles();
}
}

View File

@@ -0,0 +1,185 @@
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* 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 io.quarkus.gradle;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.result.DependencyResult;
import org.gradle.api.artifacts.result.ResolutionResult;
import org.gradle.api.artifacts.result.ResolvedComponentResult;
import org.gradle.api.artifacts.result.ResolvedDependencyResult;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import io.quarkus.creator.AppArtifact;
import io.quarkus.creator.AppArtifactResolverBase;
import io.quarkus.creator.AppCreatorException;
import io.quarkus.creator.AppDependency;
/**
* @author <a href="mailto:stalep@gmail.com">Ståle Pedersen</a>
*/
public class ResolvedGradleArtifactDeps extends AppArtifactResolverBase {
private final String groupId;
private final String artifactId;
private final String classifier;
private final String type;
private final String version;
private final List<AppDependency> deps;
private List<File> dependencyFiles;
private File projectFile;
public ResolvedGradleArtifactDeps(Project project) {
groupId = project.getGroup().toString();
artifactId = project.getName();
//not sure what we should set here
classifier = "";
//TODO: set this to jar for now
type = "jar";
version = project.getVersion().toString();
deps = Collections.unmodifiableList(extractDependencies(project));
}
private List<AppDependency> extractDependencies(Project project) {
List<AppDependency> dependencies = new ArrayList<>();
Configuration configuration = project.getConfigurations().getByName("compileOnly");
ResolutionResult resolutionResult = configuration.getIncoming().getResolutionResult();
ResolvedComponentResult root = resolutionResult.getRoot();
//TODO: Ideally the dependencyFiles should be added to the AppArtifacts while traversing the dependencies
// - atm this is the only way to fetch the dependency files
dependencyFiles = new ArrayList<>();
SourceSet sourceSet = project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().getByName("main");
sourceSet.getCompileClasspath().forEach(dependencyFiles::add);
//dirty hack to add the project target
projectFile = new File(project.getBuildDir().getAbsolutePath() + File.separator +
"libs" + File.separator +
artifactId + "-" + version + ".jar");
traverseDependencies(root.getDependencies(), dependencies);
return dependencies;
}
private void traverseDependencies(Set<? extends DependencyResult> dependencies, List<AppDependency> appDependencies) {
dependencies.forEach(dependency -> {
if (dependency instanceof ResolvedDependencyResult) {
ResolvedComponentResult result = ((ResolvedDependencyResult) dependency).getSelected();
appDependencies.add(new AppDependency(toAppArtifact(result), "provided"));
traverseDependencies(result.getDependencies(), appDependencies);
}
});
}
@Override
public void relink(AppArtifact artifact, Path path) throws AppCreatorException {
throw new UnsupportedOperationException();
}
@Override
protected void doResolve(AppArtifact coords) throws AppCreatorException {
if (coords.getGroupId().equals(groupId) && coords.getArtifactId().equals(artifactId)) {
setPath(coords, projectFile.toPath());
} else {
File dep = findMatchingDependencyFile(coords.getGroupId(), coords.getArtifactId());
if (dep != null)
setPath(coords, dep.toPath());
else
throw new AppCreatorException("Did not find dependency file for: " + coords.toString());
}
}
private AppArtifact toAppArtifact(ResolvedComponentResult result) {
AppArtifact appArtifacat = new AppArtifact(result.getModuleVersion().getGroup(),
result.getModuleVersion().getName(), result.getModuleVersion().getVersion());
File dep = findMatchingDependencyFile(appArtifacat.getGroupId(), appArtifacat.getArtifactId());
if (dep != null) {
setPath(appArtifacat, dep.toPath());
}
return appArtifacat;
}
private File findMatchingDependencyFile(String group, String artifact) {
String searchCriteria1 = group + File.separator + artifact;
String searchCriteria2 = group.replace('.', File.separatorChar) + File.separator + artifact;
for (File file : dependencyFiles) {
if (file.getPath().contains(searchCriteria1) || file.getPath().contains(searchCriteria2))
return file;
}
return null;
}
@Override
public List<AppDependency> collectDependencies(AppArtifact coords) throws AppCreatorException {
if (!coords.getGroupId().equals(groupId) ||
!coords.getArtifactId().equals(artifactId) ||
!coords.getClassifier().equals(classifier) ||
!coords.getType().equals(type) ||
!coords.getVersion().equals(version)) {
throw new AppCreatorException("The resolve can only resolve dependencies for " + groupId + ':' + artifactId + ':'
+ classifier + ':' + type + ':' + version + ": " + coords);
}
return deps;
}
@Override
public List<AppDependency> collectDependencies(AppArtifact root, List<AppDependency> deps) throws AppCreatorException {
throw new UnsupportedOperationException();
}
@Override
public List<String> listLaterVersions(AppArtifact artifact, String upToVersion, boolean inclusive)
throws AppCreatorException {
throw new UnsupportedOperationException();
}
@Override
public String getNextVersion(AppArtifact artifact, String upToVersion, boolean inclusive) throws AppCreatorException {
throw new UnsupportedOperationException();
}
@Override
public String getLatestVersion(AppArtifact artifact, String upToVersion, boolean inclusive) throws AppCreatorException {
throw new UnsupportedOperationException();
}
@Override
public String toString() {
return "ResolvedGradleArtifactDeps{" +
"groupId='" + groupId + '\n' +
", artifactId='" + artifactId + '\n' +
", classifier='" + classifier + '\n' +
", type='" + type + '\n' +
", version='" + version + '\n' +
", deps=" + deps +
", dependencyFiles=" + dependencyFiles +
", projectFile=" + projectFile +
'}';
}
}

View File

@@ -0,0 +1,198 @@
package io.quarkus.gradle.tasks;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.Map;
import java.util.function.Supplier;
import org.jboss.logging.Logger;
import org.jboss.logging.LoggerProvider;
import org.wildfly.common.Assert;
/**
* @author <a href="mailto:stalep@gmail.com">Ståle Pedersen</a>
*/
public class GradleLogger implements LoggerProvider {
static final Object[] NO_PARAMS = new Object[0];
public static volatile Supplier<org.gradle.api.logging.Logger> logSupplier;
@Override
public Logger getLogger(final String name) {
return new Logger(name) {
@Override
protected void doLog(final Level level, final String loggerClassName, final Object message,
final Object[] parameters, final Throwable thrown) {
final Supplier<org.gradle.api.logging.Logger> logSupplier = GradleLogger.logSupplier;
if (logSupplier != null) {
org.gradle.api.logging.Logger log = logSupplier.get();
String text;
if (parameters == null || parameters.length == 0) {
text = String.valueOf(message);
} else
try {
text = MessageFormat.format(String.valueOf(message), parameters);
} catch (Exception e) {
text = invalidFormat(String.valueOf(message), parameters);
}
doActualLog(log, level, text, thrown);
}
}
@Override
protected void doLogf(final Level level, final String loggerClassName, final String format,
final Object[] parameters, final Throwable thrown) {
final Supplier<org.gradle.api.logging.Logger> logSupplier = GradleLogger.logSupplier;
if (logSupplier != null) {
org.gradle.api.logging.Logger log = logSupplier.get();
String text;
if (parameters == null)
try {
//noinspection RedundantStringFormatCall
text = String.format(format);
} catch (Exception e) {
text = invalidFormat(format, NO_PARAMS);
}
else
try {
text = String.format(format, (Object[]) parameters);
} catch (Exception e) {
text = invalidFormat(format, parameters);
}
doActualLog(log, level, text, thrown);
}
}
@Override
public boolean isEnabled(final Level level) {
final Supplier<org.gradle.api.logging.Logger> logSupplier = GradleLogger.logSupplier;
if (logSupplier == null)
return false;
org.gradle.api.logging.Logger log = logSupplier.get();
switch (level) {
case FATAL:
case ERROR:
return log.isErrorEnabled();
case WARN:
return log.isWarnEnabled();
case INFO:
return log.isInfoEnabled();
default:
return log.isDebugEnabled();
}
}
void doActualLog(final org.gradle.api.logging.Logger log, final Level level, final String message,
final Throwable thrown) {
//TODO: will fix this in the upcoming version of æsh
// style options are limited unless we crack into jansi ourselves
//buffer.strong("[").project(name).strong("]").a(" ").a(message);
StringBuilder buffer = new StringBuilder();
buffer.append("[").append(name).append("]").append(" ").append(message);
if (thrown != null) {
switch (level) {
case FATAL:
case ERROR:
log.error(buffer.toString(), thrown);
break;
case WARN:
log.warn(buffer.toString(), thrown);
break;
case INFO:
log.info(buffer.toString(), thrown);
break;
default:
log.debug(buffer.toString(), thrown);
break;
}
} else {
switch (level) {
case FATAL:
case ERROR:
log.error(buffer.toString());
break;
case WARN:
log.warn(buffer.toString());
break;
case INFO:
log.info(buffer.toString());
break;
default:
log.debug(buffer.toString());
break;
}
}
}
};
}
String invalidFormat(final String format, final Object[] parameters) {
final StringBuilder b = new StringBuilder("** invalid format \'" + format + "\'");
if (parameters != null && parameters.length > 0) {
b.append(" [").append(parameters[0]);
for (int i = 1; i < parameters.length; i++) {
b.append(',').append(parameters[i]);
}
b.append("]");
}
return b.toString();
}
@Override
public void clearMdc() {
}
@Override
public Object putMdc(final String key, final Object value) {
//throw Assert.unsupported();
return null;
}
@Override
public Object getMdc(final String key) {
return null;
}
@Override
public void removeMdc(final String key) {
}
@Override
public Map<String, Object> getMdcMap() {
return Collections.emptyMap();
}
@Override
public void clearNdc() {
}
@Override
public String getNdc() {
return "";
}
@Override
public int getNdcDepth() {
return 0;
}
@Override
public String popNdc() {
return "";
}
@Override
public String peekNdc() {
return "";
}
@Override
public void pushNdc(final String message) {
throw Assert.unsupported();
}
@Override
public void setNdcMaxDepth(final int maxDepth) {
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2019 Red Hat, Inc.
*
* 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 io.quarkus.gradle.tasks;
import org.gradle.api.tasks.TaskAction;
/**
* @author <a href="mailto:stalep@gmail.com">Ståle Pedersen</a>
*/
public class QuarkusAddExtension extends QuarkusTask {
public QuarkusAddExtension() {
super("Adds one of the available quarkus extensions to the current project");
}
@TaskAction
public void addExtension() {
getLogger().lifecycle("Adding extension is not implemented yet");
}
}

View File

@@ -0,0 +1,182 @@
/*
* Copyright 2019 Red Hat, Inc.
*
* 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 io.quarkus.gradle.tasks;
import java.io.File;
import java.util.List;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.options.Option;
import io.quarkus.creator.AppArtifact;
import io.quarkus.creator.AppCreator;
import io.quarkus.creator.AppCreatorException;
import io.quarkus.creator.AppDependency;
import io.quarkus.creator.phase.augment.AugmentPhase;
import io.quarkus.creator.phase.curate.CurateOutcome;
import io.quarkus.creator.phase.runnerjar.RunnerJarOutcome;
import io.quarkus.creator.phase.runnerjar.RunnerJarPhase;
import io.quarkus.gradle.ResolvedGradleArtifactDeps;
/**
* @author <a href="mailto:stalep@gmail.com">Ståle Pedersen</a>
*/
public class QuarkusBuild extends QuarkusTask {
private String transformedClassesDirectory;
private String wiringClassesDirectory;
private String buildDir;
private String libDir;
private String mainClass = "io.quarkus.runner.GeneratedMain";
private boolean useStaticInit = true;
private boolean uberJar = false;
public QuarkusBuild() {
super("Quarkus builds a runner jar based on the build jar");
}
public File getTransformedClassesDirectory() {
if (transformedClassesDirectory == null)
return extension().transformedClassesDirectory();
else
return new File(transformedClassesDirectory);
}
@Option(description = "The directory for application classes transformed by processing.", option = "transformed-classes-directory")
@Optional
public void setTransformedClassesDirectory(String transformedClassesDirectory) {
this.transformedClassesDirectory = transformedClassesDirectory;
}
public File getWiringClassesDirectory() {
if (wiringClassesDirectory == null)
return extension().wiringClassesDirectory();
else
return new File(wiringClassesDirectory);
}
@Option(description = "The directory for classes generated by processing", option = "wiring-classes-directory")
@Optional
public void setWiringClassesDirectory(String wiringClassesDirectory) {
this.wiringClassesDirectory = wiringClassesDirectory;
}
public File getBuildDir() {
if (buildDir == null)
return extension().buildDir();
else
return new File(buildDir);
}
@Option(description = "The directory where built classes are stored", option = "build-dir")
@Optional
public void setBuildDir(String buildDir) {
this.buildDir = buildDir;
}
public File getLibDir() {
if (libDir == null)
return extension().libDir();
else
return new File(libDir);
}
@Option(description = "The directory for library jars", option = "lib-dir")
@Optional
public void setLibDir(String libDir) {
this.libDir = libDir;
}
public String getMainClass() {
return mainClass;
}
@Option(description = "Name of the main class generated by the quarkus build process", option = "main-class")
@Optional
public void setMainClass(String mainClass) {
this.mainClass = mainClass;
}
public boolean isUseStaticInit() {
return useStaticInit;
}
@Option(description = "", option = "use-static-init")
@Optional
public void setUseStaticInit(boolean useStaticInit) {
this.useStaticInit = useStaticInit;
}
public boolean isUberJar() {
return uberJar;
}
@Option(description = "Set to true if the build task should build an uberjar", option = "uber-jar")
@Optional
public void setUberJar(boolean uberJar) {
this.uberJar = uberJar;
}
@TaskAction
public void buildQuarkus() {
getLogger().lifecycle("building quarkus runner");
try (AppCreator appCreator = AppCreator.builder()
// configure the build phases we want the app to go through
.addPhase(new AugmentPhase()
.setAppClassesDir(extension().outputDirectory().toPath())
.setTransformedClassesDir(getTransformedClassesDirectory().toPath())
.setWiringClassesDir(getWiringClassesDirectory().toPath()))
.addPhase(new RunnerJarPhase()
.setLibDir(getLibDir().toPath())
.setFinalName(extension().finalName())
.setMainClass(getMainClass())
.setUberJar(isUberJar()))
.setWorkDir(extension().buildDir().toPath())
.build()) {
final AppArtifact appArtifact = new AppArtifact(extension().groupId(), extension().artifactId(),
extension().version());
try {
ResolvedGradleArtifactDeps resolvedGradleArtifactDeps = new ResolvedGradleArtifactDeps(getProject());
final List<AppDependency> appDeps = resolvedGradleArtifactDeps.collectDependencies(appArtifact);
// push resolved application state
appCreator.pushOutcome(CurateOutcome.builder()
.setAppArtifact(appArtifact)
.setArtifactResolver(resolvedGradleArtifactDeps)
.setInitialDeps(appDeps)
.build());
// resolve the outcome we need here
appCreator.resolveOutcome(RunnerJarOutcome.class);
} catch (AppCreatorException e) {
e.printStackTrace();
}
} catch (AppCreatorException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,308 @@
/*
* Copyright 2019 Red Hat, Inc.
*
* 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 io.quarkus.gradle.tasks;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.gradle.api.GradleException;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.options.Option;
import io.quarkus.dev.ClassLoaderCompiler;
import io.quarkus.dev.DevModeMain;
import io.quarkus.gradle.QuarkusPluginExtension;
/**
* @author <a href="mailto:stalep@gmail.com">Ståle Pedersen</a>
*/
public class QuarkusDev extends QuarkusTask {
private String debug;
private String buildDir;
private String sourceDir;
private String jvmArgs;
private boolean preventnoverify = false;
private static final String RESOURCES_PROP = "quarkus.undertow.resources";
public QuarkusDev() {
super("Creates a native image");
}
public String getDebug() {
return debug;
}
@Option(description = "If this server should be started in debug mode. " +
"The default is to start in debug mode without suspending and listen on port 5005." +
" It supports the following options:\n" +
" \"false\" - The JVM is not started in debug mode\n" +
" \"true\" - The JVM is started in debug mode and suspends until a debugger is attached to port 5005\n" +
" \"client\" - The JVM is started in client mode, and attempts to connect to localhost:5005\n" +
"\"{port}\" - The JVM is started in debug mode and suspends until a debugger is attached to {port}", option = "debug")
@Optional
public void setDebug(String debug) {
this.debug = debug;
}
public File getBuildDir() {
if (buildDir == null)
return extension().buildDir();
else
return new File(buildDir);
}
@Option(description = "Set build directory", option = "build-dir")
@Optional
public void setBuildDir(String buildDir) {
this.buildDir = buildDir;
}
public File getSourceDir() {
if (sourceDir == null)
return extension().sourceDir();
else
return new File(sourceDir);
}
@Option(description = "Set source directory", option = "source-dir")
@Optional
public void setSourceDir(String sourceDir) {
this.sourceDir = sourceDir;
}
public String getJvmArgs() {
return jvmArgs;
}
@Option(description = "Set debug", option = "jvm-args")
@Optional
public void setJvmArgs(String jvmArgs) {
this.jvmArgs = jvmArgs;
}
public boolean isPreventnoverify() {
return preventnoverify;
}
@Option(description = "value is intended to be set to true when some generated bytecode is" +
" erroneous causing the JVM to crash when the verify:none option is set " +
"(which is on by default)", option = "prevent-noverify")
@Optional
public void setPreventnoverify(boolean preventnoverify) {
this.preventnoverify = preventnoverify;
}
@TaskAction
public void startDev() {
QuarkusPluginExtension extension = (QuarkusPluginExtension) getProject().getExtensions().findByName("quarkus");
if (!getSourceDir().isDirectory()) {
throw new GradleException("The `src/main/java` directory is required, please create it.");
}
if (!getBuildDir().isDirectory() ||
!new File(getBuildDir(), "classes").isDirectory()) {
throw new GradleException("The project has no output yet, " +
"this should not happen as build should have been executed first. " +
"Do the project have any source files?");
}
try {
List<String> args = new ArrayList<>();
args.add("java");
if (getDebug() == null) {
// debug mode not specified
// make sure 5005 is not used, we don't want to just fail if something else is using it
try (Socket socket = new Socket(InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }), 5005)) {
System.err.println("Port 5005 in use, not starting in debug mode");
} catch (IOException e) {
args.add("-Xdebug");
args.add("-Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n");
}
} else if (getDebug().toLowerCase().equals("client")) {
args.add("-Xdebug");
args.add("-Xrunjdwp:transport=dt_socket,address=localhost:5005,server=n,suspend=n");
} else if (getDebug().toLowerCase().equals("true")) {
args.add("-Xdebug");
args.add("-Xrunjdwp:transport=dt_socket,address=localhost:5005,server=y,suspend=y");
} else if (!getDebug().toLowerCase().equals("false")) {
try {
int port = Integer.parseInt(getDebug());
if (port <= 0) {
throw new GradleException("The specified debug port must be greater than 0");
}
args.add("-Xdebug");
args.add("-Xrunjdwp:transport=dt_socket,address=" + port + ",server=y,suspend=y");
} catch (NumberFormatException e) {
throw new GradleException(
"Invalid value for debug parameter: " + getDebug() + " must be true|false|client|{port}");
}
}
if (getJvmArgs() != null) {
args.addAll(Arrays.asList(getJvmArgs().split(" ")));
}
for (File f : extension.resourcesDir()) {
File servletRes = new File(f, "META-INF/resources");
if (servletRes.exists()) {
args.add("-D" + RESOURCES_PROP + "=" + servletRes.getAbsolutePath());
System.out.println("Using servlet resources " + servletRes.getAbsolutePath());
break;
}
}
// the following flags reduce startup time and are acceptable only for dev purposes
args.add("-XX:TieredStopAtLevel=1");
if (!isPreventnoverify()) {
args.add("-Xverify:none");
}
//build a class-path string for the base platform
//this stuff does not change
// Do not include URIs in the manifest, because some JVMs do not like that
StringBuilder classPathManifest = new StringBuilder();
StringBuilder classPath = new StringBuilder();
for (File f : extension.dependencyFiles()) {
addToClassPaths(classPathManifest, classPath, f);
}
args.add("-Djava.util.logging.manager=org.jboss.logmanager.LogManager");
File wiringClassesDirectory = new File(getBuildDir(), "wiring-classes");
wiringClassesDirectory.mkdirs();
addToClassPaths(classPathManifest, classPath, wiringClassesDirectory);
//we also want to add the maven plugin jar to the class path
//this allows us to just directly use classes, without messing around copying them
//to the runner jar
URL classFile = DevModeMain.class.getClassLoader()
.getResource(DevModeMain.class.getName().replace('.', '/') + ".class");
File path;
if (classFile.getProtocol().equals("jar")) {
String jarPath = classFile.getPath().substring(0, classFile.getPath().lastIndexOf('!'));
if (jarPath.startsWith("file:"))
jarPath = jarPath.substring(5);
path = new File(jarPath);
} else if (classFile.getProtocol().equals("file")) {
String filePath = classFile.getPath().substring(0,
classFile.getPath().lastIndexOf(DevModeMain.class.getName().replace('.', '/')));
path = new File(filePath);
} else {
throw new GradleException("Unsupported DevModeMain artifact URL:" + classFile);
}
addToClassPaths(classPathManifest, classPath, path);
//now we need to build a temporary jar to actually run
File tempFile = new File(getBuildDir(), extension.finalName() + "-dev.jar");
tempFile.delete();
tempFile.deleteOnExit();
try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(tempFile))) {
out.putNextEntry(new ZipEntry("META-INF/"));
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
manifest.getMainAttributes().put(Attributes.Name.CLASS_PATH, classPathManifest.toString());
manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, DevModeMain.class.getName());
out.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
manifest.write(out);
out.putNextEntry(new ZipEntry(ClassLoaderCompiler.DEV_MODE_CLASS_PATH));
out.write(classPath.toString().getBytes(StandardCharsets.UTF_8));
}
StringBuilder resources = new StringBuilder();
for (File file : extension.resourcesDir()) {
if (resources.length() > 0)
resources.append(File.pathSeparator);
resources.append(file.getAbsolutePath());
}
extension.outputDirectory().mkdirs();
args.add("-Dquarkus.runner.classes=" + extension.outputDirectory().getAbsolutePath());
args.add("-Dquarkus.runner.sources=" + getSourceDir().getAbsolutePath());
if (resources != null) {
args.add("-Dquarkus.runner.resources=" + resources.toString());
}
args.add("-jar");
args.add(tempFile.getAbsolutePath());
args.add(extension.outputDirectory().getAbsolutePath());
args.add(wiringClassesDirectory.getAbsolutePath());
args.add(new File(getBuildDir(), "transformer-cache").getAbsolutePath());
ProcessBuilder pb = new ProcessBuilder(args.toArray(new String[0]));
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.redirectInput(ProcessBuilder.Redirect.INHERIT);
pb.directory(extension.outputDirectory());
System.out.println("Starting process: ");
pb.command().forEach(System.out::println);
System.out.println("Args: ");
args.forEach(System.out::println);
Process p = pb.start();
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
p.destroy();
}
}, "Development Mode Shutdown Hook"));
try {
p.waitFor();
} catch (Exception e) {
p.destroy();
throw e;
}
} catch (Exception e) {
throw new GradleException("Failed to run", e);
}
}
private void addToClassPaths(StringBuilder classPathManifest, StringBuilder classPath, File file)
throws MalformedURLException {
URI uri = file.toPath().toAbsolutePath().toUri();
classPathManifest.append(uri.getPath());
classPath.append(uri.toURL().toString());
if (file.isDirectory()) {
classPathManifest.append("/");
classPath.append("/");
}
classPathManifest.append(" ");
classPath.append(" ");
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2019 Red Hat, Inc.
*
* 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 io.quarkus.gradle.tasks;
import org.gradle.api.tasks.TaskAction;
import io.quarkus.dependencies.Extension;
import io.quarkus.maven.utilities.MojoUtils;
/**
* @author <a href="mailto:stalep@gmail.com">Ståle Pedersen</a>
*/
public class QuarkusListExtensions extends QuarkusTask {
public QuarkusListExtensions() {
super("Lists the available quarkus extensions");
}
@TaskAction
public void listExtensions() {
for (Extension ext : MojoUtils.loadExtensions()) {
getLogger().lifecycle(
ext.getName() + " (" + ext.getGroupId() + ":" + ext.getArtifactId() + ":" + ext.getVersion() + ")");
}
}
}

View File

@@ -0,0 +1,389 @@
/*
* Copyright 2019 Red Hat, Inc.
*
* 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 io.quarkus.gradle.tasks;
import java.io.File;
import java.nio.file.Path;
import java.util.List;
import org.gradle.api.GradleException;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.options.Option;
import io.quarkus.creator.AppCreator;
import io.quarkus.creator.AppCreatorException;
import io.quarkus.creator.AppDependency;
import io.quarkus.creator.phase.augment.AugmentOutcome;
import io.quarkus.creator.phase.nativeimage.NativeImageOutcome;
import io.quarkus.creator.phase.nativeimage.NativeImagePhase;
import io.quarkus.creator.phase.runnerjar.RunnerJarOutcome;
/**
* @author <a href="mailto:stalep@gmail.com">Ståle Pedersen</a>
*/
public class QuarkusNative extends QuarkusTask {
private String wiringClassesDirectory;
private boolean reportErrorsAtRuntime = false;
private boolean debugSymbols = false;
private boolean debugBuildProcess;
private boolean cleanupServer;
private boolean enableHttpUrlHandler;
private boolean enableHttpsUrlHandler;
private boolean enableAllSecurityServices;
private boolean enableRetainedHeapReporting;
private boolean enableIsolates;
private boolean enableCodeSizeReporting;
private String graalvmHome = System.getenv("GRAALVM_HOME");
private boolean enableServer = false;
private boolean enableJni = false;
private boolean autoServiceLoaderRegistration = false;
private boolean dumpProxies = false;
private String nativeImageXmx;
private String dockerBuild;
private boolean enableVMInspection = false;
private boolean fullStackTraces = true;
private boolean disableReports;
private List<String> additionalBuildArgs;
public QuarkusNative() {
super("Building a native image");
}
public File getWiringClassesDirectory() {
if (wiringClassesDirectory == null)
return extension().wiringClassesDirectory();
else
return new File(wiringClassesDirectory);
}
@Option(description = "The directory for classes generated by processing", option = "wiring-classes-directory")
@Optional
public void setWiringClassesDirectory(String wiringClassesDirectory) {
this.wiringClassesDirectory = wiringClassesDirectory;
}
public boolean isReportErrorsAtRuntime() {
return reportErrorsAtRuntime;
}
@Option(description = "Report errors at runtime", option = "report-errors-runtime")
@Optional
public void setReportErrorsAtRuntime(boolean reportErrorsAtRuntime) {
this.reportErrorsAtRuntime = reportErrorsAtRuntime;
}
public boolean isDebugSymbols() {
return debugSymbols;
}
@Option(description = "Specify if debug symbols should be set", option = "debug-symbols")
@Optional
public void setDebugSymbols(boolean debugSymbols) {
this.debugSymbols = debugSymbols;
}
public boolean isDebugBuildProcess() {
return debugBuildProcess;
}
@Option(description = "Specify if debug is set during build process", option = "debug-build-process")
@Optional
public void setDebugBuildProcess(boolean debugBuildProcess) {
this.debugBuildProcess = debugBuildProcess;
}
public boolean isCleanupServer() {
return cleanupServer;
}
@Option(description = "Cleanup server", option = "cleanup-server")
@Optional
public void setCleanupServer(boolean cleanupServer) {
this.cleanupServer = cleanupServer;
}
public boolean isEnableHttpUrlHandler() {
return enableHttpUrlHandler;
}
@Option(description = "Specify if http url handler is enabled", option = "enable-http-url-handler")
@Optional
public void setEnableHttpUrlHandler(boolean enableHttpUrlHandler) {
this.enableHttpUrlHandler = enableHttpUrlHandler;
}
public boolean isEnableHttpsUrlHandler() {
return enableHttpsUrlHandler;
}
@Option(description = "Specify if https url handler is enabled", option = "enable-https-url-handler")
@Optional
public void setEnableHttpsUrlHandler(boolean enableHttpsUrlHandler) {
this.enableHttpsUrlHandler = enableHttpsUrlHandler;
}
public boolean isEnableAllSecurityServices() {
return enableAllSecurityServices;
}
@Option(description = "Enable all security services", option = "enable-all-security-services")
@Optional
public void setEnableAllSecurityServices(boolean enableAllSecurityServices) {
this.enableAllSecurityServices = enableAllSecurityServices;
}
public boolean isEnableRetainedHeapReporting() {
return enableRetainedHeapReporting;
}
@Option(description = "Specify if retained heap reporting should be enabled", option = "enable-retained-heap-reporting")
@Optional
public void setEnableRetainedHeapReporting(boolean enableRetainedHeapReporting) {
this.enableRetainedHeapReporting = enableRetainedHeapReporting;
}
public boolean isEnableIsolates() {
return enableIsolates;
}
@Option(description = "Report errors at runtime", option = "enable-isolates")
@Optional
public void setEnableIsolates(boolean enableIsolates) {
this.enableIsolates = enableIsolates;
}
public boolean isEnableCodeSizeReporting() {
return enableCodeSizeReporting;
}
@Option(description = "Report errors at runtime", option = "enable-code-size-reporting")
@Optional
public void setEnableCodeSizeReporting(boolean enableCodeSizeReporting) {
this.enableCodeSizeReporting = enableCodeSizeReporting;
}
public String getGraalvmHome() {
if (graalvmHome == null || graalvmHome.length() < 1)
throw new GradleException(
"The GRAALVM_HOME environment variable need to be set to your GraalVM root directory to use native mode");
return graalvmHome;
}
@Option(description = "Specify the GraalVM directory (default to $GRAALVM_HOME)", option = "graalvm")
@Optional
public void setGraalvmHome(String graalvmHome) {
this.graalvmHome = graalvmHome;
}
public boolean isEnableServer() {
return enableServer;
}
@Option(description = "Enable server", option = "enable-server")
@Optional
public void setEnableServer(boolean enableServer) {
this.enableServer = enableServer;
}
public boolean isEnableJni() {
return enableJni;
}
@Option(description = "Enable jni", option = "enable-jni")
@Optional
public void setEnableJni(boolean enableJni) {
this.enableJni = enableJni;
}
public boolean isAutoServiceLoaderRegistration() {
return autoServiceLoaderRegistration;
}
@Option(description = "Auto ServiceLoader registration", option = "auto-serviceloader-registration")
@Optional
public void setAutoServiceLoaderRegistration(boolean autoServiceLoaderRegistration) {
this.autoServiceLoaderRegistration = autoServiceLoaderRegistration;
}
public boolean isDumpProxies() {
return dumpProxies;
}
@Option(description = "Dump proxies", option = "dump-proxies")
@Optional
public void setDumpProxies(boolean dumpProxies) {
this.dumpProxies = dumpProxies;
}
public String getNativeImageXmx() {
return nativeImageXmx;
}
@Option(description = "Specify the native image maximum heap size", option = "native-image-xmx")
@Optional
public void setNativeImageXmx(String nativeImageXmx) {
this.nativeImageXmx = nativeImageXmx;
}
public String getDockerBuild() {
return dockerBuild;
}
@Option(description = "Docker build", option = "docker-build")
@Optional
public void setDockerBuild(String dockerBuild) {
this.dockerBuild = dockerBuild;
}
public boolean isEnableVMInspection() {
return enableVMInspection;
}
@Option(description = "Enable VM inspection", option = "enable-vm-inspection")
@Optional
public void setEnableVMInspection(boolean enableVMInspection) {
this.enableVMInspection = enableVMInspection;
}
public boolean isFullStackTraces() {
return fullStackTraces;
}
@Option(description = "Specify full stacktraces", option = "full-stacktraces")
@Optional
public void setFullStackTraces(boolean fullStackTraces) {
this.fullStackTraces = fullStackTraces;
}
public boolean isDisableReports() {
return disableReports;
}
@Option(description = "Disable reports", option = "disable-reports")
@Optional
public void setDisableReports(boolean disableReports) {
this.disableReports = disableReports;
}
public List<String> getAdditionalBuildArgs() {
return additionalBuildArgs;
}
@Option(description = "Additional build arguments", option = "additional-build-args")
@Optional
public void setAdditionalBuildArgs(List<String> additionalBuildArgs) {
this.additionalBuildArgs = additionalBuildArgs;
}
@TaskAction
public void buildNative() {
getLogger().lifecycle("building native image");
try (AppCreator appCreator = AppCreator.builder()
// configure the build phase we want the app to go through
.addPhase(new NativeImagePhase()
.setAdditionalBuildArgs(getAdditionalBuildArgs())
.setAutoServiceLoaderRegistration(isAutoServiceLoaderRegistration())
.setOutputDir(extension().buildDir().toPath())
.setCleanupServer(isCleanupServer())
.setDebugBuildProcess(isDebugBuildProcess())
.setDebugSymbols(isDebugSymbols())
.setDisableReports(isDisableReports())
.setDockerBuild(getDockerBuild())
.setDumpProxies(isDumpProxies())
.setEnableAllSecurityServices(isEnableAllSecurityServices())
.setEnableCodeSizeReporting(isEnableCodeSizeReporting())
.setEnableHttpsUrlHandler(isEnableHttpsUrlHandler())
.setEnableHttpUrlHandler(isEnableHttpUrlHandler())
.setEnableIsolates(isEnableIsolates())
.setEnableJni(isEnableJni())
.setEnableRetainedHeapReporting(isEnableRetainedHeapReporting())
.setEnableServer(isEnableServer())
.setEnableVMInspection(isEnableVMInspection())
.setFullStackTraces(isFullStackTraces())
.setGraalvmHome(getGraalvmHome())
.setNativeImageXmx(getNativeImageXmx())
.setReportErrorsAtRuntime(isReportErrorsAtRuntime()))
.build()) {
appCreator.pushOutcome(AugmentOutcome.class, new AugmentOutcome() {
final Path classesDir = extension().outputDirectory().toPath();
@Override
public Path getAppClassesDir() {
return classesDir;
}
@Override
public Path getTransformedClassesDir() {
// not relevant for this mojo
throw new UnsupportedOperationException();
}
@Override
public Path getWiringClassesDir() {
// not relevant for this mojo
throw new UnsupportedOperationException();
}
@Override
public boolean isWhitelisted(AppDependency dep) {
// not relevant for this mojo
throw new UnsupportedOperationException();
}
}).pushOutcome(RunnerJarOutcome.class, new RunnerJarOutcome() {
final Path runnerJar = extension().buildDir().toPath().resolve(extension().finalName() + "-runner.jar");
@Override
public Path getRunnerJar() {
return runnerJar;
}
@Override
public Path getLibDir() {
return runnerJar.getParent().resolve("lib");
}
}).resolveOutcome(NativeImageOutcome.class);
} catch (AppCreatorException e) {
throw new GradleException("Failed to generate a native image", e);
}
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2019 Red Hat, Inc.
*
* 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 io.quarkus.gradle.tasks;
import org.gradle.api.DefaultTask;
import io.quarkus.gradle.QuarkusPluginExtension;
/**
* @author <a href="mailto:stalep@gmail.com">Ståle Pedersen</a>
*/
public abstract class QuarkusTask extends DefaultTask {
private QuarkusPluginExtension extension;
QuarkusTask(String description) {
GradleLogger.logSupplier = this::getLogger;
setDescription(description);
setGroup("quarkus");
}
QuarkusPluginExtension extension() {
if (extension == null)
extension = (QuarkusPluginExtension) getProject().getExtensions().findByName("quarkus");
return extension;
}
}

View File

@@ -0,0 +1 @@
implementation-class=io.quarkus.gradle.QuarkusPlugin

View File

@@ -0,0 +1,22 @@
package io.quarkus.gradle;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.gradle.api.Project;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.jupiter.api.Test;
public class QuarkusPluginTest {
@Test
public void quarkusTest() {
Project project = ProjectBuilder.builder().build();
project.getPluginManager().apply("io.quarkus.gradle.plugin");
assertTrue(project.getPluginManager().hasPlugin("io.quarkus.gradle.plugin"));
assertNotNull(project.getTasks().getByName("quarkus-build"));
}
}

View File

@@ -40,6 +40,7 @@
<module>extension-plugin</module>
<module>common</module>
<module>maven</module>
<module>gradle</module>
<module>aesh</module>
</modules>
</project>