Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 39 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<img width="400" src="https://www.jenkins.io/images/jenkins-logo-title-dark.svg" alt="Jenkins logo">
</a>

# About
# About Jenkins

[![Jenkins Regular Release](https://img.shields.io/endpoint?url=https%3A%2F%2Fwww.jenkins.io%2Fchangelog%2Fbadge.json)](https://www.jenkins.io/changelog)
[![Jenkins LTS Release](https://img.shields.io/endpoint?url=https%3A%2F%2Fwww.jenkins.io%2Fchangelog-stable%2Fbadge.json)](https://www.jenkins.io/changelog-stable)
Expand All @@ -11,64 +11,69 @@
[![Reproducible Builds](https://img.shields.io/badge/Reproducible_Builds-ok-green)](https://maven.apache.org/guides/mini/guide-reproducible-builds.html)
[![Gitter](https://img.shields.io/gitter/room/jenkinsci/jenkins)](https://app.gitter.im/#/room/#jenkinsci_jenkins:gitter.im)

In a nutshell, Jenkins is the leading open-source automation server.
Built with Java, it provides over 2,000 [plugins](https://plugins.jenkins.io/) to support automating virtually anything,
so that humans can spend their time doing things machines cannot.
Jenkins is the leading open-source automation server. Built with Java, it provides over 2,000 [plugins](https://plugins.jenkins.io/) to automate virtually any task, allowing humans to focus on work machines cannot do.

# What to Use Jenkins for and When to Use It
---

Use Jenkins to automate your development workflow, so you can focus on work that matters most. Jenkins is commonly used for:
# What Jenkins Is Used For

Use Jenkins to automate your development workflow so you can focus on tasks that matter most. Common use cases include:

- Building projects
- Running tests to detect bugs and other issues as soon as they are introduced
- Running tests to detect bugs or issues early
- Static code analysis
- Deployment
- Deployment automation

Automate repetitive tasks, save time, and optimize your development process with Jenkins.

Execute repetitive tasks, save time, and optimize your development process with Jenkins.
---

# Downloads

The Jenkins project provides official distributions as WAR files, Docker images, native packages and installers for platforms including several Linux distributions and Windows.
See the [Downloads](https://www.jenkins.io/download) page for references.
Jenkins is available as WAR files, Docker images, and native packages for various platforms including Linux and Windows. See the [Downloads](https://www.jenkins.io/download) page.

For all distributions Jenkins offers two release lines:
Jenkins offers two release lines:

- [Weekly](https://www.jenkins.io/download/weekly/) -
Frequent releases which include all new features, improvements, and bug fixes.
- [Long-Term Support (LTS)](https://www.jenkins.io/download/lts/) -
Older release line which gets periodically updated via bug fix backports.
- [Weekly](https://www.jenkins.io/download/weekly/) – Frequent releases with new features, improvements, and bug fixes.
- [Long-Term Support (LTS)](https://www.jenkins.io/download/lts/) – Older releases with periodic bug fix backports.

Latest releases:
[![Jenkins Regular Release](https://img.shields.io/endpoint?url=https%3A%2F%2Fwww.jenkins.io%2Fchangelog%2Fbadge.json)](https://www.jenkins.io/changelog)
[![Jenkins LTS Release](https://img.shields.io/endpoint?url=https%3A%2F%2Fwww.jenkins.io%2Fchangelog-stable%2Fbadge.json)](https://www.jenkins.io/changelog-stable)
---

# Source Code

# Source
The latest Jenkins source code is available on [GitHub](https://github.com/jenkinsci/jenkins). Fork us and contribute!

Our latest and greatest source of Jenkins can be found on [GitHub](https://github.com/jenkinsci/jenkins). Fork us!
---

# Contributing to Jenkins
# Contributing

Follow the [contributing guidelines](CONTRIBUTING.md) if you want to propose a change in the Jenkins core.
For more information about participating in the community and contributing to the Jenkins project,
see [this page](https://www.jenkins.io/participate/).
Follow the [contributing guidelines](CONTRIBUTING.md) for changes to Jenkins core.
For more information about participating in the community, see [this page](https://www.jenkins.io/participate/).

Documentation for Jenkins core maintainers is in the [maintainers guidelines](docs/MAINTAINERS.adoc).
Documentation for Jenkins core maintainers is available in the [maintainers guidelines](docs/MAINTAINERS.adoc).

# News and Website
---

All information about Jenkins can be found on our [website](https://www.jenkins.io/).
Follow us on [Twitter](https://twitter.com/jenkinsci) or [LinkedIn](https://www.linkedin.com/company/jenkins-project/).
# News & Website

All information about Jenkins is available on our [website](https://www.jenkins.io/).
Follow Jenkins on [Twitter](https://twitter.com/jenkinsci) or [LinkedIn](https://www.linkedin.com/company/jenkins-project/).

---

# Governance

See the [Jenkins Governance Document](https://www.jenkins.io/project/governance/) for information about the project's open governance, our philosophy and values, and development practices.
Jenkins Code of Conduct can be found [here](https://www.jenkins.io/project/conduct/).
See the [Jenkins Governance Document](https://www.jenkins.io/project/governance/) for open governance practices, philosophy, and values.
Read the [Jenkins Code of Conduct](https://www.jenkins.io/project/conduct/) for community guidelines.

---

# Adopters

Jenkins is used by millions of users and thousands of companies.
See [adopters](https://www.jenkins.io/project/adopters/) for the list of Jenkins adopters and their success stories.
Jenkins is used by millions of users and thousands of companies. See [adopters](https://www.jenkins.io/project/adopters/) for success stories.

---

# License

Jenkins is **licensed** under the **[MIT License](LICENSE.txt)**.
Jenkins is licensed under the **[MIT License](LICENSE.txt)**.
79 changes: 54 additions & 25 deletions core/src/main/java/hudson/model/JDK.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* copies, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't change the license of existing source files.

Suggested change
* subject to the following conditions:
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:

*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
Expand Down Expand Up @@ -53,8 +53,10 @@
import org.kohsuke.stapler.DataBoundConstructor;

/**
* Information about JDK installation.
*
* Information about a JDK installation.
* Provides utility methods for validation, environment setup, and version detection.
* Includes improved Javadoc and getJavaVersion() for enhanced usability.
*
* @author Kohsuke Kawaguchi
*/
public final class JDK extends ToolInstallation implements NodeSpecific<JDK>, EnvironmentSpecific<JDK> {
Expand All @@ -64,12 +66,12 @@ public final class JDK extends ToolInstallation implements NodeSpecific<JDK>, En
* @since 1.577
*/
public static final String DEFAULT_NAME = "(System)";

private static final long serialVersionUID = -3318291200160313357L;

@Restricted(NoExternalUse.class)
public static boolean isDefaultName(String name) {
if ("(Default)".equals(name)) {
// DEFAULT_NAME took this value prior to 1.598.
return true;
}
return DEFAULT_NAME.equals(name) || name == null;
Expand All @@ -81,6 +83,9 @@ public static boolean isDefaultName(String name) {
@Deprecated // kept for backward compatibility - use getHome() instead
private transient String javaHome;

/**
* Basic constructor with name and home directory.
*/
public JDK(String name, String javaHome) {
super(name, javaHome, Collections.emptyList());
}
Expand All @@ -91,38 +96,70 @@ public JDK(String name, String home, List<? extends ToolProperty<?>> properties)
}

/**
* install directory.
*
* @deprecated as of 1.304
* Use {@link #getHome()}
* Use {@link #getHome()}
*/
@Deprecated
public String getJavaHome() {
return getHome();
}

/**
* Gets the path to the bin directory.
* Returns the path to the bin directory of this JDK.
* @return bin directory
*/
public File getBinDir() {
return new File(getHome(), "bin");
}

/**
* Gets the path to 'java'.
* Returns the path to the 'java' executable.
* Automatically selects java.exe for Windows.
* @return java executable file
*/

private File getExecutable() {
String execName = File.separatorChar == '\\' ? "java.exe" : "java";
return new File(getHome(), "bin/" + execName);
}

/**
* Returns true if the executable exists.
* Returns true if the 'java' executable exists on disk.
* @return true if java exists in JDK bin directory
*/
public boolean getExists() {
return getExecutable().exists();
}

/**
* Returns the installed JDK version by executing 'java -version'.
* Logs warnings if the executable is missing or if version detection fails.
*
* @return version string like "1.8.0_302" or "Unknown" if not detectable
*/
public String getJavaVersion() {
File javaExec = getExecutable();
if (!javaExec.exists()) {
LOGGER.warning("Java executable not found at: " + javaExec.getAbsolutePath());
return "Unknown";
}
try {
Process process = new ProcessBuilder(javaExec.getAbsolutePath(), "-version")
.redirectErrorStream(true)
.start();
try (var reader = new java.io.BufferedReader(new java.io.InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.contains("version")) {
return line.split("\"")[1];
}
}
}
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Failed to determine JDK version", e);
}
return "Unknown";
}

/**
* @deprecated as of 1.460. Use {@link #buildEnvVars(EnvVars)}
*/
Expand All @@ -132,7 +169,6 @@ public void buildEnvVars(Map<String, String> env) {
if (home == null) {
return;
}
// see EnvVars javadoc for why this adds PATH.
env.put("PATH+JDK", home + "/bin");
env.put("JAVA_HOME", home);
}
Expand All @@ -157,10 +193,7 @@ public JDK forEnvironment(EnvVars environment) {

/**
* Checks if "java" is in PATH on the given node.
*
* <p>
* If it's not, then the user must specify a configured JDK,
* so this is often useful for form field validation.
* Useful for form validation.
*/
public static boolean isDefaultJDKValid(Node n) {
try {
Expand Down Expand Up @@ -206,28 +239,24 @@ public List<? extends ToolInstaller> getDefaultInstallers() {
}
}

/**
* Checks if the JAVA_HOME is a valid JAVA_HOME path.
*/
@Override protected FormValidation checkHomeDirectory(File value) {
@Override
protected FormValidation checkHomeDirectory(File value) {
File toolsJar = new File(value, "lib/tools.jar");
File mac = new File(value, "lib/dt.jar");

// JENKINS-25601: JDK 9+ no longer has tools.jar. Keep the existing dt.jar/tools.jar checks to be safe.
File javac = new File(value, "bin/javac");
File javacExe = new File(value, "bin/javac.exe");
if (!toolsJar.exists() && !mac.exists() && !javac.exists() && !javacExe.exists())
return FormValidation.error(Messages.Hudson_NotJDKDir(value));

return FormValidation.ok();
}

}

public static class ConverterImpl extends ToolConverter {
public ConverterImpl(XStream2 xstream) { super(xstream); }

@Override protected String oldHomeField(ToolInstallation obj) {
@Override
protected String oldHomeField(ToolInstallation obj) {
return ((JDK) obj).javaHome;
}
}
Expand Down
32 changes: 32 additions & 0 deletions core/src/test/java/hudson/model/JDKTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package hudson.model;

import org.junit.Test;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use JUnit 5 for tests instead of JUnit 4.

Suggested change
import org.junit.Test;
import org.junit.jupiter.api.Test;

import static org.junit.Assert.*;

import java.io.File;

public class JDKTest {

/**
* Test getJavaVersion() method.
* Verifies that it returns a non-null string.
*/
@Test
public void testGetJavaVersion() {
// Use a system JDK installation if available
String javaHome = System.getProperty("java.home");
JDK jdk = new JDK("TestJDK", javaHome);

String version = jdk.getJavaVersion();

// The version should never be null
assertNotNull("Java version should not be null", version);

// Optionally, check if it looks like a version string
assertTrue("Java version should contain a dot", version.contains("."));

// The executable should exist
File javaExec = new File(javaHome, "bin/java");
assertTrue("Java executable should exist", javaExec.exists() || new File(javaHome, "bin/java.exe").exists());
}
}
Loading