Skip to content

Commit

Permalink
Merge pull request #23 from mdedetrich/change-from-jkd9-to-jdk-11
Browse files Browse the repository at this point in the history
Change from JDK9 to JDK11
  • Loading branch information
mdedetrich authored Dec 6, 2023
2 parents c0060e5 + 356e88d commit 6a09fb0
Show file tree
Hide file tree
Showing 57 changed files with 214 additions and 210 deletions.
2 changes: 1 addition & 1 deletion .java-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9
11
1 change: 1 addition & 0 deletions .jvmopts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-Djava.security.manager=default -Djava.security.policy=policy
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# JDK 9 build via https://github.com/reactive-streams/reactive-streams-jvm/pull/296/files
# JDK 11 build via https://github.com/reactive-streams/reactive-streams-jvm/pull/296/files

sudo: required
language: scala
Expand All @@ -20,8 +20,8 @@ dist: trusty

matrix:
include:
# - jdk: oraclejdk8 # should then NOT compile any of the JDK 9 stuff
- jdk: oraclejdk9
# - jdk: oraclejdk8 # should then NOT compile any of the JDK 11 stuff
- jdk: oraclejdk11

env:
global:
Expand Down
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ sbt-multi-release-jar


Provides support for [JEP 238: Multi-Release JAR Files](http://openjdk.java.net/jeps/238).
Note that this plugin is not building the jar itself, but just making sure to compile using the right JDK version files which live under `src/[test|main]/[java|scala]-jdk9`. The packaging into a JAR you can still use your favourite plugin of choice, such as sbt-assembly or others.
Note that this plugin is not building the jar itself, but just making sure to compile using the right JDK version files which live under `src/[test|main]/[java|scala]-jdk11`. The packaging into a JAR you can still use your favourite plugin of choice, such as sbt-assembly or others.

Usage
-----
Expand All @@ -15,31 +15,31 @@ Usage
addSbtPlugin("com.lightbend.sbt" % "sbt-multi-release-jar" % "0.1.2")
```

This plugin allows you to keep "Java 9 only" sources in:
This plugin allows you to keep "Java 11 only" sources in:

- `src/main/scala-jdk9`
- `src/main/java-jdk9`
- `src/test/scala-jdk9`
- `src/test/java-jdk9`
- `src/main/scala-jdk11`
- `src/main/java-jdk11`
- `src/test/scala-jdk11`
- `src/test/java-jdk11`

which will only be compiled (and tests would only run) if running on JDK9.
which will only be compiled (and tests would only run) if running on JDK11.

**The purpose of this plugin** though is not only that, it is to be able to `package`
such classes into the special "multi-release jar format" defined by JEP-238 (see link above).

For example this allows you to implement a specific class once using pre-JDK9 features,
and also separately using the JDK9+ features (like varhandles or other library additions).
For example this allows you to implement a specific class once using pre-JDK11 features,
and also separately using the JDK11+ features (like varhandles or other library additions).
Assuming the such implemented class is `akka.stream.impl.MagicEngine` for example, you'd
implement it in `src/main/scala/akka/stream/impl/MagicEngine.scala`
and `src/main/scala-jdk9/akka/stream/impl/MagicEngine.scala`, and the resulting JAR will end up containing:
and `src/main/scala-jdk11/akka/stream/impl/MagicEngine.scala`, and the resulting JAR will end up containing:

```
akka/stream/impl/MagicEngine.class
...
META-INF/versions/9/akka/stream/impl/MagicEngine.class
META-INF/versions/11/akka/stream/impl/MagicEngine.class
```

In runtime, when Java 9 is used, the `META-INF/versions/9/...` class is automatically loaded instead of the
In runtime, when Java 11 is used, the `META-INF/versions/11/...` class is automatically loaded instead of the
"normal class". This is a feature of the Java 9 Runtime and is transparent to the application itself.
Java runtimes prior to version 9 do not know about the special meaning of these directories, and thus will
simply load the "normal class" from the root of the JAR.
Expand Down
2 changes: 1 addition & 1 deletion plugin-tester/.java-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9
11
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public class Example {
public static void main(String[] args) {
System.out.println(
Console.GREEN() +
"Class from `java9`, while running [Java " + System.getProperty("java.version") + "]" +
"Class from `java11`, while running [Java " + System.getProperty("java.version") + "]" +
Console.RESET()
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.concurrent.Flow;

public class OnlyJDK9 implements Flow.Subscriber<String> {
public class OnlyJDK11 implements Flow.Subscriber<String> {

@Override
public void onSubscribe(Flow.Subscription subscription) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.example

import org.scalatest._

class Jdk11VersionOfSomeTests extends WordSpec with Matchers {

"src/test/scala-jdk11 tests" should {

"only run on JDK11" in {
System.getProperty("java.version") should === ("11")
}

"load the JDK11 specific class" in {
// do nothing
}

}
}

This file was deleted.

3 changes: 3 additions & 0 deletions policy
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
grant {
permission java.security.AllPermission;
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

TaskKey[Unit]("check") := {
validateClassMajorVersion("", "major version: 52") // java 8
validateClassMajorVersion("META-INF/versions/9/", "major version: 53") // java 9
validateClassMajorVersion("META-INF/versions/11/", "major version: 55") // java 11
}

def validateClassMajorVersion(subdir: String, expectedVersion: String) = {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class MyJavaVersionDependentImpl {
public void print() throws IOException {
System.out.println(
Console.GREEN() +
"Class from `java9`, while running Java " + System.getProperty("java.version") +
"Class from `java11`, while running Java " + System.getProperty("java.version") +
Console.RESET());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.concurrent.Flow;

public class OnlyJDK9Subscriber implements Flow.Subscriber<String> {
public class OnlyJDK11Subscriber implements Flow.Subscriber<String> {

@Override
public void onSubscribe(Flow.Subscription subscription) {
Expand Down
17 changes: 17 additions & 0 deletions src/java11-sources-test/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
> plugins

> compile

> runMain com.example.MainRunner

# --- assert generated files ---
$ exists target/scala-2.12/classes/com/example/MainRunner.class
$ absent target/scala-2.12/classes/META-INF/versions/11/com/example/MainRunner.class

$ exists target/scala-2.12/classes/com/example/MyJavaVersionDependentImpl.class
$ exists target/scala-2.12/classes/META-INF/versions/11/com/example/MyJavaVersionDependentImpl.class

$ absent target/scala-2.12/classes/com/example/OnlyJDK11Subscriber.class
$ exists target/scala-2.12/classes/META-INF/versions/11/com/example/OnlyJDK11Subscriber.class

> check
17 changes: 0 additions & 17 deletions src/java9-sources-test/test

This file was deleted.

78 changes: 39 additions & 39 deletions src/main/scala/com/lightbend/sbt/MultiReleaseJarPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ object MultiReleaseJarPlugin extends AutoPlugin {
object MultiReleaseJarKeys {
val MultiReleaseJar = config("MultiReleaseJar") extend Compile

val keepOnlyNeeded9MultiReleaseFiles = taskKey[Seq[File]]("Since the JDK9 task will compile 'everything' we need to remove some classes")

val jdkDirectorySuffix = settingKey[String]("The suffix added to src/main/java or src/main/java to form [scala-jdk9]. " +
"The format should be '-jdk#' where # indicates where the version number will be injected. This is for future implementations to use JDK10 etc.")
val java9Directory = settingKey[File]("Where the java9 sources are")
val scala9Directory = settingKey[File]("Where the scala9 sources are")
val metaInfVersionsTargetDirectory = settingKey[File]("Where the java9 classes should be written to." +
"Usually this is: ./target/scala-2.12/classes/META-INF/versions/9")
val keepOnlyNeeded11MultiReleaseFiles = taskKey[Seq[File]]("Since the JDK11 task will compile 'everything' we need to remove some classes")

val jdkDirectorySuffix = settingKey[String]("The suffix added to src/main/java or src/main/java to form [scala-jdk11]. " +
"The format should be '-jdk#' where # indicates where the version number will be injected.")
val java11Directory = settingKey[File]("Where the java11 sources are")
val scala11Directory = settingKey[File]("Where the scala11 sources are")
val metaInfVersionsTargetDirectory = settingKey[File]("Where the java11 classes should be written to." +
"Usually this is: ./target/scala-2.12/classes/META-INF/versions/11")
}

import MultiReleaseJarKeys._
Expand All @@ -31,30 +31,30 @@ object MultiReleaseJarPlugin extends AutoPlugin {
override def projectConfigurations = Seq(MultiReleaseJar)

// ---------------------------------------
// This could be taken from`java.util.jar.Attributes.MULTI_RELEASE`, but we don't want to requirerunning on JDK9!
// This could be taken from`java.util.jar.Attributes.MULTI_RELEASE`, but we don't want to requirerunning on JDK11!
val MULTI_RELEASE_KEY = "Multi-Release"
// ---------------------------------------

val jdkVersion: String = System.getProperty("java.version")

private[this] val isJdk9 =
if (jdkVersion startsWith "9") true
private[this] val isJdk11 =
if (jdkVersion startsWith "11") true
else if (jdkVersion startsWith "1.8") false
else throw new IllegalStateException(s"Only JDK 8 or 9 is supported by this build, because of the mult-release-jar plugin. Detected version: $jdkVersion")
else throw new IllegalStateException(s"Only JDK 8 or 11 is supported by this build, because of the mult-release-jar plugin. Detected version: $jdkVersion")

override def globalSettings = {
def log(s: String) =
println(scala.Console.BOLD + "[multi-release-jar plugin] " + s + scala.Console.RESET)
if (isJdk9)
log("Running using JDK9! Will include classes and tests that require JDK9.")
if (isJdk11)
log("Running using JDK11! Will include classes and tests that require JDK11.")
else
log("Running using JDK 8, note that JDK9 classes and tests will not be included in compile/test runs.")
log("Running using JDK 8, note that JDK11 classes and tests will not be included in compile/test runs.")
super.globalSettings
}

override def projectSettings: Seq[Def.Setting[_]] = if (isJdk9) jdk9ProjectSettings else Seq.empty
override def projectSettings: Seq[Def.Setting[_]] = if (isJdk11) jdk11ProjectSettings else Seq.empty

def jdk9ProjectSettings: Seq[Def.Setting[_]] = Seq(
def jdk11ProjectSettings: Seq[Def.Setting[_]] = Seq(
compile :=
(compile in MultiReleaseJar).dependsOn(
compile in Compile
Expand All @@ -78,22 +78,22 @@ object MultiReleaseJarPlugin extends AutoPlugin {

) ++ Seq(
unmanagedSourceDirectories in Test ++= {
val suffix = (jdkDirectorySuffix in MultiReleaseJar).value.replace("#", "9")
val suffix = (jdkDirectorySuffix in MultiReleaseJar).value.replace("#", "11")
Seq(
(sourceDirectory in Test).value / ("java" + suffix),
(sourceDirectory in Test).value / ("scala" + suffix)
)
},

// instead of changing unmanagedClasspath we override fullClasspath
// since we want to make sure the "java9" classes are FIRST on the classpath
// since we want to make sure the "java11" classes are FIRST on the classpath
// FIXME if possible I'd love to make this in one step, but could not figure out the right way (conversions fail)
fullClasspath in Test += (classDirectory in MultiReleaseJar).value,
fullClasspath in Test := {
val prev = (fullClasspath in Test).value
// move the "java9" classes FIRST, so they get picked up first in case of conflicts
val j9Classes = prev.find(_.toString contains "/versions/9").get
Seq(j9Classes) ++ prev.filterNot(_.toString contains "/versions/9")
// move the "java11" classes FIRST, so they get picked up first in case of conflicts
val j11Classes = prev.find(_.toString contains "/versions/11").get
Seq(j11Classes) ++ prev.filterNot(_.toString contains "/versions/11")
}

// fullClasspath in Test := {
Expand All @@ -102,12 +102,12 @@ object MultiReleaseJarPlugin extends AutoPlugin {

) ++ inConfig(MultiReleaseJar)(Defaults.compileSettings ++ Seq(

// default suffix for directories: java-jdk9, scala-jdk9
// default suffix for directories: java-jdk11, scala-jdk11
jdkDirectorySuffix in MultiReleaseJar := "-jdk#",

// here we want to generate the JDK9 files, so they target Java 9:
// here we want to generate the JDK11 files, so they target Java 11:
javacOptions in MultiReleaseJar ++=
Seq("-source", "1.9", "-target", "1.9"),
Seq("-source", "11", "-target", "11"),
// in Compile we want to generage Java 8 compatible things though:
javacOptions in Compile ++=
Seq("-source", "1.8", "-target", "1.8"),
Expand All @@ -116,33 +116,33 @@ object MultiReleaseJarPlugin extends AutoPlugin {
packageOptions in(Compile, packageBin) +=
Package.ManifestAttributes("Multi-Release" -> "true"),

// "9" source directories
java9Directory in MultiReleaseJar := {
val suffix = (jdkDirectorySuffix in MultiReleaseJar).value.replace("#", "9")
// "11" source directories
java11Directory in MultiReleaseJar := {
val suffix = (jdkDirectorySuffix in MultiReleaseJar).value.replace("#", "11")
(sourceDirectory in Compile).value / ("java" + suffix)
},
scala9Directory in MultiReleaseJar := {
val suffix = (jdkDirectorySuffix in MultiReleaseJar).value.replace("#", "9")
scala11Directory in MultiReleaseJar := {
val suffix = (jdkDirectorySuffix in MultiReleaseJar).value.replace("#", "11")
(sourceDirectory in Compile).value / ("scala" + suffix)
},

// target - we kind of 'inject' our sources into the right spot:
metaInfVersionsTargetDirectory := {
(classDirectory in Compile).value / "META-INF" / "versions" / "9"
(classDirectory in Compile).value / "META-INF" / "versions" / "11"
},

classDirectory in MultiReleaseJar := metaInfVersionsTargetDirectory.value,

sources in MultiReleaseJar := {
val j9SourcesDir = (java9Directory in MultiReleaseJar).value
val j9Sources = (j9SourcesDir ** "*").filter(_.isFile).get.toSet
val j11SourcesDir = (java11Directory in MultiReleaseJar).value
val j11Sources = (j11SourcesDir ** "*").filter(_.isFile).get.toSet

val s9SourcesDir = (scala9Directory in MultiReleaseJar).value
val s9Sources = (s9SourcesDir ** "*").filter(_.isFile).get.toSet
val s11SourcesDir = (scala11Directory in MultiReleaseJar).value
val s11Sources = (s11SourcesDir ** "*").filter(_.isFile).get.toSet

val j9Files = (j9Sources union s9Sources).toSeq
streams.value.log.debug("JDK9 Source files detected: " + j9Files)
j9Files
val j11Files = (j11Sources union s11Sources).toSeq
streams.value.log.debug("JDK11 Source files detected: " + j11Files)
j11Files
}
))

Expand All @@ -151,7 +151,7 @@ object MultiReleaseJarPlugin extends AutoPlugin {

final class FileComparableByName(baseDir: File, val file: File) {
val internalPath = {
val rel = file.relativeTo(baseDir).get.toString // `java-jdk9/com/example/MyJavaVersionDependentImpl.java`
val rel = file.relativeTo(baseDir).get.toString // `java-jdk11/com/example/MyJavaVersionDependentImpl.java`
rel.substring(rel.indexOf('/') + 1) // just `com/example/MyJavaVersionDependentImpl.java`
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

TaskKey[Unit]("check") := {
validateClassMajorVersion("", "major version: 52") // java 8
validateClassMajorVersion("META-INF/versions/9/", "major version: 53") // java 9
validateClassMajorVersion("META-INF/versions/11/", "major version: 55") // java 11
}

def validateClassMajorVersion(subdir: String, expectedVersion: String) = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class MyJavaVersionDependentImpl {
public void print() throws IOException {
System.out.println(
Console.GREEN() +
"Class from `java9`, while running Java " + System.getProperty("java.version") +
"Class from `java11`, while running Java " + System.getProperty("java.version") +
Console.RESET());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.concurrent.Flow;

public class OnlyJDK9Subscriber implements Flow.Subscriber<String> {
public class OnlyJDK11Subscriber implements Flow.Subscriber<String> {

@Override
public void onSubscribe(Flow.Subscription subscription) {
Expand Down
Loading

0 comments on commit 6a09fb0

Please sign in to comment.