diff --git a/src/docs/asciidoc/30-plugin-configuration.adoc b/src/docs/asciidoc/30-plugin-configuration.adoc index 31097771..842fdcf6 100644 --- a/src/docs/asciidoc/30-plugin-configuration.adoc +++ b/src/docs/asciidoc/30-plugin-configuration.adoc @@ -8,4 +8,6 @@ include::33-add-source-directories.adoc[] include::34-compiler-options.adoc[] -include::35-add-distribution-files.adoc[] \ No newline at end of file +include::35-add-distribution-files.adoc[] + +include::36-prefixing-dependencies.adoc[] \ No newline at end of file diff --git a/src/docs/asciidoc/36-prefixing-dependencies.adoc b/src/docs/asciidoc/36-prefixing-dependencies.adoc new file mode 100644 index 00000000..edc98308 --- /dev/null +++ b/src/docs/asciidoc/36-prefixing-dependencies.adoc @@ -0,0 +1,14 @@ +=== Prefixing dependencies + +By default, your project's distribution task will prefix all your dependencies as follows: + +* Each jar will be prefixed with the library's group name - e.g. `com.typesafe.play-play_2.12-2.6.25.jar` +* Each sub-module's jar, in a multi-module project, will be prefixed with the module's name + +The default behavior can be turned off using the `prefixDependencies` configuration. + +[source,groovy] +.build.gradle +---- +include::{samplesCodeDir}/play-2.4/groovy/build.gradle[tag=prefix-dependencies-off] +---- \ No newline at end of file diff --git a/src/docs/samples/play-2.4/groovy/build.gradle b/src/docs/samples/play-2.4/groovy/build.gradle index 2f36f758..6736488b 100644 --- a/src/docs/samples/play-2.4/groovy/build.gradle +++ b/src/docs/samples/play-2.4/groovy/build.gradle @@ -33,3 +33,9 @@ play { injectedRoutesGenerator = true } // end::injected-routes-compiler[] + +// tag::prefix-dependencies-off[] +play { + prefixDependencies = false +} +// end::prefix-dependencies-off[] diff --git a/src/integTest/groovy/org/gradle/playframework/application/PlayDistributionApplicationIntegrationTest.groovy b/src/integTest/groovy/org/gradle/playframework/application/PlayDistributionApplicationIntegrationTest.groovy index 17719e41..de21dc43 100644 --- a/src/integTest/groovy/org/gradle/playframework/application/PlayDistributionApplicationIntegrationTest.groovy +++ b/src/integTest/groovy/org/gradle/playframework/application/PlayDistributionApplicationIntegrationTest.groovy @@ -2,13 +2,10 @@ package org.gradle.playframework.application import org.gradle.playframework.PlayMultiVersionApplicationIntegrationTest import org.gradle.playframework.fixtures.archive.ArchiveTestFixture -import org.gradle.playframework.fixtures.archive.JarTestFixture import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.TaskOutcome import org.gradle.util.VersionNumber -import java.util.jar.Attributes - import static org.gradle.playframework.plugins.PlayApplicationPlugin.ASSETS_JAR_TASK_NAME import static org.gradle.playframework.plugins.PlayRoutesPlugin.ROUTES_COMPILE_TASK_NAME import static org.gradle.playframework.plugins.PlayTwirlPlugin.TWIRL_COMPILE_TASK_NAME @@ -38,6 +35,7 @@ abstract class PlayDistributionApplicationIntegrationTest extends PlayMultiVersi and: verifyJars() verifyStagedFiles() + verifyDependenciesPrefix() when: result = build("dist") @@ -56,6 +54,7 @@ abstract class PlayDistributionApplicationIntegrationTest extends PlayMultiVersi List archives() { [ zip("build/distributions/main.zip"), tar("build/distributions/main.tar") ] } + void verifyArchives() { archives()*.containsDescendants( "main/lib/${playApp.name}.jar", @@ -66,6 +65,15 @@ abstract class PlayDistributionApplicationIntegrationTest extends PlayMultiVersi "main/README") } + protected boolean shouldPrefixDependencies() { + return true + } + + final void verifyDependenciesPrefix() { + def dependencies = file("build/stage/main/lib/").listFiles().collect { it.name } + assert dependencies.any { it.startsWith("com.typesafe.play-play_") } == shouldPrefixDependencies() + } + void verifyStagedFiles() { File stageMainDir = file("build/stage/main") [ diff --git a/src/integTest/groovy/org/gradle/playframework/application/dependencies/PlayDistributionAppWithDependenciesNoPrefixIntegrationTest.groovy b/src/integTest/groovy/org/gradle/playframework/application/dependencies/PlayDistributionAppWithDependenciesNoPrefixIntegrationTest.groovy new file mode 100644 index 00000000..243b614f --- /dev/null +++ b/src/integTest/groovy/org/gradle/playframework/application/dependencies/PlayDistributionAppWithDependenciesNoPrefixIntegrationTest.groovy @@ -0,0 +1,18 @@ +package org.gradle.playframework.application.dependencies + +import org.gradle.playframework.application.PlayDistributionApplicationIntegrationTest +import org.gradle.playframework.fixtures.app.PlayApp +import org.gradle.playframework.fixtures.app.PlayAppWithDependenciesNoPrefix + +class PlayDistributionAppWithDependenciesNoPrefixIntegrationTest extends PlayDistributionApplicationIntegrationTest { + + @Override + PlayApp getPlayApp() { + new PlayAppWithDependenciesNoPrefix(playVersion) + } + + @Override + protected boolean shouldPrefixDependencies() { + return false + } +} diff --git a/src/integTestFixtures/groovy/org/gradle/playframework/fixtures/app/PlayAppWithDependenciesNoPrefix.groovy b/src/integTestFixtures/groovy/org/gradle/playframework/fixtures/app/PlayAppWithDependenciesNoPrefix.groovy new file mode 100644 index 00000000..a0f227b9 --- /dev/null +++ b/src/integTestFixtures/groovy/org/gradle/playframework/fixtures/app/PlayAppWithDependenciesNoPrefix.groovy @@ -0,0 +1,9 @@ +package org.gradle.playframework.fixtures.app + +import org.gradle.util.VersionNumber + +class PlayAppWithDependenciesNoPrefix extends PlayApp { + PlayAppWithDependenciesNoPrefix(VersionNumber version) { + super(version) + } +} \ No newline at end of file diff --git a/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/app/controllers/Application.scala.ftl b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/app/controllers/Application.scala.ftl new file mode 100644 index 00000000..d7401c04 --- /dev/null +++ b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/app/controllers/Application.scala.ftl @@ -0,0 +1,53 @@ +/* + * Copyright 2014 the original author or authors. + * + * 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 controllers + +<#if playVersion == "2.8" || playVersion == "2.7" || playVersion == "2.6"> +import javax.inject._ +import com.google.common.base.Strings +import play.api._ +import play.api.mvc._ + +@Singleton +class Application @Inject() extends InjectedController { + + def index = Action { + Ok(views.html.index(Strings.nullToEmpty("Your new application is ready."))) + } + + def shutdown = Action { + Runtime.getRuntime().halt(0) + Ok("shutdown") + } +} +<#else> +import com.google.common.base.Strings +import play.api._ +import play.api.mvc._ + +object Application extends Controller { + + def index = Action { + Ok(views.html.index(Strings.nullToEmpty("Your new application is ready."))) + } + + def shutdown = Action { + System.exit(0) + Ok("shutdown") + } +} + diff --git a/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/app/views/index.scala.html b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/app/views/index.scala.html new file mode 100644 index 00000000..86801c8b --- /dev/null +++ b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/app/views/index.scala.html @@ -0,0 +1,7 @@ +@(message: String) + +@main("Welcome to Play") { + +

