mirror of
https://github.com/actions/setup-java.git
synced 2026-07-31 22:51:39 +08:00
Harden java-package validation (#1165)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 10b8fe1e-18f4-42cb-8672-11215715a713
This commit is contained in:
parent
6e26972896
commit
19c23b379e
@ -48,7 +48,7 @@ For more details, see the full release notes on the [releases page](https://git
|
|||||||
|
|
||||||
- `distribution`: Java [distribution](#supported-distributions). Required unless `java-version-file` points to `.sdkmanrc` with a recognized distribution suffix (for example `java=21.0.5-tem`).
|
- `distribution`: Java [distribution](#supported-distributions). Required unless `java-version-file` points to `.sdkmanrc` with a recognized distribution suffix (for example `java=21.0.5-tem`).
|
||||||
|
|
||||||
- `java-package`: The packaging variant of the chosen distribution. Possible values: `jdk`, `jre`, `jdk+fx`, `jre+fx`. For Azul Zulu, `jdk+crac` and `jre+crac` are also supported. For Eclipse Temurin 24 and later, `jdk+jmods` includes the separately packaged JMOD files. Default value: `jdk`.
|
- `java-package`: The packaging variant of the chosen distribution. Possible values across all distributions are `jdk`, `jre`, `jdk+fx`, `jre+fx`, `jdk+crac`, `jre+crac`, `jdk+jmods`, `jdk+jcef`, `jre+jcef`, `jdk+ft`, and `jre+ft`. Supported values vary by distribution; see the [package compatibility table](docs/advanced-usage.md#package-compatibility). Default value: `jdk`.
|
||||||
|
|
||||||
- `architecture`: The target architecture of the package. Possible values: `x86`, `x64`, `armv7`, `aarch64`, `ppc64le`. Default value: Derived from the runner machine.
|
- `architecture`: The target architecture of the package. Possible values: `x86`, `x64`, `armv7`, `aarch64`, `ppc64le`. Default value: Derived from the runner machine.
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,16 @@
|
|||||||
import {getJavaDistribution} from '../../src/distributions/distribution-factory.js';
|
import {getJavaDistribution} from '../../src/distributions/distribution-factory.js';
|
||||||
import {RetryingHttpClient} from '../../src/retrying-http-client.js';
|
import {RetryingHttpClient} from '../../src/retrying-http-client.js';
|
||||||
|
import {
|
||||||
|
JAVA_PACKAGE_CAPABILITIES,
|
||||||
|
JavaDistribution
|
||||||
|
} from '../../src/distributions/package-types.js';
|
||||||
|
|
||||||
|
const installerOptions = (packageType: string, version = '25') => ({
|
||||||
|
version,
|
||||||
|
architecture: 'x64',
|
||||||
|
packageType,
|
||||||
|
checkLatest: false
|
||||||
|
});
|
||||||
|
|
||||||
describe('getJavaDistribution', () => {
|
describe('getJavaDistribution', () => {
|
||||||
it.each([
|
it.each([
|
||||||
@ -33,16 +44,71 @@ describe('getJavaDistribution', () => {
|
|||||||
expect(distribution!['http']).toBeInstanceOf(RetryingHttpClient);
|
expect(distribution!['http']).toBeInstanceOf(RetryingHttpClient);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each(
|
||||||
|
Object.entries(JAVA_PACKAGE_CAPABILITIES).flatMap(
|
||||||
|
([distributionName, packageTypes]) =>
|
||||||
|
packageTypes.map(packageType => [distributionName, packageType])
|
||||||
|
)
|
||||||
|
)('accepts %s with java-package %s', (distributionName, packageType) => {
|
||||||
|
expect(
|
||||||
|
getJavaDistribution(
|
||||||
|
distributionName,
|
||||||
|
installerOptions(packageType as string)
|
||||||
|
)
|
||||||
|
).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(Object.entries(JAVA_PACKAGE_CAPABILITIES))(
|
||||||
|
'rejects unsupported java-package values for %s',
|
||||||
|
(distributionName, packageTypes) => {
|
||||||
|
expect(() =>
|
||||||
|
getJavaDistribution(distributionName, installerOptions('jdk+typo'))
|
||||||
|
).toThrow(
|
||||||
|
`Java package 'jdk+typo' is not supported for distribution '${distributionName}'. Supported package types: ${packageTypes.join(', ')}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
it("rejects java-package 'jdk+jmods' for non-Temurin distributions", () => {
|
it("rejects java-package 'jdk+jmods' for non-Temurin distributions", () => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
getJavaDistribution('zulu', {
|
getJavaDistribution('zulu', installerOptions('jdk+jmods'))
|
||||||
version: '25',
|
|
||||||
architecture: 'x64',
|
|
||||||
packageType: 'jdk+jmods',
|
|
||||||
checkLatest: false
|
|
||||||
})
|
|
||||||
).toThrow(
|
).toThrow(
|
||||||
"java-package 'jdk+jmods' is only supported for distribution 'temurin'."
|
"Java package 'jdk+jmods' is not supported for distribution 'zulu'. Supported package types: jdk, jre, jdk+fx, jre+fx, jdk+crac, jre+crac."
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each(['8', '23.x', '23.0.1.1', '<24'])(
|
||||||
|
"rejects Temurin java-package 'jdk+jmods' for version %s",
|
||||||
|
version => {
|
||||||
|
expect(() =>
|
||||||
|
getJavaDistribution(
|
||||||
|
JavaDistribution.Temurin,
|
||||||
|
installerOptions('jdk+jmods', version)
|
||||||
|
)
|
||||||
|
).toThrow(
|
||||||
|
`Java package 'jdk+jmods' is not supported for distribution 'temurin'. Supported package types: jdk, jre, jdk+jmods. Package 'jdk+jmods' requires Java 24 or later; requested version '${version}'.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it.each(['24', '24.0.1.1', '25-ea', '>=21', 'latest'])(
|
||||||
|
"accepts Temurin java-package 'jdk+jmods' for version %s",
|
||||||
|
version => {
|
||||||
|
expect(
|
||||||
|
getJavaDistribution(
|
||||||
|
JavaDistribution.Temurin,
|
||||||
|
installerOptions('jdk+jmods', version)
|
||||||
|
)
|
||||||
|
).not.toBeNull();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it('preserves unsupported distribution handling', () => {
|
||||||
|
expect(
|
||||||
|
getJavaDistribution(
|
||||||
|
'not-a-distribution',
|
||||||
|
installerOptions('not-a-package')
|
||||||
|
)
|
||||||
|
).toBeNull();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
82
__tests__/java-package-contract.test.ts
Normal file
82
__tests__/java-package-contract.test.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import {
|
||||||
|
JAVA_PACKAGE_CAPABILITIES,
|
||||||
|
JavaDistribution
|
||||||
|
} from '../src/distributions/package-types.js';
|
||||||
|
|
||||||
|
const repositoryRoot = process.cwd();
|
||||||
|
const readRepositoryFile = (filePath: string) =>
|
||||||
|
fs.readFileSync(path.join(repositoryRoot, filePath), 'utf8');
|
||||||
|
const allPackageTypes = [
|
||||||
|
...new Set(Object.values(JAVA_PACKAGE_CAPABILITIES).flat())
|
||||||
|
];
|
||||||
|
|
||||||
|
describe('java-package published contract', () => {
|
||||||
|
it.each(['action.yml', 'README.md'])(
|
||||||
|
'documents every supported package type in %s',
|
||||||
|
filePath => {
|
||||||
|
const content = readRepositoryFile(filePath);
|
||||||
|
const contractLine =
|
||||||
|
filePath === 'action.yml'
|
||||||
|
? content.match(/ {2}java-package:\n(?: {4}.+\n)+/)?.[0]
|
||||||
|
: content
|
||||||
|
.split('\n')
|
||||||
|
.find(line => line.includes('- `java-package`:'));
|
||||||
|
|
||||||
|
expect(contractLine).toBeDefined();
|
||||||
|
for (const packageType of allPackageTypes) {
|
||||||
|
expect(contractLine).toContain(`\`${packageType}\``);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it.each(Object.entries(JAVA_PACKAGE_CAPABILITIES))(
|
||||||
|
'keeps the advanced compatibility table aligned for %s',
|
||||||
|
(distributionName, packageTypes) => {
|
||||||
|
const advancedUsage = readRepositoryFile('docs/advanced-usage.md');
|
||||||
|
const compatibilityTable = advancedUsage.slice(
|
||||||
|
advancedUsage.indexOf('### Package compatibility')
|
||||||
|
);
|
||||||
|
const compatibilityRow = compatibilityTable
|
||||||
|
.split('\n')
|
||||||
|
.find(
|
||||||
|
line =>
|
||||||
|
line.startsWith('|') && line.includes(`\`${distributionName}\``)
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(compatibilityRow).toBeDefined();
|
||||||
|
for (const packageType of packageTypes) {
|
||||||
|
expect(compatibilityRow).toContain(`\`${packageType}\``);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it('only exercises supported distribution/package combinations in E2E', () => {
|
||||||
|
const workflow = readRepositoryFile('.github/workflows/e2e-versions.yml');
|
||||||
|
const defaultMatrix = workflow.match(
|
||||||
|
/distribution:\s*\n\s*\[([^\]]+)\]\s*\n\s*java-package:\s*\['([^']+)'\]/
|
||||||
|
);
|
||||||
|
expect(defaultMatrix).not.toBeNull();
|
||||||
|
|
||||||
|
const defaultDistributions = [
|
||||||
|
...defaultMatrix![1].matchAll(/'([^']+)'/g)
|
||||||
|
].map(match => match[1]);
|
||||||
|
const defaultPackage = defaultMatrix![2];
|
||||||
|
for (const distributionName of defaultDistributions) {
|
||||||
|
expect(supportedPackagesFor(distributionName)).toContain(defaultPackage);
|
||||||
|
}
|
||||||
|
|
||||||
|
const includedPackages = workflow.matchAll(
|
||||||
|
/- distribution: '([^']+)'\s*\n\s*java-package: ([^\s]+)/g
|
||||||
|
);
|
||||||
|
for (const match of includedPackages) {
|
||||||
|
const [, distributionName, packageType] = match;
|
||||||
|
expect(supportedPackagesFor(distributionName)).toContain(packageType);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function supportedPackagesFor(distributionName: string): readonly string[] {
|
||||||
|
return JAVA_PACKAGE_CAPABILITIES[distributionName as JavaDistribution] ?? [];
|
||||||
|
}
|
||||||
@ -13,7 +13,7 @@ inputs:
|
|||||||
description: 'Java distribution. See the list of supported distributions in README file. This input is required except when java-version-file points to .sdkmanrc with a recognized distribution suffix (e.g., java=21.0.5-tem).'
|
description: 'Java distribution. See the list of supported distributions in README file. This input is required except when java-version-file points to .sdkmanrc with a recognized distribution suffix (e.g., java=21.0.5-tem).'
|
||||||
required: false
|
required: false
|
||||||
java-package:
|
java-package:
|
||||||
description: 'The package type (jdk, jre, jdk+fx, jre+fx, jdk+crac, jre+crac, jdk+jmods)'
|
description: 'The package type (`jdk`, `jre`, `jdk+fx`, `jre+fx`, `jdk+crac`, `jre+crac`, `jdk+jmods`, `jdk+jcef`, `jre+jcef`, `jdk+ft`, or `jre+ft`). Supported values vary by distribution.'
|
||||||
required: false
|
required: false
|
||||||
default: 'jdk'
|
default: 'jdk'
|
||||||
architecture:
|
architecture:
|
||||||
|
|||||||
121
dist/setup/index.js
vendored
121
dist/setup/index.js
vendored
@ -132121,21 +132121,7 @@ class OpenJdkDistribution extends JavaBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
;// CONCATENATED MODULE: ./src/distributions/distribution-factory.ts
|
;// CONCATENATED MODULE: ./src/distributions/package-types.ts
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var JavaDistribution;
|
var JavaDistribution;
|
||||||
@ -132160,11 +132146,108 @@ var JavaDistribution;
|
|||||||
JavaDistribution["Kona"] = "kona";
|
JavaDistribution["Kona"] = "kona";
|
||||||
JavaDistribution["OracleOpenJdk"] = "oracle-openjdk";
|
JavaDistribution["OracleOpenJdk"] = "oracle-openjdk";
|
||||||
})(JavaDistribution || (JavaDistribution = {}));
|
})(JavaDistribution || (JavaDistribution = {}));
|
||||||
function getJavaDistribution(distributionName, installerOptions, jdkFile) {
|
const JAVA_PACKAGE_CAPABILITIES = {
|
||||||
if (installerOptions.packageType === 'jdk+jmods' &&
|
[JavaDistribution.Adopt]: ['jdk', 'jre'],
|
||||||
distributionName !== JavaDistribution.Temurin) {
|
[JavaDistribution.AdoptHotspot]: ['jdk', 'jre'],
|
||||||
throw new Error("java-package 'jdk+jmods' is only supported for distribution 'temurin'.");
|
[JavaDistribution.AdoptOpenJ9]: ['jdk', 'jre'],
|
||||||
|
[JavaDistribution.Temurin]: ['jdk', 'jre', 'jdk+jmods'],
|
||||||
|
[JavaDistribution.Zulu]: [
|
||||||
|
'jdk',
|
||||||
|
'jre',
|
||||||
|
'jdk+fx',
|
||||||
|
'jre+fx',
|
||||||
|
'jdk+crac',
|
||||||
|
'jre+crac'
|
||||||
|
],
|
||||||
|
[JavaDistribution.Liberica]: ['jdk', 'jre', 'jdk+fx', 'jre+fx'],
|
||||||
|
[JavaDistribution.LibericaNik]: ['jdk', 'jdk+fx'],
|
||||||
|
[JavaDistribution.JdkFile]: ['jdk'],
|
||||||
|
[JavaDistribution.Microsoft]: ['jdk'],
|
||||||
|
[JavaDistribution.Semeru]: ['jdk', 'jre'],
|
||||||
|
[JavaDistribution.Corretto]: ['jdk', 'jre'],
|
||||||
|
[JavaDistribution.Oracle]: ['jdk'],
|
||||||
|
[JavaDistribution.Dragonwell]: ['jdk'],
|
||||||
|
[JavaDistribution.SapMachine]: ['jdk', 'jre'],
|
||||||
|
[JavaDistribution.GraalVM]: ['jdk'],
|
||||||
|
[JavaDistribution.GraalVMCommunity]: ['jdk'],
|
||||||
|
[JavaDistribution.JetBrains]: [
|
||||||
|
'jdk',
|
||||||
|
'jre',
|
||||||
|
'jdk+jcef',
|
||||||
|
'jre+jcef',
|
||||||
|
'jdk+ft',
|
||||||
|
'jre+ft'
|
||||||
|
],
|
||||||
|
[JavaDistribution.Kona]: ['jdk'],
|
||||||
|
[JavaDistribution.OracleOpenJdk]: ['jdk']
|
||||||
|
};
|
||||||
|
function validateJavaPackage(distributionName, packageType, version) {
|
||||||
|
if (!isJavaDistribution(distributionName)) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
const supportedPackages = JAVA_PACKAGE_CAPABILITIES[distributionName];
|
||||||
|
if (!supportedPackages.includes(packageType)) {
|
||||||
|
throw createUnsupportedPackageError(distributionName, packageType, supportedPackages);
|
||||||
|
}
|
||||||
|
if (distributionName === JavaDistribution.Temurin &&
|
||||||
|
packageType === 'jdk+jmods' &&
|
||||||
|
!canResolveTemurinJmods(version)) {
|
||||||
|
throw createUnsupportedPackageError(distributionName, packageType, supportedPackages, `Package 'jdk+jmods' requires Java 24 or later; requested version '${version}'.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isJavaDistribution(value) {
|
||||||
|
return Object.prototype.hasOwnProperty.call(JAVA_PACKAGE_CAPABILITIES, value);
|
||||||
|
}
|
||||||
|
function canResolveTemurinJmods(version) {
|
||||||
|
const normalizedVersion = version.trim().toLowerCase();
|
||||||
|
if (normalizedVersion === 'latest') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
let normalizedRange = normalizedVersion
|
||||||
|
.replace(/-ea$/, '')
|
||||||
|
.replace('-ea.', '+');
|
||||||
|
if (/^\d+(\.\d+){3,}$/.test(normalizedRange)) {
|
||||||
|
normalizedRange = convertVersionToSemver(normalizedRange);
|
||||||
|
}
|
||||||
|
if (!semver_default().validRange(normalizedRange)) {
|
||||||
|
// JavaBase owns general version validation and its targeted error messages.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return semver_default().intersects(normalizedRange, '>=24.0.0', {
|
||||||
|
includePrerelease: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function createUnsupportedPackageError(distributionName, packageType, supportedPackages, detail) {
|
||||||
|
const message = [
|
||||||
|
`Java package '${packageType}' is not supported for distribution '${distributionName}'.`,
|
||||||
|
`Supported package types: ${supportedPackages.join(', ')}.`
|
||||||
|
];
|
||||||
|
if (detail) {
|
||||||
|
message.push(detail);
|
||||||
|
}
|
||||||
|
return new Error(message.join(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
;// CONCATENATED MODULE: ./src/distributions/distribution-factory.ts
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function getJavaDistribution(distributionName, installerOptions, jdkFile) {
|
||||||
|
validateJavaPackage(distributionName, installerOptions.packageType, installerOptions.version);
|
||||||
switch (distributionName) {
|
switch (distributionName) {
|
||||||
case JavaDistribution.JdkFile:
|
case JavaDistribution.JdkFile:
|
||||||
return new LocalDistribution(installerOptions, jdkFile);
|
return new LocalDistribution(installerOptions, jdkFile);
|
||||||
|
|||||||
@ -321,12 +321,10 @@ The package types have these meanings:
|
|||||||
| `graalvm-community` | `jdk` | Stable GraalVM Community releases for JDK 17 and later only. |
|
| `graalvm-community` | `jdk` | Stable GraalVM Community releases for JDK 17 and later only. |
|
||||||
| `jetbrains` | `jdk`, `jre`, `jdk+jcef`, `jre+jcef`, `jdk+ft`, `jre+ft` | JetBrains publishes selected LTS-based releases rather than every OpenJDK patch. JDK/JRE and JCEF bundles start with the Java 11 release family; FreeType bundles start with Java 17. Exact package, LTS family, patch, OS, and architecture availability is determined from release assets. |
|
| `jetbrains` | `jdk`, `jre`, `jdk+jcef`, `jre+jcef`, `jdk+ft`, `jre+ft` | JetBrains publishes selected LTS-based releases rather than every OpenJDK patch. JDK/JRE and JCEF bundles start with the Java 11 release family; FreeType bundles start with Java 17. Exact package, LTS family, patch, OS, and architecture availability is determined from release assets. |
|
||||||
| `kona` | `jdk` | Stable Java 8, 11, 17, 21, and 25 releases only. |
|
| `kona` | `jdk` | Stable Java 8, 11, 17, 21, and 25 releases only. |
|
||||||
| `jdkfile` | `jdk` (recommended) | The package contents and version are supplied by `jdk-file`; `setup-java` does not validate them. `java-package` only separates the local archive's tool-cache entry, so use `jdk` unless separate cache namespaces are required. |
|
| `jdkfile` | `jdk` | The package contents and version are supplied by `jdk-file`; `setup-java` validates the package type but does not inspect the archive contents. |
|
||||||
|
|
||||||
Values outside this table are unsupported even when a distribution forwards the
|
Values outside this table are unsupported. The action rejects them before
|
||||||
value to its vendor API instead of rejecting it immediately. In that case, the
|
checking the tool cache or requesting a vendor catalog.
|
||||||
action normally fails with a version-not-found error because no matching
|
|
||||||
artifact exists.
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@ -22,42 +22,18 @@ import {
|
|||||||
import {JetBrainsDistribution} from './jetbrains/installer.js';
|
import {JetBrainsDistribution} from './jetbrains/installer.js';
|
||||||
import {KonaDistribution} from './kona/installer.js';
|
import {KonaDistribution} from './kona/installer.js';
|
||||||
import {OpenJdkDistribution} from './openjdk/installer.js';
|
import {OpenJdkDistribution} from './openjdk/installer.js';
|
||||||
|
import {JavaDistribution, validateJavaPackage} from './package-types.js';
|
||||||
enum JavaDistribution {
|
|
||||||
Adopt = 'adopt',
|
|
||||||
AdoptHotspot = 'adopt-hotspot',
|
|
||||||
AdoptOpenJ9 = 'adopt-openj9',
|
|
||||||
Temurin = 'temurin',
|
|
||||||
Zulu = 'zulu',
|
|
||||||
Liberica = 'liberica',
|
|
||||||
LibericaNik = 'liberica-nik',
|
|
||||||
JdkFile = 'jdkfile',
|
|
||||||
Microsoft = 'microsoft',
|
|
||||||
Semeru = 'semeru',
|
|
||||||
Corretto = 'corretto',
|
|
||||||
Oracle = 'oracle',
|
|
||||||
Dragonwell = 'dragonwell',
|
|
||||||
SapMachine = 'sapmachine',
|
|
||||||
GraalVM = 'graalvm',
|
|
||||||
GraalVMCommunity = 'graalvm-community',
|
|
||||||
JetBrains = 'jetbrains',
|
|
||||||
Kona = 'kona',
|
|
||||||
OracleOpenJdk = 'oracle-openjdk'
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getJavaDistribution(
|
export function getJavaDistribution(
|
||||||
distributionName: string,
|
distributionName: string,
|
||||||
installerOptions: JavaInstallerOptions,
|
installerOptions: JavaInstallerOptions,
|
||||||
jdkFile?: string
|
jdkFile?: string
|
||||||
): JavaBase | null {
|
): JavaBase | null {
|
||||||
if (
|
validateJavaPackage(
|
||||||
installerOptions.packageType === 'jdk+jmods' &&
|
distributionName,
|
||||||
distributionName !== JavaDistribution.Temurin
|
installerOptions.packageType,
|
||||||
) {
|
installerOptions.version
|
||||||
throw new Error(
|
);
|
||||||
"java-package 'jdk+jmods' is only supported for distribution 'temurin'."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (distributionName) {
|
switch (distributionName) {
|
||||||
case JavaDistribution.JdkFile:
|
case JavaDistribution.JdkFile:
|
||||||
|
|||||||
135
src/distributions/package-types.ts
Normal file
135
src/distributions/package-types.ts
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
import semver from 'semver';
|
||||||
|
import {convertVersionToSemver} from '../util.js';
|
||||||
|
|
||||||
|
export enum JavaDistribution {
|
||||||
|
Adopt = 'adopt',
|
||||||
|
AdoptHotspot = 'adopt-hotspot',
|
||||||
|
AdoptOpenJ9 = 'adopt-openj9',
|
||||||
|
Temurin = 'temurin',
|
||||||
|
Zulu = 'zulu',
|
||||||
|
Liberica = 'liberica',
|
||||||
|
LibericaNik = 'liberica-nik',
|
||||||
|
JdkFile = 'jdkfile',
|
||||||
|
Microsoft = 'microsoft',
|
||||||
|
Semeru = 'semeru',
|
||||||
|
Corretto = 'corretto',
|
||||||
|
Oracle = 'oracle',
|
||||||
|
Dragonwell = 'dragonwell',
|
||||||
|
SapMachine = 'sapmachine',
|
||||||
|
GraalVM = 'graalvm',
|
||||||
|
GraalVMCommunity = 'graalvm-community',
|
||||||
|
JetBrains = 'jetbrains',
|
||||||
|
Kona = 'kona',
|
||||||
|
OracleOpenJdk = 'oracle-openjdk'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const JAVA_PACKAGE_CAPABILITIES = {
|
||||||
|
[JavaDistribution.Adopt]: ['jdk', 'jre'],
|
||||||
|
[JavaDistribution.AdoptHotspot]: ['jdk', 'jre'],
|
||||||
|
[JavaDistribution.AdoptOpenJ9]: ['jdk', 'jre'],
|
||||||
|
[JavaDistribution.Temurin]: ['jdk', 'jre', 'jdk+jmods'],
|
||||||
|
[JavaDistribution.Zulu]: [
|
||||||
|
'jdk',
|
||||||
|
'jre',
|
||||||
|
'jdk+fx',
|
||||||
|
'jre+fx',
|
||||||
|
'jdk+crac',
|
||||||
|
'jre+crac'
|
||||||
|
],
|
||||||
|
[JavaDistribution.Liberica]: ['jdk', 'jre', 'jdk+fx', 'jre+fx'],
|
||||||
|
[JavaDistribution.LibericaNik]: ['jdk', 'jdk+fx'],
|
||||||
|
[JavaDistribution.JdkFile]: ['jdk'],
|
||||||
|
[JavaDistribution.Microsoft]: ['jdk'],
|
||||||
|
[JavaDistribution.Semeru]: ['jdk', 'jre'],
|
||||||
|
[JavaDistribution.Corretto]: ['jdk', 'jre'],
|
||||||
|
[JavaDistribution.Oracle]: ['jdk'],
|
||||||
|
[JavaDistribution.Dragonwell]: ['jdk'],
|
||||||
|
[JavaDistribution.SapMachine]: ['jdk', 'jre'],
|
||||||
|
[JavaDistribution.GraalVM]: ['jdk'],
|
||||||
|
[JavaDistribution.GraalVMCommunity]: ['jdk'],
|
||||||
|
[JavaDistribution.JetBrains]: [
|
||||||
|
'jdk',
|
||||||
|
'jre',
|
||||||
|
'jdk+jcef',
|
||||||
|
'jre+jcef',
|
||||||
|
'jdk+ft',
|
||||||
|
'jre+ft'
|
||||||
|
],
|
||||||
|
[JavaDistribution.Kona]: ['jdk'],
|
||||||
|
[JavaDistribution.OracleOpenJdk]: ['jdk']
|
||||||
|
} as const satisfies Record<JavaDistribution, readonly string[]>;
|
||||||
|
|
||||||
|
export function validateJavaPackage(
|
||||||
|
distributionName: string,
|
||||||
|
packageType: string,
|
||||||
|
version: string
|
||||||
|
): void {
|
||||||
|
if (!isJavaDistribution(distributionName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const supportedPackages: readonly string[] =
|
||||||
|
JAVA_PACKAGE_CAPABILITIES[distributionName];
|
||||||
|
if (!supportedPackages.includes(packageType)) {
|
||||||
|
throw createUnsupportedPackageError(
|
||||||
|
distributionName,
|
||||||
|
packageType,
|
||||||
|
supportedPackages
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
distributionName === JavaDistribution.Temurin &&
|
||||||
|
packageType === 'jdk+jmods' &&
|
||||||
|
!canResolveTemurinJmods(version)
|
||||||
|
) {
|
||||||
|
throw createUnsupportedPackageError(
|
||||||
|
distributionName,
|
||||||
|
packageType,
|
||||||
|
supportedPackages,
|
||||||
|
`Package 'jdk+jmods' requires Java 24 or later; requested version '${version}'.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isJavaDistribution(value: string): value is JavaDistribution {
|
||||||
|
return Object.prototype.hasOwnProperty.call(JAVA_PACKAGE_CAPABILITIES, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function canResolveTemurinJmods(version: string): boolean {
|
||||||
|
const normalizedVersion = version.trim().toLowerCase();
|
||||||
|
if (normalizedVersion === 'latest') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let normalizedRange = normalizedVersion
|
||||||
|
.replace(/-ea$/, '')
|
||||||
|
.replace('-ea.', '+');
|
||||||
|
if (/^\d+(\.\d+){3,}$/.test(normalizedRange)) {
|
||||||
|
normalizedRange = convertVersionToSemver(normalizedRange);
|
||||||
|
}
|
||||||
|
if (!semver.validRange(normalizedRange)) {
|
||||||
|
// JavaBase owns general version validation and its targeted error messages.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return semver.intersects(normalizedRange, '>=24.0.0', {
|
||||||
|
includePrerelease: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createUnsupportedPackageError(
|
||||||
|
distributionName: JavaDistribution,
|
||||||
|
packageType: string,
|
||||||
|
supportedPackages: readonly string[],
|
||||||
|
detail?: string
|
||||||
|
): Error {
|
||||||
|
const message = [
|
||||||
|
`Java package '${packageType}' is not supported for distribution '${distributionName}'.`,
|
||||||
|
`Supported package types: ${supportedPackages.join(', ')}.`
|
||||||
|
];
|
||||||
|
if (detail) {
|
||||||
|
message.push(detail);
|
||||||
|
}
|
||||||
|
return new Error(message.join(' '));
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user