Skip to content

Commit

Permalink
moditect#141 Support JDK 11.0.11+ multi-release and --multi-release=X…
Browse files Browse the repository at this point in the history
… single argument

* Add helper to parse and extract java version
* Use version for multi release JDK 11.0.11+
* Support --multi-release=X case
  • Loading branch information
fax4ever committed Sep 1, 2021
1 parent 55630ba commit 30e9769
Show file tree
Hide file tree
Showing 4 changed files with 310 additions and 7 deletions.
27 changes: 20 additions & 7 deletions core/src/main/java/org/moditect/commands/GenerateModuleInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@

import org.moditect.internal.analyzer.ServiceLoaderUseScanner;
import org.moditect.internal.compiler.ModuleInfoCompiler;
import org.moditect.internal.parser.JavaVersionHelper;
import org.moditect.internal.parser.JdepsExtraArgsExtractor;
import org.moditect.model.DependencePattern;
import org.moditect.model.DependencyDescriptor;
import org.moditect.model.GeneratedModuleInfo;
Expand Down Expand Up @@ -381,13 +383,9 @@ private Map<String, Boolean> generateModuleInfo() throws AssertionError {

private ModuleDeclaration parseGeneratedModuleInfo() {
Path moduleDir = workingDirectory.resolve( autoModuleNameForInputJar );
int javaMajorVersion = Integer.parseInt(
System.getProperty("java.specification.version").replace("-ea", "").split("\\.")[0]
);
if (javaMajorVersion >= 14) {
int multiReleaseIdx = jdepsExtraArgs.indexOf("--multi-release");
if (multiReleaseIdx >= 0)
moduleDir = moduleDir.resolve("versions").resolve(jdepsExtraArgs.get(multiReleaseIdx + 1));
Optional<Integer> versionToResolve = resolveWithVersion(jdepsExtraArgs, log);
if (versionToResolve.isPresent()) {
moduleDir = moduleDir.resolve("versions").resolve(versionToResolve.get().toString());
}
Path moduleInfo = moduleDir.resolve( "module-info.java" );

Expand Down Expand Up @@ -438,4 +436,19 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx

return dir;
}

public static Optional<Integer> resolveWithVersion(List<String> jdepsExtraArgs, Log log) {
if (!new JavaVersionHelper(log).resolveWithVersionIfMultiRelease()) {
log.debug("Java version does not need to check if " + JdepsExtraArgsExtractor.MULTI_RELEASE_ARGUMENT + " is set");
return Optional.empty();
}

Optional<Integer> result = new JdepsExtraArgsExtractor(log).extractVersion(jdepsExtraArgs);
if (result.isPresent()) {
log.debug("Resolve with version: multi release is set to " + result.get());
} else {
log.debug("Resolve without version: multi release not set");
}
return result;
}
}
134 changes: 134 additions & 0 deletions core/src/main/java/org/moditect/internal/parser/JavaVersionHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* Copyright 2017 - 2018 The ModiTect 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 org.moditect.internal.parser;

import org.moditect.spi.log.Log;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Helper to extract and parse the current Java version to check if multi release path should be used or not.
*
* @author Fabio Massimo Ercoli
*/
public final class JavaVersionHelper {

private static final String VERSION_REGEXP = "^(\\d+)\\.(\\d+)\\.(\\d+).*";
private static final Pattern VERSION_PATTERN = Pattern.compile(VERSION_REGEXP);
private static final String JAVA_VERSION_PROPERTY_NAME = "java.version";

private final Log log;

JavaVersionHelper() {
this.log = null;
}

public JavaVersionHelper(Log log) {
this.log = log;
}

public boolean resolveWithVersionIfMultiRelease() {
Version version = javaVersion();
if (version == null) {
return false;
}

if (version.major >= 14) {
debug("Detected JDK 14+");
return true;
}

// See https://github.com/moditect/moditect/issues/141
if (version.major == 11 && version.minor == 0 && version.mini >= 11) {
debug("Detected JDK 11.0.11+");
return true;
}
return false;
}

Version javaVersion() {
String versionString = System.getProperty(JAVA_VERSION_PROPERTY_NAME);
debug(JAVA_VERSION_PROPERTY_NAME + " -> " + versionString);

return javaVersion(versionString);
}

Version javaVersion(String versionString) {
Matcher matcher = VERSION_PATTERN.matcher(versionString);
if (!matcher.matches()) {
warn("The java version " + versionString + " cannot be parsed as " + VERSION_REGEXP);
return null;
}

try {
Version version = new Version(Integer.parseInt(matcher.group(1)),
Integer.parseInt(matcher.group(2)),
Integer.parseInt(matcher.group(3)));

debug("parsed.version -> " + version);
return version;
} catch (IndexOutOfBoundsException | NumberFormatException ex) {
error("The java version " + versionString + " has an invalid format. " + ex.getMessage());
return null;
}
}

private void debug(String message) {
if (log != null) {
log.debug(message);
}
}

private void warn(String message) {
if (log != null) {
log.warn(message);
}
}

private void error(String message) {
if (log != null) {
log.error(message);
}
}

static class Version {
private int major;
private int minor;
private int mini;

private Version(int major, int minor, int mini) {
this.major = major;
this.minor = minor;
this.mini = mini;
}

int major() {
return major;
}
int minor() {
return minor;
}
int mini() {
return mini;
}

@Override
public String toString() {
return major + "." + minor + "." + mini;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2017 - 2018 The ModiTect 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 org.moditect.internal.parser;

import org.moditect.spi.log.Log;

import java.util.List;
import java.util.Optional;

public final class JdepsExtraArgsExtractor {

public static final String MULTI_RELEASE_ARGUMENT = "--multi-release";

private final Log log;

public JdepsExtraArgsExtractor(Log log) {
this.log = log;
}

public Optional<Integer> extractVersion(List<String> jdepsExtraArgs) {
for (int i = 0; i < jdepsExtraArgs.size(); i++) {
String extraArg = jdepsExtraArgs.get(i);

if (extraArg.startsWith(MULTI_RELEASE_ARGUMENT)) {
if (extraArg.length() == MULTI_RELEASE_ARGUMENT.length()) {
// we expect the version number in the next argument
return extractVersionFromNextArgument(jdepsExtraArgs, i);
}
return extractVersionFromSameArgument(extraArg);
}
}

debug("No version can be extracted from arguments: " + jdepsExtraArgs);
return Optional.empty();
}

private Optional<Integer> extractVersionFromNextArgument(List<String> jdepsExtraArgs, int i) {
if (i == jdepsExtraArgs.size() - 1) {
// there is no next argument
error("No argument value for " + MULTI_RELEASE_ARGUMENT);
return Optional.empty();
}

String versionString = jdepsExtraArgs.get(i + 1);
debug("Version extracted from the next argument: " + versionString);
return parseVersionNumber(versionString);
}

private Optional<Integer> extractVersionFromSameArgument(String multiReleaseArgument) {
if (multiReleaseArgument.length() < MULTI_RELEASE_ARGUMENT.length() + 2) {
error("Invalid argument value for " + MULTI_RELEASE_ARGUMENT + ": " + multiReleaseArgument);
return Optional.empty();
}

String versionString = multiReleaseArgument.substring(MULTI_RELEASE_ARGUMENT.length()+1);
debug("Version extracted from the same argument: " + versionString);
return parseVersionNumber(versionString);
}

private Optional<Integer> parseVersionNumber(String versionString) {
try {
return Optional.of(Integer.parseInt(versionString));
} catch (NumberFormatException ex) {
error("Invalid argument value for " + MULTI_RELEASE_ARGUMENT + ": " + versionString);
return Optional.empty();
}
}

private void debug(String message) {
if (log != null) {
log.debug(message);
}
}

private void error(String message) {
if (log != null) {
log.error(message);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2017 - 2018 The ModiTect 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 org.moditect.internal.parser;

import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class JavaVersionHelperTest {

private JavaVersionHelper testTarget = new JavaVersionHelper();

@Test
public void current() {
JavaVersionHelper.Version version = testTarget.javaVersion();
assertThat(version.major()).isPositive();
assertThat(version.minor()).isNotNull();
assertThat(version.mini()).isNotNull();
}

@Test
public void simple() {
JavaVersionHelper.Version version = testTarget.javaVersion("11.0.10");
assertThat(version.major()).isEqualTo(11);
assertThat(version.minor()).isEqualTo(0);
assertThat(version.mini()).isEqualTo(10);
}

@Test
public void incomplete() {
JavaVersionHelper.Version version = testTarget.javaVersion("11");
assertThat(version).isNull();
}

@Test
public void oldStyle() {
JavaVersionHelper.Version version = testTarget.javaVersion("1.6.0_23");
assertThat(version.major()).isEqualTo(1);
assertThat(version.minor()).isEqualTo(6);
assertThat(version.mini()).isZero();
}

@Test
public void otherStuff() {
JavaVersionHelper.Version version = testTarget.javaVersion("1.6.0_23-otherStuff");
assertThat(version.major()).isEqualTo(1);
assertThat(version.minor()).isEqualTo(6);
assertThat(version.mini()).isZero();
}
}

0 comments on commit 30e9769

Please sign in to comment.