@message

+ +} \ No newline at end of file diff --git a/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/app/views/main.scala.html b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/app/views/main.scala.html new file mode 100644 index 00000000..d245c518 --- /dev/null +++ b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/app/views/main.scala.html @@ -0,0 +1,13 @@ +@(title: String)(content: Html) + + + + @title + + + + + +@content + + \ No newline at end of file diff --git a/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/build.gradle.ftl b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/build.gradle.ftl new file mode 100644 index 00000000..e614c5e4 --- /dev/null +++ b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/build.gradle.ftl @@ -0,0 +1,35 @@ +<#if playVersion == "2.8" || playVersion == "2.7" || playVersion == "2.6"> +plugins { + id 'org.gradle.playframework' +} + +dependencies { + implementation "com.google.guava:guava:17.0" + implementation "com.typesafe.play:play-guice_2.12:2.6.15" + implementation "ch.qos.logback:logback-classic:1.2.3" + testImplementation "commons-lang:commons-lang:2.6" +} + +play { + prefixDependencies = false +} + +// repositories added in PlayApp class + +<#else> +plugins { + id 'org.gradle.playframework' +} + +dependencies { + implementation "com.google.guava:guava:17.0" + testImplementation "commons-lang:commons-lang:2.6" +} + +// repositories added in PlayApp class + +play { + prefixDependencies = false +} + + diff --git a/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/conf/routes.ftl b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/conf/routes.ftl new file mode 100644 index 00000000..94e9450d --- /dev/null +++ b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/conf/routes.ftl @@ -0,0 +1,21 @@ +<#if playVersion == "2.8" || playVersion == "2.7" || playVersion == "2.6"> +# Routes +# Home page +GET / @controllers.Application.index + +GET /shutdown @controllers.Application.shutdown + +# Map static resources from the /public folder to the /assets URL path +GET /assets/*file @controllers.Assets.at(path="/public", file) + +<#else> +# Routes +# Home page +GET / controllers.Application.index + +GET /shutdown controllers.Application.shutdown + +# Map static resources from the /public folder to the /assets URL path +GET /assets/*file controllers.Assets.at(path="/public", file) + + diff --git a/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/test/ApplicationSpec.scala b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/test/ApplicationSpec.scala new file mode 100644 index 00000000..1d5b0fc1 --- /dev/null +++ b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/test/ApplicationSpec.scala @@ -0,0 +1,26 @@ +/* + * Copyright 2014 the original author or authors. + * + * 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. + */ + +import org.junit._ + +class ApplicationSpec { + @Test + def passingTest() { + } + @Test + def passingTest2() { + } +} diff --git a/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/test/IntegrationSpec.scala b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/test/IntegrationSpec.scala new file mode 100644 index 00000000..a1fdc66f --- /dev/null +++ b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/test/IntegrationSpec.scala @@ -0,0 +1,23 @@ +/* + * Copyright 2014 the original author or authors. + * + * 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. + */ + +import org.junit._ + +class IntegrationSpec { + @Test + def passingTest() { + } +} diff --git a/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/test/notATest.yaml b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/test/notATest.yaml new file mode 100644 index 00000000..d7fb7ab6 --- /dev/null +++ b/src/integTestFixtures/resources/org/gradle/playframework/fixtures/app/playappwithdependenciesnoprefix/test/notATest.yaml @@ -0,0 +1,7 @@ +name: Test +number: 1234 +items: + - name: item1 + description: first item + - name: item2 + description: second item diff --git a/src/main/java/org/gradle/playframework/extensions/PlayExtension.java b/src/main/java/org/gradle/playframework/extensions/PlayExtension.java index da5177fb..1ea5419e 100644 --- a/src/main/java/org/gradle/playframework/extensions/PlayExtension.java +++ b/src/main/java/org/gradle/playframework/extensions/PlayExtension.java @@ -1,9 +1,12 @@ package org.gradle.playframework.extensions; +import javax.inject.Inject; + import org.gradle.api.Action; import org.gradle.api.JavaVersion; import org.gradle.api.model.ObjectFactory; import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; import org.gradle.playframework.extensions.internal.PlayMajorVersion; import static org.gradle.playframework.extensions.PlayPlatform.DEFAULT_PLAY_VERSION; @@ -22,6 +25,7 @@ * javaVersion = JavaVersion.VERSION_1_9 * } * injectedRoutesGenerator = true + * prefixDependencies = false * } * */ @@ -29,14 +33,17 @@ public class PlayExtension { private final PlayPlatform platform; private final Property injectedRoutesGenerator; + private final Property prefixDependencies; + @Inject public PlayExtension(ObjectFactory objectFactory) { this.platform = objectFactory.newInstance(PlayPlatform.class, objectFactory); this.platform.getPlayVersion().convention(DEFAULT_PLAY_VERSION); this.platform.getJavaVersion().convention(JavaVersion.current()); this.platform.getScalaVersion().convention(platform.getPlayVersion().map(playVersion -> PlayMajorVersion.forPlayVersion(playVersion).getDefaultScalaPlatform())); - this.injectedRoutesGenerator = objectFactory.property(Boolean.class); - injectedRoutesGenerator.convention(platform.getPlayVersion().map(playVersion -> !PlayMajorVersion.forPlayVersion(playVersion).hasSupportForStaticRoutesGenerator())); + this.injectedRoutesGenerator = objectFactory.property(Boolean.class) + .convention(platform.getPlayVersion().map(playVersion -> !PlayMajorVersion.forPlayVersion(playVersion).hasSupportForStaticRoutesGenerator())); + this.prefixDependencies = objectFactory.property(Boolean.class).convention(true); } /** @@ -66,4 +73,13 @@ public PlayPlatform getPlatform() { public Property getInjectedRoutesGenerator() { return injectedRoutesGenerator; } + + /** + * Returns the property configuring if the dependencies for the distribution should be prefixed. + * + * @return Property configuring the renaming of dependencies + */ + public Property getPrefixDependencies() { + return prefixDependencies; + } } diff --git a/src/main/java/org/gradle/playframework/plugins/PlayDistributionPlugin.java b/src/main/java/org/gradle/playframework/plugins/PlayDistributionPlugin.java index 44dd12ff..360ab57b 100644 --- a/src/main/java/org/gradle/playframework/plugins/PlayDistributionPlugin.java +++ b/src/main/java/org/gradle/playframework/plugins/PlayDistributionPlugin.java @@ -15,6 +15,7 @@ import org.gradle.api.distribution.plugins.DistributionPlugin; import org.gradle.api.file.CopySpec; import org.gradle.api.file.FileCopyDetails; +import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; import org.gradle.api.provider.ProviderFactory; import org.gradle.api.tasks.Sync; @@ -94,7 +95,7 @@ private void createDistributionContentTasks(Project project, Distribution distri jar.getArchiveBaseName().convention(mainJarTask.flatMap(AbstractArchiveTask::getArchiveBaseName)); Map classpath = new HashMap<>(); - classpath.put("Class-Path", new PlayManifestClasspath(project.getConfigurations().getByName(RUNTIME_CLASSPATH_CONFIGURATION_NAME), assetsJarTask.get().getArchivePath())); + classpath.put("Class-Path", new PlayManifestClasspath(project.getConfigurations().getByName(RUNTIME_CLASSPATH_CONFIGURATION_NAME), assetsJarTask.get().getArchivePath(), playExtension.getPrefixDependencies())); jar.getManifest().attributes(classpath); }); @@ -113,7 +114,7 @@ private void createDistributionContentTasks(Project project, Distribution distri copySpec.from(distributionJarTask); copySpec.from(assetsJarTask.flatMap(AbstractArchiveTask::getArchiveFile)); copySpec.from(project.getConfigurations().getByName(RUNTIME_CLASSPATH_CONFIGURATION_NAME)); - copySpec.eachFile(new PrefixArtifactFileNames(project.getConfigurations().getByName(RUNTIME_CLASSPATH_CONFIGURATION_NAME))); + copySpec.eachFile(new PrefixArtifactFileNames(project.getConfigurations().getByName(RUNTIME_CLASSPATH_CONFIGURATION_NAME), playExtension.getPrefixDependencies())); }); distSpec.into("bin", copySpec -> { @@ -201,16 +202,18 @@ private String capitalizeDistributionName(String distributionName) { static class PlayManifestClasspath { final Configuration configuration; final File assetsJarFile; + final Property prefixDependencies; - public PlayManifestClasspath(Configuration configuration, File assetsJarFile) { + public PlayManifestClasspath(Configuration configuration, File assetsJarFile, Property prefixDependencies) { this.configuration = configuration; this.assetsJarFile = assetsJarFile; + this.prefixDependencies = prefixDependencies; } @Override public String toString() { Stream allFiles = Stream.concat(configuration.getFiles().stream(), Collections.singleton(assetsJarFile).stream()); - Stream transformedFiles = allFiles.map(new PrefixArtifactFileNames(configuration)); + Stream transformedFiles = allFiles.map(new PrefixArtifactFileNames(configuration, this.prefixDependencies)); return String.join(" ", transformedFiles.collect(Collectors.toList()) ); @@ -219,10 +222,12 @@ public String toString() { static class PrefixArtifactFileNames implements Action, Function { private final Configuration configuration; + private final Property prefixDependencies; Map renames; - PrefixArtifactFileNames(Configuration configuration) { + PrefixArtifactFileNames(Configuration configuration, Property prefixDependencies) { this.configuration = configuration; + this.prefixDependencies = prefixDependencies; } @Override @@ -234,7 +239,7 @@ public void execute(FileCopyDetails fileCopyDetails) { public String apply(File input) { calculateRenames(); String rename = renames.get(input); - if (rename!=null) { + if (rename != null) { return rename; } return input.getName(); @@ -253,10 +258,10 @@ private Map calculate() { if (componentId instanceof ProjectComponentIdentifier) { // rename project dependencies ProjectComponentIdentifier projectComponentIdentifier = (ProjectComponentIdentifier) componentId; - files.put(artifact.getFile(), renameForProject(projectComponentIdentifier, artifact.getFile())); + files.put(artifact.getFile(), renameForProject(projectComponentIdentifier, artifact.getFile(), this.prefixDependencies)); } else if (componentId instanceof ModuleComponentIdentifier) { ModuleComponentIdentifier moduleComponentIdentifier = (ModuleComponentIdentifier) componentId; - files.put(artifact.getFile(), renameForModule(moduleComponentIdentifier, artifact.getFile())); + files.put(artifact.getFile(), renameForModule(moduleComponentIdentifier, artifact.getFile(), this.prefixDependencies)); } else { // don't rename other types of dependencies files.put(artifact.getFile(), artifact.getFile().getName()); @@ -270,9 +275,9 @@ Set getResolvedArtifacts() { return artifacts.getArtifacts(); } - static String renameForProject(ProjectComponentIdentifier id, File file) { + static String renameForProject(ProjectComponentIdentifier id, File file, Property prefixDependencies) { String fileName = file.getName(); - if (shouldBeRenamed(file)) { + if (shouldBeRenamed(file, prefixDependencies)) { String projectPath = id.getProjectPath(); projectPath = projectPathToSafeFileName(projectPath); return maybePrefix(projectPath, file); @@ -280,8 +285,8 @@ static String renameForProject(ProjectComponentIdentifier id, File file) { return fileName; } - static String renameForModule(ModuleComponentIdentifier id, File file) { - if (shouldBeRenamed(file)) { + static String renameForModule(ModuleComponentIdentifier id, File file, Property prefixDependencies) { + if (shouldBeRenamed(file, prefixDependencies)) { return maybePrefix(id.getGroup(), file); } return file.getName(); @@ -301,8 +306,8 @@ private static String projectPathToSafeFileName(String projectPath) { return projectPath.replaceAll(":", ".").substring(1); } - private static boolean shouldBeRenamed(File file) { - return hasExtension(file, ".jar"); + private static boolean shouldBeRenamed(File file, Property prefixDependencies) { + return hasExtension(file, ".jar") && prefixDependencies.get(); } }