diff --git a/sbt-play-ebean/src/main/scala/play/ebean/sbt/PlayEbean.scala b/sbt-play-ebean/src/main/scala/play/ebean/sbt/PlayEbean.scala index 4863f748..7f98e550 100644 --- a/sbt-play-ebean/src/main/scala/play/ebean/sbt/PlayEbean.scala +++ b/sbt-play-ebean/src/main/scala/play/ebean/sbt/PlayEbean.scala @@ -23,7 +23,6 @@ import xsbti.compile.CompileResult import xsbti.compile.analysis.Stamp import sbt._ import xsbti.VirtualFileRef -import scala.util.control.NonFatal object PlayEbean extends AutoPlugin { @@ -64,6 +63,25 @@ object PlayEbean extends AutoPlugin { // This is replacement of old Stamp `Exists` representation private final val notPresent = "absent" + /** + * Turns the configured models into the packages the enhancer processes: packages (`models.*` or `models`) as they + * are, and single classes (`models.Task`) via their package. Entries without compiled classes (e.g. packages not + * existing yet, or provided by a dependency) are skipped, because the enhancer fails for them. + */ + private def packagesToEnhance(models: Seq[String], classes: File): Seq[String] = { + def isPackage(name: String) = new File(classes, name.replace('.', '/')).isDirectory + models + .map(_.trim) + .flatMap { model => + // Like the enhancer, ignore a trailing ".*" or ".**" + val pkg = model.stripSuffix("*").stripSuffix("*").stripSuffix(".") + if (isPackage(pkg)) Some(pkg) + else if (pkg == model && model.contains('.')) Some(model.substring(0, model.lastIndexOf('.'))).filter(isPackage) + else None + } + .distinct + } + def ebeanEnhance: Def.Initialize[Task[CompileResult]] = Def.task { @@ -85,10 +103,10 @@ object PlayEbean extends AutoPlugin { val transformer = new Transformer(classLoader, agentArgsString) val fileTransform = new OfflineFileTransform(transformer, classLoader, classes.getAbsolutePath) - try { - fileTransform.process(playEbeanModels.value.mkString(",")) - } catch { - case NonFatal(_) => + val packages = packagesToEnhance(playEbeanModels.value, classes) + // An empty list would make the enhancer process all classes + if (packages.nonEmpty) { + fileTransform.process(packages.mkString(",")) } } finally { diff --git a/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/app/models/Task.java b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/app/models/Task.java new file mode 100644 index 00000000..0af270d9 --- /dev/null +++ b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/app/models/Task.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. + */ + +package models; + +import java.util.*; +import jakarta.persistence.*; + +import io.ebean.*; +import play.data.format.*; +import play.data.validation.*; + +@Entity +public class Task extends Model { + + public static final Finder find = new Finder<>(Task.class); + + @Id + public Long id; + + @Constraints.Required + public String name; + + public boolean done; + + @Formats.DateTime(pattern = "dd/MM/yyyy") + public Date dueDate = new Date(); +} diff --git a/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/build.sbt b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/build.sbt new file mode 100644 index 00000000..33e7fd70 --- /dev/null +++ b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/build.sbt @@ -0,0 +1,17 @@ +// Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. + +lazy val root = project + .in(file(".")) + .enablePlugins(PlayJava, PlayEbean) + +scalaVersion := sys.props("scala.version") + +Test / sourceDirectory := baseDirectory.value / "tests" + +Test / scalaSource := baseDirectory.value / "tests" + +Test / javaSource := baseDirectory.value / "tests" + +resolvers ++= DefaultOptions.resolvers(snapshot = true) + +libraryDependencies += "com.h2database" % "h2" % "2.5.252" diff --git a/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/conf/application.conf b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/conf/application.conf new file mode 100644 index 00000000..62509a28 --- /dev/null +++ b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/conf/application.conf @@ -0,0 +1,3 @@ +# A package without any compiled classes (listed first, so it must not stop the enhancement of the +# following entries) and a single model class instead of a package +ebean.default = [ "missing.*", "models.Task" ] diff --git a/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/project/plugins.sbt b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/project/plugins.sbt new file mode 100644 index 00000000..ffaa76e1 --- /dev/null +++ b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/project/plugins.sbt @@ -0,0 +1,4 @@ +// Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. + +resolvers ++= DefaultOptions.resolvers(snapshot = true) +addSbtPlugin("org.playframework" % "sbt-play-ebean" % sys.props("project.version")) diff --git a/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/test b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/test new file mode 100644 index 00000000..0f99eb3c --- /dev/null +++ b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/test @@ -0,0 +1,2 @@ +> test +$ exists conf/evolutions/default/1.sql \ No newline at end of file diff --git a/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/tests/models/TestTask.java b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/tests/models/TestTask.java new file mode 100644 index 00000000..06dee9f3 --- /dev/null +++ b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-model-entries/tests/models/TestTask.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. + */ + +package models; + +import org.junit.*; + +import static org.junit.Assert.*; + +import play.test.*; +import play.Application; + +import static play.test.Helpers.*; + +public class TestTask extends WithApplication { + + protected Application provideApplication() { + return fakeApplication(inMemoryDatabase()); + } + + @Test + public void saveAndFind() { + Task task = new Task(); + task.id = 10L; + task.name = "Hello"; + task.done = false; + task.save(); + + Task saved = Task.find.byId(10L); + assertEquals("Hello", saved.name); + } + +} diff --git a/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/app/models/Task.java b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/app/models/Task.java new file mode 100644 index 00000000..0af270d9 --- /dev/null +++ b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/app/models/Task.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. + */ + +package models; + +import java.util.*; +import jakarta.persistence.*; + +import io.ebean.*; +import play.data.format.*; +import play.data.validation.*; + +@Entity +public class Task extends Model { + + public static final Finder find = new Finder<>(Task.class); + + @Id + public Long id; + + @Constraints.Required + public String name; + + public boolean done; + + @Formats.DateTime(pattern = "dd/MM/yyyy") + public Date dueDate = new Date(); +} diff --git a/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/app/other/Other.java b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/app/other/Other.java new file mode 100644 index 00000000..468bf1b5 --- /dev/null +++ b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/app/other/Other.java @@ -0,0 +1,14 @@ +/* + * Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. + */ + +package other; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +/** An entity outside of the configured package, so it must not get enhanced. */ +@Entity +public class Other { + @Id public Long id; +} diff --git a/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/build.sbt b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/build.sbt new file mode 100644 index 00000000..d58e4c6e --- /dev/null +++ b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/build.sbt @@ -0,0 +1,20 @@ +// Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. + +lazy val root = project + .in(file(".")) + .enablePlugins(PlayJava, PlayEbean) + +scalaVersion := sys.props("scala.version") + +Test / sourceDirectory := baseDirectory.value / "tests" + +Test / scalaSource := baseDirectory.value / "tests" + +Test / javaSource := baseDirectory.value / "tests" + +resolvers ++= DefaultOptions.resolvers(snapshot = true) + +libraryDependencies += "com.h2database" % "h2" % "2.5.252" + +// A plain package name (without ".*"), which must not be taken for a class +Compile / playEbeanModels := Seq("models") diff --git a/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/project/plugins.sbt b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/project/plugins.sbt new file mode 100644 index 00000000..ffaa76e1 --- /dev/null +++ b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/project/plugins.sbt @@ -0,0 +1,4 @@ +// Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. + +resolvers ++= DefaultOptions.resolvers(snapshot = true) +addSbtPlugin("org.playframework" % "sbt-play-ebean" % sys.props("project.version")) diff --git a/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/test b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/test new file mode 100644 index 00000000..dfffb838 --- /dev/null +++ b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/test @@ -0,0 +1 @@ +> test diff --git a/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/tests/models/EnhancementTest.java b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/tests/models/EnhancementTest.java new file mode 100644 index 00000000..7c752550 --- /dev/null +++ b/sbt-play-ebean/src/sbt-test/sbt-ebean/enhancement-plain-package/tests/models/EnhancementTest.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. + */ + +package models; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import io.ebean.bean.EntityBean; +import org.junit.Test; + +public class EnhancementTest { + + @Test + public void enhancesOnlyTheConfiguredPackage() { + assertTrue(EntityBean.class.isAssignableFrom(models.Task.class)); + assertFalse(EntityBean.class.isAssignableFrom(other.Other.class)); + } +}