mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8357404: jpackage should attempt to get a package version from the JDK's release file if the --version option is not specified [v5]
This commit is contained in:
parent
6cd845508f
commit
6da599179e
@ -53,11 +53,13 @@ import static jdk.jpackage.internal.model.StandardPackageType.MAC_DMG;
|
||||
import static jdk.jpackage.internal.model.StandardPackageType.MAC_PKG;
|
||||
import static jdk.jpackage.internal.util.function.ExceptionBox.toUnchecked;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.UnaryOperator;
|
||||
import jdk.jpackage.internal.ApplicationBuilder.MainLauncherStartupInfo;
|
||||
import jdk.jpackage.internal.SigningIdentityBuilder.ExpiredCertificateException;
|
||||
import jdk.jpackage.internal.SigningIdentityBuilder.StandardCertificateSelector;
|
||||
@ -65,6 +67,7 @@ import jdk.jpackage.internal.cli.OptionValue;
|
||||
import jdk.jpackage.internal.cli.Options;
|
||||
import jdk.jpackage.internal.cli.StandardFaOption;
|
||||
import jdk.jpackage.internal.model.Application;
|
||||
import jdk.jpackage.internal.model.DottedVersion;
|
||||
import jdk.jpackage.internal.model.ApplicationLaunchers;
|
||||
import jdk.jpackage.internal.model.ExternalApplication;
|
||||
import jdk.jpackage.internal.model.FileAssociation;
|
||||
@ -219,24 +222,10 @@ final class MacFromOptions {
|
||||
if (isRuntimeInstaller(options) && !APP_VERSION.containsIn(options)) {
|
||||
// User didn't explicitly specify the version on the command line. jpackage derived it from the input.
|
||||
// In this case it should ensure the derived value is valid MacOS version.
|
||||
var ver = normalizeVersion(app.version());
|
||||
if (!ver.equals(app.version())) {
|
||||
Log.verbose(I18N.format("message.version-normalized",
|
||||
ver, app.version()));
|
||||
}
|
||||
|
||||
app = new Application.Stub(
|
||||
app.name(),
|
||||
app.description(),
|
||||
ver,
|
||||
app.vendor(),
|
||||
app.copyright(),
|
||||
app.srcDir(),
|
||||
app.contentDirs(),
|
||||
app.imageLayout(),
|
||||
app.runtimeBuilder(),
|
||||
app.launchers(),
|
||||
app.extraAppImageFileData());
|
||||
UnaryOperator<String> versionNormalizer = version -> {
|
||||
return normalizeVersion(version);
|
||||
};
|
||||
app = ApplicationBuilder.normalizeVersion(app, app.version(), versionNormalizer);
|
||||
}
|
||||
|
||||
final var appBuilder = new MacApplicationBuilder(app);
|
||||
@ -359,10 +348,10 @@ final class MacFromOptions {
|
||||
// macOS requires 1, 2 or 3 components version string.
|
||||
// When reading from release file it can be 1 or 3 or maybe more.
|
||||
// We always normalize to 3 components.
|
||||
String[] components = version.split("\\.");
|
||||
DottedVersion ver = DottedVersion.greedy(version);
|
||||
BigInteger[] components = ver.getComponents();
|
||||
if (components.length >= 4) {
|
||||
components = version.split("\\.", 4);
|
||||
return String.join(".", Arrays.copyOf(components, components.length - 1));
|
||||
return ver.toComponentsStringWithPadding(3);
|
||||
}
|
||||
|
||||
return version;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,6 +35,7 @@ import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.UnaryOperator;
|
||||
import jdk.jpackage.internal.model.AppImageLayout;
|
||||
import jdk.jpackage.internal.model.Application;
|
||||
import jdk.jpackage.internal.model.ApplicationLaunchers;
|
||||
@ -227,6 +228,28 @@ final class ApplicationBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
static Application normalizeVersion(Application app, String version,
|
||||
UnaryOperator<String> versionNormalizer) {
|
||||
final var ver = versionNormalizer.apply(version);
|
||||
if (!ver.equals(app.version())) {
|
||||
Log.verbose(I18N.format("message.version-normalized",
|
||||
ver, app.version()));
|
||||
}
|
||||
|
||||
return new Application.Stub(
|
||||
app.name(),
|
||||
app.description(),
|
||||
ver,
|
||||
app.vendor(),
|
||||
app.copyright(),
|
||||
app.srcDir(),
|
||||
app.contentDirs(),
|
||||
app.imageLayout(),
|
||||
app.runtimeBuilder(),
|
||||
app.launchers(),
|
||||
app.extraAppImageFileData());
|
||||
}
|
||||
|
||||
static Launcher overrideLauncherStartupInfo(Launcher launcher, LauncherStartupInfo startupInfo) {
|
||||
return new Launcher.Stub(
|
||||
launcher.name(),
|
||||
|
||||
@ -45,6 +45,8 @@ import static jdk.jpackage.internal.cli.StandardOption.PREDEFINED_RUNTIME_IMAGE;
|
||||
import static jdk.jpackage.internal.cli.StandardOption.RESOURCE_DIR;
|
||||
import static jdk.jpackage.internal.cli.StandardOption.VENDOR;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@ -54,6 +56,7 @@ import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import jdk.jpackage.internal.cli.Options;
|
||||
import jdk.jpackage.internal.util.RuntimeImageUtils;
|
||||
import jdk.jpackage.internal.util.RuntimeVersionReader;
|
||||
import jdk.jpackage.internal.model.Application;
|
||||
import jdk.jpackage.internal.model.ApplicationLaunchers;
|
||||
@ -176,12 +179,18 @@ final class FromOptions {
|
||||
appBuilder.appImageLayout(runtimeLayout);
|
||||
if (!APP_VERSION.containsIn(options)) {
|
||||
// Version is not specified explicitly. Try to get it from the release file.
|
||||
RuntimeVersionReader.readVersion(PREDEFINED_RUNTIME_IMAGE.getFrom(options))
|
||||
.ifPresent(version -> {
|
||||
appBuilder.version(version);
|
||||
Log.verbose(I18N.format("message.release-version",
|
||||
version, PREDEFINED_RUNTIME_IMAGE.getFrom(options)));
|
||||
});
|
||||
final Path releaseFile = RuntimeImageUtils.getReleaseFilePath(
|
||||
PREDEFINED_RUNTIME_IMAGE.getFrom(options));
|
||||
try {
|
||||
RuntimeVersionReader.readVersion(releaseFile)
|
||||
.ifPresent(version -> {
|
||||
appBuilder.version(version);
|
||||
Log.verbose(I18N.format("message.release-version",
|
||||
version, PREDEFINED_RUNTIME_IMAGE.getFrom(options)));
|
||||
});
|
||||
} catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
appBuilder.appImageLayout(appLayout);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,7 +35,7 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import jdk.internal.util.OperatingSystem;
|
||||
import jdk.jpackage.internal.util.RuntimeImageUtils;
|
||||
|
||||
record ModuleInfo(String name, Optional<String> version, Optional<String> mainClass, Optional<URI> location) {
|
||||
|
||||
@ -61,18 +61,7 @@ record ModuleInfo(String name, Optional<String> version, Optional<String> mainCl
|
||||
// is linked in the runtime by simply analysing the data
|
||||
// of `release` file.
|
||||
|
||||
final Path releaseFile;
|
||||
if (!OperatingSystem.isMacOS()) {
|
||||
releaseFile = cookedRuntime.resolve("release");
|
||||
} else {
|
||||
// On Mac `cookedRuntime` can be runtime root or runtime home.
|
||||
Path runtimeHome = cookedRuntime.resolve("Contents/Home");
|
||||
if (!Files.isDirectory(runtimeHome)) {
|
||||
runtimeHome = cookedRuntime;
|
||||
}
|
||||
releaseFile = runtimeHome.resolve("release");
|
||||
}
|
||||
|
||||
final Path releaseFile = RuntimeImageUtils.getReleaseFilePath(cookedRuntime);
|
||||
try (Reader reader = Files.newBufferedReader(releaseFile)) {
|
||||
Properties props = new Properties();
|
||||
props.load(reader);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -224,6 +224,16 @@ public final class DottedVersion {
|
||||
return Stream.of(components).map(BigInteger::toString).collect(Collectors.joining("."));
|
||||
}
|
||||
|
||||
public String toComponentsStringWithPadding(int numberOfComponents) {
|
||||
if (components.length >= numberOfComponents) {
|
||||
return Stream.of(components).map(BigInteger::toString)
|
||||
.limit(numberOfComponents).collect(Collectors.joining("."));
|
||||
} else {
|
||||
return toComponentsString()
|
||||
.concat(".0".repeat(numberOfComponents - components.length));
|
||||
}
|
||||
}
|
||||
|
||||
public BigInteger[] getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.jpackage.internal.util;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import jdk.internal.util.OperatingSystem;
|
||||
|
||||
public final class RuntimeImageUtils {
|
||||
|
||||
public static Path getReleaseFilePath(Path runtimePath) {
|
||||
final Path releaseFile;
|
||||
if (!OperatingSystem.isMacOS()) {
|
||||
releaseFile = runtimePath.resolve("release");
|
||||
} else {
|
||||
// On Mac `runtimePath` can be runtime root or runtime home.
|
||||
Path runtimeHome = runtimePath.resolve("Contents/Home");
|
||||
if (!Files.isDirectory(runtimeHome)) {
|
||||
runtimeHome = runtimePath;
|
||||
}
|
||||
releaseFile = runtimeHome.resolve("release");
|
||||
}
|
||||
|
||||
return releaseFile;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,53 +32,21 @@ import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
|
||||
import jdk.jpackage.internal.Log;
|
||||
import jdk.internal.util.OperatingSystem;
|
||||
|
||||
public final class RuntimeVersionReader {
|
||||
|
||||
public static Optional<String> readVersion(Path runtimeImage) {
|
||||
Optional<Path> releasePath = getRuntimeReleaseFile(runtimeImage);
|
||||
Optional<String> releaseVersion = Optional.empty();
|
||||
|
||||
if (releasePath.isPresent()) {
|
||||
try (Reader reader = Files.newBufferedReader(releasePath.get())) {
|
||||
Properties props = new Properties();
|
||||
props.load(reader);
|
||||
String version = props.getProperty("JAVA_VERSION");
|
||||
if (version != null) {
|
||||
version = version.replaceAll("^\"|\"$", "");
|
||||
}
|
||||
releaseVersion = Optional.ofNullable(version);
|
||||
} catch (IOException ex) {
|
||||
Log.verbose(ex);
|
||||
}
|
||||
};
|
||||
|
||||
return releaseVersion;
|
||||
}
|
||||
|
||||
private static Optional<Path> checkReleaseFilePath(Path releaseFilePath) {
|
||||
if (Files.isRegularFile(releaseFilePath)) {
|
||||
return Optional.of(releaseFilePath);
|
||||
} else {
|
||||
public static Optional<String> readVersion(Path releaseFilePath) throws IOException {
|
||||
if (!Files.isRegularFile(releaseFilePath)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private static Optional<Path> getRuntimeReleaseFile(Path runtimeImage) {
|
||||
Optional<Path> releasePath = Optional.empty();
|
||||
|
||||
// Try special case for macOS first ("Contents/Home/release").
|
||||
if (OperatingSystem.isMacOS()) {
|
||||
releasePath = checkReleaseFilePath(runtimeImage.resolve("Contents/Home/release"));
|
||||
try (Reader reader = Files.newBufferedReader(releaseFilePath)) {
|
||||
Properties props = new Properties();
|
||||
props.load(reader);
|
||||
String version = props.getProperty("JAVA_VERSION");
|
||||
if (version != null) {
|
||||
version = version.replaceAll("^\"|\"$", "");
|
||||
}
|
||||
return Optional.ofNullable(version);
|
||||
}
|
||||
|
||||
// Try root for all platforms including macOS if releasePath is not set
|
||||
if (releasePath.isEmpty()) {
|
||||
releasePath = checkReleaseFilePath(runtimeImage.resolve("release"));
|
||||
}
|
||||
|
||||
return releasePath;
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,10 +43,13 @@ import static jdk.jpackage.internal.cli.StandardOption.WIN_UPDATE_URL;
|
||||
import static jdk.jpackage.internal.cli.StandardOption.WIN_UPGRADE_UUID;
|
||||
import static jdk.jpackage.internal.model.StandardPackageType.WIN_MSI;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import jdk.jpackage.internal.cli.Options;
|
||||
import jdk.jpackage.internal.model.Application;
|
||||
import jdk.jpackage.internal.model.DottedVersion;
|
||||
import jdk.jpackage.internal.model.Launcher;
|
||||
import jdk.jpackage.internal.model.WinApplication;
|
||||
import jdk.jpackage.internal.model.WinExePackage;
|
||||
@ -83,24 +86,10 @@ final class WinFromOptions {
|
||||
if (isRuntimeInstaller(options) && !APP_VERSION.containsIn(options)) {
|
||||
// User didn't explicitly specify the version on the command line. jpackage derived it from the input.
|
||||
// In this case it should ensure the derived value is valid Windows version.
|
||||
var ver = normalizeVersion(app.version());
|
||||
if (!ver.equals(app.version())) {
|
||||
Log.verbose(I18N.format("message.version-normalized",
|
||||
ver, app.version()));
|
||||
}
|
||||
|
||||
app = new Application.Stub(
|
||||
app.name(),
|
||||
app.description(),
|
||||
ver,
|
||||
app.vendor(),
|
||||
app.copyright(),
|
||||
app.srcDir(),
|
||||
app.contentDirs(),
|
||||
app.imageLayout(),
|
||||
app.runtimeBuilder(),
|
||||
app.launchers(),
|
||||
app.extraAppImageFileData());
|
||||
UnaryOperator<String> versionNormalizer = version -> {
|
||||
return normalizeVersion(version);
|
||||
};
|
||||
app = ApplicationBuilder.normalizeVersion(app, app.version(), versionNormalizer);
|
||||
}
|
||||
|
||||
return WinApplication.create(app);
|
||||
@ -147,14 +136,11 @@ final class WinFromOptions {
|
||||
// Windows requires 2 or 4 components version string.
|
||||
// When reading from release file it can be 1 or 3 or maybe more.
|
||||
// We always normalize to 4 components.
|
||||
String[] components = version.split("\\.");
|
||||
if (components.length == 1) {
|
||||
return version.concat(".0.0.0");
|
||||
} else if (components.length == 3) {
|
||||
return version.concat(".0");
|
||||
} else if (components.length >= 5) {
|
||||
components = version.split("\\.", 5);
|
||||
return String.join(".", Arrays.copyOf(components, components.length - 1));
|
||||
DottedVersion ver = DottedVersion.greedy(version);
|
||||
BigInteger[] components = ver.getComponents();
|
||||
if (components.length == 1 || components.length == 3 ||
|
||||
components.length >= 5) {
|
||||
return ver.toComponentsStringWithPadding(4);
|
||||
}
|
||||
|
||||
return version;
|
||||
|
||||
@ -63,6 +63,7 @@ import java.util.spi.ToolProvider;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
import jdk.jpackage.internal.util.RuntimeImageUtils;
|
||||
import jdk.jpackage.internal.util.RuntimeVersionReader;
|
||||
import jdk.jpackage.internal.util.function.ExceptionBox;
|
||||
import jdk.jpackage.internal.util.function.ThrowingConsumer;
|
||||
@ -248,26 +249,27 @@ public class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
}
|
||||
|
||||
public String version() {
|
||||
if (isRuntime()) {
|
||||
String appVersion = getArgumentValue("--app-version");
|
||||
if (appVersion != null) {
|
||||
return appVersion;
|
||||
} else {
|
||||
Optional<String> releaseVersion = RuntimeVersionReader
|
||||
.readVersion(Path.of(getArgumentValue("--runtime-image")));
|
||||
if (releaseVersion.isPresent()) {
|
||||
if (TKit.isWindows()) {
|
||||
return WindowsHelper.getNormalizedVersion(this, releaseVersion.get());
|
||||
} else if (TKit.isOSX()) {
|
||||
return MacHelper.getNormalizedVersion(this, releaseVersion.get());
|
||||
}
|
||||
|
||||
return releaseVersion.get();
|
||||
return Optional.ofNullable(getArgumentValue("--app-version")).or(() -> {
|
||||
if (isRuntime()) {
|
||||
final Path releaseFile = RuntimeImageUtils.getReleaseFilePath(
|
||||
Path.of(getArgumentValue("--runtime-image")));
|
||||
try {
|
||||
return RuntimeVersionReader.readVersion(releaseFile).map(releaseVersion -> {
|
||||
if (TKit.isWindows()) {
|
||||
return WindowsHelper.getNormalizedVersion(releaseVersion);
|
||||
} else if (TKit.isOSX()) {
|
||||
return MacHelper.getNormalizedVersion(releaseVersion);
|
||||
} else {
|
||||
return releaseVersion;
|
||||
}
|
||||
});
|
||||
} catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
return getArgumentValue("--app-version", () -> "1.0");
|
||||
}).orElse("1.0");
|
||||
}
|
||||
|
||||
public String name() {
|
||||
@ -315,10 +317,6 @@ public class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
}
|
||||
|
||||
public JPackageCommand setFakeRuntime() {
|
||||
return setFakeRuntime(Optional.empty());
|
||||
}
|
||||
|
||||
public JPackageCommand setFakeRuntime(Optional<String> version) {
|
||||
verifyMutable();
|
||||
|
||||
ThrowingConsumer<Path, IOException> createBulkFile = path -> {
|
||||
@ -347,19 +345,6 @@ public class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
// an error by PackageTest.
|
||||
createBulkFile.accept(fakeRuntimeDir.resolve(Path.of("lib", "bulk")));
|
||||
|
||||
// Create release file with version if provided
|
||||
version.ifPresent(ver -> {
|
||||
Properties props = new Properties();
|
||||
props.setProperty("JAVA_VERSION", ver);
|
||||
try (Writer writer = Files.newBufferedWriter(fakeRuntimeDir.resolve("release"))) {
|
||||
props.store(writer, null);
|
||||
} catch (IOException ex) {
|
||||
TKit.trace(String.format(
|
||||
"Failed to create [%s] file: %s",
|
||||
fakeRuntimeDir.resolve("release"), ex));
|
||||
}
|
||||
});
|
||||
|
||||
cmd.setArgumentValue("--runtime-image", fakeRuntimeDir);
|
||||
});
|
||||
|
||||
|
||||
@ -42,6 +42,7 @@ import java.io.UncheckedIOException;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.LinkOption;
|
||||
@ -72,6 +73,7 @@ import jdk.jpackage.internal.util.PListReader;
|
||||
import jdk.jpackage.internal.util.PathUtils;
|
||||
import jdk.jpackage.internal.util.RetryExecutor;
|
||||
import jdk.jpackage.internal.util.XmlUtils;
|
||||
import jdk.jpackage.internal.model.DottedVersion;
|
||||
import jdk.jpackage.internal.util.function.ThrowingConsumer;
|
||||
import jdk.jpackage.internal.util.function.ThrowingSupplier;
|
||||
import jdk.jpackage.test.MacSign.CertificateRequest;
|
||||
@ -761,14 +763,13 @@ public final class MacHelper {
|
||||
cmd.packageType().getSuffix());
|
||||
}
|
||||
|
||||
static String getNormalizedVersion(JPackageCommand cmd, String version) {
|
||||
cmd.verifyIsOfType(PackageType.MAC);
|
||||
static String getNormalizedVersion(String version) {
|
||||
// macOS requires 1, 2 or 3 components version string.
|
||||
// We always normalize to 3 components.
|
||||
String[] components = version.split("\\.");
|
||||
DottedVersion ver = DottedVersion.greedy(version);
|
||||
BigInteger[] components = ver.getComponents();
|
||||
if (components.length >= 4) {
|
||||
components = version.split("\\.", 4);
|
||||
return String.join(".", Arrays.copyOf(components, components.length - 1));
|
||||
return ver.toComponentsStringWithPadding(3);
|
||||
}
|
||||
|
||||
return version;
|
||||
|
||||
@ -29,6 +29,7 @@ import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
@ -44,6 +45,7 @@ import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.jpackage.internal.model.DottedVersion;
|
||||
import jdk.jpackage.internal.util.function.ThrowingRunnable;
|
||||
import jdk.jpackage.test.PackageTest.PackageHandlers;
|
||||
|
||||
@ -55,18 +57,14 @@ public class WindowsHelper {
|
||||
cmd.packageType().getSuffix());
|
||||
}
|
||||
|
||||
static String getNormalizedVersion(JPackageCommand cmd, String version) {
|
||||
cmd.verifyIsOfType(PackageType.WINDOWS);
|
||||
static String getNormalizedVersion(String version) {
|
||||
// Windows requires 2 or 4 components version string.
|
||||
// We always normalize to 4 components.
|
||||
String[] components = version.split("\\.");
|
||||
if (components.length == 1) {
|
||||
return version.concat(".0.0.0");
|
||||
} else if (components.length == 3) {
|
||||
return version.concat(".0");
|
||||
} else if (components.length >= 5) {
|
||||
components = version.split("\\.", 5);
|
||||
return String.join(".", Arrays.copyOf(components, components.length - 1));
|
||||
DottedVersion ver = DottedVersion.greedy(version);
|
||||
BigInteger[] components = ver.getComponents();
|
||||
if (components.length == 1 || components.length == 3 ||
|
||||
components.length >= 5) {
|
||||
return ver.toComponentsStringWithPadding(4);
|
||||
}
|
||||
|
||||
return version;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -41,26 +41,30 @@ public class DottedVersionTest {
|
||||
|
||||
public record TestConfig(String input,
|
||||
Function<String, DottedVersion> createVersion, String expectedSuffix,
|
||||
int expectedComponentCount, String expectedToComponent) {
|
||||
int expectedComponentCount, String expectedToComponent, int numberOfComponents) {
|
||||
|
||||
TestConfig(String input, Type type, int expectedComponentCount, String expectedToComponent) {
|
||||
this(input, type.createVersion, "", expectedComponentCount, expectedToComponent);
|
||||
this(input, type.createVersion, "", expectedComponentCount, expectedToComponent, -1);
|
||||
}
|
||||
|
||||
TestConfig(String input, Type type, int expectedComponentCount) {
|
||||
this(input, type.createVersion, "", expectedComponentCount, input);
|
||||
this(input, type.createVersion, "", expectedComponentCount, input, -1);
|
||||
}
|
||||
|
||||
TestConfig(String input, Type type, String expectedToComponent, int numberOfComponents) {
|
||||
this(input, type.createVersion, "", -1, expectedToComponent, numberOfComponents);
|
||||
}
|
||||
|
||||
static TestConfig greedy(String input, int expectedComponentCount, String expectedToComponent) {
|
||||
return new TestConfig(input, Type.GREEDY.createVersion, "", expectedComponentCount, expectedToComponent);
|
||||
return new TestConfig(input, Type.GREEDY.createVersion, "", expectedComponentCount, expectedToComponent, -1);
|
||||
}
|
||||
|
||||
static TestConfig greedy(String input, int expectedComponentCount) {
|
||||
return new TestConfig(input, Type.GREEDY.createVersion, "", expectedComponentCount, input);
|
||||
return new TestConfig(input, Type.GREEDY.createVersion, "", expectedComponentCount, input, -1);
|
||||
}
|
||||
|
||||
static TestConfig lazy(String input, String expectedSuffix, int expectedComponentCount, String expectedToComponent) {
|
||||
return new TestConfig(input, Type.LAZY.createVersion, expectedSuffix, expectedComponentCount, expectedToComponent);
|
||||
return new TestConfig(input, Type.LAZY.createVersion, expectedSuffix, expectedComponentCount, expectedToComponent, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,6 +118,29 @@ public class DottedVersionTest {
|
||||
return data;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource
|
||||
public void testComponentsStringWithPadding(TestConfig cfg) {
|
||||
var dv = cfg.createVersion.apply(cfg.input());
|
||||
assertEquals(cfg.expectedToComponent(),
|
||||
dv.toComponentsStringWithPadding(cfg.numberOfComponents()));
|
||||
}
|
||||
|
||||
private static List<TestConfig> testComponentsStringWithPadding() {
|
||||
List<TestConfig> data = new ArrayList<>();
|
||||
for (var type : Type.values()) {
|
||||
data.addAll(List.of(
|
||||
new TestConfig("1", type, "1.0.0.0", 4),
|
||||
new TestConfig("1.2", type, "1.2.0.0", 4),
|
||||
new TestConfig("1.2.3", type, "1.2.3.0", 4),
|
||||
new TestConfig("1.2.3.4", type, "1.2.3.4", 4),
|
||||
new TestConfig("1.2.3.4.5", type, "1.2.3.4", 4)
|
||||
));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
record InvalidVersionTestSpec(String version, String invalidComponent) {
|
||||
public InvalidVersionTestSpec {
|
||||
Objects.requireNonNull(version);
|
||||
|
||||
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.jpackage.internal.util;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
public class RuntimeVersionReaderTest {
|
||||
|
||||
@Test
|
||||
public void test_release_file_with_version(@TempDir Path workdir) {
|
||||
final Optional<String> version;
|
||||
try {
|
||||
version = RuntimeVersionReader.readVersion(
|
||||
createPropFileWithValue(workdir, "JAVA_VERSION", "27.1.2"));
|
||||
} catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
assertTrue(version.isPresent());
|
||||
version.ifPresent(ver -> {
|
||||
assertEquals("27.1.2", version.get());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_release_file_without_version(@TempDir Path workdir) {
|
||||
final Optional<String> version;
|
||||
try {
|
||||
version = RuntimeVersionReader.readVersion(
|
||||
createPropFileWithValue(workdir, "JDK_VERSION", "27.1.2"));
|
||||
} catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
assertFalse(version.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_release_file_invalid_input(@TempDir Path workdir) {
|
||||
final Optional<String> version;
|
||||
try {
|
||||
version = RuntimeVersionReader.readVersion(workdir);
|
||||
} catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
assertFalse(version.isPresent());
|
||||
}
|
||||
|
||||
private Path createPropFileWithValue(Path workdir, String name, String value)
|
||||
throws IOException {
|
||||
Path releaseFile = workdir.resolve("release");
|
||||
Properties props = new Properties();
|
||||
props.setProperty(name, "\"" + value + "\"");
|
||||
try (Writer writer = Files.newBufferedWriter(releaseFile)) {
|
||||
props.store(writer, null);
|
||||
}
|
||||
|
||||
return releaseFile;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -23,17 +23,22 @@
|
||||
|
||||
import static jdk.internal.util.OperatingSystem.LINUX;
|
||||
import static jdk.internal.util.OperatingSystem.MACOS;
|
||||
import static jdk.internal.util.OperatingSystem.WINDOWS;
|
||||
import static jdk.jpackage.test.TKit.assertFalse;
|
||||
import static jdk.jpackage.test.TKit.assertTrue;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import jdk.jpackage.test.Annotations.Parameter;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.JPackageStringBundle;
|
||||
import jdk.jpackage.test.LinuxHelper;
|
||||
import jdk.jpackage.test.MacHelper;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
@ -79,15 +84,15 @@ import jdk.jpackage.test.TKit;
|
||||
*/
|
||||
public class RuntimePackageTest {
|
||||
|
||||
@Test
|
||||
public static void test() {
|
||||
init().run();
|
||||
}
|
||||
// @Test
|
||||
// public static void test() {
|
||||
// init().run();
|
||||
// }
|
||||
|
||||
@Test(ifOS = MACOS)
|
||||
public static void testFromBundle() {
|
||||
init(MacHelper::createRuntimeBundle).run();
|
||||
}
|
||||
// @Test(ifOS = MACOS)
|
||||
// public static void testFromBundle() {
|
||||
// init(MacHelper::createRuntimeBundle).run();
|
||||
// }
|
||||
|
||||
@Test(ifOS = LINUX)
|
||||
@Parameter("/usr")
|
||||
@ -98,27 +103,66 @@ public class RuntimePackageTest {
|
||||
.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testName() {
|
||||
// Test that jpackage can derive package name from the path to runtime image.
|
||||
init()
|
||||
.addInitializer(cmd -> cmd.removeArgumentWithValue("--name"))
|
||||
// Don't attempt to install this package as it may have an odd name derived from
|
||||
// the runtime image path. Say, on Linux for `--runtime-image foo/bar/sed`
|
||||
// command line jpackage will create a package named 'sed' that will conflict
|
||||
// with the default 'sed' package.
|
||||
.run(Action.CREATE_AND_UNPACK);
|
||||
}
|
||||
// @Test
|
||||
// public static void testName() {
|
||||
// // Test that jpackage can derive package name from the path to runtime image.
|
||||
// init()
|
||||
// .addInitializer(cmd -> cmd.removeArgumentWithValue("--name"))
|
||||
// // Don't attempt to install this package as it may have an odd name derived from
|
||||
// // the runtime image path. Say, on Linux for `--runtime-image foo/bar/sed`
|
||||
// // command line jpackage will create a package named 'sed' that will conflict
|
||||
// // with the default 'sed' package.
|
||||
// .run(Action.CREATE_AND_UNPACK);
|
||||
// }
|
||||
|
||||
@Test
|
||||
@Parameter("27")
|
||||
@Parameter("27.1")
|
||||
@Parameter("27.1.2")
|
||||
@Parameter("27.1.2.3")
|
||||
@Parameter("27.1.2.3.4")
|
||||
public static void testReleaseFileVersion(String version) {
|
||||
init()
|
||||
.addInitializer(cmd -> cmd.setFakeRuntime(Optional.of(version)))
|
||||
// 27
|
||||
@Parameter(value = {"27", ""}, ifOS = {LINUX, MACOS})
|
||||
@Parameter(value = {"27", "27.0.0.0"}, ifOS = WINDOWS)
|
||||
// 27.1
|
||||
@Parameter(value = {"27.1", ""})
|
||||
// 27.1.2
|
||||
@Parameter(value = {"27.1.2", ""}, ifOS = {LINUX, MACOS})
|
||||
@Parameter(value = {"27.1.2", "27.1.2.0"}, ifOS = WINDOWS)
|
||||
// 27.1.2.3
|
||||
@Parameter(value = {"27.1.2.3", ""}, ifOS = {LINUX, WINDOWS})
|
||||
@Parameter(value = {"27.1.2.3", "27.1.2"}, ifOS = MACOS)
|
||||
// 27.1.2.3.4
|
||||
@Parameter(value = {"27.1.2.3.4", ""}, ifOS = LINUX)
|
||||
@Parameter(value = {"27.1.2.3.4", "27.1.2"}, ifOS = MACOS)
|
||||
@Parameter(value = {"27.1.2.3.4", "27.1.2.3"}, ifOS = WINDOWS)
|
||||
public static void testReleaseFileVersion(String version, String normalizedVersion) {
|
||||
new PackageTest()
|
||||
.addInitializer(cmd -> {
|
||||
// Remove --input parameter from jpackage command line as we don't
|
||||
// create input directory in the test and jpackage fails
|
||||
// if --input references non existant directory.
|
||||
cmd.removeArgumentWithValue("--input");
|
||||
|
||||
cmd.setFakeRuntime();
|
||||
|
||||
// Execute prerequisite actions, so fake runtime gets created
|
||||
cmd.executePrerequisiteActions();
|
||||
|
||||
// Create release file with version in fake runtime
|
||||
Path runtimeImage = Path.of(cmd.getArgumentValue("--runtime-image"));
|
||||
Path releaseFile = runtimeImage.resolve("release");
|
||||
Properties props = new Properties();
|
||||
props.setProperty("JAVA_VERSION", "\"" + version + "\"");
|
||||
try (Writer writer = Files.newBufferedWriter(releaseFile)) {
|
||||
props.store(writer, null);
|
||||
}
|
||||
|
||||
// Validate output
|
||||
cmd.validateOutput(JPackageStringBundle.MAIN
|
||||
.cannedFormattedString("message.release-version",
|
||||
version, runtimeImage.toString()));
|
||||
if (!normalizedVersion.isEmpty()) {
|
||||
cmd.validateOutput(JPackageStringBundle.MAIN
|
||||
.cannedFormattedString("message.version-normalized",
|
||||
normalizedVersion, version));
|
||||
}
|
||||
})
|
||||
// Just create package. It is enough to verify version in bundle name.
|
||||
.run(Action.CREATE);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user