-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Gradle] Initial version of Play Gradle Plugin
* Play Routes compiler plugin * Play Assets plugin * Play Run DEV-mode plugin * Support Play application layout * Helper function to add dependencies
- Loading branch information
Showing
21 changed files
with
1,145 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,3 +3,4 @@ | |
|
||
# Ignore Gradle build output directory | ||
build | ||
bin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
dev-mode/gradle-plugin/src/main/java/play/gradle/AssetsSettings.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* | ||
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com> | ||
*/ | ||
package play.gradle; | ||
|
||
import org.gradle.api.provider.Property; | ||
|
||
public abstract class AssetsSettings { | ||
public abstract Property<String> getPath(); | ||
} |
30 changes: 30 additions & 0 deletions
30
dev-mode/gradle-plugin/src/main/java/play/gradle/PlayExtension.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com> | ||
*/ | ||
package play.gradle; | ||
|
||
import org.gradle.api.Action; | ||
import org.gradle.api.tasks.Nested; | ||
|
||
/** | ||
* The extension of the plugin allowing for configuring the target Scala version used for the | ||
* application. | ||
*/ | ||
public abstract class PlayExtension { | ||
|
||
public static final String PLAY_EXTENSION_NAME = "play"; | ||
|
||
@Nested | ||
public abstract RoutesSettings getRoutes(); | ||
|
||
public void routes(Action<? super RoutesSettings> action) { | ||
action.execute(getRoutes()); | ||
} | ||
|
||
@Nested | ||
public abstract AssetsSettings getAssets(); | ||
|
||
public void assets(Action<? super AssetsSettings> action) { | ||
action.execute(getAssets()); | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
dev-mode/gradle-plugin/src/main/java/play/gradle/RoutesSettings.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* | ||
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com> | ||
*/ | ||
package play.gradle; | ||
|
||
import org.gradle.api.provider.Property; | ||
import org.gradle.api.provider.SetProperty; | ||
|
||
public abstract class RoutesSettings { | ||
|
||
public abstract Property<Boolean> getNamespaceReverseRouter(); | ||
|
||
public abstract Property<Boolean> getGenerateReverseRouter(); | ||
|
||
public abstract SetProperty<String> getImports(); | ||
} |
139 changes: 139 additions & 0 deletions
139
dev-mode/gradle-plugin/src/main/java/play/gradle/internal/PlayRunHandle.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
/* | ||
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com> | ||
*/ | ||
package play.gradle.internal; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.concurrent.locks.ReadWriteLock; | ||
import java.util.concurrent.locks.ReentrantReadWriteLock; | ||
import java.util.stream.Collectors; | ||
import javax.inject.Inject; | ||
import org.gradle.deployment.internal.Deployment; | ||
import org.gradle.deployment.internal.DeploymentHandle; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import play.api.PlayException; | ||
import play.runsupport.CompileResult; | ||
import play.runsupport.CompileResult.CompileFailure; | ||
import play.runsupport.CompileResult.CompileSuccess; | ||
import play.runsupport.DevServer; | ||
import play.runsupport.DevServerRunner; | ||
import play.runsupport.classloader.AssetsClassLoader; | ||
|
||
public class PlayRunHandle implements DeploymentHandle { | ||
|
||
public static final Logger LOGGER = LoggerFactory.getLogger(PlayRunHandle.class); | ||
|
||
private Deployment deployment; | ||
|
||
private final ReadWriteLock lock = new ReentrantReadWriteLock(); | ||
private final PlayRunParams params; | ||
|
||
private DevServer devServer = null; | ||
|
||
@Inject | ||
public PlayRunHandle(PlayRunParams params) { | ||
this.params = params; | ||
} | ||
|
||
@Override | ||
public boolean isRunning() { | ||
lock.readLock().lock(); | ||
try { | ||
return devServer != null; | ||
} finally { | ||
lock.readLock().unlock(); | ||
} | ||
} | ||
|
||
/** Force reload Play application before next request. */ | ||
public void forceReload() { | ||
lock.writeLock().lock(); | ||
try { | ||
devServer.buildLink().forceReload(); | ||
} finally { | ||
lock.writeLock().unlock(); | ||
} | ||
} | ||
|
||
private boolean isChanged() { | ||
lock.readLock().lock(); | ||
try { | ||
return deployment.status().hasChanged(); | ||
} finally { | ||
lock.readLock().unlock(); | ||
} | ||
} | ||
|
||
private CompileResult reloadCompile() { | ||
lock.readLock().lock(); | ||
try { | ||
Throwable failure = deployment.status().getFailure(); | ||
if (failure != null) { | ||
return new CompileFailure( | ||
new PlayException("Gradle Build Failure", failure.getMessage(), failure)); | ||
} | ||
return new CompileSuccess(Map.of(), params.getApplicationClasspath()); | ||
} catch (Exception e) { | ||
LOGGER.error(e.getMessage(), e); | ||
return new CompileFailure(new PlayException("Gradle Build Failure", e.getMessage(), e)); | ||
} finally { | ||
lock.readLock().unlock(); | ||
} | ||
} | ||
|
||
private ClassLoader createAssetClassLoader(ClassLoader parent) { | ||
return new AssetsClassLoader( | ||
parent, | ||
params.getAssetsDirectories().stream() | ||
.map(file -> Map.entry(params.getAssetsPrefix() + "/", file)) | ||
.collect(Collectors.toList())); | ||
} | ||
|
||
@Override | ||
public void start(@NotNull Deployment deployment) { | ||
lock.writeLock().lock(); | ||
this.deployment = deployment; | ||
try { | ||
devServer = | ||
DevServerRunner.startDevMode( | ||
List.of(), | ||
List.of(), | ||
ClassLoader.getPlatformClassLoader(), | ||
params.getDependencyClasspath(), | ||
this::reloadCompile, | ||
this::createAssetClassLoader, | ||
this::isChanged, | ||
List.of(), | ||
null, | ||
Map.of(), | ||
params.getHttpPort(), | ||
"0.0.0.0", | ||
params.getProjectPath(), | ||
Map.of(), | ||
List.of(), | ||
"play.core.server.DevServerStart", | ||
lock); | ||
} finally { | ||
lock.writeLock().unlock(); | ||
} | ||
} | ||
|
||
@Override | ||
public void stop() { | ||
lock.writeLock().lock(); | ||
LOGGER.info("PlayApplication is stopping ..."); | ||
try { | ||
devServer.close(); | ||
LOGGER.info("PlayApplication stopped."); | ||
} catch (Exception e) { | ||
LOGGER.error("PlayApplication stopped with exception", e); | ||
} finally { | ||
devServer = null; | ||
deployment = null; | ||
lock.writeLock().unlock(); | ||
} | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
dev-mode/gradle-plugin/src/main/java/play/gradle/internal/PlayRunParams.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com> | ||
*/ | ||
package play.gradle.internal; | ||
|
||
import java.io.File; | ||
import java.util.List; | ||
|
||
public class PlayRunParams { | ||
private final List<File> dependenciesClasspath; | ||
private final List<File> applicationClasspath; | ||
private final List<File> assetsDirectories; | ||
private final String assetsPath; | ||
private final File projectPath; | ||
private final int httpPort; | ||
|
||
public PlayRunParams( | ||
List<File> dependenciesClasspath, | ||
List<File> applicationClasspath, | ||
List<File> assetsDirectories, | ||
String assetsPath, | ||
File projectPath, | ||
int httpPort) { | ||
this.dependenciesClasspath = dependenciesClasspath; | ||
this.applicationClasspath = applicationClasspath; | ||
this.assetsDirectories = assetsDirectories; | ||
this.assetsPath = assetsPath; | ||
this.projectPath = projectPath; | ||
this.httpPort = httpPort; | ||
} | ||
|
||
public List<File> getDependencyClasspath() { | ||
return dependenciesClasspath; | ||
} | ||
|
||
public List<File> getApplicationClasspath() { | ||
return applicationClasspath; | ||
} | ||
|
||
public List<File> getAssetsDirectories() { | ||
return assetsDirectories; | ||
} | ||
|
||
public File getProjectPath() { | ||
return projectPath; | ||
} | ||
|
||
public int getHttpPort() { | ||
return httpPort; | ||
} | ||
|
||
public String getAssetsPrefix() { | ||
return assetsPath; | ||
} | ||
} |
87 changes: 87 additions & 0 deletions
87
dev-mode/gradle-plugin/src/main/java/play/gradle/internal/RoutesCompileAction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com> | ||
*/ | ||
package play.gradle.internal; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.Collection; | ||
import java.util.stream.Stream; | ||
import org.gradle.api.logging.Logger; | ||
import org.gradle.api.logging.Logging; | ||
import org.gradle.work.ChangeType; | ||
import org.gradle.workers.WorkAction; | ||
import play.routes.compiler.RoutesCompiler$; | ||
import play.routes.compiler.RoutesCompiler.GeneratedSource; | ||
import play.routes.compiler.RoutesCompiler.GeneratedSource$; | ||
import scala.Option; | ||
|
||
/** Gradle work action that compile or delete one Routes file. */ | ||
public abstract class RoutesCompileAction implements WorkAction<RoutesCompileParams> { | ||
|
||
private static final Logger LOGGER = Logging.getLogger(RoutesCompileAction.class); | ||
|
||
@Override | ||
public void execute() { | ||
if (getParameters().getChangeType().get() == ChangeType.REMOVED) { | ||
delete(); | ||
} else { | ||
compile(); | ||
} | ||
} | ||
|
||
private boolean isGeneratedBy(File file, File origin) { | ||
Option<GeneratedSource> generatedSource = GeneratedSource$.MODULE$.unapply(file); | ||
if (generatedSource.isEmpty() || generatedSource.get().source().isEmpty()) return false; | ||
return origin.equals(generatedSource.get().source().get()); | ||
} | ||
|
||
private void delete() { | ||
File routes = getParameters().getRoutesFile().getAsFile().get(); | ||
File destinationDirectory = getParameters().getDestinationDirectory().getAsFile().get(); | ||
try (Stream<Path> paths = Files.walk(destinationDirectory.toPath())) { | ||
paths | ||
.filter(Files::isRegularFile) | ||
.filter(file -> isGeneratedBy(file.toFile(), routes)) | ||
.forEach( | ||
file -> { | ||
try { | ||
Files.delete(file); | ||
} catch (IOException e) { | ||
LOGGER.warn("Deletion {} failed", file, e); | ||
} | ||
}); | ||
} catch (IOException e) { | ||
LOGGER.error(e.getMessage(), e); | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private void compile() { | ||
try { | ||
File routes = getParameters().getRoutesFile().getAsFile().get(); | ||
File destinationDirectory = getParameters().getDestinationDirectory().getAsFile().get(); | ||
boolean namespaceReverseRouter = getParameters().getNamespaceReverseRouter().get(); | ||
boolean generateReverseRouter = getParameters().getGenerateReverseRouter().get(); | ||
Collection<String> imports = getParameters().getImports().get(); | ||
if (LOGGER.isInfoEnabled()) { | ||
LOGGER.info( | ||
"Compile Routes file {} into {}", | ||
routes.getCanonicalPath(), | ||
destinationDirectory.getCanonicalPath()); | ||
} | ||
RoutesCompiler$.MODULE$.compile( | ||
routes, | ||
imports, | ||
true, | ||
generateReverseRouter, | ||
namespaceReverseRouter, | ||
destinationDirectory); | ||
} catch (Exception e) { | ||
LOGGER.error(e.getMessage(), e); | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
dev-mode/gradle-plugin/src/main/java/play/gradle/internal/RoutesCompileParams.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* | ||
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com> | ||
*/ | ||
package play.gradle.internal; | ||
|
||
import org.gradle.api.file.DirectoryProperty; | ||
import org.gradle.api.file.RegularFileProperty; | ||
import org.gradle.api.provider.Property; | ||
import org.gradle.api.provider.SetProperty; | ||
import org.gradle.work.ChangeType; | ||
import org.gradle.workers.WorkParameters; | ||
|
||
/** Parameters of Routes compilation work action. */ | ||
public interface RoutesCompileParams extends WorkParameters { | ||
|
||
Property<ChangeType> getChangeType(); | ||
|
||
RegularFileProperty getRoutesFile(); | ||
|
||
DirectoryProperty getDestinationDirectory(); | ||
|
||
Property<Boolean> getNamespaceReverseRouter(); | ||
|
||
Property<Boolean> getGenerateReverseRouter(); | ||
|
||
SetProperty<String> getImports(); | ||
} |
Oops, something went wrong.